[xiph-commits] r3216 - liboggz/trunk/src/liboggz

shans at svn.annodex.net shans at svn.annodex.net
Sun Sep 2 21:57:14 PDT 2007


Author: shans
Date: 2007-09-02 21:57:14 -0700 (Sun, 02 Sep 2007)
New Revision: 3216

Modified:
   liboggz/trunk/src/liboggz/oggz.c
   liboggz/trunk/src/liboggz/oggz_auto.c
   liboggz/trunk/src/liboggz/oggz_dlist.c
   liboggz/trunk/src/liboggz/oggz_private.h
   liboggz/trunk/src/liboggz/oggz_read.c
   liboggz/trunk/src/liboggz/oggz_stream.h
Log:
Code to generate initial granulepos values for packets before the end of the first page.  



Modified: liboggz/trunk/src/liboggz/oggz.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz.c	2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz.c	2007-09-03 04:57:14 UTC (rev 3216)
@@ -101,6 +101,8 @@
   oggz->order = NULL;
   oggz->order_user_data = NULL;
 
+  oggz->packet_buffer = oggz_dlist_new ();
+
   if (OGGZ_CONFIG_WRITE && (oggz->flags & OGGZ_WRITE)) {
     oggz_write_init (oggz);
   } else if (OGGZ_CONFIG_READ) {

Modified: liboggz/trunk/src/liboggz/oggz_auto.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz_auto.c	2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_auto.c	2007-09-03 04:57:14 UTC (rev 3216)
@@ -444,6 +444,26 @@
 
 }
 
+auto_rcalc_theora(ogg_int64_t next_packet_gp, oggz_stream_t *stream, 
+                  ogg_packet *this_packet, ogg_packet *next_packet) {
+
+  int keyframe = (int)(next_packet_gp >> stream->granuleshift);
+  int offset = (int)(next_packet_gp - (keyframe << stream->granuleshift));
+
+  /* assume kf is 60 frames ago. NOTE: This is going to cause problems,
+   * but I can't think of what else to do.  The position of the last kf
+   * is fundamentally unknowable.
+   */
+  if (offset == 0) {
+    return ((keyframe - 60L) << stream->granuleshift) + 59;
+  }
+  else {
+    return (((ogg_int64_t)keyframe) << stream->granuleshift) + (offset - 1);
+  }
+
+}
+
+
 /*
  * Vorbis packets can be short or long, and each packet overlaps the previous
  * and next packets.  The granulepos of a packet is always the last sample
@@ -721,6 +741,25 @@
   
 }
 
+ogg_int64_t
+auto_rcalc_vorbis(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
+                  ogg_packet *this_packet, ogg_packet *next_packet) {
+
+  auto_calc_vorbis_info_t *info = 
+                  (auto_calc_vorbis_info_t *)stream->calculate_data;
+
+  int mode = 
+      (this_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
+  int this_size = info->mode_sizes[mode] ? info->long_size : info->short_size;
+  int next_size;
+
+  mode = (next_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
+  next_size = info->mode_sizes[mode] ? info->long_size : info->short_size;
+
+  return next_packet_gp - ((this_size + next_size) / 4);
+
+}
+
 /**
  * FLAC
  * Defined at: http://flac.sourceforge.net/ogg_mapping.html
@@ -838,17 +877,17 @@
 }
 
 const oggz_auto_contenttype_t oggz_auto_codec_ident[] = {
-  {"\200theora", 7, "Theora", auto_theora, auto_calc_theora},
-  {"\001vorbis", 7, "Vorbis", auto_vorbis, auto_calc_vorbis},
-  {"Speex", 5, "Speex", auto_speex, auto_calc_speex},
-  {"PCM     ", 8, "PCM", auto_oggpcm2, NULL},
-  {"CMML\0\0\0\0", 8, "CMML", auto_cmml, NULL},
-  {"Annodex", 8, "Annodex", auto_annodex, NULL},
-  {"fishead", 7, "Skeleton", auto_fishead, NULL},
-  {"fLaC", 4, "Flac0", auto_flac0, auto_calc_flac},
-  {"\177FLAC", 4, "Flac", auto_flac, auto_calc_flac},
-  {"AnxData", 7, "AnxData", auto_anxdata, NULL},
-  {"", 0, "Unknown", NULL, NULL}
+  {"\200theora", 7, "Theora", auto_theora, auto_calc_theora, auto_rcalc_theora},
+  {"\001vorbis", 7, "Vorbis", auto_vorbis, auto_calc_vorbis, auto_rcalc_vorbis},
+  {"Speex", 5, "Speex", auto_speex, auto_calc_speex, NULL},
+  {"PCM     ", 8, "PCM", auto_oggpcm2, NULL, NULL},
+  {"CMML\0\0\0\0", 8, "CMML", auto_cmml, NULL, NULL},
+  {"Annodex", 8, "Annodex", auto_annodex, NULL, NULL},
+  {"fishead", 7, "Skeleton", auto_fishead, NULL, NULL},
+  {"fLaC", 4, "Flac0", auto_flac0, auto_calc_flac, NULL},
+  {"\177FLAC", 4, "Flac", auto_flac, auto_calc_flac, NULL},
+  {"AnxData", 7, "AnxData", auto_anxdata, NULL, NULL},
+  {"", 0, "Unknown", NULL, NULL, NULL}
 }; 
 
 int oggz_auto_identify (OGGZ *oggz, ogg_page *og, long serialno) {
@@ -892,30 +931,25 @@
                 oggz_stream_t *stream, ogg_packet *op) {
   if (oggz_auto_codec_ident[content].calculator != NULL) {
     ogg_int64_t r = oggz_auto_codec_ident[content].calculator(now, stream, op);
-    /*
-     * this will cause a hiccough at the end of the first data page if there are
-     * more than one packets on that page.  In the absence of pervasive access
-     * to the packets on a page, though, it might have to do.
-     *
-     * Why a hiccough?  Because there's no granulepos attached to any packets
-     * except for the last on a page.  If the stream doesn't start at gp 0 (a
-     * very common occurrence) then we don't realise until we get to the end of
-     * the page.  By that time we've already junked the first packets on the 
-     * page.
-     */
-    /*
-    if (now != -1LL) {
-      return op->granulepos;
-    }
-    */
     return r;
   } 
 
   return now;
-  
-  
 }
 
+ogg_int64_t
+oggz_auto_calculate_gp_backwards(int content, ogg_int64_t next_packet_gp,
+      oggz_stream_t *stream, ogg_packet *this_packet, ogg_packet *next_packet) {
+
+  if (oggz_auto_codec_ident[content].r_calculator != NULL) {
+    return oggz_auto_codec_ident[content].r_calculator(next_packet_gp,
+            stream, this_packet, next_packet);
+  }
+
+  return 0;
+
+}
+
 int
 oggz_auto_read_comments (OGGZ * oggz, oggz_stream_t * stream, long serialno,
                          ogg_packet * op)

Modified: liboggz/trunk/src/liboggz/oggz_dlist.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz_dlist.c	2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_dlist.c	2007-09-03 04:57:14 UTC (rev 3216)
@@ -63,6 +63,8 @@
   dlist->head = dummy_front;
   dlist->tail = dummy_back;
 
+  return dlist;
+
 }
 
 void
@@ -77,6 +79,8 @@
   free(dlist->tail);
   free(dlist);
 
+  printf("dlist:DELETE complete\n");
+
 }
 
 int
@@ -137,13 +141,14 @@
 void
 oggz_dlist_deliter(OggzDList *dlist, OggzDListIterFunc func) {
 
-  OggzDListElem *p;
+  OggzDListElem *p, *q;
 
-  for (p = dlist->head->next; p != dlist->tail; p = p->next) {
+  for (p = dlist->head->next; p != dlist->tail; p = q) {
     if (func(p->data) == DLIST_ITER_CANCEL) {
       break;
     }
 
+    q = p->next;
     p->prev->next = p->next;
     p->next->prev = p->prev;
 
@@ -155,13 +160,14 @@
 void
 oggz_dlist_reverse_deliter(OggzDList *dlist, OggzDListIterFunc func) {
 
-  OggzDListElem *p;
+  OggzDListElem *p, *q;
 
-  for (p = dlist->tail->prev; p != dlist->head; p = p->prev) {
+  for (p = dlist->tail->prev; p != dlist->head; p = q) {
     if (func(p->data) == DLIST_ITER_CANCEL) {
       break;
     }
 
+    q = p->prev;
     p->prev->next = p->next;
     p->next->prev = p->prev;
 

Modified: liboggz/trunk/src/liboggz/oggz_private.h
===================================================================
--- liboggz/trunk/src/liboggz/oggz_private.h	2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_private.h	2007-09-03 04:57:14 UTC (rev 3216)
@@ -42,8 +42,8 @@
 
 #include "oggz_macros.h"
 #include "oggz_vector.h"
+#include "oggz_dlist.h"
 
-
 typedef struct _OGGZ OGGZ;
 typedef struct _OggzComment OggzComment;
 typedef struct _OggzIO OggzIO;
@@ -118,6 +118,7 @@
   ogg_int64_t last_granulepos;
   ogg_int64_t page_granulepos;
   void * calculate_data;
+  ogg_packet  * last_packet;
 };
 
 struct _OggzReader {
@@ -237,6 +238,8 @@
     OggzReader reader;
     OggzWriter writer;
   } x;
+
+  OggzDList * packet_buffer;
 };
 
 OGGZ * oggz_read_init (OGGZ * oggz);

Modified: liboggz/trunk/src/liboggz/oggz_read.c
===================================================================
--- liboggz/trunk/src/liboggz/oggz_read.c	2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_read.c	2007-09-03 04:57:14 UTC (rev 3216)
@@ -238,6 +238,96 @@
   return ret;
 }
 
+typedef struct {
+  ogg_packet      packet;
+  ogg_int64_t     calced_granulepos;
+  oggz_stream_t * stream;
+  OggzReader    * reader;
+  OGGZ          * oggz;
+  long            serialno;
+} OggzBufferedPacket;
+
+OggzBufferedPacket *
+oggz_read_new_pbuffer_entry(OGGZ *oggz, ogg_packet *packet, 
+            ogg_int64_t granulepos, long serialno, oggz_stream_t * stream, 
+            OggzReader *reader) {
+
+  OggzBufferedPacket *p = malloc(sizeof(OggzBufferedPacket));
+  memcpy(&(p->packet), packet, sizeof(ogg_packet));
+  p->packet.packet = malloc(packet->bytes);
+  memcpy(p->packet.packet, packet->packet, packet->bytes);
+
+  p->calced_granulepos = granulepos;
+  p->stream = stream;
+  p->serialno = serialno;
+  p->reader = reader;
+  p->oggz = oggz;
+
+  return p;
+}
+
+void
+oggz_read_free_pbuffer_entry(OggzBufferedPacket *p) {
+  
+  free(p->packet.packet);
+  free(p);
+
+}
+
+OggzDListIterResponse
+oggz_read_update_gp(void *elem) {
+
+  OggzBufferedPacket *p = (OggzBufferedPacket *)elem;
+
+  if (p->calced_granulepos == -1 && p->stream->last_granulepos != -1) {
+    int content = oggz_stream_get_content(p->oggz, p->serialno);
+    p->calced_granulepos = 
+      oggz_auto_calculate_gp_backwards(content, p->stream->last_granulepos,
+      p->stream, &(p->packet), p->stream->last_packet);
+      
+    p->stream->last_granulepos = p->calced_granulepos;
+    p->stream->last_packet = &(p->packet);
+  }
+
+  return DLIST_ITER_CONTINUE;
+
+}
+
+OggzDListIterResponse
+oggz_read_deliver_packet(void *elem) {
+
+  OggzBufferedPacket *p = (OggzBufferedPacket *)elem;
+  ogg_int64_t gp_stored;
+  long unit_stored;
+
+  if (p->calced_granulepos == -1) {
+    return DLIST_ITER_CANCEL;
+  }
+
+  gp_stored = p->reader->current_granulepos;
+  unit_stored = p->reader->current_unit;
+
+  p->reader->current_granulepos = p->calced_granulepos;
+
+  p->reader->current_unit =
+    oggz_get_unit (p->oggz, p->serialno, p->calced_granulepos);
+
+  if (p->stream->read_packet) {
+    p->stream->read_packet(p->oggz, &(p->packet), p->serialno, 
+            p->stream->read_user_data);
+  } else if (p->reader->read_packet) {
+    p->reader->read_packet(p->oggz, &(p->packet), p->serialno, 
+            p->reader->read_user_data);
+  }
+
+  p->reader->current_granulepos = gp_stored;
+  p->reader->current_unit = unit_stored;
+
+  oggz_read_free_pbuffer_entry(p);
+
+  return DLIST_ITER_CONTINUE;
+}
+
 static int
 oggz_read_sync (OGGZ * oggz)
 {
@@ -348,6 +438,44 @@
             oggz_auto_read_comments (oggz, stream, serialno, op);
           }
 
+          /*
+           * while we are getting invalid granulepos values, store the incoming
+           * packets in a dlist */
+          if (reader->current_granulepos == -1) {
+            OggzBufferedPacket *p = oggz_read_new_pbuffer_entry(
+                              oggz, &packet, reader->current_granulepos, 
+                              serialno, stream, reader);
+
+            oggz_dlist_append(oggz->packet_buffer, p);
+            continue;
+          } else if (!oggz_dlist_is_empty(oggz->packet_buffer)) {
+            /*
+             * move backward through the list assigning gp values based upon
+             * the granulepos we just recieved.  Then move forward through
+             * the list delivering any packets at the beginning with valid
+             * gp values
+             */
+            ogg_int64_t gp_stored = stream->last_granulepos;
+            stream->last_packet = &packet;
+            oggz_dlist_reverse_iter(oggz->packet_buffer, oggz_read_update_gp);
+            oggz_dlist_deliter(oggz->packet_buffer, oggz_read_deliver_packet);
+
+            /*
+             * fix up the stream granulepos 
+             */
+            stream->last_granulepos = gp_stored;
+
+            if (!oggz_dlist_is_empty(oggz->packet_buffer)) {
+              OggzBufferedPacket *p = oggz_read_new_pbuffer_entry(
+                              oggz, &packet, reader->current_granulepos, 
+                              serialno, stream, reader);
+
+              oggz_dlist_append(oggz->packet_buffer, p);
+              continue;
+            }
+
+          }
+
           if (stream->read_packet) {
             cb_ret =
               stream->read_packet (oggz, op, serialno, stream->read_user_data);

Modified: liboggz/trunk/src/liboggz/oggz_stream.h
===================================================================
--- liboggz/trunk/src/liboggz/oggz_stream.h	2007-09-01 06:49:31 UTC (rev 3215)
+++ liboggz/trunk/src/liboggz/oggz_stream.h	2007-09-03 04:57:14 UTC (rev 3216)
@@ -42,6 +42,9 @@
   OggzReadPacket  reader;
   ogg_int64_t     (*calculator)(ogg_int64_t now, oggz_stream_t *stream, 
                   ogg_packet *op);
+  ogg_int64_t     (*r_calculator)(ogg_int64_t next_packet_gp, 
+                  oggz_stream_t *stream, ogg_packet *this_packet, 
+                  ogg_packet *next_packet);
 } oggz_auto_contenttype_t;
 
 extern const oggz_auto_contenttype_t oggz_auto_codec_ident[];
@@ -57,4 +60,9 @@
 ogg_int64_t 
 oggz_auto_calculate_granulepos(int content, ogg_int64_t now, 
                 oggz_stream_t *stream, ogg_packet *op);
+
+ogg_int64_t
+oggz_auto_calculate_gp_backwards(int content, ogg_int64_t next_packet_gp,
+      oggz_stream_t *stream, ogg_packet *this_packet, ogg_packet *next_packet);
+
 #endif /* __OGGZ_STREAM_H__ */



More information about the commits mailing list