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 &&
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;
/* 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,
*/
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 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;
/**
GstV4lJpegSrc *v4ljpegsrc;
GstV4lSrc *v4lsrc;
gint w, h, palette = -1;
- gdouble fps;
+ const GValue *fps;
GstStructure *structure;
gboolean was_capturing;
struct video_window *vwin;
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)) {
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);
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);
}
-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) {
/* 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
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
{
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;
break;
}
+ g_value_unset (&fps);
return res;
}
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 */
* 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),
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) -
{
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);
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))) {
}
}
- 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) {
}
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) {
}
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;
}
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;
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 */
/* 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'):
gboolean quit;
gint offset;
- gfloat fps;
/* list of supported colorspaces (as integers) */
GList *colorspaces;
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);
}
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
/* 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 */
/* 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
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);
GST_DEBUG_OBJECT (v4lsrc, "fps_index is %d, so webcam", fps_index);
{
- gfloat current_fps;
int i;
GValue *list = NULL;
GValue value = { 0 };
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);
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);
}
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;
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;
}
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);