oggparse: Set DELTA_UNIT on buffers
authorDavid Schleef <ds@schleef.org>
Sun, 21 Nov 2010 03:02:50 +0000 (19:02 -0800)
committerDavid Schleef <ds@schleef.org>
Fri, 3 Dec 2010 01:36:26 +0000 (17:36 -0800)
ext/ogg/gstoggparse.c
ext/ogg/gstoggstream.c
ext/ogg/gstoggstream.h

index 69e1e2e..e05c054 100644 (file)
@@ -72,6 +72,8 @@ struct _GstOggParse
   ogg_sync_state sync;          /* Ogg page synchronisation */
 
   GstCaps *caps;                /* Our src caps */
+
+  GstOggStream *video_stream;   /* Stream used to construct delta_unit flags */
 };
 
 struct _GstOggParseClass
@@ -155,6 +157,9 @@ gst_ogg_parse_new_stream (GstOggParse * parser, ogg_page * page)
   ret = ogg_stream_packetout (&stream->stream, &packet);
   if (ret == 1) {
     gst_ogg_stream_setup_map (stream, &packet);
+    if (stream->is_video) {
+      parser->video_stream = stream;
+    }
   }
 
   parser->oggstreams = g_slist_append (parser->oggstreams, stream);
@@ -345,7 +350,7 @@ gst_ogg_parse_is_header (GstOggParse * ogg, GstOggStream * stream,
 
 static GstBuffer *
 gst_ogg_parse_buffer_from_page (ogg_page * page,
-    guint64 offset, gboolean delta, GstClockTime timestamp)
+    guint64 offset, gboolean keyframe, GstClockTime timestamp)
 {
   int size = page->header_len + page->body_len;
   GstBuffer *buf = gst_buffer_new_and_alloc (size);
@@ -356,6 +361,9 @@ gst_ogg_parse_buffer_from_page (ogg_page * page,
   GST_BUFFER_TIMESTAMP (buf) = timestamp;
   GST_BUFFER_OFFSET (buf) = offset;
   GST_BUFFER_OFFSET_END (buf) = offset + size;
+  if (!keyframe) {
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+  }
 
   return buf;
 }
@@ -402,6 +410,7 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer)
 #endif
       guint64 startoffset = ogg->offset;
       GstOggStream *stream;
+      gboolean keyframe;
 
       serialno = ogg_page_serialno (&page);
       stream = gst_ogg_parse_find_stream (ogg, serialno);
@@ -409,10 +418,24 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer)
       GST_LOG_OBJECT (ogg, "Timestamping outgoing buffer as %" GST_TIME_FORMAT,
           GST_TIME_ARGS (buffertimestamp));
 
-      buffertimestamp = gst_ogg_stream_get_end_time_for_granulepos (stream,
-          granule);
-      pagebuffer = gst_ogg_parse_buffer_from_page (&page, startoffset, FALSE,
-          buffertimestamp);
+      if (stream) {
+        buffertimestamp = gst_ogg_stream_get_end_time_for_granulepos (stream,
+            granule);
+        if (ogg->video_stream) {
+          if (stream == ogg->video_stream) {
+            keyframe = gst_ogg_stream_granulepos_is_key_frame (stream, granule);
+          } else {
+            keyframe = FALSE;
+          }
+        } else {
+          keyframe = TRUE;
+        }
+      } else {
+        buffertimestamp = GST_CLOCK_TIME_NONE;
+        keyframe = TRUE;
+      }
+      pagebuffer = gst_ogg_parse_buffer_from_page (&page, startoffset,
+          keyframe, buffertimestamp);
 
       /* We read out 'ret' bytes, so we set the next offset appropriately */
       ogg->offset += ret;
@@ -420,9 +443,9 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer)
       GST_LOG_OBJECT (ogg,
           "processing ogg page (serial %08x, pageno %ld, "
           "granule pos %" G_GUINT64_FORMAT ", bos %d, offset %"
-          G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ")",
+          G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ") keyframe=%d",
           serialno, ogg_page_pageno (&page),
-          granule, bos, startoffset, ogg->offset);
+          granule, bos, startoffset, ogg->offset, keyframe);
 
       if (ogg_page_bos (&page)) {
         /* If we've seen this serialno before, this is technically an error,
index 82df0bb..e25b5ca 100644 (file)
@@ -173,10 +173,8 @@ gst_ogg_stream_granule_to_granulepos (GstOggStream * pad, gint64 granule,
       keyframe_granule);
 }
 
-#if 0
 gboolean
-gst_ogg_stream_packet_granulepos_is_key_frame (GstOggStream * pad,
-    gint64 granulepos)
+gst_ogg_stream_granulepos_is_key_frame (GstOggStream * pad, gint64 granulepos)
 {
   if (granulepos == -1) {
     return FALSE;
@@ -189,7 +187,6 @@ gst_ogg_stream_packet_granulepos_is_key_frame (GstOggStream * pad,
 
   return mappers[pad->map].is_key_frame_func (pad, granulepos);
 }
-#endif
 
 gboolean
 gst_ogg_stream_packet_is_header (GstOggStream * pad, ogg_packet * packet)
@@ -304,6 +301,7 @@ setup_theora_mapper (GstOggStream * pad, ogg_packet * packet)
   pad->granuleshift = ((GST_READ_UINT8 (data + 40) & 0x03) << 3) +
       (GST_READ_UINT8 (data + 41) >> 5);
 
+  pad->is_video = TRUE;
   pad->n_header_packets = 3;
   pad->frame_size = 1;
 
@@ -362,7 +360,7 @@ is_keyframe_theora (GstOggStream * pad, gint64 granulepos)
   if (granulepos == (gint64) - 1)
     return FALSE;
 
-  frame_mask = (1 << (pad->granuleshift + 1)) - 1;
+  frame_mask = (1 << pad->granuleshift) - 1;
 
   return ((granulepos & frame_mask) == 0);
 }
@@ -388,6 +386,7 @@ setup_dirac_mapper (GstOggStream * pad, ogg_packet * packet)
     return FALSE;
   }
 
+  pad->is_video = TRUE;
   pad->granulerate_n = header.frame_rate_numerator * 2;
   pad->granulerate_d = header.frame_rate_denominator;
   pad->granuleshift = 22;
@@ -508,6 +507,7 @@ setup_vp8_mapper (GstOggStream * pad, ogg_packet * packet)
   fps_n = GST_READ_UINT32_BE (packet->packet + 18);
   fps_d = GST_READ_UINT32_BE (packet->packet + 22);
 
+  pad->is_video = TRUE;
   pad->is_vp8 = TRUE;
   pad->granulerate_n = fps_n;
   pad->granulerate_d = fps_d;
@@ -1276,6 +1276,7 @@ setup_ogmvideo_mapper (GstOggStream * pad, ogg_packet * packet)
   GST_DEBUG ("time unit %d", GST_READ_UINT32_LE (data + 16));
   GST_DEBUG ("samples per unit %d", GST_READ_UINT32_LE (data + 24));
 
+  pad->is_video = TRUE;
   pad->granulerate_n = 10000000;
   time_unit = GST_READ_UINT64_LE (data + 17);
   if (time_unit > G_MAXINT || time_unit < G_MININT) {
index a8bc2c8..54d2fa4 100644 (file)
@@ -70,6 +70,7 @@ struct _GstOggStream
 
   GstCaps *caps;
 
+  gboolean is_video;
   /* vorbis stuff */
   int nln_increments[4];
   int nsn_increment;