ext/theora/theoradec.c: Use higher precision timestamps calculation.
authorWim Taymans <wim.taymans@gmail.com>
Tue, 31 Jan 2006 17:27:00 +0000 (17:27 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Tue, 31 Jan 2006 17:27:00 +0000 (17:27 +0000)
Original commit message from CVS:
* ext/theora/theoradec.c: (_theora_granule_frame),
(_theora_granule_time), (_inc_granulepos),
(theora_dec_src_convert), (theora_dec_sink_convert),
(theora_handle_type_packet), (theora_handle_data_packet),
(theora_dec_chain):
Use higher precision timestamps calculation.
Convert some other conversions to _scale.

ChangeLog
ext/theora/theoradec.c

index ac285f08b4dfdf699cfcee933ef7248f51f9c366..e4991049af5e548599749a0b8bfa23174c8ab277 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2006-01-31  Wim Taymans  <wim@fluendo.com>
+
+       * ext/theora/theoradec.c: (_theora_granule_frame),
+       (_theora_granule_time), (_inc_granulepos),
+       (theora_dec_src_convert), (theora_dec_sink_convert),
+       (theora_handle_type_packet), (theora_handle_data_packet),
+       (theora_dec_chain):
+       Use higher precision timestamps calculation.
+       Convert some other conversions to _scale.
+
 2006-01-31  Stefan Kost  <ensonic@users.sf.net>
 
        * gst/audiotestsrc/gstaudiotestsrc.c:
index 7316ac8257c11830b5f87083e38d1cec5e8ae186..4fe7ff7214c29cdaae60208d4553c7c5d673b750 100644 (file)
@@ -56,6 +56,7 @@ struct _GstTheoraDec
 
   gboolean have_header;
   guint64 granulepos;
+  guint64 granule_shift;
 
   GstClockTime last_timestamp;
   guint64 frame_nr;
@@ -208,25 +209,52 @@ _theora_ilog (unsigned int v)
   return (ret);
 }
 
-static void
-_inc_granulepos (GstTheoraDec * dec)
+static gint64
+_theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
 {
   guint ilog;
   gint framecount;
 
-  if (dec->granulepos == -1)
-    return;
+  if (granulepos == -1)
+    return -1;
 
-  ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
+  ilog = dec->granule_shift;
 
-  framecount = dec->granulepos >> ilog;
-  framecount += dec->granulepos - (framecount << ilog);
+  /* granulepos is last ilog bits for counting pframes since last iframe and 
+   * bits in front of that for the framenumber of the last iframe. */
+  framecount = granulepos >> ilog;
+  framecount += granulepos - (framecount << ilog);
 
   GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framecount, ilog);
 
-  framecount++;
+  return framecount;
+}
+
+static GstClockTime
+_theora_granule_time (GstTheoraDec * dec, gint64 granulepos)
+{
+  gint framecount;
+
+  if (granulepos == -1)
+    return -1;
+
+  framecount = _theora_granule_frame (dec, dec->granulepos);
+
+  return gst_util_uint64_scale_int (framecount * GST_SECOND,
+      dec->info.fps_denominator, dec->info.fps_numerator);
+}
+
+static gint64
+_inc_granulepos (GstTheoraDec * dec, gint64 granulepos)
+{
+  gint framecount;
+
+  if (granulepos == -1)
+    return -1;
 
-  dec->granulepos = (framecount << ilog);
+  framecount = _theora_granule_frame (dec, granulepos);
+
+  return (framecount + 1) << dec->granule_shift;
 }
 
 #if 0
@@ -298,8 +326,8 @@ theora_dec_src_convert (GstPad * pad,
     case GST_FORMAT_BYTES:
       switch (*dest_format) {
         case GST_FORMAT_DEFAULT:
-          *dest_value =
-              src_value * 2 / (dec->info.height * dec->info.width * 3);
+          *dest_value = gst_util_uint64_scale_int (src_value, 2,
+              dec->info.height * dec->info.width * 3);
           break;
         case GST_FORMAT_TIME:
           /* seems like a rather silly conversion, implement me if you like */
@@ -312,9 +340,8 @@ theora_dec_src_convert (GstPad * pad,
         case GST_FORMAT_BYTES:
           scale = 3 * (dec->info.width * dec->info.height) / 2;
         case GST_FORMAT_DEFAULT:
-          *dest_value =
-              scale * (((guint64) src_value * dec->info.fps_numerator) /
-              (dec->info.fps_denominator * GST_SECOND));
+          *dest_value = scale * gst_util_uint64_scale_int (src_value,
+              dec->info.fps_numerator, dec->info.fps_denominator * GST_SECOND);
           break;
         default:
           res = FALSE;
@@ -323,8 +350,8 @@ theora_dec_src_convert (GstPad * pad,
     case GST_FORMAT_DEFAULT:
       switch (*dest_format) {
         case GST_FORMAT_TIME:
-          *dest_value = src_value * (GST_SECOND * dec->info.fps_denominator /
-              dec->info.fps_numerator);
+          *dest_value = gst_util_uint64_scale_int (src_value,
+              GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator);
           break;
         case GST_FORMAT_BYTES:
           *dest_value =
@@ -363,20 +390,9 @@ theora_dec_sink_convert (GstPad * pad,
   switch (src_format) {
     case GST_FORMAT_DEFAULT:
     {
-      guint64 framecount;
-      guint ilog;
-
-      ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
-
-      /* granulepos is last ilog bits for counting pframes since last iframe and 
-       * bits in front of that for the framenumber of the last iframe. */
-      framecount = src_value >> ilog;
-      framecount += src_value - (framecount << ilog);
-
       switch (*dest_format) {
         case GST_FORMAT_TIME:
-          *dest_value = framecount * (GST_SECOND * dec->info.fps_denominator /
-              dec->info.fps_numerator);
+          *dest_value = _theora_granule_time (dec, src_value);
           break;
         default:
           res = FALSE;
@@ -388,17 +404,16 @@ theora_dec_sink_convert (GstPad * pad,
       switch (*dest_format) {
         case GST_FORMAT_DEFAULT:
         {
-          guint ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
           guint rest;
 
           /* framecount */
-          *dest_value = src_value * dec->info.fps_numerator /
-              (GST_SECOND * dec->info.fps_denominator);
+          *dest_value = gst_util_uint64_scale_int (src_value,
+              dec->info.fps_numerator, GST_SECOND * dec->info.fps_denominator);
 
           /* funny way of calculating granulepos in theora */
           rest = *dest_value / dec->info.keyframe_frequency_force;
           *dest_value -= rest;
-          *dest_value <<= ilog;
+          *dest_value <<= dec->granule_shift;
           *dest_value += rest;
           break;
         }
@@ -743,6 +758,8 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
     dec->offset_y = 0;
   }
 
+  dec->granule_shift = _theora_ilog (dec->info.keyframe_frequency_force - 1);
+
   GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
       dec->width, dec->height, dec->offset_x, dec->offset_y);
 
@@ -941,8 +958,8 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
   dec->frame_nr++;
   GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
   GST_BUFFER_DURATION (out) =
-      GST_SECOND * ((gdouble) dec->info.fps_denominator) /
-      dec->info.fps_numerator;
+      gst_util_uint64_scale_int (GST_SECOND, dec->info.fps_denominator,
+      dec->info.fps_numerator);
   GST_BUFFER_TIMESTAMP (out) = outtime;
 
   result = theora_dec_push (dec, out);
@@ -1005,11 +1022,9 @@ theora_dec_chain (GstPad * pad, GstBuffer * buf)
   if (dec->have_header) {
     if (packet.granulepos != -1) {
       dec->granulepos = packet.granulepos;
-      dec->last_timestamp =
-          GST_SECOND * theora_granule_time (&dec->state, packet.granulepos);
+      dec->last_timestamp = _theora_granule_time (dec, packet.granulepos);
     } else if (dec->last_timestamp != -1) {
-      dec->last_timestamp +=
-          (GST_SECOND * dec->info.fps_denominator) / dec->info.fps_numerator;
+      dec->last_timestamp = _theora_granule_time (dec, dec->granulepos);
     }
   } else {
     dec->last_timestamp = -1;
@@ -1030,7 +1045,7 @@ theora_dec_chain (GstPad * pad, GstBuffer * buf)
   }
 
 done:
-  _inc_granulepos (dec);
+  dec->granulepos = _inc_granulepos (dec, dec->granulepos);
 
   gst_object_unref (dec);