More fractional framerate conversions
authorJan Schmidt <thaytan@mad.scientist.com>
Tue, 22 Nov 2005 22:21:37 +0000 (22:21 +0000)
committerJan Schmidt <thaytan@mad.scientist.com>
Tue, 22 Nov 2005 22:21:37 +0000 (22:21 +0000)
Original commit message from CVS:
* ext/cairo/gsttextoverlay.c: (gst_text_overlay_init),
(gst_text_overlay_setcaps), (gst_text_overlay_collected):
* ext/cairo/gsttextoverlay.h:
* ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_sink_link):
* ext/gdk_pixbuf/gstgdkpixbuf.h:
* ext/libpng/gstpngdec.c: (gst_pngdec_init),
(gst_pngdec_caps_create_and_set):
* ext/libpng/gstpngdec.h:
* ext/libpng/gstpngenc.c: (gst_pngenc_setcaps):
* gst/alpha/gstalphacolor.c: (gst_alpha_color_set_caps):
* gst/avi/gstavimux.c: (gst_avimux_init),
(gst_avimux_vidsinkconnect):
* gst/flx/gstflxdec.c: (gst_flxdec_chain):
* gst/goom/gstgoom.c: (gst_goom_init), (gst_goom_src_setcaps),
(gst_goom_src_negotiate), (gst_goom_chain):
* gst/goom/gstgoom.h:
* gst/matroska/matroska-demux.c: (gst_matroska_demux_video_caps):
* gst/matroska/matroska-mux.c:
(gst_matroska_mux_video_pad_setcaps):
* sys/osxvideo/osxvideosink.h:
* sys/osxvideo/osxvideosink.m:
More fractional framerate conversions

15 files changed:
ChangeLog
ext/cairo/gsttextoverlay.c
ext/cairo/gsttextoverlay.h
ext/gdk_pixbuf/gstgdkpixbuf.c
ext/gdk_pixbuf/gstgdkpixbuf.h
ext/libpng/gstpngdec.c
ext/libpng/gstpngdec.h
ext/libpng/gstpngenc.c
gst/alpha/gstalphacolor.c
gst/avi/gstavimux.c
gst/flx/gstflxdec.c
gst/goom/gstgoom.c
gst/goom/gstgoom.h
gst/matroska/matroska-demux.c
gst/matroska/matroska-mux.c

index 47c6009..2cb6cf7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
 2005-11-22  Jan Schmidt  <thaytan@mad.scientist.com>
 
+       * ext/cairo/gsttextoverlay.c: (gst_text_overlay_init),
+       (gst_text_overlay_setcaps), (gst_text_overlay_collected):
+       * ext/cairo/gsttextoverlay.h:
+       * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_sink_link):
+       * ext/gdk_pixbuf/gstgdkpixbuf.h:
+       * ext/libpng/gstpngdec.c: (gst_pngdec_init),
+       (gst_pngdec_caps_create_and_set):
+       * ext/libpng/gstpngdec.h:
+       * ext/libpng/gstpngenc.c: (gst_pngenc_setcaps):
+       * gst/alpha/gstalphacolor.c: (gst_alpha_color_set_caps):
+       * gst/avi/gstavimux.c: (gst_avimux_init),
+       (gst_avimux_vidsinkconnect):
+       * gst/flx/gstflxdec.c: (gst_flxdec_chain):
+       * gst/goom/gstgoom.c: (gst_goom_init), (gst_goom_src_setcaps),
+       (gst_goom_src_negotiate), (gst_goom_chain):
+       * gst/goom/gstgoom.h:
+       * gst/matroska/matroska-demux.c: (gst_matroska_demux_video_caps):
+       * gst/matroska/matroska-mux.c:
+       (gst_matroska_mux_video_pad_setcaps):
+       * sys/osxvideo/osxvideosink.h:
+       * sys/osxvideo/osxvideosink.m:
+         More fractional framerate conversions 
+
+2005-11-22  Jan Schmidt  <thaytan@mad.scientist.com>
+
        * ext/aalib/gstaasink.c: (gst_aasink_fixate):
        * gst/debug/gstnavigationtest.c:
        (gst_navigationtest_handle_src_event):
index a6a889b..b8bf1c8 100644 (file)
@@ -251,7 +251,8 @@ gst_text_overlay_init (GstTextOverlay * overlay, GstTextOverlayClass * klass)
   overlay->scale = 20;
   gst_text_overlay_font_init (overlay);
 
-  overlay->framerate = 0.0;
+  overlay->fps_n = 0;
+  overlay->fps_d = 1;
 
   overlay->collect = gst_collect_pads_new ();
 
@@ -530,7 +531,7 @@ gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps)
   GstTextOverlay *overlay;
   GstStructure *structure;
   gboolean ret = FALSE;
-  gdouble fps = 0.0;
+  const GValue *fps;
 
   if (!GST_PAD_IS_SINK (pad))
     return TRUE;
@@ -542,13 +543,16 @@ gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps)
   overlay->width = 0;
   overlay->height = 0;
   structure = gst_caps_get_structure (caps, 0);
+  fps = gst_structure_get_value (structure, "framerate");
+
   if (gst_structure_get_int (structure, "width", &overlay->width) &&
-      gst_structure_get_int (structure, "height", &overlay->height)) {
+      gst_structure_get_int (structure, "height", &overlay->height) &&
+      fps != NULL) {
     ret = gst_pad_set_caps (overlay->srcpad, caps);
   }
 
-  (void) gst_structure_get_double (structure, "framerate", &fps);
-  overlay->framerate = fps;
+  overlay->fps_n = gst_value_get_fraction_numerator (fps);
+  overlay->fps_d = gst_value_get_fraction_denominator (fps);
 
   return ret;
 }
@@ -780,8 +784,9 @@ gst_text_overlay_collected (GstCollectPads * pads, gpointer data)
 
   if (GST_BUFFER_DURATION (video_frame) != GST_CLOCK_TIME_NONE) {
     frame_end = now + GST_BUFFER_DURATION (video_frame);
-  } else if (overlay->framerate > 0.0) {
-    frame_end = now + (GST_SECOND / overlay->framerate);
+  } else if (overlay->fps_n > 0) {
+    frame_end = now + gst_util_clock_time_scale (GST_SECOND,
+        overlay->fps_d, overlay->fps_n);
   } else {
     /* magic value, does not really matter since texts
      * tend to span quite a few frames in practice anyway */
index 66cd11d..8f105ca 100644 (file)
@@ -51,7 +51,8 @@ struct _GstTextOverlay {
 
     gint                  width;
     gint                  height;
-    gdouble               framerate;
+    gint                  fps_n;
+    gint                  fps_d;
 
     GstTextOverlayVAlign  valign;
     GstTextOverlayHAlign  halign;
index 5846b18..9a602ea 100644 (file)
@@ -107,14 +107,18 @@ static GstPadLinkReturn
 gst_gdk_pixbuf_sink_link (GstPad * pad, const GstCaps * caps)
 {
   GstGdkPixbuf *filter;
+  const GValue *fps;
 
   filter = GST_GDK_PIXBUF (gst_pad_get_parent (pad));
   g_return_val_if_fail (filter != NULL, GST_PAD_LINK_REFUSED);
   g_return_val_if_fail (GST_IS_GDK_PIXBUF (filter), GST_PAD_LINK_REFUSED);
 
-  filter->framerate = 1.0;
-  gst_structure_get_double (gst_caps_get_structure (caps, 0), "framerate",
-      &filter->framerate);
+  fps = gst_structure_get_value (gst_caps_get_structure (caps, 0), "framerate");
+  if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
+    filter->fps_n = gst_value_get_fraction_numerator (fps);
+    filter->fps_d = gst_value_get_fraction_denominator (fps);
+  } else
+    return GST_PAD_LINK_REFUSED;
 
   return GST_PAD_LINK_OK;
 }
index dc308cc..4a1f9a3 100644 (file)
@@ -56,7 +56,8 @@ struct _GstGdkPixbuf
   int rowstride;
   unsigned int image_size;
 
-  double framerate;
+  gint fps_n;
+  gint fps_d;
 };
 
 struct _GstGdkPixbufClass 
index 42acbc2..67a19e7 100644 (file)
@@ -155,7 +155,8 @@ gst_pngdec_init (GstPngDec * pngdec)
   pngdec->width = -1;
   pngdec->height = -1;
   pngdec->bpp = -1;
-  pngdec->fps = 0.0;
+  pngdec->fps_n = 0;
+  pngdec->fps_d = 1;
 }
 
 static void
@@ -336,7 +337,7 @@ gst_pngdec_caps_create_and_set (GstPngDec * pngdec)
       "width", G_TYPE_INT, pngdec->width,
       "height", G_TYPE_INT, pngdec->height,
       "bpp", G_TYPE_INT, pngdec->bpp,
-      "framerate", G_TYPE_DOUBLE, pngdec->fps, NULL);
+      "framerate", GST_TYPE_FRACTION, pngdec->fps_n, pngdec->fps_d, NULL);
 
   templ = gst_static_pad_template_get (&gst_pngdec_src_pad_template);
 
index 5f5cdca..9930b83 100644 (file)
@@ -58,7 +58,8 @@ struct _GstPngDec
   gint height;
   gint bpp;
   gint color_type;
-  gdouble fps;
+  gint fps_n;
+  gint fps_d;
 };
 
 struct _GstPngDecClass
index f0ce7b8..261f420 100644 (file)
@@ -63,7 +63,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("image/png, "
         "width = (int) [ 16, 4096 ], "
-        "height = (int) [ 16, 4096 ], " "framerate = (double) [ 0.0, MAX ]")
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0.0, MAX ]")
     );
 
 static GstStaticPadTemplate pngenc_sink_template =
@@ -147,7 +147,7 @@ static gboolean
 gst_pngenc_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstPngEnc *pngenc;
-  gdouble fps;
+  const GValue *fps;
   GstStructure *structure;
   GstCaps *pcaps;
   gboolean ret = TRUE;
@@ -158,15 +158,17 @@ gst_pngenc_setcaps (GstPad * pad, GstCaps * caps)
   structure = gst_caps_get_structure (caps, 0);
   gst_structure_get_int (structure, "width", &pngenc->width);
   gst_structure_get_int (structure, "height", &pngenc->height);
-  gst_structure_get_double (structure, "framerate", &fps);
+  fps = gst_structure_get_value (structure, "framerate");
   gst_structure_get_int (structure, "bpp", &pngenc->bpp);
 
   opeer = gst_pad_get_peer (pngenc->srcpad);
   if (opeer) {
     pcaps = gst_caps_new_simple ("image/png",
-        "framerate", G_TYPE_DOUBLE, fps,
         "width", G_TYPE_INT, pngenc->width,
         "height", G_TYPE_INT, pngenc->height, NULL);
+    structure = gst_caps_get_structure (pcaps, 0);
+    gst_structure_set_value (structure, "framerate", fps);
+
     if (gst_pad_accept_caps (opeer, pcaps)) {
       gst_pad_set_caps (pngenc->srcpad, pcaps);
     } else
index 9d28bbe..04bc70c 100644 (file)
@@ -193,7 +193,7 @@ gst_alpha_color_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
   GstAlphaColor *alpha;
   GstStructure *structure;
   gboolean ret;
-  gdouble fps;
+  const GValue *fps;
   gint red_mask;
 
   alpha = GST_ALPHA_COLOR (btrans);
@@ -201,7 +201,8 @@ gst_alpha_color_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
 
   ret = gst_structure_get_int (structure, "width", &alpha->in_width);
   ret &= gst_structure_get_int (structure, "height", &alpha->in_height);
-  ret &= gst_structure_get_double (structure, "framerate", &fps);
+  fps = gst_structure_get_value (structure, "framerate");
+  ret &= (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
   ret &= gst_structure_get_int (structure, "red_mask", &red_mask);
 
   if (!ret)
index 084d0e2..a17f106 100644 (file)
@@ -71,51 +71,51 @@ static GstStaticPadTemplate video_sink_factory =
         "format = (fourcc) { YUY2, I420 }, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ]; "
+        "framerate = (fraction) [ 0, MAX ]; "
         "image/jpeg, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ]; "
+        "framerate = (fraction) [ 0, MAX ]; "
         "video/x-divx, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ], "
+        "framerate = (fraction) [ 0, MAX ], "
         "divxversion = (int) [ 3, 5 ]; "
         "video/x-xvid, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ]; "
+        "framerate = (fraction) [ 0, MAX ]; "
         "video/x-3ivx, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ]; "
+        "framerate = (fraction) [ 0, MAX ]; "
         "video/x-msmpeg, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ], "
+        "framerate = (fraction) [ 0, MAX ], "
         "msmpegversion = (int) [ 41, 43 ]; "
         "video/mpeg, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ], "
+        "framerate = (fraction) [ 0, MAX ], "
         "mpegversion = (int) 1, "
         "systemstream = (boolean) FALSE; "
         "video/x-h263, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ]; "
+        "framerate = (fraction) [ 0, MAX ]; "
         "video/x-h264, "
         "width = (int) [ 16, 4096 ], "
         "height = (int) [ 16, 4096 ], "
-        "framerate = (double) [ 0, MAX ]; "
+        "framerate = (fraction) [ 0, MAX ]; "
         "video/x-dv, "
         "width = (int) 720, "
         "height = (int) { 576, 480 }, "
-        "framerate = (double) [ 0, MAX ], "
+        "framerate = (fraction) [ 0, MAX ], "
         "systemstream = (boolean) FALSE; "
         "video/x-huffyuv, "
         "width = (int) [ 16, 4096 ], "
-        "height = (int) [ 16, 4096 ], " "framerate = (double) [ 0, MAX ]")
+        "height = (int) [ 16, 4096 ], " "framerate = (fraction) [ 0, MAX ]")
     );
 
 static GstStaticPadTemplate audio_sink_factory =
@@ -277,7 +277,7 @@ gst_avimux_init (GstAviMux * avimux)
   memset (&(avimux->auds_hdr), 0, sizeof (gst_riff_strh));
   memset (&(avimux->auds), 0, sizeof (gst_riff_strf_auds));
   avimux->vids_hdr.type = GST_MAKE_FOURCC ('v', 'i', 'd', 's');
-  avimux->vids_hdr.rate = 1000000;
+  avimux->vids_hdr.rate = 1;
   avimux->avi_hdr.max_bps = 10000000;
   avimux->auds_hdr.type = GST_MAKE_FOURCC ('a', 'u', 'd', 's');
   avimux->vids_hdr.quality = 0xFFFFFFFF;
@@ -299,7 +299,7 @@ gst_avimux_vidsinkconnect (GstPad * pad, const GstCaps * vscaps)
   GstAviMux *avimux;
   GstStructure *structure;
   const gchar *mimetype;
-  gdouble fps = 0.;
+  const GValue *fps;
   gboolean ret;
 
   avimux = GST_AVIMUX (gst_pad_get_parent (pad));
@@ -315,12 +315,13 @@ gst_avimux_vidsinkconnect (GstPad * pad, const GstCaps * vscaps)
   avimux->vids.planes = 1;
   ret = gst_structure_get_int (structure, "width", &avimux->vids.width);
   ret &= gst_structure_get_int (structure, "height", &avimux->vids.height);
-  ret &= gst_structure_get_double (structure, "framerate", &fps);
+  fps = gst_structure_get_value (structure, "framerate");
+  ret &= (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
   if (!ret)
     return GST_PAD_LINK_REFUSED;
 
-  if (fps != 0.)
-    avimux->vids_hdr.scale = avimux->vids_hdr.rate / fps;
+  avimux->vids_hdr.rate = gst_value_get_fraction_numerator (fps);
+  avimux->vids_hdr.scale = gst_value_get_fraction_denominator (fps);
 
   if (!strcmp (mimetype, "video/x-raw-yuv")) {
     guint32 format;
index 0ca9fc4..93c10fd 100644 (file)
@@ -498,8 +498,8 @@ gst_flxdec_chain (GstPad * pad, GstBuffer * buf)
       gst_caps_set_simple (caps,
           "width", G_TYPE_INT, flxh->width,
           "height", G_TYPE_INT, flxh->height,
-          "framerate", G_TYPE_DOUBLE,
-          (gdouble) (GST_SECOND / flxdec->frame_time), NULL);
+          "framerate", GST_TYPE_FRACTION, (gint) GST_MSECOND,
+          (gint) flxdec->frame_time / 1000, NULL);
 
       gst_pad_set_caps (flxdec->srcpad, caps);
       gst_caps_unref (caps);
index 75f754d..99173da 100644 (file)
@@ -174,7 +174,8 @@ gst_goom_init (GstGoom * goom)
 
   goom->width = 320;
   goom->height = 200;
-  goom->fps = 25.;              /* desired frame rate */
+  goom->fps_n = 25;             /* desired frame rate */
+  goom->fps_d = 1;              /* desired frame rate */
   goom->channels = 0;
   goom->sample_rate = 0;
   goom->audio_basetime = GST_CLOCK_TIME_NONE;
@@ -221,14 +222,22 @@ gst_goom_src_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstGoom *goom;
   GstStructure *structure;
+  const GValue *fps;
 
   goom = GST_GOOM (GST_PAD_PARENT (pad));
 
   structure = gst_caps_get_structure (caps, 0);
 
-  gst_structure_get_int (structure, "width", &goom->width);
-  gst_structure_get_int (structure, "height", &goom->height);
-  gst_structure_get_double (structure, "framerate", &goom->fps);
+  if (!gst_structure_get_int (structure, "width", &goom->width) ||
+      !gst_structure_get_int (structure, "height", &goom->height))
+    return FALSE;
+
+  fps = gst_structure_get_value (structure, "framerate");
+  if (fps == NULL || !GST_VALUE_HOLDS_FRACTION (fps))
+    return FALSE;
+
+  goom->fps_n = gst_value_get_fraction_numerator (fps);
+  goom->fps_d = gst_value_get_fraction_denominator (fps);
 
   goom_set_resolution (goom->width, goom->height);
 
@@ -241,6 +250,7 @@ gst_goom_src_negotiate (GstGoom * goom)
   GstCaps *othercaps, *target, *intersect;
   GstStructure *structure;
   const GstCaps *templ;
+  GValue fps = { 0 };
 
   templ = gst_pad_get_pad_template_caps (goom->srcpad);
 
@@ -262,7 +272,11 @@ gst_goom_src_negotiate (GstGoom * goom)
   structure = gst_caps_get_structure (target, 0);
   gst_structure_fixate_field_nearest_int (structure, "width", 320);
   gst_structure_fixate_field_nearest_int (structure, "height", 240);
-  gst_structure_fixate_field_nearest_double (structure, "framerate", 30.0);
+
+  g_value_init (&fps, GST_TYPE_FRACTION);
+  gst_value_set_fraction (&fps, 30, 1);
+  gst_structure_fixate_field_nearest_fraction (structure, "framerate", &fps);
+  g_value_unset (&fps);
 
   gst_pad_set_caps (goom->srcpad, target);
   gst_caps_unref (target);
@@ -326,7 +340,7 @@ gst_goom_chain (GstPad * pad, GstBuffer * bufin)
     goom->audio_basetime = 0;
 
   bytesperread = GOOM_SAMPLES * goom->channels * sizeof (gint16);
-  samples_per_frame = goom->sample_rate / goom->fps;
+  samples_per_frame = goom->sample_rate * goom->fps_d / goom->fps_n;
   data = (gint16 *) GST_BUFFER_DATA (bufin);
 
   gst_adapter_push (goom->adapter, bufin);
@@ -351,7 +365,8 @@ gst_goom_chain (GstPad * pad, GstBuffer * bufin)
     GstClockTimeDiff frame_duration;
     gint i;
 
-    frame_duration = GST_SECOND / goom->fps;
+    frame_duration = gst_util_clock_time_scale (GST_SECOND, goom->fps_d,
+        goom->fps_n);
     data = (const guint16 *) gst_adapter_peek (goom->adapter, bytesperread);
 
     if (goom->channels == 2) {
index ca5f5ce..ea17c74 100644 (file)
@@ -53,7 +53,8 @@ struct _GstGoom
   guint64 samples_consumed;
 
   /* video state */
-  gdouble fps;
+  gint fps_n;
+  gint fps_d;
   gint width;
   gint height;
   gint channels;
index 19cfab6..d7f46d4 100644 (file)
@@ -3069,21 +3069,29 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
         }
 
         if (context->default_duration > 0) {
-          gdouble framerate = (gdouble) GST_SECOND / context->default_duration;
-
-          gst_structure_set (structure,
-              "framerate", G_TYPE_DOUBLE, framerate, NULL);
+          GValue fps_double = { 0 };
+          GValue fps_fraction = { 0 };
+
+          g_value_init (&fps_double, G_TYPE_DOUBLE);
+          g_value_init (&fps_fraction, GST_TYPE_FRACTION);
+          g_value_set_double (&fps_double,
+              GST_SECOND / context->default_duration);
+          g_value_transform (&fps_double, &fps_fraction);
+
+          gst_structure_set_value (structure, "framerate", &fps_fraction);
+          g_value_unset (&fps_double);
+          g_value_unset (&fps_fraction);
         } else {
           /* sort of a hack to get most codecs to support,
            * even if the default_duration is missing */
-          gst_structure_set (structure, "framerate", G_TYPE_DOUBLE,
-              (gdouble) 25.0, NULL);
+          gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
+              25, 1, NULL);
         }
       } else {
         gst_structure_set (structure,
             "width", GST_TYPE_INT_RANGE, 16, 4096,
             "height", GST_TYPE_INT_RANGE, 16, 4096,
-            "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL);
+            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
       }
     }
   }
index 32f8eb7..1030935 100644 (file)
@@ -56,7 +56,7 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
 #define COMMON_VIDEO_CAPS \
   "width = (int) [ 16, 4096 ], " \
   "height = (int) [ 16, 4096 ], " \
-  "framerate = (double) [ 0, MAX ]"
+  "framerate = (fraction) [ 0, MAX ]"
 
 static GstStaticPadTemplate videosink_templ =
     GST_STATIC_PAD_TEMPLATE ("video_%d",
@@ -424,7 +424,7 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
   GstMatroskaPad *collect_pad;
   const gchar *mimetype;
   gint width, height, pixel_width, pixel_height;
-  gdouble framerate;
+  const GValue *framerate;
   GstStructure *structure;
   gboolean ret;
 
@@ -444,11 +444,15 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
   /* get general properties */
   gst_structure_get_int (structure, "width", &width);
   gst_structure_get_int (structure, "height", &height);
-  gst_structure_get_double (structure, "framerate", &framerate);
+  framerate = gst_structure_get_value (structure, "framerate");
+  if (framerate == NULL || !GST_VALUE_HOLDS_FRACTION (framerate))
+    return FALSE;
 
   videocontext->pixel_width = width;
   videocontext->pixel_height = height;
-  context->default_duration = GST_SECOND / framerate;
+  context->default_duration = gst_util_clock_time_scale (GST_SECOND,
+      gst_value_get_fraction_numerator (framerate),
+      gst_value_get_fraction_denominator (framerate));
 
   ret = gst_structure_get_int (structure, "pixel_width", &pixel_width);
   ret &= gst_structure_get_int (structure, "pixel_height", &pixel_height);