[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