From 674ee67e8baa2f3a1e84b16cc7b662404981108d Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 22 Nov 2005 23:39:12 +0000 Subject: [PATCH] ext/libvisual/visual.c: Fix the fps calculations. 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 | 7 ++-- gst/ffmpegcolorspace/avcodec.h | 18 ++++---- sys/v4l/gstv4ljpegsrc.c | 8 ++-- sys/v4l/gstv4lmjpegsink.c | 2 +- sys/v4l/gstv4lmjpegsrc.c | 95 +++++++++++++++++++++++++++--------------- sys/v4l/gstv4lsrc.c | 43 ++++++++++++------- sys/v4l/gstv4lsrc.h | 1 - sys/v4l/v4l_calls.c | 6 ++- sys/v4l/v4lsrc_calls.c | 52 ++++++++++++----------- sys/v4l/v4lsrc_calls.h | 2 +- 10 files changed, 142 insertions(+), 92 deletions(-) diff --git a/ext/libvisual/visual.c b/ext/libvisual/visual.c index cee88d8..e33a309 100644 --- a/ext/libvisual/visual.c +++ b/ext/libvisual/visual.c @@ -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, diff --git a/gst/ffmpegcolorspace/avcodec.h b/gst/ffmpegcolorspace/avcodec.h index e25f8e5..9b5370e 100644 --- a/gst/ffmpegcolorspace/avcodec.h +++ b/gst/ffmpegcolorspace/avcodec.h @@ -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; /** diff --git a/sys/v4l/gstv4ljpegsrc.c b/sys/v4l/gstv4ljpegsrc.c index 1c34fcc..e414c66 100644 --- a/sys/v4l/gstv4ljpegsrc.c +++ b/sys/v4l/gstv4ljpegsrc.c @@ -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)) { diff --git a/sys/v4l/gstv4lmjpegsink.c b/sys/v4l/gstv4lmjpegsink.c index 2b5a1ff..6e49234 100644 --- a/sys/v4l/gstv4lmjpegsink.c +++ b/sys/v4l/gstv4lmjpegsink.c @@ -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); diff --git a/sys/v4l/gstv4lmjpegsrc.c b/sys/v4l/gstv4lmjpegsrc.c index f8bf153..c4f2429 100644 --- a/sys/v4l/gstv4lmjpegsrc.c +++ b/sys/v4l/gstv4lmjpegsrc.c @@ -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); diff --git a/sys/v4l/gstv4lsrc.c b/sys/v4l/gstv4lsrc.c index 3f5a4aa..94e5f0e 100644 --- a/sys/v4l/gstv4lsrc.c +++ b/sys/v4l/gstv4lsrc.c @@ -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'): diff --git a/sys/v4l/gstv4lsrc.h b/sys/v4l/gstv4lsrc.h index 6eab6a7..cdc6497 100644 --- a/sys/v4l/gstv4lsrc.h +++ b/sys/v4l/gstv4lsrc.h @@ -82,7 +82,6 @@ struct _GstV4lSrc gboolean quit; gint offset; - gfloat fps; /* list of supported colorspaces (as integers) */ GList *colorspaces; diff --git a/sys/v4l/v4l_calls.c b/sys/v4l/v4l_calls.c index 72fa567..0f92c4e 100644 --- a/sys/v4l/v4l_calls.c +++ b/sys/v4l/v4l_calls.c @@ -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); } diff --git a/sys/v4l/v4lsrc_calls.c b/sys/v4l/v4lsrc_calls.c index fc4aa39..babf536 100644 --- a/sys/v4l/v4lsrc_calls.c +++ b/sys/v4l/v4lsrc_calls.c @@ -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; } diff --git a/sys/v4l/v4lsrc_calls.h b/sys/v4l/v4lsrc_calls.h index 6b92542..755d354 100644 --- a/sys/v4l/v4lsrc_calls.h +++ b/sys/v4l/v4lsrc_calls.h @@ -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); -- 2.7.4