[xiph-cvs] cvs commit: w3d info.c .cvsignore Makefile tarkin-io.h tarkin.c tarkin.h tarkin_dec.c tarkin_enc.c
Holger Waechtler
holger at xiph.org
Wed Nov 7 13:19:04 PST 2001
holger 01/11/07 13:19:04
Modified: . .cvsignore Makefile tarkin-io.h tarkin.c tarkin.h
tarkin_dec.c tarkin_enc.c
Added: . info.c
Log:
We have an OGG packetizer! Thanks to <olivier at infolibre.org> !!
Revision Changes Path
1.3 +1 -1 w3d/.cvsignore
Index: .cvsignore
===================================================================
RCS file: /usr/local/cvsroot/w3d/.cvsignore,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- .cvsignore 2001/09/07 10:56:29 1.2
+++ .cvsignore 2001/11/07 21:19:02 1.3
@@ -7,5 +7,5 @@
tarkin_enc
*.pgm
*.ppm
-stream.tarkin
+stream.ogg
1.18 +6 -3 w3d/Makefile
Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/w3d/Makefile,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- Makefile 2001/09/13 16:27:33 1.17
+++ Makefile 2001/11/07 21:19:02 1.18
@@ -18,13 +18,16 @@
# dump a lot debug images
CFLAGS+= -DDBG_XFORM
+# dump ogg packet infos
+CFLAGS+= -DDBG_OGG
+
# disable assertions
#CFLAGS+= -DNDEBUG
-LFLAGS = -g -lefence
+LFLAGS = -g -lefence -logg
OBJS = mem.o pnm.o wavelet.o wavelet_xform.o wavelet_coeff.o \
- yuv.o tarkin.o tarkin-io.o
+ yuv.o tarkin.o info.o
TEST_TARGETS = _test_bitcoder _test_rle _test_huffman
@@ -49,7 +52,7 @@
$(RM) $(TEST_TARGETS) $(TEST_OBJS)
$(RM) tarkin_enc tarkin_dec tarkin_enc.o tarkin_dec.o
$(RM) *.ppm *.pgm
- $(RM) stream.tarkin
+ $(RM) stream.ogg
test: .depend $(TEST_TARGETS)
1.2 +17 -0 w3d/tarkin-io.h
Index: tarkin-io.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/tarkin-io.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- tarkin-io.h 2001/06/29 09:19:25 1.1
+++ tarkin-io.h 2001/11/07 21:19:02 1.2
@@ -3,6 +3,23 @@
#include "tarkin.h"
+extern TarkinStream * tarkin_stream_new();
+void tarkin_stream_destroy (TarkinStream *s);
+
+/* free_frame() is called anytime the codec encoded a frame,
+ * so the caller application can free it. */
+void tarkin_stream_encinit(void (*free_frame)(uint8_t **buf));
+
+extern
+TarkinError tarkin_stream_write_layer_descs (TarkinStream *s,
+ uint32_t n_layers,
+ TarkinVideoLayerDesc desc []);
+
+uint32_t tarkin_stream_write(TarkinStream *s, uint8_t **buf);
+int tarkin_stream_packetout(TarkinStream *s, ogg_packet *op);
+
+int tarkin_stream_headerin();
+int tarkin_stream_packetin();
extern int write_tarkin_header (int fd, TarkinStream *s);
extern int write_layer_descs (int fd, TarkinStream *s);
extern int write_tarkin_bitstream (int fd, uint8_t *bitstream, uint32_t len);
1.12 +214 -139 w3d/tarkin.c
Index: tarkin.c
===================================================================
RCS file: /usr/local/cvsroot/w3d/tarkin.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- tarkin.c 2001/09/13 16:27:33 1.11
+++ tarkin.c 2001/11/07 21:19:02 1.12
@@ -5,7 +5,6 @@
#include "mem.h"
#include "tarkin.h"
-#include "tarkin-io.h"
#include "yuv.h"
@@ -13,14 +12,14 @@
-TarkinStream* tarkin_stream_new (int fd)
+TarkinStream* tarkin_stream_new ()
{
TarkinStream *s = (TarkinStream*) CALLOC (1, sizeof(TarkinStream));
if (!s)
return NULL;
+ memset(s,0,sizeof(*s));
- s->fd = fd;
s->frames_per_buf = N_FRAMES;
return s;
@@ -38,39 +37,62 @@
if (s->layer[i].waveletbuf) {
for (j=0; j<s->layer[i].n_comp; j++) {
wavelet_3d_buf_destroy (s->layer[i].waveletbuf[j]);
+ FREE (s->layer[i].packet[j].data);
}
FREE(s->layer[i].waveletbuf);
+ FREE(s->layer[i].packet);
}
}
-
+
if (s->layer)
FREE(s->layer);
+
+ if (s->headers.header);
+ FREE(s->headers.header);
+
+ if (s->headers.header1);
+ FREE(s->headers.header1);
- if (s->bitstream);
- FREE(s->bitstream);
+ if (s->headers.header2);
+ FREE(s->headers.header2);
FREE(s);
}
-
-TarkinError tarkin_stream_write_layer_descs (TarkinStream *s,
- uint32_t n_layers,
- TarkinVideoLayerDesc desc [])
+int tarkin_analysis_init(TarkinStream *s, TarkinInfo *ti,
+ TarkinError (*free_frame)(void *s, void *ptr),
+ TarkinError (*packet_out)(void *s, ogg_packet *ptr),
+ void *user_ptr)
{
- TarkinError err;
- uint32_t max_bitstream_len = 0;
- uint32_t i, j;
-
- s->n_layers = n_layers;
- s->layer = (TarkinVideoLayer*) CALLOC (n_layers, sizeof(TarkinVideoLayer));
-
- for (i=0; i<n_layers; i++) {
- TarkinVideoLayer *layer = &s->layer[i];
+ if((!ti->inter.numerator)||(!ti->inter.denominator))return (-TARKIN_FAULT);
+ if((!free_frame) || (!packet_out)) return (-TARKIN_FAULT);
+ s->ti = ti;
+ s->free_frame = free_frame;
+ s->packet_out = packet_out;
+ s->user_ptr = user_ptr;
+ return(0);
+}
- memcpy (&layer->desc, &desc[i], sizeof(TarkinVideoLayerDesc));
- switch (layer->desc.format) {
+extern int tarkin_analysis_add_layer(TarkinStream *s,
+ TarkinVideoLayerDesc *tvld)
+{
+ int i;
+ TarkinVideoLayer *layer;
+ if(s->n_layers) {
+ s->layer = REALLOC(s->layer,(s->n_layers+1) * sizeof(*s->layer));
+ } else {
+ s->layer = MALLOC(sizeof(*s->layer));
+ }
+ layer = s->layer + s->n_layers;
+ memcpy (&layer->desc , tvld, sizeof(TarkinVideoLayerDesc));
+
+ s->n_layers++;
+ s->ti->n_layers = s->n_layers;
+ s->ti->layer = s->layer;
+ printf("n_layers: %d\n",s->n_layers);
+ switch (layer->desc.format) {
case TARKIN_GRAYSCALE:
layer->n_comp = 1;
layer->color_fwd_xform = grayscale_to_y;
@@ -93,32 +115,60 @@
break;
default:
return -TARKIN_INVALID_COLOR_FORMAT;
- };
+ };
- layer->waveletbuf = (Wavelet3DBuf**) CALLOC (layer->n_comp,
+ layer->waveletbuf = (Wavelet3DBuf**) CALLOC (layer->n_comp,
sizeof(Wavelet3DBuf*));
- for (j=0; j<layer->n_comp; j++)
- layer->waveletbuf[j] = wavelet_3d_buf_new (desc[i].width,
- desc[i].height,
- desc[i].frames_per_buf);
- max_bitstream_len += layer->desc.bitstream_len
- + 2 * 10 * sizeof(uint32_t) * layer->n_comp; // truncation tables
+ layer->packet = MALLOC (layer->n_comp * sizeof(*layer->packet));
+ memset(layer->packet, 0, layer->n_comp * sizeof(*layer->packet));
+
+ for (i=0; i<layer->n_comp; i++){
+ layer->waveletbuf[i] = wavelet_3d_buf_new (layer->desc.width,
+ layer->desc.height,
+ layer->desc.frames_per_buf);
+ layer->packet[i].data = MALLOC(layer->desc.bitstream_len);
+ layer->packet[i].storage = layer->desc.bitstream_len;
}
-
- if ((err = write_tarkin_header(s->fd, s)) != TARKIN_OK)
- return err;
-
- if ((err = write_layer_descs(s->fd, s)) != TARKIN_OK)
- return err;
-
- s->bitstream = (uint8_t*) MALLOC (max_bitstream_len);
-
- return TARKIN_OK;
+ /*
+ max_bitstream_len += layer->desc.bitstream_len
+ + 2 * 10 * sizeof(uint32_t) * layer->n_comp; // truncation tables
+ */
+ return (TARKIN_OK);
}
+TarkinError _analysis_packetout(TarkinStream *s, uint32_t layer_id,
+ uint32_t comp)
+{
+ ogg_packet op;
+ oggpack_buffer opb;
+ uint8_t *data;
+ uint32_t data_len;
+ int i;
+ data = s->layer[layer_id].packet[comp].data;
+ data_len = s->layer[layer_id].packet[comp].data_len;
+
+ oggpack_writeinit(&opb);
+ oggpack_write(&opb,0,8); /* No feature flags for now */
+ oggpack_write(&opb,layer_id,12);
+ oggpack_write(&opb,comp,12);
+ for(i=0;i<data_len;i++)
+ oggpack_write(&opb,*(data + i), 8);
+
+ op.b_o_s = 0;
+ op.e_o_s = data_len?0:1;
+ op.granulepos = 0;
+ op.bytes = oggpack_bytes(&opb)+4;
+ op.packet = opb.buffer;
+#ifdef DBG_OGG
+ printf("ogg: writing packet layer %d, comp %d, data_len %d\n",
+ layer_id, comp, data_len);
+#endif
+ s->layer[layer_id].packet[comp].data_len = 0; /* so direct call => eos */
+ return(s->packet_out(s,&op));
+}
-void tarkin_stream_flush (TarkinStream *s)
+void _stream_flush (TarkinStream *s)
{
uint32_t i, j;
@@ -129,7 +179,7 @@
for (j=0; j<layer->n_comp; j++) {
uint32_t comp_bitstream_len;
- uint32_t bitstream_len;
+ TarkinPacket *packet = layer->packet + j;
/**
* implicit 6:1:1 subsampling
@@ -139,6 +189,11 @@
else
comp_bitstream_len = layer->desc.bitstream_len/(layer->n_comp+5);
+ if(packet->storage < comp_bitstream_len) {
+ packet->storage = comp_bitstream_len;
+ packet->data = REALLOC (packet->data, comp_bitstream_len);
+ }
+
wavelet_3d_buf_dump ("color-%d-%03d.pgm",
s->current_frame, j,
layer->waveletbuf[j], j == 0 ? 0 : 128);
@@ -151,31 +206,33 @@
s->current_frame, j,
layer->waveletbuf[j], 128);
- bitstream_len = wavelet_3d_buf_encode_coeff (layer->waveletbuf[j],
- s->bitstream,
+ packet->data_len = wavelet_3d_buf_encode_coeff (layer->waveletbuf[j],
+ packet->data,
comp_bitstream_len);
- write_tarkin_bitstream (s->fd, s->bitstream, bitstream_len);
+ _analysis_packetout (s, i, j);
}
}
}
-uint32_t tarkin_stream_write_frame (TarkinStream *s, uint8_t **rgba)
+uint32_t tarkin_analysis_framein (TarkinStream *s, uint8_t *frame,
+ uint32_t layer_id, TarkinTime *date)
{
- uint32_t i;
-
- for (i=0; i<s->n_layers; i++) {
- TarkinVideoLayer *layer = &s->layer[i];
-
- layer->color_fwd_xform (rgba[i], layer->waveletbuf,
+ TarkinVideoLayer *layer;
+ if(!frame) return (_analysis_packetout(s, 0, 0)); /* eos */
+ if((layer_id>=s->n_layers) || (date->denominator==0)) return (TARKIN_FAULT);
+
+ layer = s->layer + layer_id;
+ layer->color_fwd_xform (frame, layer->waveletbuf,
s->current_frame_in_buf);
- }
+ /* We don't use this feature for now, neither date... */
+ s->free_frame(s,frame);
s->current_frame_in_buf++;
if (s->current_frame_in_buf == s->frames_per_buf)
- tarkin_stream_flush (s);
+ _stream_flush (s);
return (++s->current_frame);
}
@@ -184,70 +241,11 @@
/**
- * return value: number of layers, 0 on i/o error
+ * tarkin_stream_read_header() is now info.c:_tarkin_unpack_layer_desc()
*/
-uint32_t tarkin_stream_read_header (TarkinStream *s)
-{
- uint32_t max_bitstream_len = 0;
- uint32_t i, j;
-
- if (read_tarkin_header(s->fd, s) != TARKIN_OK)
- return 0;
- s->layer = (TarkinVideoLayer*) CALLOC (1, s->n_layers * sizeof(TarkinVideoLayer));
- if (read_layer_descs(s->fd, s) != TARKIN_OK)
- return 0;
-
- for (i=0; i<s->n_layers; i++) {
- TarkinVideoLayer *layer = &s->layer[i];
- switch (layer->desc.format) {
- case TARKIN_GRAYSCALE:
- layer->n_comp = 1;
- layer->color_fwd_xform = grayscale_to_y;
- layer->color_inv_xform = y_to_grayscale;
- break;
- case TARKIN_RGB24:
- layer->n_comp = 3;
- layer->color_fwd_xform = rgb24_to_yuv;
- layer->color_inv_xform = yuv_to_rgb24;
- break;
- case TARKIN_RGB32:
- layer->n_comp = 3;
- layer->color_fwd_xform = rgb32_to_yuv;
- layer->color_inv_xform = yuv_to_rgb32;
- break;
- case TARKIN_RGBA:
- layer->n_comp = 4;
- layer->color_fwd_xform = rgba_to_yuv;
- layer->color_inv_xform = yuv_to_rgba;
- break;
- default:
- BUG("unknown color format");
- };
-
- layer->waveletbuf = (Wavelet3DBuf**) CALLOC (layer->n_comp,
- sizeof(Wavelet3DBuf*));
- for (j=0; j<layer->n_comp; j++) {
- layer->waveletbuf[j] = wavelet_3d_buf_new (layer->desc.width,
- layer->desc.height,
- layer->desc.frames_per_buf);
- if (!layer->waveletbuf[j])
- return 0;
- }
-
- max_bitstream_len += layer->desc.bitstream_len
- + 2 * 10 * sizeof(uint32_t) * layer->n_comp;
- }
-
- s->bitstream = (uint8_t*) MALLOC (max_bitstream_len);
-
- return s->n_layers;
-}
-
-
-
TarkinError tarkin_stream_get_layer_desc (TarkinStream *s,
uint32_t layer_id,
TarkinVideoLayerDesc *desc)
@@ -260,54 +258,131 @@
return TARKIN_OK;
}
+TarkinError tarkin_synthesis_init (TarkinStream *s, TarkinInfo *ti)
+{
+ s->ti = ti;
+ s->layer = ti->layer; /* It was malloc()ed by headerin() */
+ s->n_layers = ti->n_layers;
+#ifdef DBG_OGG
+ printf("tarkin_synthesis_init\n");
+#endif
+ return (TARKIN_OK);
+}
-uint32_t tarkin_stream_read_frame (TarkinStream *s, uint8_t **rgba)
+TarkinError tarkin_synthesis_packetin (TarkinStream *s, ogg_packet *op)
{
- uint32_t i, j;
+ uint32_t i, layer_id, comp, data_len;
+ uint32_t flags, junk;
+ int nread;
+ oggpack_buffer opb;
+ TarkinPacket *packet;
+#ifdef DBG_OGG
+ printf("Reading packet %lld: ", op->packetno);
+#endif
+ oggpack_readinit(&opb,op->packet,op->bytes);
+ flags = oggpack_read(&opb,8);
+ layer_id = oggpack_read(&opb,12); /* Theses are required for */
+ comp = oggpack_read(&opb,12); /* data hole handling (or maybe
+ * packetno would be enough ?) */
+ nread = 4;
+
+#ifdef DBG_OGG
+ printf("layer_id %d, comp %d", layer_id, comp);
+#endif
+ if(flags){ /* This is void "infinite future features" feature ;) */
+ if(flags & 1<<7){
+ junk = flags;
+ while (junk & 1<<7)
+ junk = oggpack_read(&opb,8); /* allow for many future flags
+ that must be correctly ordonned. */
+ }
+ /* This shows how to get a feature's data:
+ if (flags & TARKIN_FLAGS_EXAMPLE){
+ tp->example = oggpack_read(&opb,32);
+ junk = tp->example & 3<<30;
+ tp->example &= 0x4fffffff;
+ }
+ */
+ for(junk=1<<31;junk & 1<<31;) /* and many future data */
+ while((junk=oggpack_read(&opb,32)) & 1<<30);
+ /* That is, feature data comes in 30 bit chunks. We also have
+ * 31 potentially usefull bits in last chunk. */
+ }
+
+ /* We now have for shure our data. */
+ packet = &s->layer[layer_id].packet[comp];
+ if(packet->data_len)return(-TARKIN_UNUSED); /* Previous data wasn't used */
+ data_len = op->bytes - (opb.ptr - opb.buffer);
+
+ if(packet->storage < data_len){
+ packet->storage = data_len + 255;
+ packet->data = REALLOC (packet->data, packet->storage);
+ }
+
+ for(i=0;i < data_len ; i++)
+ packet->data[i] = oggpack_read(&opb,8);
+
+ packet->data_len = data_len;
+ return(TARKIN_OK);
+}
+
+TarkinError tarkin_synthesis_frameout(TarkinStream *s,
+ uint8_t **frame,
+ uint32_t layer_id, TarkinTime *date)
+{
+ int j;
+ TarkinVideoLayer *layer = &s->layer[layer_id];
if (s->current_frame_in_buf == 0) {
- for (i=0; i<s->n_layers; i++) {
- TarkinVideoLayer *layer = &s->layer[i];
-
- for (j=0; j<layer->n_comp; j++) {
- uint32_t bitstream_len;
-
- bitstream_len = read_tarkin_bitstream (s->fd, s->bitstream);
-
- if (bitstream_len == 0)
- return 0xffffffff;
-
- wavelet_3d_buf_decode_coeff (layer->waveletbuf[j], s->bitstream,
- bitstream_len);
+ *frame = MALLOC (layer->desc.width * layer->desc.height * layer->n_comp);
+ for (j=0; j<layer->n_comp; j++) {
+ TarkinPacket *packet = layer->packet + j;
+
+ if(packet->data_len == 0) return (TARKIN_NEED_MORE);
+
+ wavelet_3d_buf_decode_coeff (layer->waveletbuf[j], packet->data,
+ packet->data_len);
- wavelet_3d_buf_dump ("rcoeff-%d-%03d.pgm",
+ wavelet_3d_buf_dump ("rcoeff-%d-%03d.pgm",
s->current_frame, j, layer->waveletbuf[j],
128);
- wavelet_3d_buf_inv_xform (layer->waveletbuf[j],
+ wavelet_3d_buf_inv_xform (layer->waveletbuf[j],
layer->desc.a_moments,
layer->desc.s_moments);
- wavelet_3d_buf_dump ("rcolor-%d-%03d.pgm",
+ wavelet_3d_buf_dump ("rcolor-%d-%03d.pgm",
s->current_frame, j,
layer->waveletbuf[j], j == 0 ? 0 : 128);
- }
}
- }
- for (i=0; i<s->n_layers; i++) {
- TarkinVideoLayer *layer = &s->layer[i];
-
- layer->color_inv_xform (layer->waveletbuf, rgba[i],
- s->current_frame_in_buf);
+ /* We did successfylly read a block from this layer, acknowledge it. */
+ for (j=0; j < layer->n_comp; j++)
+ layer->packet[j].data_len = 0;
}
+ layer->color_inv_xform (layer->waveletbuf, *frame,
+ s->current_frame_in_buf);
s->current_frame_in_buf++;
if (s->current_frame_in_buf == s->frames_per_buf)
s->current_frame_in_buf=0;
- return (++s->current_frame);
+ return (TARKIN_OK);
}
+
+int tarkin_synthesis_freeframe(TarkinStream *s, uint8_t *frame)
+{
+ FREE(frame);
+ return(TARKIN_OK);
+}
+
+
+
+
+
+
+
+
1.8 +167 -51 w3d/tarkin.h
Index: tarkin.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/tarkin.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- tarkin.h 2001/09/13 16:27:33 1.7
+++ tarkin.h 2001/11/07 21:19:02 1.8
@@ -3,6 +3,7 @@
#include <stdio.h>
#include "wavelet.h"
+#include <ogg/ogg.h>
#define BUG(x...) \
@@ -14,23 +15,45 @@
} while (0);
+/* Theses determine what infos the packet comes with */
+#define TARKIN_PACK_EXAMPLE 1
+typedef struct {
+ uint8_t *data;
+ uint32_t data_len;
+ uint32_t storage;
+} TarkinPacket;
+
+
typedef enum {
TARKIN_GRAYSCALE,
TARKIN_RGB24, /* tight packed RGB */
TARKIN_RGB32, /* 32bit, no alphachannel */
TARKIN_RGBA, /* dito w/ alphachannel */
+ TARKIN_YUV2, /* 16 bits YUV */
+ TARKIN_YUV12, /* 12 bits YUV */
+ TARKIN_FYUV, /* Tarkin's Fast YUV-like? */
} TarkinColorFormat;
+#define TARKIN_INTERNAL_FORMAT TARKIN_FYUV
+
typedef enum {
TARKIN_OK = 0,
TARKIN_IO_ERROR,
TARKIN_SIGNATURE_NOT_FOUND,
TARKIN_INVALID_LAYER,
- TARKIN_INVALID_COLOR_FORMAT
+ TARKIN_INVALID_COLOR_FORMAT,
+ TARKIN_VERSION,
+ TARKIN_BAD_HEADER,
+ TARKIN_NOT_TARKIN,
+ TARKIN_FAULT,
+ TARKIN_UNUSED,
+ TARKIN_NEED_MORE,
+ TARKIN_NOT_IMPLEMENTED
} TarkinError;
+
typedef struct {
uint32_t width;
uint32_t height;
@@ -46,77 +69,170 @@
TarkinVideoLayerDesc desc;
uint32_t n_comp; /* number of color components */
Wavelet3DBuf **waveletbuf;
+ TarkinPacket *packet;
uint32_t current_frame_in_buf;
void (*color_fwd_xform) (uint8_t *rgba, Wavelet3DBuf *yuva [], uint32_t count);
void (*color_inv_xform) (Wavelet3DBuf *yuva [], uint8_t *rgba, uint32_t count);
} TarkinVideoLayer;
+typedef struct {
+ uint32_t numerator;
+ uint32_t denominator;
+} TarkinTime; /* Let's say the unit is 1 second */
+
+typedef struct TarkinInfo {
+ int version;
+ int n_layers;
+ TarkinVideoLayer *layer;
+ TarkinTime inter; /* numerator == O if per-frame time info. */
+ int frames_per_block;
+ int comp_per_block; /* AKA "packets per block" for now */
+ uint32_t max_bitstream_len;
+
+ /* The below bitrate declarations are *hints*.
+ Combinations of the three values carry the following implications:
+
+ all three set to the same value:
+ implies a fixed rate bitstream
+ only nominal set:
+ implies a VBR stream that averages the nominal bitrate. No hard
+ upper/lower limit
+ upper and or lower set:
+ implies a VBR bitstream that obeys the bitrate limits. nominal
+ may also be set to give a nominal rate.
+ none set:
+ the coder does not care to speculate.
+ */
+
+ long bitrate_upper;
+ long bitrate_nominal;
+ long bitrate_lower;
+ long bitrate_window;
+} TarkinInfo;
+/* This is used for encoding */
typedef struct {
- int fd;
+ unsigned char *header;
+ unsigned char *header1;
+ unsigned char *header2;
+} tarkin_header_store;
+
+
+
+
+ /* Some of the fields in TarkinStream are redundent with TarkinInfo ones
+ * and will probably get deleted, namely n_layers and frames_per_buf */
+typedef struct TarkinStream {
uint32_t n_layers;
TarkinVideoLayer *layer;
uint32_t current_frame;
uint32_t current_frame_in_buf;
+ ogg_int64_t packetno;
uint32_t frames_per_buf;
- uint8_t *bitstream;
+ uint32_t max_bitstream_len;
+ TarkinInfo *ti;
+ tarkin_header_store headers;
+ /* These callbacks are only used for encoding */
+ TarkinError (*free_frame)(void *tarkinstream, void *ptr);
+ /* These thing allows not to buffer but it needs global var in caller. */
+ TarkinError (*packet_out)(void *tarkinstream, ogg_packet *ptr);
+ void * user_ptr;
} TarkinStream;
-extern
-TarkinStream* tarkin_stream_new (int fd);
+typedef struct TarkinComment{
+ /* unlimited user comment fields. libtarkin writes 'libtarkin'
+ whatever vendor is set to in encode */
+ char **user_comments;
+ int *comment_lengths;
+ int comments;
+ char *vendor;
+
+} TarkinComment;
+
+/* Tarkin PRIMITIVES: general ***************************************/
+
+/* The Tarkin header is in three packets, the initial small packet in
+ the first page that identifies basic parameters, that is a TarkinInfo
+ structure, a second packet with bitstream comments and a third packet
+ that holds the layers description structures. */
+
+
+/* Theses are the very same than Vorbis versions, they could be shared. */
+extern TarkinStream* tarkin_stream_new ();
+extern void tarkin_stream_destroy (TarkinStream *s);
+extern void tarkin_info_init(TarkinInfo *vi);
+extern void tarkin_info_clear(TarkinInfo *vi);
+extern void tarkin_comment_init(TarkinComment *vc);
+extern void tarkin_comment_add(TarkinComment *vc, char *comment);
+extern void tarkin_comment_add_tag(TarkinComment *vc,
+ char *tag, char *contents);
+extern char *tarkin_comment_query(TarkinComment *vc, char *tag, int count);
+extern int tarkin_comment_query_count(TarkinComment *vc, char *tag);
+extern void tarkin_comment_clear(TarkinComment *vc);
+
+/* Tarkin PRIMITIVES: analysis layer ****************************/
+/* Tarkin encoding is done this way : you init it passing a fresh
+ * TarkinStream and a fresh TarkinInfo which has at least the rate_num
+ * field renseigned. You also pass it two callback functions: free_frame()
+ * is called when the lib doesn't need a frame anymore, and packet_out
+ * is called when a packet is ready. The pointers given as arguments to
+ * these callback functions are of course only valid at the function call
+ * time. The user_ptr is stored in s and can be used by packet_out(). */
+extern int tarkin_analysis_init(TarkinStream *s,
+ TarkinInfo *ti,
+ TarkinError (*free_frame)(void *tarkinstream, void *ptr),
+ TarkinError (*packet_out)(void *tarkinstream, ogg_packet *ptr),
+ void *user_ptr
+ );
+/* Then you need to add at least a layer in your stream, passing a
+ * TarkinVideoLayerDesc renseigned at least on the width, height and
+ * format parameters. */
+extern int tarkin_analysis_add_layer(TarkinStream *s,
+ TarkinVideoLayerDesc *tvld);
+/* At that point you are ready to get headers out the lib by calling
+ * tarkin_analysis_headerout() passing it a renseigned TarkinComment
+ * structure. It does fill your 3 ogg_packet headers, which are valid
+ * till next call */
+extern int TarkinCommentheader_out(TarkinComment *vc, ogg_packet *op);
+extern TarkinError tarkin_analysis_headerout(TarkinStream *s,
+ TarkinComment *vc,
+ ogg_packet *op,
+ ogg_packet *op_comm,
+ ogg_packet *op_code);
+/* You are now ready to pass in frames to the codec, however don't free
+ * them before the codec told you so. It'll tell you when packets are
+ * ready to be taken out. When you have no more frame, simply pass NULL.
+ * If you encode multiple layers you have to do it synchronously, putting
+ * one frame from each layer at a time. */
+extern uint32_t tarkin_analysis_framein(TarkinStream *s,
+ uint8_t *frame, /* NULL for EOS */
+ uint32_t layer,
+ TarkinTime *date);
+
+/* Tarkin PRIMITIVES: synthesis layer *******************************/
+/* For decoding, you needs first to give the three first packet of the
+ * stream to tarkin_synthesis_headerin() which will fill for you blank
+ * TarkinInfo and TarkinComment. */
+extern TarkinError tarkin_synthesis_headerin(TarkinInfo *vi,TarkinComment *vc,
+ ogg_packet *op);
+/* Then you can init your stream with your TarkinInfo struct. */
+extern TarkinError tarkin_synthesis_init(TarkinStream *s,TarkinInfo *ti);
+/* All subsequent packets are to this be passed to tarkin_synthesis_packetin*/
+extern TarkinError tarkin_synthesis_packetin(TarkinStream *s, ogg_packet *op);
+/* and then tarkin_synthesis_frameout gives you ptr on next frame, or NULL. It
+ * also fills for you date. */
+extern TarkinError tarkin_synthesis_frameout(TarkinStream *s,
+ uint8_t **frame, uint32_t layer_id, TarkinTime *date);
+/* When you're done with a frame, tell it to the codec with this. */
+extern int tarkin_synthesis_freeframe(TarkinStream *s, uint8_t *frame);
-extern
-void tarkin_stream_destroy (TarkinStream *s);
+#endif
-/**
- * Copy layer description of layer into desc
- */
-extern
-TarkinError tarkin_stream_get_layer_desc (TarkinStream *s,
- uint32_t layer_id,
- TarkinVideoLayerDesc *desc);
-
-/**
- * Return value: number of layers, 0 on i/o error
- */
-extern
-uint32_t tarkin_stream_read_header (TarkinStream *s);
-
-
-/**
- * Read all layers of the next frame to buf[0..n_layers]
- * returns the number of this frame on success, -1 on error
- */
-extern
-uint32_t tarkin_stream_read_frame (TarkinStream *s, uint8_t **buf);
-
-
-/**
- * Setup file configuration by writing layer descriptions
- * Has to be done once after creating the stream
- */
-extern
-TarkinError tarkin_stream_write_layer_descs (TarkinStream *s,
- uint32_t n_layers,
- TarkinVideoLayerDesc desc []);
-
-/**
- * Write a single frame. This means that content is copied into
- * a wavelet buffer. As soon this gets filled, the stream will be
- * flushed implicitly.
- * Each pointer in buf points to an layer imaged described by the
- * tarkin_stream_write_layer_descs() call
- */
-extern
-uint32_t tarkin_stream_write_frame (TarkinStream *s, uint8_t **buf);
-extern
-void tarkin_stream_flush (TarkinStream *s);
-#endif
1.4 +51 -22 w3d/tarkin_dec.c
Index: tarkin_dec.c
===================================================================
RCS file: /usr/local/cvsroot/w3d/tarkin_dec.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- tarkin_dec.c 2001/09/13 16:27:33 1.3
+++ tarkin_dec.c 2001/11/07 21:19:03 1.4
@@ -6,19 +6,32 @@
#include "mem.h"
#include "tarkin.h"
#include "pnm.h"
+#include <ogg/ogg.h>
+#define CHUNK_SIZE 4096
-
int main (int argc, char **argv)
{
- char *fname = "stream.tarkin";
+ char *fname = "stream.ogg";
char ofname [11];
uint32_t frame = 0;
uint8_t *rgb;
int fd;
TarkinStream *tarkin_stream;
uint32_t n_layers;
- TarkinVideoLayerDesc layer;
+ int nread;
+ int nheader = 0;
+ ogg_sync_state oy;
+ ogg_stream_state os;
+ ogg_page og;
+ ogg_packet op;
+ TarkinInfo ti;
+ TarkinComment tc;
+ TarkinTime date;
+
+ char *buffer;
+
+ TarkinVideoLayerDesc *layer;
if (argc == 2) {
fname = argv[1];
@@ -33,26 +46,42 @@
}
tarkin_stream = tarkin_stream_new (fd);
- n_layers = tarkin_stream_read_header (tarkin_stream);
-
- if (n_layers == 0) {
- printf ("empty tarkin stream !!!\n");
- exit (-1);
+ ogg_sync_init(&oy);
+ ogg_stream_init(&os,1);
+ tarkin_info_init(&ti);
+ tarkin_comment_init(&tc);
+ while(1){
+ buffer = ogg_sync_buffer(&oy, CHUNK_SIZE);
+ if((nread = read(fd, buffer, CHUNK_SIZE))>0)
+ ogg_sync_wrote(&oy, nread);
+ else{
+ ogg_sync_wrote(&oy,0);
+ break;
+ }
+ if(ogg_sync_pageout(&oy,&og)){
+ ogg_stream_pagein(&os,&og);
+ while(ogg_stream_packetout(&os,&op)){
+ if(nheader<3){
+ tarkin_synthesis_headerin(&ti, &tc, &op);
+ if(nheader == 2){
+ tarkin_synthesis_init(tarkin_stream, &ti);
+ }
+ nheader++;
+ } else {
+ tarkin_synthesis_packetin(tarkin_stream, &op);
+ while(tarkin_synthesis_frameout(tarkin_stream, &rgb, 0, &date)==0){
+ layer = tarkin_stream->layer;
+ snprintf(ofname, 11, layer->format == TARKIN_GRAYSCALE ? "out%03d.pgm" : "out%03d.ppm", frame);
+ printf ("write '%s' %dx%d\n", ofname, layer->width, layer->height);
+ write_pnm (ofname, rgb, layer->width, layer->height);
+ tarkin_synthesis_freeframe(tarkin_stream, rgb);
+
+ frame ++;
+ }
+ }
+ }
+ }
}
-
- tarkin_stream_get_layer_desc (tarkin_stream, 0, &layer);
-
- rgb = MALLOC (layer.width * layer.height * (layer.format == TARKIN_GRAYSCALE ? 1 : 3));
-
- while (tarkin_stream_read_frame (tarkin_stream, &rgb) != 0xffffffff) {
- snprintf(ofname, 11, layer.format == TARKIN_GRAYSCALE ? "out%03d.pgm" : "out%03d.ppm", frame);
- printf ("write '%s'\n", ofname);
- write_pnm (ofname, rgb, layer.width, layer.height);
-
- frame ++;
- };
-
- FREE (rgb);
tarkin_stream_destroy (tarkin_stream);
close (fd);
1.13 +65 -11 w3d/tarkin_enc.c
Index: tarkin_enc.c
===================================================================
RCS file: /usr/local/cvsroot/w3d/tarkin_enc.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- tarkin_enc.c 2001/09/13 16:27:33 1.12
+++ tarkin_enc.c 2001/11/07 21:19:03 1.13
@@ -25,18 +25,50 @@
exit (-1);
}
+TarkinError free_frame(void *s, void *ptr) {
+ FREE (ptr);
+ return(TARKIN_OK);
+}
+
+struct tarkin_enc {
+ ogg_stream_state os;
+ int fd;
+};
+
+TarkinError packet_out(void *stream, ogg_packet *op) {
+ ogg_page og;
+ TarkinStream *s = stream;
+ struct tarkin_enc *te = s->user_ptr;
+ ogg_stream_packetin(&te->os,op);
+ if(op->e_o_s){
+ ogg_stream_flush(&te->os, &og);
+ write(te->fd, og.header, og.header_len);
+ write(te->fd, og.body , og.body_len);
+ } else {
+ while(ogg_stream_pageout(&te->os,&og)){
+ write(te->fd, og.header, og.header_len);
+ write(te->fd, og.body , og.body_len);
+ }
+ }
+ return (TARKIN_OK);
+}
-
int main (int argc, char **argv)
{
char *fmt = "%i.ppm";
char fname[256];
uint32_t frame = 0;
uint8_t *rgb;
- int fd;
+ struct tarkin_enc te;
TarkinStream *tarkin_stream;
TarkinVideoLayerDesc layer [] = { { 0, 0, 1, 5000, TARKIN_RGB24 } };
- int type;
+ int type,i;
+ TarkinComment tc;
+ TarkinInfo ti;
+ ogg_page og;
+ ogg_packet op[3];
+ TarkinTime date;
+
if (argc == 1) {
layer[0].bitstream_len = 1000;
@@ -61,17 +93,36 @@
layer[0].format = (type == 3) ? TARKIN_RGB24 : TARKIN_GRAYSCALE;
- rgb = (uint8_t*) MALLOC (layer[0].width * layer[0].height * type);
- if ((fd = open ("stream.tarkin", O_CREAT | O_RDWR | O_TRUNC, 0644)) < 0) {
- printf ("error opening '%s' for writing !\n", "stream.tarkin");
+ if ((te.fd = open ("stream.ogg", O_CREAT | O_RDWR | O_TRUNC, 0644)) < 0) {
+ printf ("error opening '%s' for writing !\n", "stream.ogg");
usage (argv[0]);
}
+
+ ogg_stream_init(&te.os,1);
+ tarkin_info_init(&ti);
- tarkin_stream = tarkin_stream_new (fd);
- tarkin_stream_write_layer_descs (tarkin_stream, 1, layer);
+ ti.inter.numerator = 1;
+ ti.inter.denominator = 1;
+ tarkin_comment_init(&tc);
+ tarkin_comment_add_tag(&tc, "TITLE", "tarkin_enc produced file");
+ tarkin_comment_add_tag(&tc, "ARTIST", "C coders ;)");
+ tarkin_stream = tarkin_stream_new ();
+ tarkin_analysis_init(tarkin_stream, &ti, free_frame, packet_out,(void*)&te);
+ tarkin_analysis_add_layer(tarkin_stream, &layer[0]);
+ printf("n_layers: %d\n", tarkin_stream->n_layers);
+ tarkin_analysis_headerout(tarkin_stream, &tc, op, &op[1], &op[2]);
+ for(i=0;i<3;i++){
+ ogg_stream_packetin(&te.os, &op[i]);
+ }
+ ogg_stream_flush(&te.os,&og);
+ write(te.fd, og.header, og.header_len);
+ write(te.fd, og.body, og.body_len);
+
+
do {
+ rgb = (uint8_t*) MALLOC (layer[0].width * layer[0].height * type);
snprintf (fname, 256, fmt, frame);
printf ("read '");
printf (fname, frame);
@@ -83,14 +134,17 @@
break;
}
printf ("\n");
-
- tarkin_stream_write_frame (tarkin_stream, &rgb);
+ date.numerator = frame;
+ date.denominator = 1;
+ tarkin_analysis_framein (tarkin_stream, rgb, 0, &date);
frame++;
} while (1);
FREE (rgb);
+ tarkin_analysis_framein (tarkin_stream, NULL, 0, NULL); /* EOS */
+ tarkin_comment_clear (&tc);
tarkin_stream_destroy (tarkin_stream);
- close (fd);
+ close (te.fd);
return 0;
}
1.1 w3d/info.c
Index: info.c
===================================================================
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
* by the XIPHOPHORUS Company http://www.xiph.org/ *
********************************************************************
function: maintain the info structure, info <-> header packets
last mod: $Id: info.c,v 1.1 2001/11/07 21:19:02 holger Exp $
********************************************************************/
/* general handling of the header and the TarkinInfo structure (and
substructures) */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <ogg/ogg.h>
#include "tarkin.h"
#include "yuv.h"
#include "mem.h"
/* helpers */
static void _v_writestring(oggpack_buffer *o,char *s, int bytes){
while(bytes--){
oggpack_write(o,*s++,8);
}
}
tatic void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
while(bytes--){
*buf++=oggpack_read(o,8);
}
}
void tarkin_comment_init(TarkinComment *vc){
memset(vc,0,sizeof(*vc));
}
void tarkin_comment_add(TarkinComment *vc,char *comment){
vc->user_comments=REALLOC(vc->user_comments,
(vc->comments+2)*sizeof(*vc->user_comments));
vc->comment_lengths=REALLOC(vc->comment_lengths,
(vc->comments+2)*sizeof(*vc->comment_lengths));
vc->comment_lengths[vc->comments]=strlen(comment);
vc->user_comments[vc->comments]=MALLOC(vc->comment_lengths[vc->comments]+1);
strcpy(vc->user_comments[vc->comments], comment);
vc->comments++;
vc->user_comments[vc->comments]=NULL;
}
void tarkin_comment_add_tag(TarkinComment *vc, char *tag, char *contents){
char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
strcpy(comment, tag);
strcat(comment, "=");
strcat(comment, contents);
tarkin_comment_add(vc, comment);
}
/* This is more or less the same as strncasecmp - but that doesn't exist
* everywhere, and this is a fairly trivial function, so we include it */
static int tagcompare(const char *s1, const char *s2, int n){
int c=0;
while(c < n){
if(toupper(s1[c]) != toupper(s2[c]))
return !0;
c++;
}
return 0;
}
char *tarkin_comment_query(TarkinComment *vc, char *tag, int count){
long i;
int found = 0;
int taglen = strlen(tag)+1; /* +1 for the = we append */
char *fulltag = alloca(taglen+ 1);
strcpy(fulltag, tag);
strcat(fulltag, "=");
for(i=0;i<vc->comments;i++){
if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
if(count == found)
/* We return a pointer to the data, not a copy */
return vc->user_comments[i] + taglen;
else
found++;
}
}
return NULL; /* didn't find anything */
}
int tarkin_comment_query_count(TarkinComment *vc, char *tag){
int i,count=0;
int taglen = strlen(tag)+1; /* +1 for the = we append */
char *fulltag = alloca(taglen+1);
strcpy(fulltag,tag);
strcat(fulltag, "=");
for(i=0;i<vc->comments;i++){
if(!tagcompare(vc->user_comments[i], fulltag, taglen))
count++;
}
return count;
}
void tarkin_comment_clear(TarkinComment *vc){
if(vc){
long i;
for(i=0;i<vc->comments;i++)
if(vc->user_comments[i])FREE(vc->user_comments[i]);
if(vc->user_comments)FREE(vc->user_comments);
if(vc->comment_lengths)FREE(vc->comment_lengths);
if(vc->vendor)FREE(vc->vendor);
}
memset(vc,0,sizeof(*vc));
}
/* used by synthesis, which has a full, alloced vi */
void tarkin_info_init(TarkinInfo *vi){
memset(vi,0,sizeof(*vi));
}
void tarkin_info_clear(TarkinInfo *vi){
memset(vi,0,sizeof(*vi));
}
/* Header packing/unpacking ********************************************/
tatic int _tarkin_unpack_info(TarkinInfo *vi,oggpack_buffer *opb)
{
#ifdef DBG_OGG
printf("ogg: Decoding Info: ");
#endif
vi->version=oggpack_read(opb,32);
if(vi->version!=0)return(-TARKIN_VERSION);
vi->n_layers=oggpack_read(opb,8);
vi->inter.numerator=oggpack_read(opb,32);
vi->inter.denominator=oggpack_read(opb,32);
vi->bitrate_upper=oggpack_read(opb,32);
vi->bitrate_nominal=oggpack_read(opb,32);
vi->bitrate_lower=oggpack_read(opb,32);
#ifdef DBG_OGG
printf("n_layers %d, interleave: %d/%d.",
vi->n_layers, vi->inter.numerator, vi->inter.denominator);
#endif
if(vi->inter.numerator<1)goto err_out;
if(vi->inter.denominator<1)goto err_out;
if(vi->n_layers<1)goto err_out;
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
#ifdef DBG_OGG
printf("Success\n");
#endif
return(0);
err_out:
#ifdef DBG_OGG
printf("Failed\n");
#endif
tarkin_info_clear(vi);
return(-TARKIN_BAD_HEADER);
}
tatic int _tarkin_unpack_comment(TarkinComment *vc,oggpack_buffer *opb)
{
int i;
int vendorlen=oggpack_read(opb,32);
#ifdef DBG_OGG
printf("ogg: Decoding comment....");
#endif
if(vendorlen<0)goto err_out;
vc->vendor=_ogg_calloc(vendorlen+1,1);
_v_readstring(opb,vc->vendor,vendorlen);
vc->comments=oggpack_read(opb,32);
if(vc->comments<0)goto err_out;
vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
vc->comment_lengths=_ogg_calloc(vc->comments+1,
sizeof(*vc->comment_lengths));
for(i=0;i<vc->comments;i++){
int len=oggpack_read(opb,32);
if(len<0)goto err_out;
vc->comment_lengths[i]=len;
vc->user_comments[i]=_ogg_calloc(len+1,1);
_v_readstring(opb,vc->user_comments[i],len);
}
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
#ifdef DBG_OGG
printf("Success\n");
#endif
return(0);
err_out:
#ifdef DBG_OGG
printf("Failed\n");
#endif
tarkin_comment_clear(vc);
return(-TARKIN_BAD_HEADER);
}
/* the real encoding details are here, currently TarkinVideoLayerDesc. */
static int _tarkin_unpack_layer_desc(TarkinInfo *vi,oggpack_buffer *opb){
int i,j;
vi->layer = _ogg_calloc(vi->n_layers, (sizeof(*vi->layer)));
#ifdef DBG_OGG
printf("ogg: Decoding layers desc....");
#endif
for(i=0;i<vi->n_layers;i++){
TarkinVideoLayer *layer = vi->layer + i;
layer->desc.width = oggpack_read(opb,32);
layer->desc.height = oggpack_read(opb,32);
layer->desc.a_moments = oggpack_read(opb,32);
layer->desc.s_moments = oggpack_read(opb,32);
layer->desc.frames_per_buf = oggpack_read(opb,32);
layer->desc.bitstream_len = oggpack_read(opb,32);
layer->desc.format = oggpack_read(opb,32);
switch (layer->desc.format) {
case TARKIN_GRAYSCALE:
layer->n_comp = 1;
layer->color_fwd_xform = grayscale_to_y;
layer->color_inv_xform = y_to_grayscale;
break;
case TARKIN_RGB24:
layer->n_comp = 3;
layer->color_fwd_xform = rgb24_to_yuv;
layer->color_inv_xform = yuv_to_rgb24;
break;
case TARKIN_RGB32:
layer->n_comp = 3;
layer->color_fwd_xform = rgb32_to_yuv;
layer->color_inv_xform = yuv_to_rgb32;
break;
case TARKIN_RGBA:
layer->n_comp = 4;
layer->color_fwd_xform = rgba_to_yuv;
layer->color_inv_xform = yuv_to_rgba;
break;
default:
return -TARKIN_INVALID_COLOR_FORMAT;
};
layer->waveletbuf = (Wavelet3DBuf**) CALLOC (layer->n_comp,
sizeof(Wavelet3DBuf*));
layer->packet = MALLOC (layer->n_comp * sizeof(*layer->packet));
memset(layer->packet, 0, layer->n_comp * sizeof(*layer->packet));
for (j=0; j<layer->n_comp; j++){
layer->waveletbuf[j] = wavelet_3d_buf_new (layer->desc.width,
layer->desc.height,
layer->desc.frames_per_buf);
layer->packet[j].data = MALLOC(layer->desc.bitstream_len);
layer->packet[j].storage = layer->desc.bitstream_len;
}
vi->max_bitstream_len += layer->desc.bitstream_len
+ 2 * 10 * sizeof(uint32_t) * layer->n_comp; // truncation tables
} /* for each layer */
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
#ifdef DBG_OGG
printf("Success\n");
#endif
return(0);
err_out:
#ifdef DBG_OGG
printf("Failed\n");
#endif
tarkin_info_clear(vi);
return(-TARKIN_BAD_HEADER);
}
/* The Tarkin header is in three packets; the initial small packet in
the first page that identifies basic parameters, a second packet
with bitstream comments and a third packet that holds the
layer description structures. */
TarkinError tarkin_synthesis_headerin(TarkinInfo *vi,TarkinComment *vc,ogg_packet *op){
oggpack_buffer opb;
if(op){
oggpack_readinit(&opb,op->packet,op->bytes);
/* Which of the three types of header is this? */
/* Also verify header-ness, tarkin */
{
char buffer[6];
int packtype=oggpack_read(&opb,8);
memset(buffer,0,6);
_v_readstring(&opb,buffer,6);
if(memcmp(buffer,"tarkin",6)){
/* not a tarkin header */
return(-TARKIN_NOT_TARKIN);
}
switch(packtype){
case 0x01: /* least significant *bit* is read first */
if(!op->b_o_s){
/* Not the initial packet */
return(-TARKIN_BAD_HEADER);
}
if(vi->inter.numerator!=0){
/* previously initialized info header */
return(-TARKIN_BAD_HEADER);
}
return(_tarkin_unpack_info(vi,&opb));
case 0x03: /* least significant *bit* is read first */
if(vi->inter.denominator==0){
/* um... we didn't get the initial header */
return(-TARKIN_BAD_HEADER);
}
return(_tarkin_unpack_comment(vc,&opb));
case 0x05: /* least significant *bit* is read first */
if(vi->inter.numerator == 0 || vc->vendor==NULL){
/* um... we didn;t get the initial header or comments yet */
return(-TARKIN_BAD_HEADER);
}
return(_tarkin_unpack_layer_desc(vi,&opb));
default:
/* Not a valid tarkin header type */
return(-TARKIN_BAD_HEADER);
break;
}
}
}
return(-TARKIN_BAD_HEADER);
}
/* pack side **********************************************************/
tatic int _tarkin_pack_info(oggpack_buffer *opb,TarkinInfo *vi){
/* preamble */
oggpack_write(opb,0x01,8);
_v_writestring(opb,"tarkin", 6);
/* basic information about the stream */
oggpack_write(opb,0x00,32);
oggpack_write(opb,vi->n_layers,8);
oggpack_write(opb,vi->inter.numerator,32);
oggpack_write(opb,vi->inter.denominator,32);
oggpack_write(opb,vi->bitrate_upper,32);
oggpack_write(opb,vi->bitrate_nominal,32);
oggpack_write(opb,vi->bitrate_lower,32);
oggpack_write(opb,1,1);
return(0);
}
tatic int _tarkin_pack_comment(oggpack_buffer *opb,TarkinComment *vc){
char temp[]="libTarkin debugging edition 20011104";
int bytes = strlen(temp);
/* preamble */
oggpack_write(opb,0x03,8);
_v_writestring(opb,"tarkin", 6);
/* vendor */
oggpack_write(opb,bytes,32);
_v_writestring(opb,temp, bytes);
/* comments */
oggpack_write(opb,vc->comments,32);
if(vc->comments){
int i;
for(i=0;i<vc->comments;i++){
if(vc->user_comments[i]){
oggpack_write(opb,vc->comment_lengths[i],32);
_v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
}else{
oggpack_write(opb,0,32);
}
}
}
oggpack_write(opb,1,1);
return(0);
}
static int _tarkin_pack_layer_desc(oggpack_buffer *opb,TarkinInfo *vi)
{
int i;
TarkinVideoLayer *layer;
oggpack_write(opb,0x05,8);
_v_writestring(opb,"tarkin", 6);
for(i=0;i<vi->n_layers;i++){
layer = vi->layer + i;
oggpack_write(opb,layer->desc.width,32);
oggpack_write(opb,layer->desc.height,32);
oggpack_write(opb,layer->desc.a_moments,32);
oggpack_write(opb,layer->desc.s_moments,32);
oggpack_write(opb,layer->desc.frames_per_buf,32);
oggpack_write(opb,layer->desc.bitstream_len,32);
oggpack_write(opb,layer->desc.format,32);
}
oggpack_write(opb,1,1);
return(0);
}
int TarkinCommentheader_out(TarkinComment *vc, ogg_packet *op)
{
oggpack_buffer opb;
oggpack_writeinit(&opb);
if(_tarkin_pack_comment(&opb,vc)) return -TARKIN_NOT_IMPLEMENTED;
op->packet = MALLOC(oggpack_bytes(&opb));
memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
op->bytes=oggpack_bytes(&opb);
op->b_o_s=0;
op->e_o_s=0;
op->granulepos=0;
return 0;
}
TarkinError tarkin_analysis_headerout(TarkinStream *v,
TarkinComment *vc,
ogg_packet *op,
ogg_packet *op_comm,
ogg_packet *op_code)
{
int ret=-TARKIN_NOT_IMPLEMENTED;
TarkinInfo * vi;
oggpack_buffer opb;
tarkin_header_store *b=&v->headers;
vi = v->ti;
/* first header packet **********************************************/
oggpack_writeinit(&opb);
if(_tarkin_pack_info(&opb,vi))goto err_out;
/* build the packet */
if(b->header)FREE(b->header);
b->header=MALLOC(oggpack_bytes(&opb));
memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
op->packet=b->header;
op->bytes=oggpack_bytes(&opb);
op->b_o_s=1;
op->e_o_s=0;
op->granulepos=0;
/* second header packet (comments) **********************************/
oggpack_reset(&opb);
if(_tarkin_pack_comment(&opb,vc))goto err_out;
if(b->header1)FREE(b->header1);
b->header1=MALLOC(oggpack_bytes(&opb));
memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
op_comm->packet=b->header1;
op_comm->bytes=oggpack_bytes(&opb);
op_comm->b_o_s=0;
op_comm->e_o_s=0;
op_comm->granulepos=0;
/* third header packet (modes/codebooks) ****************************/
oggpack_reset(&opb);
if(_tarkin_pack_layer_desc(&opb,vi))goto err_out;
if(b->header2)FREE(b->header2);
b->header2=MALLOC(oggpack_bytes(&opb));
memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
op_code->packet=b->header2;
op_code->bytes=oggpack_bytes(&opb);
op_code->b_o_s=0;
op_code->e_o_s=0;
op_code->granulepos=0;
oggpack_writeclear(&opb);
return(0);
err_out:
oggpack_writeclear(&opb);
memset(op,0,sizeof(*op));
memset(op_comm,0,sizeof(*op_comm));
memset(op_code,0,sizeof(*op_code));
if(b->header)FREE(b->header);
if(b->header1)FREE(b->header1);
if(b->header2)FREE(b->header2);
b->header=NULL;
b->header1=NULL;
b->header2=NULL;
return(ret);
}
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list