ext/libvisual/visual.c: Fix the fps calculations.
authorJan Schmidt <thaytan@mad.scientist.com>
Tue, 22 Nov 2005 23:39:12 +0000 (23:39 +0000)
committerJan Schmidt <thaytan@mad.scientist.com>
Tue, 22 Nov 2005 23:39:12 +0000 (23:39 +0000)
Original commit message from CVS:

* ext/libvisual/visual.c: (gst_visual_chain):
Fix the fps calculations.

* gst/ffmpegcolorspace/avcodec.h:
Move structure element for clarity

* gst-libs/gst/interfaces/tunernorm.c: (gst_tuner_norm_init):
* gst-libs/gst/interfaces/tunernorm.h:
* sys/v4l/gstv4ljpegsrc.c: (gst_v4ljpegsrc_src_link):
* sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_base_init):
* sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_base_init),
(gst_v4lmjpegsrc_get_fps), (gst_v4lmjpegsrc_src_convert),
(gst_v4lmjpegsrc_src_query), (gst_v4lmjpegsrc_get),
(gst_v4lmjpegsrc_getcaps):
* sys/v4l/gstv4lsrc.c: (gst_v4lsrc_fixate), (gst_v4lsrc_get_caps),
(gst_v4lsrc_set_caps):
* sys/v4l/gstv4lsrc.h:
* sys/v4l/v4l_calls.c: (gst_v4l_open):
* sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_get_fps),
(gst_v4lsrc_get_fps_list), (gst_v4lsrc_buffer_new):
* sys/v4l/v4lsrc_calls.h:
Fractional framerates...

ext/libvisual/visual.c
gst/ffmpegcolorspace/avcodec.h
sys/v4l/gstv4ljpegsrc.c
sys/v4l/gstv4lmjpegsink.c
sys/v4l/gstv4lmjpegsrc.c
sys/v4l/gstv4lsrc.c
sys/v4l/gstv4lsrc.h
sys/v4l/v4l_calls.c
sys/v4l/v4lsrc_calls.c
sys/v4l/v4lsrc_calls.h

index cee88d8..e33a309 100644 (file)
@@ -396,7 +396,7 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
     visual->next_ts = GST_BUFFER_TIMESTAMP (buffer);
 
   /* spf = samples per frame */
-  spf = ((guint64) (visual->rate) * visual->fps_n) / visual->fps_d;
+  spf = ((guint64) (visual->rate) * visual->fps_d) / visual->fps_n;
   gst_adapter_push (visual->adapter, buffer);
 
   while (gst_adapter_available (visual->adapter) > MAX (512, spf) * 4 &&
@@ -423,7 +423,8 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
       visual_actor_run (visual->actor, &visual->audio);
 
       GST_BUFFER_TIMESTAMP (outbuf) = visual->next_ts;
-      GST_BUFFER_DURATION (outbuf) = GST_SECOND * visual->fps_n / visual->fps_d;
+      GST_BUFFER_DURATION (outbuf) = gst_util_clock_time_scale (GST_SECOND,
+          visual->fps_d, visual->fps_n);
       visual->next_ts += GST_BUFFER_DURATION (outbuf);
       ret = gst_pad_push (visual->srcpad, outbuf);
       outbuf = NULL;
@@ -431,7 +432,7 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
 
     /* Flush out the number of samples per frame * channels * sizeof (gint16) */
     /* Recompute spf in case caps changed */
-    spf = ((guint64) (visual->rate) * visual->fps_n) / visual->fps_d;
+    spf = ((guint64) (visual->rate) * visual->fps_d) / visual->fps_n;
     GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
         spf);
     gst_adapter_flush (visual->adapter,
index e25f8e5..9b5370e 100644 (file)
@@ -133,6 +133,14 @@ typedef struct AVCodecContext {
     int frame_rate;
     
     /**
+     * frame_rate_base.
+     * for variable fps this is 1
+     * - encoding: set by user.
+     * - decoding: set by lavc.
+     */
+
+    int frame_rate_base;
+    /**
      * picture width / height.
      * - encoding: MUST be set by user. 
      * - decoding: set by lavc.
@@ -162,16 +170,6 @@ typedef struct AVCodecContext {
      * - decoding: set by user.
      */
     struct AVPaletteControl *palctrl;
-
-    /**
-     * frame_rate_base.
-     * for variable fps this is 1
-     * - encoding: set by user.
-     * - decoding: set by lavc.
-     * @todo move this after frame_rate
-     */
-
-    int frame_rate_base;
 } AVCodecContext;
 
 /**
index 1c34fcc..e414c66 100644 (file)
@@ -117,7 +117,7 @@ gst_v4ljpegsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
   GstV4lJpegSrc *v4ljpegsrc;
   GstV4lSrc *v4lsrc;
   gint w, h, palette = -1;
-  gdouble fps;
+  const GValue *fps;
   GstStructure *structure;
   gboolean was_capturing;
   struct video_window *vwin;
@@ -144,9 +144,11 @@ gst_v4ljpegsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
 
   gst_structure_get_int (structure, "width", &w);
   gst_structure_get_int (structure, "height", &h);
-  gst_structure_get_double (structure, "framerate", &fps);
+  fps = gst_structure_get_value (structure, "framerate");
 
-  GST_DEBUG_OBJECT (v4ljpegsrc, "linking with %dx%d at %f fps", w, h, fps);
+  GST_DEBUG_OBJECT (v4ljpegsrc, "linking with %dx%d at %d/%d fps", w, h,
+      gst_value_get_fraction_numerator (fps),
+      gst_value_get_fraction_denominator (fps));
 
   /* set framerate if it's not already correct */
   if (fps != gst_v4lsrc_get_fps (v4lsrc)) {
index 2b5a1ff..6e49234 100644 (file)
@@ -114,7 +114,7 @@ gst_v4lmjpegsink_base_init (gpointer g_class)
       GST_PAD_ALWAYS,
       GST_STATIC_CAPS ("image/jpeg, "
           "width = (int) [ 1, MAX ], "
-          "height = (int) [ 1, MAX ], " "framerate = (double) [ 0, MAX ]")
+          "height = (int) [ 1, MAX ], " "framerate = (fraction) [ 0, MAX ]")
       );
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 
index f8bf153..c4f2429 100644 (file)
@@ -143,7 +143,7 @@ gst_v4lmjpegsrc_base_init (gpointer g_class)
       GST_PAD_ALWAYS,
       GST_STATIC_CAPS ("image/jpeg, "
           "width = (int) [ 0, MAX ], "
-          "height = (int) [ 0, MAX ], " "framerate = (double) [ 0, MAX ]")
+          "height = (int) [ 0, MAX ], " "framerate = (fraction) [ 0, MAX ]")
       );
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 
@@ -268,11 +268,12 @@ gst_v4lmjpegsrc_init (GstV4lMjpegSrc * v4lmjpegsrc)
 }
 
 
-static gfloat
-gst_v4lmjpegsrc_get_fps (GstV4lMjpegSrc * v4lmjpegsrc)
+static gboolean
+gst_v4lmjpegsrc_get_fps (GstV4lMjpegSrc * v4lmjpegsrc, GValue * fps)
 {
   gint norm;
-  gfloat fps;
+
+  g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (fps), FALSE);
 
   if (!v4lmjpegsrc->use_fixed_fps &&
       v4lmjpegsrc->clock != NULL && v4lmjpegsrc->handled > 0) {
@@ -285,17 +286,17 @@ gst_v4lmjpegsrc_get_fps (GstV4lMjpegSrc * v4lmjpegsrc)
   /* if that failed ... */
 
   if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lmjpegsrc)))
-    return 0.;
+    return FALSE;
 
   if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lmjpegsrc), NULL, &norm))
-    return 0.;
+    return FALSE;
 
   if (norm == VIDEO_MODE_NTSC)
-    fps = 30000 / 1001;
+    gst_value_set_fraction (fps, 30000, 1001);
   else
-    fps = 25.;
+    gst_value_set_fraction (fps, 25, 1);
 
-  return fps;
+  return TRUE;
 }
 
 static gboolean
@@ -304,39 +305,46 @@ gst_v4lmjpegsrc_src_convert (GstPad * pad,
     gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
 {
   GstV4lMjpegSrc *v4lmjpegsrc;
-  gdouble fps;
+  GValue fps = { 0 };
+  gboolean result = TRUE;
 
   v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
 
-  if ((fps = gst_v4lmjpegsrc_get_fps (v4lmjpegsrc)) == 0)
+  g_value_init (&fps, GST_VALUE_FRACTION);
+  if (!gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps))
     return FALSE;
 
   switch (src_format) {
     case GST_FORMAT_TIME:
       switch (*dest_format) {
         case GST_FORMAT_DEFAULT:
-          *dest_value = src_value * fps / GST_SECOND;
+          *dest_value = gst_util_uint64_scale (src_value,
+              gst_value_get_fraction_numerator (&fps),
+              gst_value_get_fraction_denominator (&fps) * GST_SECOND);
           break;
         default:
-          return FALSE;
+          result = FALSE;
       }
       break;
 
     case GST_FORMAT_DEFAULT:
       switch (*dest_format) {
         case GST_FORMAT_TIME:
-          *dest_value = src_value * GST_SECOND / fps;
+          *dest_value = src_value * gst_util_clock_time_scale (GST_SECOND,
+              gst_value_get_fraction_denominator (&fps),
+              gst_value_get_fraction_numerator (&fps));
           break;
         default:
-          return FALSE;
+          result = FALSE;
       }
       break;
 
     default:
-      return FALSE;
+      result = FALSE;
   }
 
-  return TRUE;
+  g_value_unset (&fps);
+  return result;
 }
 
 static gboolean
@@ -345,16 +353,19 @@ gst_v4lmjpegsrc_src_query (GstPad * pad,
 {
   GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
   gboolean res = TRUE;
-  gdouble fps;
+  GValue fps = { 0 };
 
-  if ((fps = gst_v4lmjpegsrc_get_fps (v4lmjpegsrc)) == 0)
+  g_value_init (&fps, GST_VALUE_FRACTION);
+  if (!gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps))
     return FALSE;
 
   switch (type) {
     case GST_QUERY_POSITION:
       switch (*format) {
         case GST_FORMAT_TIME:
-          *value = v4lmjpegsrc->handled * GST_SECOND / fps;
+          *value = v4lmjpegsrc->handled * gst_util_clock_time_scale (GST_SECOND,
+              gst_value_get_fraction_denominator (&fps),
+              gst_value_get_fraction_numerator (&fps));
           break;
         case GST_FORMAT_DEFAULT:
           *value = v4lmjpegsrc->handled;
@@ -369,6 +380,7 @@ gst_v4lmjpegsrc_src_query (GstPad * pad,
       break;
   }
 
+  g_value_unset (&fps);
   return res;
 }
 
@@ -497,15 +509,30 @@ gst_v4lmjpegsrc_get (GstPad * pad)
   GstV4lMjpegSrc *v4lmjpegsrc;
   GstBuffer *buf;
   gint num;
-  gdouble fps = 0;
+  GValue fps = { 0 };
+  GstClockTime duration;
+  GstClockTime cur_frame_time;
 
   g_return_val_if_fail (pad != NULL, NULL);
 
   v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
 
-  if (v4lmjpegsrc->use_fixed_fps &&
-      (fps = gst_v4lmjpegsrc_get_fps (v4lmjpegsrc)) == 0)
-    return NULL;
+  if (v4lmjpegsrc->use_fixed_fps) {
+    g_value_init (&fps, GST_VALUE_FRACTION);
+    duration = gst_util_clock_time_scale (GST_SECOND,
+        gst_value_get_fraction_denominator (&fps),
+        gst_value_get_fraction_numerator (&fps));
+    cur_frame_time =
+        gst_util_clock_time_scale (v4lmjpegsrc->handled * GST_SECOND,
+        gst_value_get_fraction_denominator (&fps),
+        gst_value_get_fraction_numerator (&fps));
+
+
+    if (!gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps)) {
+      g_value_unset (&fps);
+      return NULL;
+    }
+  }
 
   if (v4lmjpegsrc->need_writes > 0) {
     /* use last frame */
@@ -550,14 +577,12 @@ gst_v4lmjpegsrc_get (GstPad * pad)
        * timeframe. This means that if time - begin_time = X sec,
        * we want to have written X*fps frames. If we've written
        * more - drop, if we've written less - dup... */
-      if (v4lmjpegsrc->handled * (GST_SECOND / fps) - time >
-          1.5 * (GST_SECOND / fps)) {
+      if (cur_frame_time - time > 1.5 * duration) {
         /* yo dude, we've got too many frames here! Drop! DROP! */
         v4lmjpegsrc->need_writes--;     /* -= (v4lmjpegsrc->handled - (time / fps)); */
         g_signal_emit (G_OBJECT (v4lmjpegsrc),
             gst_v4lmjpegsrc_signals[SIGNAL_FRAME_DROP], 0);
-      } else if (v4lmjpegsrc->handled * (GST_SECOND / fps) - time <
-          -1.5 * (GST_SECOND / fps)) {
+      } else if (cur_frame_time - time < -1.5 * duration) {
         /* this means we're lagging far behind */
         v4lmjpegsrc->need_writes++;     /* += ((time / fps) - v4lmjpegsrc->handled); */
         g_signal_emit (G_OBJECT (v4lmjpegsrc),
@@ -590,7 +615,7 @@ gst_v4lmjpegsrc_get (GstPad * pad)
   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_READONLY);
   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
   if (v4lmjpegsrc->use_fixed_fps)
-    GST_BUFFER_TIMESTAMP (buf) = v4lmjpegsrc->handled * GST_SECOND / fps;
+    GST_BUFFER_TIMESTAMP (buf) = cur_frame_time;
   else                          /* calculate time based on our own clock */
     GST_BUFFER_TIMESTAMP (buf) =
         GST_TIMEVAL_TO_TIME (v4lmjpegsrc->bsync.timestamp) -
@@ -609,23 +634,27 @@ gst_v4lmjpegsrc_getcaps (GstPad * pad)
 {
   GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
   struct video_capability *vcap = &GST_V4LELEMENT (v4lmjpegsrc)->vcap;
-  gdouble fps;
   GstCaps *caps;
   GstStructure *str;
   gint i;
   GValue w = { 0 }, h = {
   0}, w1 = {
   0}, h1 = {
+  0}, fps = {
   0};
 
   if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lmjpegsrc))) {
     return gst_caps_copy (gst_pad_get_pad_template_caps (pad));
   }
 
-  fps = gst_v4lmjpegsrc_get_fps (v4lmjpegsrc);
-  caps = gst_caps_new_simple ("image/jpeg",
-      "framerate", G_TYPE_DOUBLE, fps, NULL);
+  g_value_init (&fps, GST_TYPE_FRACTION);
+  gst_return_val_if_fail (gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps), NULL);
+
+  caps = gst_caps_new_simple ("image/jpeg", NULL);
   str = gst_caps_get_structure (caps, 0);
+  gst_structure_set_value (str, "framerate", &fps);
+  g_value_unset (&fps);
+
   g_value_init (&w, GST_TYPE_LIST);
   g_value_init (&h, GST_TYPE_LIST);
   g_value_init (&w1, G_TYPE_INT);
index 3f5a4aa..94e5f0e 100644 (file)
@@ -371,7 +371,7 @@ gst_v4lsrc_get_caps (GstBaseSrc * src)
   gint width = GST_V4LELEMENT (src)->vcap.minwidth;
   gint height = GST_V4LELEMENT (src)->vcap.minheight;
   gint i;
-  gdouble fps;
+  GValue fps = { 0 };
   GList *item;
 
   if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
@@ -402,7 +402,9 @@ gst_v4lsrc_get_caps (GstBaseSrc * src)
     }
   }
 
-  fps = gst_v4lsrc_get_fps (v4lsrc);
+
+  if (!gst_v4lsrc_get_fps (v4lsrc, &fps))
+    gst_value_set_fraction (&fps, 0, 1);
 
   list = gst_caps_new_empty ();
   for (item = v4lsrc->colorspaces; item != NULL; item = item->next) {
@@ -416,8 +418,10 @@ gst_v4lsrc_get_caps (GstBaseSrc * src)
     }
 
     GST_DEBUG_OBJECT (v4lsrc,
-        "Device reports w: %d-%d, h: %d-%d, fps: %f for palette %d",
-        vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, fps,
+        "Device reports w: %d-%d, h: %d-%d, fps: %d/%d for palette %d",
+        vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight,
+        gst_value_get_fraction_numerator (&fps),
+        gst_value_get_fraction_denominator (&fps),
         GPOINTER_TO_INT (item->data));
 
     if (vcap->minwidth < vcap->maxwidth) {
@@ -434,21 +438,22 @@ gst_v4lsrc_get_caps (GstBaseSrc * src)
     }
 
     if (v4lsrc->autoprobe_fps) {
-      if (v4lsrc->fps_list) {
-        GstStructure *structure = gst_caps_get_structure (one, 0);
+      GstStructure *structure = gst_caps_get_structure (one, 0);
 
+      if (v4lsrc->fps_list) {
         gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
       } else {
-        gst_caps_set_simple (one, "framerate", G_TYPE_DOUBLE, fps, NULL);
+        gst_structure_set_value (structure, "framerate", &fps);
       }
     } else {
-      gst_caps_set_simple (one, "framerate", GST_TYPE_DOUBLE_RANGE,
-          (gdouble) 1.0, (gdouble) 100.0, NULL);
+      gst_caps_set_simple (one, "framerate", GST_TYPE_FRACTION_RANGE,
+          1, 1, 100, 1, NULL);
     }
 
     GST_DEBUG_OBJECT (v4lsrc, "caps: %" GST_PTR_FORMAT, one);
     gst_caps_append (list, one);
   }
+  g_value_unset (&fps);
 
   return list;
 }
@@ -459,7 +464,8 @@ gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
   GstV4lSrc *v4lsrc;
   guint32 fourcc;
   gint bpp, depth, w, h, palette = -1;
-  gdouble fps;
+  const GValue *new_fps;
+  GValue cur_fps = { 0 };
   GstStructure *structure;
   struct video_window *vwin;
 
@@ -488,12 +494,19 @@ gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
 
   gst_structure_get_int (structure, "width", &w);
   gst_structure_get_int (structure, "height", &h);
-  gst_structure_get_double (structure, "framerate", &fps);
-  GST_DEBUG_OBJECT (v4lsrc, "linking with %dx%d at %f fps", w, h, fps);
+  new_fps = gst_structure_get_value (structure, "framerate");
+
+  GST_DEBUG_OBJECT (v4lsrc, "linking with %dx%d at %d/%d fps", w, h,
+      gst_value_get_fraction_numerator (new_fps),
+      gst_value_get_fraction_denominator (new_fps));
 
   /* set framerate if it's not already correct */
-  if (fps != gst_v4lsrc_get_fps (v4lsrc)) {
-    int fps_index = fps / 15.0 * 16;
+  if (!gst_v4lsrc_get_fps (v4lsrc, &cur_fps))
+    return FALSE;
+
+  if (gst_value_compare (new_fps, &cur_fps) != GST_VALUE_EQUAL) {
+    int fps_index = (gst_value_get_fraction_numerator (new_fps) * 16) /
+        (gst_value_get_fraction_denominator (new_fps) * 15);
 
     GST_DEBUG_OBJECT (v4lsrc, "Trying to set fps index %d", fps_index);
     /* set bits 16 to 21 to 0 */
@@ -501,9 +514,11 @@ gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
     /* set bits 16 to 21 to the index */
     vwin->flags |= fps_index << 16;
     if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
+      g_value_unset (&cur_fps);
       return FALSE;
     }
   }
+  g_value_unset (&cur_fps);
 
   switch (fourcc) {
     case GST_MAKE_FOURCC ('I', '4', '2', '0'):
index 6eab6a7..cdc6497 100644 (file)
@@ -82,7 +82,6 @@ struct _GstV4lSrc
   gboolean quit;
 
   gint offset;
-  gfloat fps;
 
   /* list of supported colorspaces (as integers) */
   GList *colorspaces;
index 72fa567..0f92c4e 100644 (file)
@@ -205,7 +205,11 @@ gst_v4l_open (GstV4lElement * v4lelement)
     GstTunerNorm *norm = GST_TUNER_NORM (v4lnorm);
 
     norm->label = g_strdup (norm_name[num]);
-    norm->fps = (num == 1) ? (30000. / 1001) : 25.;
+    if (num == 1)
+      gst_value_set_fraction (&norm->framerate, 30000, 1001);
+    else
+      gst_value_set_fraction (&norm->framerate, 25, 1);
+
     v4lnorm->index = num;
     v4lelement->norms = g_list_append (v4lelement->norms, (gpointer) norm);
   }
index fc4aa39..babf536 100644 (file)
@@ -500,14 +500,15 @@ gst_v4lsrc_palette_name (int i)
   return v4l_palette_name[i];
 }
 
-gfloat
-gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc)
+gboolean
+gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc, GValue * fps)
 {
   gint norm;
   gint fps_index;
-  gfloat fps;
   struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
 
+  g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (fps), FALSE);
+
   /* check if we have vwin window properties giving a framerate,
    * as is done for webcams
    * See http://www.smcc.demon.nl/webcam/api.html
@@ -516,12 +517,12 @@ gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc)
 
   /* webcams have a non-zero fps_index */
   if (fps_index != 0) {
-    gfloat current_fps;
-
     /* index of 16 corresponds to 15 fps */
-    current_fps = fps_index * 15.0 / 16;
-    GST_LOG_OBJECT (v4lsrc, "device reports fps of %.4f", current_fps);
-    return current_fps;
+    GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)",
+        fps_index * 15, 16, fps_index * 15.0 / 16);
+
+    gst_value_set_fraction (fps, fps_index * 15, 16);
+    return TRUE;
   }
 
   /* removed fps estimation code here */
@@ -529,17 +530,17 @@ gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc)
   /* if that failed ... */
 
   if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc)))
-    return 0.;
+    return FALSE;
 
   if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lsrc), NULL, &norm))
-    return 0.;
+    return FALSE;
 
   if (norm == VIDEO_MODE_NTSC)
-    fps = 30000 / 1001;
+    gst_value_set_fraction (fps, 30000, 1001);
   else
-    fps = 25.;
+    gst_value_set_fraction (fps, 25, 1);
 
-  return fps;
+  return TRUE;
 }
 
 /* get a list of possible framerates
@@ -551,7 +552,6 @@ GValue *
 gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
 {
   gint fps_index;
-  gfloat fps;
   struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
   GstV4lElement *v4lelement = GST_V4LELEMENT (v4lsrc);
 
@@ -569,7 +569,6 @@ gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
   GST_DEBUG_OBJECT (v4lsrc, "fps_index is %d, so webcam", fps_index);
 
   {
-    gfloat current_fps;
     int i;
     GValue *list = NULL;
     GValue value = { 0 };
@@ -580,8 +579,8 @@ gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
     g_value_init (list, GST_TYPE_LIST);
 
     /* index of 16 corresponds to 15 fps */
-    current_fps = fps_index * 15.0 / 16;
-    GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %.4f", current_fps);
+    GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)",
+        fps_index * 15, 16, fps_index * 15.0 / 16);
     for (i = 0; i < 63; ++i) {
       /* set bits 16 to 21 to 0 */
       vwin->flags &= (0x3F00 - 1);
@@ -589,9 +588,8 @@ gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
       vwin->flags |= i << 16;
       if (gst_v4l_set_window_properties (v4lelement)) {
         /* setting it succeeded.  FIXME: get it and check. */
-        fps = i * 15.0 / 16;
-        g_value_init (&value, G_TYPE_DOUBLE);
-        g_value_set_double (&value, fps);
+        g_value_init (&value, GST_TYPE_FRACTION);
+        gst_value_set_fraction (&value, i * 15, 16);
         gst_value_list_append_value (list, &value);
         g_value_unset (&value);
       }
@@ -687,9 +685,13 @@ GstBuffer *
 gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
 {
   GstBuffer *buf;
+  GValue fps = { 0 };
 
   GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num);
 
+  g_value_init (&fps, GST_TYPE_FRACTION);
+  g_return_val_if_fail (gst_v4lsrc_get_fps (v4lsrc, &fps), NULL);
+
   buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4LSRC_BUFFER);
 
   GST_V4LSRC_BUFFER (buf)->num = num;
@@ -701,15 +703,15 @@ gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
   GST_BUFFER_OFFSET (buf) = v4lsrc->offset++;
   GST_BUFFER_TIMESTAMP (buf) = gst_clock_get_time (GST_ELEMENT (v4lsrc)->clock);
   GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4lsrc)->base_time;
-  /* fixme: this is a most ghetto timestamp/duration */
+  /* FIXME: this is a most ghetto timestamp/duration */
 
-  if (!v4lsrc->fps)
-    v4lsrc->fps = gst_v4lsrc_get_fps (v4lsrc);
-  if (v4lsrc->fps)
-    GST_BUFFER_DURATION (buf) = GST_SECOND / v4lsrc->fps;
+  GST_BUFFER_DURATION (buf) = gst_util_clock_time_scale (GST_SECOND,
+      gst_value_get_fraction_numerator (&fps),
+      gst_value_get_fraction_denominator (&fps));
 
   /* the negotiate() method already set caps on the source pad */
   gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));
 
+  g_value_unset (&fps);
   return buf;
 }
index 6b92542..755d354 100644 (file)
@@ -39,7 +39,7 @@ guint8 * gst_v4lsrc_get_buffer     (GstV4lSrc *v4lsrc, gint  num);
 gboolean gst_v4lsrc_requeue_frame  (GstV4lSrc *v4lsrc, gint  num);
 gboolean gst_v4lsrc_capture_stop   (GstV4lSrc *v4lsrc);
 gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc);
-gfloat   gst_v4lsrc_get_fps        (GstV4lSrc * v4lsrc);
+gboolean gst_v4lsrc_get_fps        (GstV4lSrc * v4lsrc, GValue *fps);
 GValue * gst_v4lsrc_get_fps_list   (GstV4lSrc * v4lsrc);
 GstBuffer *gst_v4lsrc_buffer_new   (GstV4lSrc * v4lsrc, gint num);