ext/dv/: Fractional framerates for DV.
authorMichael Smith <msmith@xiph.org>
Tue, 22 Nov 2005 17:09:36 +0000 (17:09 +0000)
committerMichael Smith <msmith@xiph.org>
Tue, 22 Nov 2005 17:09:36 +0000 (17:09 +0000)
Original commit message from CVS:
* ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_sink_setcaps):
* ext/dv/gstdvdec.h:
* ext/dv/gstdvdemux.c: (gst_dvdemux_init),
(gst_dvdemux_src_convert), (gst_dvdemux_sink_convert),
(gst_dvdemux_demux_video), (gst_dvdemux_demux_frame),
(gst_dvdemux_flush):
* ext/dv/gstdvdemux.h:
Fractional framerates for DV.

ChangeLog
ext/dv/gstdvdec.c
ext/dv/gstdvdec.h
ext/dv/gstdvdemux.c
ext/dv/gstdvdemux.h

index 2820f98..1fc8b59 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2005-11-22  Michael Smith <msmith@fluendo.com>
+
+       * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_sink_setcaps):
+       * ext/dv/gstdvdec.h:
+       * ext/dv/gstdvdemux.c: (gst_dvdemux_init),
+       (gst_dvdemux_src_convert), (gst_dvdemux_sink_convert),
+       (gst_dvdemux_demux_video), (gst_dvdemux_demux_frame),
+       (gst_dvdemux_flush):
+       * ext/dv/gstdvdemux.h:
+         Fractional framerates for DV. 
+
 2005-11-22  Tim-Philipp Müller  <tim at centricular dot net>
 
        * gst/autodetect/gstautoaudiosink.c:
index 44c52cc..113dc34 100644 (file)
@@ -67,7 +67,7 @@ static GstStaticPadTemplate src_temp = GST_STATIC_PAD_TEMPLATE ("src",
     GST_STATIC_CAPS ("video/x-raw-yuv, "
         "format = (fourcc) YUY2, "
         "width = (int) 720, "
-        "framerate = (double) [ 1.0, 60.0 ];"
+        "framerate = (fraction) [ 1/1, 60/1 ];"
         "video/x-raw-rgb, "
         "bpp = (int) 32, "
         "depth = (int) 24, "
@@ -76,7 +76,7 @@ static GstStaticPadTemplate src_temp = GST_STATIC_PAD_TEMPLATE ("src",
         "green_mask = (int) 0x00ff0000, "
         "blue_mask =  (int) 0xff000000, "
         "width = (int) 720, "
-        "framerate = (double) [ 1.0, 60.0 ];"
+        "framerate = (fraction) [ 1/1, 60/1 ];"
         "video/x-raw-rgb, "
         "bpp = (int) 24, "
         "depth = (int) 24, "
@@ -84,7 +84,7 @@ static GstStaticPadTemplate src_temp = GST_STATIC_PAD_TEMPLATE ("src",
         "red_mask =   (int) 0x00ff0000, "
         "green_mask = (int) 0x0000ff00, "
         "blue_mask =  (int) 0x000000ff, "
-        "width = (int) 720, " "framerate = (double) [ 1.0, 60.0 ]")
+        "width = (int) 720, " "framerate = (fraction) [ 1/1, 60/1 ]")
     );
 
 #define GST_TYPE_DVDEC_QUALITY (gst_dvdec_quality_get_type())
@@ -186,7 +186,8 @@ gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
 
   gst_element_add_pad (GST_ELEMENT (dvdec), dvdec->srcpad);
 
-  dvdec->framerate = 0;
+  dvdec->framerate_numerator = 0;
+  dvdec->framerate_denominator = 0;
   dvdec->height = 0;
   dvdec->wide = FALSE;
   dvdec->drop_factor = 1;
@@ -203,7 +204,7 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
   GstDVDec *dvdec;
   GstStructure *s;
   GstCaps *othercaps;
-  const GValue *v;
+  const GValue *par, *rate;
 
   dvdec = GST_DVDEC (gst_pad_get_parent (pad));
 
@@ -212,11 +213,14 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
 
   if (!gst_structure_get_int (s, "height", &dvdec->height))
     goto error;
-  if (!(v = gst_structure_get_value (s, "pixel-aspect-ratio")))
+  if (!(par = gst_structure_get_value (s, "pixel-aspect-ratio")))
     goto error;
-  if (!gst_structure_get_double (s, "framerate", &dvdec->framerate))
+  if (!(rate = gst_structure_get_value (s, "framerate")))
     goto error;
 
+  dvdec->framerate_numerator = gst_value_get_fraction_numerator (rate);
+  dvdec->framerate_denominator = gst_value_get_fraction_denominator (rate);
+
   /* ignoring rgb, bgr0 for now */
 
   dvdec->bpp = 2;
@@ -225,9 +229,10 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
       "format", GST_TYPE_FOURCC, GST_STR_FOURCC ("YUY2"),
       "width", G_TYPE_INT, 720,
       "height", G_TYPE_INT, dvdec->height,
-      "framerate", G_TYPE_DOUBLE, dvdec->framerate, NULL);
+      "framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator,
+      dvdec->framerate_denominator, NULL);
   gst_structure_set_value (gst_caps_get_structure (othercaps, 0),
-      "pixel-aspect-ratio", v);
+      "pixel-aspect-ratio", par);
 
   gst_pad_set_caps (dvdec->srcpad, othercaps);
 
index 9f1fba4..3fc58d9 100644 (file)
@@ -58,7 +58,8 @@ struct _GstDVDec {
 
   gint                  frame_len;
   gboolean       PAL;
-  gdouble       framerate;
+  gint           framerate_numerator;
+  gint           framerate_denominator;
   gint          height;
   gboolean      wide;
 
index 882b270..f7f90f8 100644 (file)
 
 #define NTSC_HEIGHT 480
 #define NTSC_BUFFER 120000
-#define NTSC_FRAMERATE 30000/1001.
+#define NTSC_FRAMERATE_NUMERATOR 30000
+#define NTSC_FRAMERATE_DENOMINATOR 1001
 
 #define PAL_HEIGHT 576
 #define PAL_BUFFER 144000
-#define PAL_FRAMERATE 25.0
+#define PAL_FRAMERATE_NUMERATOR 25
+#define PAL_FRAMERATE_DENOMINATOR 1
 
 #define PAL_NORMAL_PAR_X       59
 #define PAL_NORMAL_PAR_Y       54
@@ -187,7 +189,9 @@ gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
   dvdemux->stop_timestamp = -1LL;
   dvdemux->need_discont = FALSE;
   dvdemux->new_media = FALSE;
-  dvdemux->framerate = 0;
+  dvdemux->framerate_numerator = 0;
+  dvdemux->framerate_denominator = 0;
+  dvdemux->total_frames = 0;
   dvdemux->height = 0;
   dvdemux->frequency = 0;
   dvdemux->channels = 0;
@@ -263,8 +267,9 @@ gst_dvdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
         case GST_FORMAT_TIME:
           *dest_format = GST_FORMAT_TIME;
           if (pad == dvdemux->videosrcpad)
-            *dest_value = src_value * GST_SECOND /
-                (dvdemux->frame_len * dvdemux->framerate);
+            *dest_value = src_value * GST_SECOND *
+                dvdemux->framerate_denominator /
+                (dvdemux->frame_len * dvdemux->framerate_numerator);
           else if (pad == dvdemux->audiosrcpad)
             *dest_value = src_value * GST_SECOND /
                 (2 * dvdemux->frequency * dvdemux->channels);
@@ -277,8 +282,9 @@ gst_dvdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
       switch (*dest_format) {
         case GST_FORMAT_BYTES:
           if (pad == dvdemux->videosrcpad)
-            *dest_value = src_value * dvdemux->frame_len * dvdemux->framerate
-                / GST_SECOND;
+            *dest_value = src_value * dvdemux->frame_len *
+                dvdemux->framerate_numerator /
+                (dvdemux->framerate_denominator * GST_SECOND);
           else if (pad == dvdemux->audiosrcpad)
             *dest_value = 2 * src_value * dvdemux->frequency *
                 dvdemux->channels / GST_SECOND;
@@ -286,7 +292,8 @@ gst_dvdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
         case GST_FORMAT_DEFAULT:
           if (pad == dvdemux->videosrcpad) {
             if (src_value)
-              *dest_value = src_value * dvdemux->framerate / GST_SECOND;
+              *dest_value = src_value * dvdemux->framerate_numerator /
+                  (dvdemux->framerate_denominator * GST_SECOND);
             else
               *dest_value = 0;
           } else if (pad == dvdemux->audiosrcpad) {
@@ -303,7 +310,8 @@ gst_dvdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
       switch (*dest_format) {
         case GST_FORMAT_TIME:
           if (pad == dvdemux->videosrcpad) {
-            *dest_value = src_value * GST_SECOND / dvdemux->framerate;
+            *dest_value = src_value * GST_SECOND *
+                dvdemux->framerate_denominator / dvdemux->framerate_numerator;
           } else if (pad == dvdemux->audiosrcpad) {
             if (src_value)
               *dest_value =
@@ -376,7 +384,8 @@ gst_dvdemux_sink_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
           /* get frame number */
           frame = src_value / dvdemux->frame_len;
 
-          *dest_value = (frame * GST_SECOND) / dvdemux->framerate;
+          *dest_value = (frame * GST_SECOND * dvdemux->framerate_denominator) /
+              dvdemux->framerate_numerator;
           break;
         }
         default:
@@ -390,7 +399,8 @@ gst_dvdemux_sink_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
           guint64 frame;
 
           /* calculate the frame */
-          frame = src_value * dvdemux->framerate / GST_SECOND;
+          frame = src_value * dvdemux->framerate_numerator /
+              (dvdemux->framerate_denominator * GST_SECOND);
           /* calculate the offset */
           *dest_value = frame * dvdemux->frame_len;
           break;
@@ -825,7 +835,8 @@ gst_dvdemux_demux_video (GstDVDemux * dvdemux, const guint8 * data)
         "systemstream", G_TYPE_BOOLEAN, FALSE,
         "width", G_TYPE_INT, 720,
         "height", G_TYPE_INT, height,
-        "framerate", G_TYPE_DOUBLE, dvdemux->framerate,
+        "framerate", GST_TYPE_FRACTION, dvdemux->framerate_numerator,
+        dvdemux->framerate_denominator,
         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_x, par_y, NULL);
     gst_pad_set_caps (dvdemux->videosrcpad, caps);
     gst_caps_unref (caps);
@@ -893,7 +904,10 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, const guint8 * data)
     dvdemux->need_discont = FALSE;
   }
 
-  next_ts = dvdemux->timestamp + GST_SECOND / dvdemux->framerate;
+  dvdemux->total_frames++;
+
+  next_ts = dvdemux->total_frames * GST_SECOND *
+      dvdemux->framerate_denominator / dvdemux->framerate_numerator;
   dvdemux->duration = next_ts - dvdemux->timestamp;
 
   dv_parse_packs (dvdemux->decoder, data);
@@ -948,7 +962,13 @@ gst_dvdemux_flush (GstDVDemux * dvdemux)
     /* after parsing the header we know the length of the data */
     dvdemux->PAL = dv_system_50_fields (dvdemux->decoder);
     length = dvdemux->frame_len = (dvdemux->PAL ? PAL_BUFFER : NTSC_BUFFER);
-    dvdemux->framerate = dvdemux->PAL ? PAL_FRAMERATE : NTSC_FRAMERATE;
+    if (dvdemux->PAL) {
+      dvdemux->framerate_numerator = PAL_FRAMERATE_NUMERATOR;
+      dvdemux->framerate_denominator = PAL_FRAMERATE_DENOMINATOR;
+    } else {
+      dvdemux->framerate_numerator = NTSC_FRAMERATE_NUMERATOR;
+      dvdemux->framerate_denominator = NTSC_FRAMERATE_DENOMINATOR;
+    }
     /* let demux_video set the height, it needs to detect when things change so
      * it can reset caps */
 
index dde236a..53121e3 100644 (file)
@@ -61,7 +61,8 @@ struct _GstDVDemux {
   /* PAL or NTSC flag */
   gboolean       PAL;
   /* video params */
-  gdouble       framerate;
+  gint           framerate_numerator;
+  gint           framerate_denominator;
   gint          height;
   gboolean      wide;
   /* audio params */
@@ -72,6 +73,7 @@ struct _GstDVDemux {
   
   guint64       timestamp;
   guint64       duration;
+  guint          total_frames;
   guint64       audio_offset;
   guint64       video_offset;