ext/theora/: Fix theora granulepos calculation.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 7 Jul 2004 15:57:48 +0000 (15:57 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 7 Jul 2004 15:57:48 +0000 (15:57 +0000)
Original commit message from CVS:
* ext/theora/theora.c: (plugin_init):
* ext/theora/theoradec.c: (theora_dec_from_granulepos),
(theora_dec_src_query), (theora_dec_chain):
* ext/theora/theoraenc.c: (gst_theora_enc_class_init),
(theora_enc_sink_link), (theora_buffer_from_packet),
(theora_push_packet), (theora_enc_chain):
Fix theora granulepos calculation.
Fix overflow in duration/position calculation.
Bump rank to PRIMARY for theoradec.
Use granulepos of last packet to calculate position.
Set keyframe flag on buffers when needed.

ChangeLog
ext/theora/theora.c
ext/theora/theoradec.c
ext/theora/theoraenc.c

index 2bd6e0b..a2d7047 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2004-07-07  Wim Taymans  <wim@fluendo.com>
+
+       * ext/theora/theora.c: (plugin_init):
+       * ext/theora/theoradec.c: (theora_dec_from_granulepos),
+       (theora_dec_src_query), (theora_dec_chain):
+       * ext/theora/theoraenc.c: (gst_theora_enc_class_init),
+       (theora_enc_sink_link), (theora_buffer_from_packet),
+       (theora_push_packet), (theora_enc_chain):
+       Fix theora granulepos calculation.
+       Fix overflow in duration/position calculation.
+       Bump rank to PRIMARY for theoradec.
+       Use granulepos of last packet to calculate position.
+       Set keyframe flag on buffers when needed.
+
 2004-07-06  David Schleef  <ds@schleef.org>
 
        * gst/playback/Makefile.am: 'test' in bin_PROGRAMS?  Are you
index 9d9470c..9f82b72 100644 (file)
@@ -32,7 +32,7 @@ plugin_init (GstPlugin * plugin)
   if (!gst_library_load ("gsttags"))
     return FALSE;
 
-  if (!gst_element_register (plugin, "theoradec", GST_RANK_SECONDARY,
+  if (!gst_element_register (plugin, "theoradec", GST_RANK_PRIMARY,
           gst_theora_dec_get_type ()))
     return FALSE;
 
index df59681..2229879 100644 (file)
@@ -154,7 +154,7 @@ theora_dec_from_granulepos (GstTheoraDec * dec, GstFormat format, guint64 from,
     guint64 * to)
 {
   guint64 framecount;
-  guint ilog = _theora_ilog (dec->info.keyframe_frequency_force);
+  guint ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
 
   if (dec->packetno < 1)
     return FALSE;
@@ -166,15 +166,14 @@ theora_dec_from_granulepos (GstTheoraDec * dec, GstFormat format, guint64 from,
 
   switch (format) {
     case GST_FORMAT_TIME:
-      *to = framecount =
-          from * GST_SECOND * dec->info.fps_denominator /
-          dec->info.fps_numerator;
+      *to = framecount * (GST_SECOND * dec->info.fps_denominator /
+          dec->info.fps_numerator);
       break;
     case GST_FORMAT_DEFAULT:
       *to = framecount;
       break;
     case GST_FORMAT_BYTES:
-      *to = framecount * dec->info.height * dec->info.width * 12 / 8;
+      *to = framecount * dec->info.height * dec->info.width * 3 / 2;
       break;
     default:
       return FALSE;
@@ -219,9 +218,13 @@ theora_dec_src_query (GstPad * pad, GstQueryType query, GstFormat * format,
   GstTheoraDec *dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
   GstFormat my_format = GST_FORMAT_DEFAULT;
 
-  if (!gst_pad_query (GST_PAD_PEER (dec->sinkpad), query, &my_format,
-          &granulepos))
-    return FALSE;
+  if (query == GST_QUERY_POSITION) {
+    granulepos = dec->granulepos;
+  } else {
+    if (!gst_pad_query (GST_PAD_PEER (dec->sinkpad), query, &my_format,
+            &granulepos))
+      return FALSE;
+  }
 
   if (!theora_dec_from_granulepos (dec, *format, granulepos, value))
     return FALSE;
@@ -321,6 +324,7 @@ theora_dec_chain (GstPad * pad, GstData * data)
   GstBuffer *buf;
   GstTheoraDec *dec;
   ogg_packet packet;
+  guint64 offset_end;
 
   dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
   if (GST_IS_EVENT (data)) {
@@ -329,10 +333,16 @@ theora_dec_chain (GstPad * pad, GstData * data)
   }
 
   buf = GST_BUFFER (data);
+
+  offset_end = GST_BUFFER_OFFSET_END (buf);
+  if (offset_end != -1) {
+    dec->granulepos = offset_end;
+  }
+
   /* make ogg_packet out of the buffer */
   packet.packet = GST_BUFFER_DATA (buf);
   packet.bytes = GST_BUFFER_SIZE (buf);
-  packet.granulepos = GST_BUFFER_OFFSET_END (buf);
+  packet.granulepos = dec->granulepos;
   packet.packetno = dec->packetno++;
   packet.b_o_s = (packet.packetno == 0) ? 1 : 0;
   packet.e_o_s = 0;
index e3ef26e..40384c7 100644 (file)
@@ -292,6 +292,12 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
   GST_BUFFER_TIMESTAMP (buf) = timestamp;
   GST_BUFFER_DURATION (buf) = duration;
 
+  /* the second most significant bit of the first data byte is cleared
+   * for keyframes */
+  if ((packet->packet[0] & 40) == 0) {
+    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_KEY_UNIT);
+  }
+
   enc->packetno++;
 
   return buf;
@@ -419,6 +425,7 @@ theora_enc_chain (GstPad * pad, GstData * data)
     yuv_buffer yuv;
     gint y_size;
     guchar *pixels;
+    gboolean first_packet = TRUE;
 
     pixels = GST_BUFFER_DATA (buf);
 
@@ -438,8 +445,12 @@ theora_enc_chain (GstPad * pad, GstData * data)
 
     theora_encode_YUVin (&enc->state, &yuv);
     while (theora_encode_packetout (&enc->state, 0, &op)) {
-      GstClockTime out_time =
-          theora_granule_time (&enc->state, op.granulepos) * GST_SECOND;
+      GstClockTime out_time;
+
+      if (first_packet) {
+        first_packet = FALSE;
+      }
+      out_time = theora_granule_time (&enc->state, op.granulepos) * GST_SECOND;
       theora_push_packet (enc, &op, out_time, GST_SECOND / enc->fps);
     }