Commit 0e828712 authored by Jan Schmidt's avatar Jan Schmidt

Convert elements to use fractions for their framerate.

Original commit message from CVS:
* ext/libvisual/visual.c: (gst_visual_src_setcaps), (get_buffer),
(gst_visual_chain):
* ext/ogg/gstogmparse.c: (gst_ogm_parse_chain):
* ext/theora/theoradec.c: (theora_handle_type_packet):
* ext/theora/theoraenc.c: (theora_enc_sink_setcaps),
(theora_enc_chain):
* gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps):
* gst-libs/gst/video/video.c: (gst_video_frame_rate):
* gst-libs/gst/video/video.h:
* gst/ffmpegcolorspace/avcodec.h:
* gst/ffmpegcolorspace/gstffmpegcodecmap.c:
(gst_ffmpeg_caps_to_pixfmt):
* gst/ffmpegcolorspace/gstffmpegcolorspace.c:
(gst_ffmpegcsp_set_caps):
* gst/videorate/gstvideorate.c: (gst_videorate_transformcaps),
(gst_videorate_setcaps), (gst_videorate_blank_data),
(gst_videorate_chain):
* gst/videotestsrc/gstvideotestsrc.c:
(gst_videotestsrc_src_fixate), (gst_videotestsrc_getcaps),
(gst_videotestsrc_parse_caps), (gst_videotestsrc_setcaps),
(gst_videotestsrc_event), (gst_videotestsrc_create):
* gst/videotestsrc/gstvideotestsrc.h:
* sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get),
(gst_ximagesink_setcaps), (gst_ximagesink_change_state),
(gst_ximagesink_get_times), (gst_ximagesink_init):
* sys/ximage/ximagesink.h:
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support),
(gst_xvimagesink_setcaps), (gst_xvimagesink_change_state),
(gst_xvimagesink_get_times), (gst_xvimagesink_init):
* sys/xvimage/xvimagesink.h:
Convert elements to use fractions for their framerate.
V4L elements to come later tonight.
parent 08cd3b97
2005-11-22 Jan Schmidt <thaytan@mad.scientist.com>
* ext/libvisual/visual.c: (gst_visual_src_setcaps), (get_buffer),
(gst_visual_chain):
* ext/ogg/gstogmparse.c: (gst_ogm_parse_chain):
* ext/theora/theoradec.c: (theora_handle_type_packet):
* ext/theora/theoraenc.c: (theora_enc_sink_setcaps),
(theora_enc_chain):
* gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps):
* gst-libs/gst/video/video.c: (gst_video_frame_rate):
* gst-libs/gst/video/video.h:
* gst/ffmpegcolorspace/avcodec.h:
* gst/ffmpegcolorspace/gstffmpegcodecmap.c:
(gst_ffmpeg_caps_to_pixfmt):
* gst/ffmpegcolorspace/gstffmpegcolorspace.c:
(gst_ffmpegcsp_set_caps):
* gst/videorate/gstvideorate.c: (gst_videorate_transformcaps),
(gst_videorate_setcaps), (gst_videorate_blank_data),
(gst_videorate_chain):
* gst/videotestsrc/gstvideotestsrc.c:
(gst_videotestsrc_src_fixate), (gst_videotestsrc_getcaps),
(gst_videotestsrc_parse_caps), (gst_videotestsrc_setcaps),
(gst_videotestsrc_event), (gst_videotestsrc_create):
* gst/videotestsrc/gstvideotestsrc.h:
* sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get),
(gst_ximagesink_setcaps), (gst_ximagesink_change_state),
(gst_ximagesink_get_times), (gst_ximagesink_init):
* sys/ximage/ximagesink.h:
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support),
(gst_xvimagesink_setcaps), (gst_xvimagesink_change_state),
(gst_xvimagesink_get_times), (gst_xvimagesink_init):
* sys/xvimage/xvimagesink.h:
Convert elements to use fractions for their framerate.
V4L elements to come later tonight.
2005-11-22 Thomas Vander Stichele <thomas at apestaart dot org>
* gst-libs/gst/audio/audio.c:
......
......@@ -56,7 +56,10 @@ struct _GstVisual
/* audio/video state */
gint rate; /* Input samplerate */
gdouble fps;
/* framerate numerator & denominator */
gint fps_n;
gint fps_d;
gint width;
gint height;
......@@ -268,6 +271,7 @@ gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
GstStructure *structure;
gint depth;
const GValue *fps;
structure = gst_caps_get_structure (caps, 0);
......@@ -275,10 +279,14 @@ gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
return FALSE;
if (!gst_structure_get_int (structure, "height", &visual->height))
return FALSE;
if (!gst_structure_get_double (structure, "framerate", &visual->fps))
return FALSE;
if (!gst_structure_get_int (structure, "bpp", &depth))
return FALSE;
fps = gst_structure_get_value (structure, "framerate");
if (fps == NULL || !GST_VALUE_HOLDS_FRACTION (fps))
return FALSE;
visual->fps_n = gst_value_get_fraction_numerator (fps);
visual->fps_d = gst_value_get_fraction_denominator (fps);
visual_video_set_depth (visual->video,
visual_video_depth_enum_from_value (depth));
......@@ -310,6 +318,7 @@ get_buffer (GstVisual * visual, GstBuffer ** outbuf)
gint width, height, bpp;
GstStructure *s;
GstCaps *caps;
GValue target_fps = { 0 };
/* No output caps current set up. Try and pick some */
caps = gst_pad_get_allowed_caps (visual->srcpad);
......@@ -328,7 +337,9 @@ get_buffer (GstVisual * visual, GstBuffer ** outbuf)
gst_structure_fixate_field_nearest_int (s, "width", 320);
gst_structure_fixate_field_nearest_int (s, "height", 240);
gst_structure_fixate_field_nearest_double (s, "framerate", 30.0);
g_value_init (&target_fps, GST_TYPE_FRACTION);
gst_value_set_fraction (&target_fps, 25, 1);
gst_structure_fixate_field_nearest_fraction (s, "framerate", &target_fps);
gst_pad_fixate_caps (visual->srcpad, caps);
} else
......@@ -380,11 +391,12 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
}
}
/* Match timestamps from the incoming audio */
if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
visual->next_ts = GST_BUFFER_TIMESTAMP (buffer);
/* spf = samples per frame */
spf = visual->rate / visual->fps;
spf = ((guint64) (visual->rate) * visual->fps_n) / visual->fps_d;
gst_adapter_push (visual->adapter, buffer);
while (gst_adapter_available (visual->adapter) > MAX (512, spf) * 4 &&
......@@ -410,9 +422,8 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
visual_audio_analyze (&visual->audio);
visual_actor_run (visual->actor, &visual->audio);
/* FIXME: Match timestamps from the incoming audio */
GST_BUFFER_TIMESTAMP (outbuf) = visual->next_ts;
GST_BUFFER_DURATION (outbuf) = GST_SECOND / visual->fps;
GST_BUFFER_DURATION (outbuf) = GST_SECOND * visual->fps_n / visual->fps_d;
visual->next_ts += GST_BUFFER_DURATION (outbuf);
ret = gst_pad_push (visual->srcpad, outbuf);
outbuf = NULL;
......@@ -420,7 +431,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 = visual->rate / visual->fps;
spf = ((guint64) (visual->rate) * visual->fps_n) / visual->fps_d;
GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
spf);
gst_adapter_flush (visual->adapter,
......
......@@ -608,7 +608,8 @@ gst_ogm_parse_chain (GstPad * pad, GstBuffer * buffer)
gst_caps_set_simple (caps,
"width", G_TYPE_INT, ogm->hdr.s.video.width,
"height", G_TYPE_INT, ogm->hdr.s.video.height,
"framerate", G_TYPE_DOUBLE, 10000000. / ogm->hdr.time_unit, NULL);
"framerate", GST_TYPE_FRACTION, 10000000, ogm->hdr.time_unit,
NULL);
break;
}
case 't':
......
......@@ -99,7 +99,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, "
"format = (fourcc) I420, "
"framerate = (double) [0, MAX], "
"framerate = (fraction) [0/1, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
......@@ -747,8 +747,8 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
caps = gst_caps_new_simple ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
"framerate", G_TYPE_DOUBLE,
((gdouble) dec->info.fps_numerator) / dec->info.fps_denominator,
"framerate", GST_TYPE_FRACTION,
dec->info.fps_numerator, dec->info.fps_denominator,
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
"width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
gst_pad_set_caps (dec->srcpad, caps);
......
......@@ -113,7 +113,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, "
"format = (fourcc) I420, "
"framerate = (double) [0, MAX], "
"framerate = (fraction) [0/1, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
......@@ -244,12 +244,11 @@ theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
GstStructure *structure = gst_caps_get_structure (caps, 0);
GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
const GValue *par;
GValue fps = { 0 };
GValue framerate = { 0 };
const GValue *framerate;
gst_structure_get_int (structure, "width", &enc->width);
gst_structure_get_int (structure, "height", &enc->height);
gst_structure_get_double (structure, "framerate", &enc->fps);
framerate = gst_structure_get_value (structure, "framerate");
par = gst_structure_get_value (structure, "pixel-aspect-ratio");
theora_info_init (&enc->info);
......@@ -272,14 +271,8 @@ theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
enc->info.offset_x = enc->offset_x;
enc->info.offset_y = enc->offset_y;
/* convert double to fraction for the framerate */
g_value_init (&fps, G_TYPE_DOUBLE);
g_value_init (&framerate, GST_TYPE_FRACTION);
g_value_set_double (&fps, enc->fps);
g_value_transform (&fps, &framerate);
enc->info.fps_numerator = gst_value_get_fraction_numerator (&framerate);
enc->info.fps_denominator = gst_value_get_fraction_denominator (&framerate);
enc->info.fps_numerator = gst_value_get_fraction_numerator (framerate);
enc->info.fps_denominator = gst_value_get_fraction_denominator (framerate);
if (par) {
enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
......@@ -471,6 +464,9 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
/* create the remaining theora headers */
theora_comment_init (&enc->comment);
/* Currently leaks due to libtheora API brokenness, I don't think we can
* portably work around it. Leaks ~50 bytes per encoder instance, so not a
* huge problem. */
theora_encode_comment (&enc->comment, &op);
ret = theora_buffer_from_packet (enc, &op, 0, 0, &buf2);
if (ret != GST_FLOW_OK) {
......
......@@ -363,12 +363,11 @@ gst_riff_create_video_caps (guint32 codec_fcc,
}
if (strh != NULL) {
gdouble fps = 1. * strh->rate / strh->scale;
gst_caps_set_simple (caps, "framerate", G_TYPE_DOUBLE, fps, NULL);
gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
strh->rate, strh->scale, NULL);
} else {
gst_caps_set_simple (caps,
"framerate", GST_TYPE_DOUBLE_RANGE, 0., G_MAXDOUBLE, NULL);
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
}
if (strf != NULL) {
......
......@@ -25,11 +25,12 @@
#include "video.h"
/* This is simply a convenience function, nothing more or less */
gdouble
const GValue *
gst_video_frame_rate (GstPad * pad)
{
gdouble fps = 0.;
const GValue *fps;
gchar *fps_string;
const GstCaps *caps = NULL;
GstStructure *structure;
......@@ -38,18 +39,27 @@ gst_video_frame_rate (GstPad * pad)
if (caps == NULL) {
g_warning ("gstvideo: failed to get caps of pad %s:%s",
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad));
return 0.;
return NULL;
}
structure = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_double (structure, "framerate", &fps)) {
if ((fps = gst_structure_get_value (structure, "framerate")) == NULL) {
g_warning ("gstvideo: failed to get framerate property of pad %s:%s",
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad));
return 0.;
return NULL;
}
if (!GST_VALUE_HOLDS_FRACTION (fps)) {
g_warning
("gstvideo: framerate property of pad %s:%s is not of type Fraction",
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad));
return NULL;
}
GST_DEBUG ("Framerate request on pad %s:%s: %f",
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad), fps);
fps_string = gst_value_serialize (fps);
GST_DEBUG ("Framerate request on pad %s:%s: %s",
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad),
fps_string);
g_free (fps_string);
return fps;
}
......
......@@ -60,7 +60,7 @@ G_BEGIN_DECLS
#define GST_VIDEO_BLUE_MASK_15_INT 0x001f
#define GST_VIDEO_SIZE_RANGE "(int) [ 1, max ]"
#define GST_VIDEO_FPS_RANGE "(double) [ 0.0, max ]"
#define GST_VIDEO_FPS_RANGE "(fraction) [ 0, max ]"
/* consider the next 2 protected */
#define __GST_VIDEO_CAPS_MAKE_32A(R, G, B, A) \
......@@ -184,7 +184,7 @@ G_BEGIN_DECLS
"framerate = " GST_VIDEO_FPS_RANGE
/* functions */
gdouble gst_video_frame_rate (GstPad *pad);
const GValue *gst_video_frame_rate (GstPad *pad);
gboolean gst_video_get_size (GstPad *pad,
gint *width,
gint *height);
......
......@@ -88,8 +88,6 @@ enum SampleFormat {
SAMPLE_FMT_S16 = 0, ///< signed 16 bits
};
#define DEFAULT_FRAME_RATE_BASE 1001000
/* thomas: extracted from imgconvert.c since it's also used in
* gstffmpegcodecmap.c */
......
......@@ -83,14 +83,14 @@ gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context)
gst_caps_new_simple (mimetype, \
"width", G_TYPE_INT, context->width, \
"height", G_TYPE_INT, context->height, \
"framerate", G_TYPE_DOUBLE, 1. * context->frame_rate / \
context->frame_rate_base, \
"framerate", GST_TYPE_FRACTION, \
(gint) context->frame_rate, (gint) context->frame_rate_base, \
__VA_ARGS__, NULL) \
: \
gst_caps_new_simple (mimetype, \
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, \
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT, \
"framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, \
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,\
__VA_ARGS__, NULL)
/* same for audio - now with channels/sample rate
......@@ -447,19 +447,22 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps,
AVCodecContext * context, gboolean raw)
{
GstStructure *structure;
gdouble fps;
const GValue *fps;
gboolean ret;
g_return_if_fail (gst_caps_get_size (caps) == 1);
structure = gst_caps_get_structure (caps, 0);
gst_structure_get_int (structure, "width", &context->width);
gst_structure_get_int (structure, "height", &context->height);
ret = gst_structure_get_int (structure, "width", &context->width);
ret &= gst_structure_get_int (structure, "height", &context->height);
g_return_if_fail (ret == TRUE);
fps = gst_structure_get_value (structure, "framerate");
g_return_if_fail (GST_VALUE_HOLDS_FRACTION (fps));
/* framerate does not really matter */
if (gst_structure_get_double (structure, "framerate", &fps)) {
context->frame_rate = fps * DEFAULT_FRAME_RATE_BASE;
context->frame_rate_base = DEFAULT_FRAME_RATE_BASE;
}
context->frame_rate = gst_value_get_fraction_numerator (fps);
context->frame_rate_base = gst_value_get_fraction_denominator (fps);
if (!raw)
return;
......
......@@ -163,7 +163,8 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
GstStructure *structure;
gint in_height, in_width;
gint out_height, out_width;
gdouble in_framerate, out_framerate;
const GValue *in_framerate = NULL;
const GValue *out_framerate = NULL;
const GValue *in_par = NULL;
const GValue *out_par = NULL;
AVCodecContext *ctx;
......@@ -177,10 +178,14 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
/* we have to have width and height */
res = gst_structure_get_int (structure, "width", &in_width);
res &= gst_structure_get_int (structure, "height", &in_height);
res &= gst_structure_get_double (structure, "framerate", &in_framerate);
if (!res)
goto no_width_height;
/* and framerate */
in_framerate = gst_structure_get_value (structure, "framerate");
if (in_framerate == NULL || !GST_VALUE_HOLDS_FRACTION (in_framerate))
goto no_framerate;
/* this is optional */
in_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
......@@ -189,16 +194,20 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
/* we have to have width and height */
res = gst_structure_get_int (structure, "width", &out_width);
res &= gst_structure_get_int (structure, "height", &out_height);
res &= gst_structure_get_double (structure, "framerate", &out_framerate);
if (!res)
goto no_width_height;
/* and framerate */
out_framerate = gst_structure_get_value (structure, "framerate");
if (out_framerate == NULL || !GST_VALUE_HOLDS_FRACTION (out_framerate))
goto no_framerate;
/* this is optional */
out_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
/* these must match */
if (in_width != out_width || in_height != out_height ||
in_framerate != out_framerate)
gst_value_compare (in_framerate, out_framerate) != GST_VALUE_EQUAL)
goto format_mismatch;
/* if present, these must match too */
......@@ -244,6 +253,13 @@ no_width_height:
space->to_pixfmt = PIX_FMT_NB;
return FALSE;
}
no_framerate:
{
GST_DEBUG ("did not specify framerate");
space->from_pixfmt = PIX_FMT_NB;
space->to_pixfmt = PIX_FMT_NB;
return FALSE;
}
format_mismatch:
{
GST_DEBUG ("input and output formats do not match");
......
......@@ -47,7 +47,8 @@ struct _GstVideorate
GstPad *sinkpad, *srcpad;
/* video state */
gdouble from_fps, to_fps;
gint from_rate_numerator, from_rate_denominator;
gint to_rate_numerator, to_rate_denominator;
guint64 next_ts; /* Timestamp of next buffer to output */
guint64 first_ts; /* Timestamp of first buffer */
GstBuffer *prevbuf;
......@@ -220,7 +221,7 @@ gst_videorate_transformcaps (GstPad * in_pad, GstCaps * in_caps,
structure = gst_caps_get_structure (intersect, i);
gst_structure_set (structure,
"framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL);
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
}
*out_caps = intersect;
......@@ -261,20 +262,27 @@ gst_videorate_setcaps (GstPad * pad, GstCaps * caps)
GstVideorate *videorate;
GstStructure *structure;
gboolean ret = TRUE;
double fps;
GstPad *otherpad, *opeer;
const GValue *rate;
gint rate_numerator, rate_denominator;
videorate = GST_VIDEORATE (GST_PAD_PARENT (pad));
structure = gst_caps_get_structure (caps, 0);
if (!(ret = gst_structure_get_double (structure, "framerate", &fps)))
rate = gst_structure_get_value (structure, "framerate");
if (!rate)
goto done;
rate_numerator = gst_value_get_fraction_numerator (rate);
rate_denominator = gst_value_get_fraction_denominator (rate);
if (pad == videorate->srcpad) {
videorate->to_fps = fps;
videorate->to_rate_numerator = rate_numerator;
videorate->to_rate_denominator = rate_denominator;
otherpad = videorate->sinkpad;
} else {
videorate->from_fps = fps;
videorate->from_rate_numerator = rate_numerator;
videorate->from_rate_denominator = rate_denominator;
otherpad = videorate->srcpad;
}
/* now try to find something for the peer */
......@@ -315,14 +323,20 @@ gst_videorate_setcaps (GstPad * pad, GstCaps * caps)
structure = gst_caps_get_structure (caps, 0);
/* and fixate */
gst_structure_fixate_field_nearest_int (structure, "framerate", fps);
gst_structure_fixate_field_nearest_fraction (structure, "framerate",
rate);
rate = gst_structure_get_value (structure, "framerate");
gst_structure_get_double (structure, "framerate", &fps);
rate_numerator = gst_value_get_fraction_numerator (rate);
rate_denominator = gst_value_get_fraction_denominator (rate);
if (otherpad == videorate->srcpad) {
videorate->to_fps = fps;
videorate->to_rate_numerator = rate_numerator;
videorate->to_rate_denominator = rate_denominator;
} else {
videorate->from_fps = fps;
videorate->from_rate_numerator = rate_numerator;
videorate->from_rate_denominator = rate_denominator;
}
gst_pad_set_caps (otherpad, caps);
ret = TRUE;
......@@ -341,8 +355,10 @@ gst_videorate_blank_data (GstVideorate * videorate)
gst_buffer_unref (videorate->prevbuf);
videorate->prevbuf = NULL;
videorate->from_fps = 0;
videorate->to_fps = 0;
videorate->from_rate_numerator = 0;
videorate->from_rate_denominator = 0;
videorate->to_rate_numerator = 0;
videorate->to_rate_denominator = 0;
videorate->in = 0;
videorate->out = 0;
videorate->drop = 0;
......@@ -435,10 +451,9 @@ gst_videorate_chain (GstPad * pad, GstBuffer * buffer)
videorate = GST_VIDEORATE (GST_PAD_PARENT (pad));
if (videorate->from_fps == 0)
return GST_FLOW_NOT_NEGOTIATED;
if (videorate->to_fps == 0)
if (videorate->from_rate_numerator == 0 ||
videorate->from_rate_denominator == 0 ||
videorate->to_rate_denominator == 0 || videorate->to_rate_numerator == 0)
return GST_FLOW_NOT_NEGOTIATED;
/* pull in 2 buffers */
......@@ -494,7 +509,8 @@ gst_videorate_chain (GstPad * pad, GstBuffer * buffer)
videorate->out++;
videorate->next_ts =
videorate->first_ts +
(videorate->out / videorate->to_fps * GST_SECOND);
(videorate->out * GST_SECOND *
videorate->to_rate_denominator / videorate->to_rate_numerator);
GST_BUFFER_DURATION (outbuf) =
videorate->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
/* adapt for looping */
......
......@@ -173,12 +173,16 @@ static void
gst_videotestsrc_src_fixate (GstPad * pad, GstCaps * caps)
{
GstStructure *structure;
GValue value = { 0 };
g_value_init (&value, GST_TYPE_FRACTION);
gst_value_set_fraction (&value, 30, 1);
structure = gst_caps_get_structure (caps, 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);
gst_structure_fixate_field_nearest_fraction (structure, "framerate", &value);
}
static void
......@@ -263,7 +267,7 @@ gst_videotestsrc_getcaps (GstBaseSrc * unused)
gst_structure_set (structure,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL);
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
gst_caps_append_structure (caps, structure);
}
......@@ -275,11 +279,12 @@ gst_videotestsrc_getcaps (GstBaseSrc * unused)
static gboolean
gst_videotestsrc_parse_caps (const GstCaps * caps,
gint * width, gint * height, gdouble * rate,
gint * width, gint * height, gint * rate_numerator, gint * rate_denominator,
struct fourcc_list_struct **fourcc)
{
const GstStructure *structure;
GstPadLinkReturn ret;
const GValue *framerate;
GST_DEBUG ("parsing caps");
......@@ -296,7 +301,14 @@ gst_videotestsrc_parse_caps (const GstCaps * caps,
ret = gst_structure_get_int (structure, "width", width);
ret &= gst_structure_get_int (structure, "height", height);
ret &= gst_structure_get_double (structure, "framerate", rate);
framerate = gst_structure_get_value (structure, "framerate");
if (framerate) {
*rate_numerator = gst_value_get_fraction_numerator (framerate);
*rate_denominator = gst_value_get_fraction_denominator (framerate);
} else
ret = FALSE;
return ret;
}
......@@ -305,24 +317,26 @@ static gboolean
gst_videotestsrc_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
{
gboolean res;
gint width, height;
gdouble rate;
gint width, height, rate_denominator, rate_numerator;
struct fourcc_list_struct *fourcc;
GstVideoTestSrc *videotestsrc;
videotestsrc = GST_VIDEOTESTSRC (bsrc);
res = gst_videotestsrc_parse_caps (caps, &width, &height, &rate, &fourcc);
res = gst_videotestsrc_parse_caps (caps, &width, &height,
&rate_numerator, &rate_denominator, &fourcc);
if (res) {
/* looks ok here */
videotestsrc->fourcc = fourcc;
videotestsrc->width = width;
videotestsrc->height = height;
videotestsrc->rate = rate;
videotestsrc->rate_numerator = rate_numerator;
videotestsrc->rate_denominator = rate_denominator;
videotestsrc->bpp = videotestsrc->fourcc->bitspp;
GST_DEBUG_OBJECT (videotestsrc, "size %dx%d, %f fps", videotestsrc->width,
videotestsrc->height, videotestsrc->rate);
GST_DEBUG_OBJECT (videotestsrc, "size %dx%d, %d/%d fps",
videotestsrc->width, videotestsrc->height,
videotestsrc->rate_numerator, videotestsrc->rate_denominator);
}
return res;
}
...