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.
This commit is contained in:
Jan Schmidt 2005-11-22 16:08:37 +00:00
parent 08cd3b973f
commit 0e82871285
18 changed files with 230 additions and 107 deletions

View file

@ -1,3 +1,38 @@
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> 2005-11-22 Thomas Vander Stichele <thomas at apestaart dot org>
* gst-libs/gst/audio/audio.c: * gst-libs/gst/audio/audio.c:

View file

@ -56,7 +56,10 @@ struct _GstVisual
/* audio/video state */ /* audio/video state */
gint rate; /* Input samplerate */ gint rate; /* Input samplerate */
gdouble fps;
/* framerate numerator & denominator */
gint fps_n;
gint fps_d;
gint width; gint width;
gint height; gint height;
@ -268,6 +271,7 @@ gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad)); GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
GstStructure *structure; GstStructure *structure;
gint depth; gint depth;
const GValue *fps;
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
@ -275,10 +279,14 @@ gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
return FALSE; return FALSE;
if (!gst_structure_get_int (structure, "height", &visual->height)) if (!gst_structure_get_int (structure, "height", &visual->height))
return FALSE; return FALSE;
if (!gst_structure_get_double (structure, "framerate", &visual->fps))
return FALSE;
if (!gst_structure_get_int (structure, "bpp", &depth)) if (!gst_structure_get_int (structure, "bpp", &depth))
return FALSE; 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_set_depth (visual->video,
visual_video_depth_enum_from_value (depth)); visual_video_depth_enum_from_value (depth));
@ -310,6 +318,7 @@ get_buffer (GstVisual * visual, GstBuffer ** outbuf)
gint width, height, bpp; gint width, height, bpp;
GstStructure *s; GstStructure *s;
GstCaps *caps; GstCaps *caps;
GValue target_fps = { 0 };
/* No output caps current set up. Try and pick some */ /* No output caps current set up. Try and pick some */
caps = gst_pad_get_allowed_caps (visual->srcpad); 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, "width", 320);
gst_structure_fixate_field_nearest_int (s, "height", 240); 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); gst_pad_fixate_caps (visual->srcpad, caps);
} else } 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) if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
visual->next_ts = GST_BUFFER_TIMESTAMP (buffer); visual->next_ts = GST_BUFFER_TIMESTAMP (buffer);
/* spf = samples per frame */ /* 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); gst_adapter_push (visual->adapter, buffer);
while (gst_adapter_available (visual->adapter) > MAX (512, spf) * 4 && 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_audio_analyze (&visual->audio);
visual_actor_run (visual->actor, &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_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); visual->next_ts += GST_BUFFER_DURATION (outbuf);
ret = gst_pad_push (visual->srcpad, outbuf); ret = gst_pad_push (visual->srcpad, outbuf);
outbuf = NULL; outbuf = NULL;
@ -420,7 +431,7 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
/* Flush out the number of samples per frame * channels * sizeof (gint16) */ /* Flush out the number of samples per frame * channels * sizeof (gint16) */
/* Recompute spf in case caps changed */ /* 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", GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
spf); spf);
gst_adapter_flush (visual->adapter, gst_adapter_flush (visual->adapter,

View file

@ -608,7 +608,8 @@ gst_ogm_parse_chain (GstPad * pad, GstBuffer * buffer)
gst_caps_set_simple (caps, gst_caps_set_simple (caps,
"width", G_TYPE_INT, ogm->hdr.s.video.width, "width", G_TYPE_INT, ogm->hdr.s.video.width,
"height", G_TYPE_INT, ogm->hdr.s.video.height, "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; break;
} }
case 't': case 't':

View file

@ -99,7 +99,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, " GST_STATIC_CAPS ("video/x-raw-yuv, "
"format = (fourcc) I420, " "format = (fourcc) I420, "
"framerate = (double) [0, MAX], " "framerate = (fraction) [0/1, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 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", caps = gst_caps_new_simple ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
"framerate", G_TYPE_DOUBLE, "framerate", GST_TYPE_FRACTION,
((gdouble) dec->info.fps_numerator) / dec->info.fps_denominator, dec->info.fps_numerator, dec->info.fps_denominator,
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den, "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
"width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL); "width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
gst_pad_set_caps (dec->srcpad, caps); gst_pad_set_caps (dec->srcpad, caps);

View file

@ -113,7 +113,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, " GST_STATIC_CAPS ("video/x-raw-yuv, "
"format = (fourcc) I420, " "format = (fourcc) I420, "
"framerate = (double) [0, MAX], " "framerate = (fraction) [0/1, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 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); GstStructure *structure = gst_caps_get_structure (caps, 0);
GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad)); GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
const GValue *par; const GValue *par;
GValue fps = { 0 }; const GValue *framerate;
GValue framerate = { 0 };
gst_structure_get_int (structure, "width", &enc->width); gst_structure_get_int (structure, "width", &enc->width);
gst_structure_get_int (structure, "height", &enc->height); 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"); par = gst_structure_get_value (structure, "pixel-aspect-ratio");
theora_info_init (&enc->info); 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_x = enc->offset_x;
enc->info.offset_y = enc->offset_y; enc->info.offset_y = enc->offset_y;
/* convert double to fraction for the framerate */ enc->info.fps_numerator = gst_value_get_fraction_numerator (framerate);
g_value_init (&fps, G_TYPE_DOUBLE); enc->info.fps_denominator = gst_value_get_fraction_denominator (framerate);
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);
if (par) { if (par) {
enc->info.aspect_numerator = gst_value_get_fraction_numerator (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 */ /* create the remaining theora headers */
theora_comment_init (&enc->comment); 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); theora_encode_comment (&enc->comment, &op);
ret = theora_buffer_from_packet (enc, &op, 0, 0, &buf2); ret = theora_buffer_from_packet (enc, &op, 0, 0, &buf2);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {

View file

@ -363,12 +363,11 @@ gst_riff_create_video_caps (guint32 codec_fcc,
} }
if (strh != NULL) { if (strh != NULL) {
gdouble fps = 1. * strh->rate / strh->scale; gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
strh->rate, strh->scale, NULL);
gst_caps_set_simple (caps, "framerate", G_TYPE_DOUBLE, fps, NULL);
} else { } else {
gst_caps_set_simple (caps, 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) { if (strf != NULL) {

View file

@ -25,11 +25,12 @@
#include "video.h" #include "video.h"
/* This is simply a convenience function, nothing more or less */ /* This is simply a convenience function, nothing more or less */
const GValue *
gdouble
gst_video_frame_rate (GstPad * pad) gst_video_frame_rate (GstPad * pad)
{ {
gdouble fps = 0.; const GValue *fps;
gchar *fps_string;
const GstCaps *caps = NULL; const GstCaps *caps = NULL;
GstStructure *structure; GstStructure *structure;
@ -38,18 +39,27 @@ gst_video_frame_rate (GstPad * pad)
if (caps == NULL) { if (caps == NULL) {
g_warning ("gstvideo: failed to get caps of pad %s:%s", g_warning ("gstvideo: failed to get caps of pad %s:%s",
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad)); GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad));
return 0.; return NULL;
} }
structure = gst_caps_get_structure (caps, 0); 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", g_warning ("gstvideo: failed to get framerate property of pad %s:%s",
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad)); 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", fps_string = gst_value_serialize (fps);
GST_ELEMENT_NAME (gst_pad_get_parent (pad)), GST_PAD_NAME (pad), 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; return fps;
} }

View file

@ -60,7 +60,7 @@ G_BEGIN_DECLS
#define GST_VIDEO_BLUE_MASK_15_INT 0x001f #define GST_VIDEO_BLUE_MASK_15_INT 0x001f
#define GST_VIDEO_SIZE_RANGE "(int) [ 1, max ]" #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 */ /* consider the next 2 protected */
#define __GST_VIDEO_CAPS_MAKE_32A(R, G, B, A) \ #define __GST_VIDEO_CAPS_MAKE_32A(R, G, B, A) \
@ -184,7 +184,7 @@ G_BEGIN_DECLS
"framerate = " GST_VIDEO_FPS_RANGE "framerate = " GST_VIDEO_FPS_RANGE
/* functions */ /* functions */
gdouble gst_video_frame_rate (GstPad *pad); const GValue *gst_video_frame_rate (GstPad *pad);
gboolean gst_video_get_size (GstPad *pad, gboolean gst_video_get_size (GstPad *pad,
gint *width, gint *width,
gint *height); gint *height);

View file

@ -88,8 +88,6 @@ enum SampleFormat {
SAMPLE_FMT_S16 = 0, ///< signed 16 bits SAMPLE_FMT_S16 = 0, ///< signed 16 bits
}; };
#define DEFAULT_FRAME_RATE_BASE 1001000
/* thomas: extracted from imgconvert.c since it's also used in /* thomas: extracted from imgconvert.c since it's also used in
* gstffmpegcodecmap.c */ * gstffmpegcodecmap.c */

View file

@ -83,14 +83,14 @@ gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context)
gst_caps_new_simple (mimetype, \ gst_caps_new_simple (mimetype, \
"width", G_TYPE_INT, context->width, \ "width", G_TYPE_INT, context->width, \
"height", G_TYPE_INT, context->height, \ "height", G_TYPE_INT, context->height, \
"framerate", G_TYPE_DOUBLE, 1. * context->frame_rate / \ "framerate", GST_TYPE_FRACTION, \
context->frame_rate_base, \ (gint) context->frame_rate, (gint) context->frame_rate_base, \
__VA_ARGS__, NULL) \ __VA_ARGS__, NULL) \
: \ : \
gst_caps_new_simple (mimetype, \ gst_caps_new_simple (mimetype, \
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, \ "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, \
"height", 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) __VA_ARGS__, NULL)
/* same for audio - now with channels/sample rate /* same for audio - now with channels/sample rate
@ -447,19 +447,22 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps,
AVCodecContext * context, gboolean raw) AVCodecContext * context, gboolean raw)
{ {
GstStructure *structure; GstStructure *structure;
gdouble fps; const GValue *fps;
gboolean ret;
g_return_if_fail (gst_caps_get_size (caps) == 1); g_return_if_fail (gst_caps_get_size (caps) == 1);
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
gst_structure_get_int (structure, "width", &context->width); ret = gst_structure_get_int (structure, "width", &context->width);
gst_structure_get_int (structure, "height", &context->height); 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 */ /* framerate does not really matter */
if (gst_structure_get_double (structure, "framerate", &fps)) { context->frame_rate = gst_value_get_fraction_numerator (fps);
context->frame_rate = fps * DEFAULT_FRAME_RATE_BASE; context->frame_rate_base = gst_value_get_fraction_denominator (fps);
context->frame_rate_base = DEFAULT_FRAME_RATE_BASE;
}
if (!raw) if (!raw)
return; return;

View file

@ -163,7 +163,8 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
GstStructure *structure; GstStructure *structure;
gint in_height, in_width; gint in_height, in_width;
gint out_height, out_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 *in_par = NULL;
const GValue *out_par = NULL; const GValue *out_par = NULL;
AVCodecContext *ctx; AVCodecContext *ctx;
@ -177,10 +178,14 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
/* we have to have width and height */ /* we have to have width and height */
res = gst_structure_get_int (structure, "width", &in_width); res = gst_structure_get_int (structure, "width", &in_width);
res &= gst_structure_get_int (structure, "height", &in_height); res &= gst_structure_get_int (structure, "height", &in_height);
res &= gst_structure_get_double (structure, "framerate", &in_framerate);
if (!res) if (!res)
goto no_width_height; 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 */ /* this is optional */
in_par = gst_structure_get_value (structure, "pixel-aspect-ratio"); 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 */ /* we have to have width and height */
res = gst_structure_get_int (structure, "width", &out_width); res = gst_structure_get_int (structure, "width", &out_width);
res &= gst_structure_get_int (structure, "height", &out_height); res &= gst_structure_get_int (structure, "height", &out_height);
res &= gst_structure_get_double (structure, "framerate", &out_framerate);
if (!res) if (!res)
goto no_width_height; 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 */ /* this is optional */
out_par = gst_structure_get_value (structure, "pixel-aspect-ratio"); out_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
/* these must match */ /* these must match */
if (in_width != out_width || in_height != out_height || 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; goto format_mismatch;
/* if present, these must match too */ /* if present, these must match too */
@ -244,6 +253,13 @@ no_width_height:
space->to_pixfmt = PIX_FMT_NB; space->to_pixfmt = PIX_FMT_NB;
return FALSE; 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: format_mismatch:
{ {
GST_DEBUG ("input and output formats do not match"); GST_DEBUG ("input and output formats do not match");

View file

@ -47,7 +47,8 @@ struct _GstVideorate
GstPad *sinkpad, *srcpad; GstPad *sinkpad, *srcpad;
/* video state */ /* 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 next_ts; /* Timestamp of next buffer to output */
guint64 first_ts; /* Timestamp of first buffer */ guint64 first_ts; /* Timestamp of first buffer */
GstBuffer *prevbuf; GstBuffer *prevbuf;
@ -220,7 +221,7 @@ gst_videorate_transformcaps (GstPad * in_pad, GstCaps * in_caps,
structure = gst_caps_get_structure (intersect, i); structure = gst_caps_get_structure (intersect, i);
gst_structure_set (structure, 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; *out_caps = intersect;
@ -261,20 +262,27 @@ gst_videorate_setcaps (GstPad * pad, GstCaps * caps)
GstVideorate *videorate; GstVideorate *videorate;
GstStructure *structure; GstStructure *structure;
gboolean ret = TRUE; gboolean ret = TRUE;
double fps;
GstPad *otherpad, *opeer; GstPad *otherpad, *opeer;
const GValue *rate;
gint rate_numerator, rate_denominator;
videorate = GST_VIDEORATE (GST_PAD_PARENT (pad)); videorate = GST_VIDEORATE (GST_PAD_PARENT (pad));
structure = gst_caps_get_structure (caps, 0); 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; goto done;
rate_numerator = gst_value_get_fraction_numerator (rate);
rate_denominator = gst_value_get_fraction_denominator (rate);
if (pad == videorate->srcpad) { if (pad == videorate->srcpad) {
videorate->to_fps = fps; videorate->to_rate_numerator = rate_numerator;
videorate->to_rate_denominator = rate_denominator;
otherpad = videorate->sinkpad; otherpad = videorate->sinkpad;
} else { } else {
videorate->from_fps = fps; videorate->from_rate_numerator = rate_numerator;
videorate->from_rate_denominator = rate_denominator;
otherpad = videorate->srcpad; otherpad = videorate->srcpad;
} }
/* now try to find something for the peer */ /* 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); structure = gst_caps_get_structure (caps, 0);
/* and fixate */ /* and fixate */
gst_structure_fixate_field_nearest_int (structure, "framerate", fps); gst_structure_fixate_field_nearest_fraction (structure, "framerate",
rate);
gst_structure_get_double (structure, "framerate", &fps); rate = gst_structure_get_value (structure, "framerate");
rate_numerator = gst_value_get_fraction_numerator (rate);
rate_denominator = gst_value_get_fraction_denominator (rate);
if (otherpad == videorate->srcpad) { if (otherpad == videorate->srcpad) {
videorate->to_fps = fps; videorate->to_rate_numerator = rate_numerator;
videorate->to_rate_denominator = rate_denominator;
} else { } else {
videorate->from_fps = fps; videorate->from_rate_numerator = rate_numerator;
videorate->from_rate_denominator = rate_denominator;
} }
gst_pad_set_caps (otherpad, caps); gst_pad_set_caps (otherpad, caps);
ret = TRUE; ret = TRUE;
@ -341,8 +355,10 @@ gst_videorate_blank_data (GstVideorate * videorate)
gst_buffer_unref (videorate->prevbuf); gst_buffer_unref (videorate->prevbuf);
videorate->prevbuf = NULL; videorate->prevbuf = NULL;
videorate->from_fps = 0; videorate->from_rate_numerator = 0;
videorate->to_fps = 0; videorate->from_rate_denominator = 0;
videorate->to_rate_numerator = 0;
videorate->to_rate_denominator = 0;
videorate->in = 0; videorate->in = 0;
videorate->out = 0; videorate->out = 0;
videorate->drop = 0; videorate->drop = 0;
@ -435,10 +451,9 @@ gst_videorate_chain (GstPad * pad, GstBuffer * buffer)
videorate = GST_VIDEORATE (GST_PAD_PARENT (pad)); videorate = GST_VIDEORATE (GST_PAD_PARENT (pad));
if (videorate->from_fps == 0) if (videorate->from_rate_numerator == 0 ||
return GST_FLOW_NOT_NEGOTIATED; videorate->from_rate_denominator == 0 ||
videorate->to_rate_denominator == 0 || videorate->to_rate_numerator == 0)
if (videorate->to_fps == 0)
return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_NOT_NEGOTIATED;
/* pull in 2 buffers */ /* pull in 2 buffers */
@ -494,7 +509,8 @@ gst_videorate_chain (GstPad * pad, GstBuffer * buffer)
videorate->out++; videorate->out++;
videorate->next_ts = videorate->next_ts =
videorate->first_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) = GST_BUFFER_DURATION (outbuf) =
videorate->next_ts - GST_BUFFER_TIMESTAMP (outbuf); videorate->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
/* adapt for looping */ /* adapt for looping */

View file

@ -173,12 +173,16 @@ static void
gst_videotestsrc_src_fixate (GstPad * pad, GstCaps * caps) gst_videotestsrc_src_fixate (GstPad * pad, GstCaps * caps)
{ {
GstStructure *structure; 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); structure = gst_caps_get_structure (caps, 0);
gst_structure_fixate_field_nearest_int (structure, "width", 320); gst_structure_fixate_field_nearest_int (structure, "width", 320);
gst_structure_fixate_field_nearest_int (structure, "height", 240); 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 static void
@ -263,7 +267,7 @@ gst_videotestsrc_getcaps (GstBaseSrc * unused)
gst_structure_set (structure, gst_structure_set (structure,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", 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); gst_caps_append_structure (caps, structure);
} }
@ -275,11 +279,12 @@ gst_videotestsrc_getcaps (GstBaseSrc * unused)
static gboolean static gboolean
gst_videotestsrc_parse_caps (const GstCaps * caps, 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) struct fourcc_list_struct **fourcc)
{ {
const GstStructure *structure; const GstStructure *structure;
GstPadLinkReturn ret; GstPadLinkReturn ret;
const GValue *framerate;
GST_DEBUG ("parsing caps"); 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, "width", width);
ret &= gst_structure_get_int (structure, "height", height); 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; return ret;
} }
@ -305,24 +317,26 @@ static gboolean
gst_videotestsrc_setcaps (GstBaseSrc * bsrc, GstCaps * caps) gst_videotestsrc_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
{ {
gboolean res; gboolean res;
gint width, height; gint width, height, rate_denominator, rate_numerator;
gdouble rate;
struct fourcc_list_struct *fourcc; struct fourcc_list_struct *fourcc;
GstVideoTestSrc *videotestsrc; GstVideoTestSrc *videotestsrc;
videotestsrc = GST_VIDEOTESTSRC (bsrc); 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) { if (res) {
/* looks ok here */ /* looks ok here */
videotestsrc->fourcc = fourcc; videotestsrc->fourcc = fourcc;
videotestsrc->width = width; videotestsrc->width = width;
videotestsrc->height = height; videotestsrc->height = height;
videotestsrc->rate = rate; videotestsrc->rate_numerator = rate_numerator;
videotestsrc->rate_denominator = rate_denominator;
videotestsrc->bpp = videotestsrc->fourcc->bitspp; videotestsrc->bpp = videotestsrc->fourcc->bitspp;
GST_DEBUG_OBJECT (videotestsrc, "size %dx%d, %f fps", videotestsrc->width, GST_DEBUG_OBJECT (videotestsrc, "size %dx%d, %d/%d fps",
videotestsrc->height, videotestsrc->rate); videotestsrc->width, videotestsrc->height,
videotestsrc->rate_numerator, videotestsrc->rate_denominator);
} }
return res; return res;
} }
@ -350,10 +364,12 @@ gst_videotestsrc_event (GstBaseSrc * bsrc, GstEvent * event)
switch (format) { switch (format) {
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
new_n_frames = cur * (double) videotestsrc->rate / GST_SECOND; new_n_frames = cur * videotestsrc->rate_numerator /
(videotestsrc->rate_denominator * GST_SECOND);
videotestsrc->segment_start_frame = new_n_frames; videotestsrc->segment_start_frame = new_n_frames;
videotestsrc->segment_end_frame = videotestsrc->segment_end_frame =
stop * (double) videotestsrc->rate / GST_SECOND; stop * videotestsrc->rate_numerator /
(videotestsrc->rate_denominator * GST_SECOND);
videotestsrc->segment = flags & GST_SEEK_FLAG_SEGMENT; videotestsrc->segment = flags & GST_SEEK_FLAG_SEGMENT;
break; break;
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
@ -442,10 +458,16 @@ gst_videotestsrc_create (GstPushSrc * psrc, GstBuffer ** buffer)
src->width, src->height); src->width, src->height);
GST_BUFFER_TIMESTAMP (outbuf) = src->timestamp_offset + src->running_time; GST_BUFFER_TIMESTAMP (outbuf) = src->timestamp_offset + src->running_time;
GST_BUFFER_DURATION (outbuf) = GST_SECOND / (double) src->rate; if (src->rate_numerator != 0) {
GST_BUFFER_DURATION (outbuf) = GST_SECOND * src->rate_denominator /
src->rate_numerator;
}
src->n_frames++; src->n_frames++;
src->running_time += GST_BUFFER_DURATION (outbuf); if (src->rate_numerator != 0) {
src->running_time = src->n_frames * GST_SECOND * src->rate_denominator /
src->rate_numerator;
}
*buffer = outbuf; *buffer = outbuf;

View file

@ -58,7 +58,8 @@ struct _GstVideoTestSrc {
gint height; gint height;
struct fourcc_list_struct *fourcc; struct fourcc_list_struct *fourcc;
gint bpp; gint bpp;
gdouble rate; gint rate_numerator;
gint rate_denominator;
/* private */ /* private */
gint64 timestamp_offset; /* base offset */ gint64 timestamp_offset; /* base offset */

View file

@ -64,7 +64,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-rgb, " GST_STATIC_CAPS ("video/x-raw-rgb, "
"framerate = (double) [ 0.0, MAX ], " "framerate = (fraction) [ 0, MAX ], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]") "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
); );
@ -968,7 +968,7 @@ gst_ximagesink_xcontext_get (GstXImageSink * ximagesink)
"blue_mask", G_TYPE_INT, xcontext->visual->blue_mask, "blue_mask", G_TYPE_INT, xcontext->visual->blue_mask,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", 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);
if (ximagesink->par) { if (ximagesink->par) {
int nom, den; int nom, den;
@ -1076,7 +1076,7 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
GstCaps *intersection; GstCaps *intersection;
const GValue *par; const GValue *par;
gint new_width, new_height; gint new_width, new_height;
gdouble fps; const GValue *fps;
ximagesink = GST_XIMAGESINK (bsink); ximagesink = GST_XIMAGESINK (bsink);
@ -1101,7 +1101,8 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
ret &= gst_structure_get_int (structure, "width", &new_width); ret &= gst_structure_get_int (structure, "width", &new_width);
ret &= gst_structure_get_int (structure, "height", &new_height); ret &= gst_structure_get_int (structure, "height", &new_height);
ret &= gst_structure_get_double (structure, "framerate", &fps); fps = gst_structure_get_value (structure, "framerate");
ret &= (fps != NULL);
if (!ret) if (!ret)
return FALSE; return FALSE;
@ -1122,7 +1123,8 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
GST_VIDEO_SINK_WIDTH (ximagesink) = new_width; GST_VIDEO_SINK_WIDTH (ximagesink) = new_width;
GST_VIDEO_SINK_HEIGHT (ximagesink) = new_height; GST_VIDEO_SINK_HEIGHT (ximagesink) = new_height;
ximagesink->framerate = fps; ximagesink->fps_n = gst_value_get_fraction_numerator (fps);
ximagesink->fps_d = gst_value_get_fraction_denominator (fps);
/* Notify application to set xwindow id now */ /* Notify application to set xwindow id now */
if (!ximagesink->xwindow) { if (!ximagesink->xwindow) {
@ -1199,7 +1201,8 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
if (ximagesink->xwindow) if (ximagesink->xwindow)
gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow); gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
ximagesink->framerate = 0; ximagesink->fps_n = 0;
ximagesink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (ximagesink) = 0; GST_VIDEO_SINK_WIDTH (ximagesink) = 0;
GST_VIDEO_SINK_HEIGHT (ximagesink) = 0; GST_VIDEO_SINK_HEIGHT (ximagesink) = 0;
break; break;
@ -1247,8 +1250,8 @@ gst_ximagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
if (GST_BUFFER_DURATION_IS_VALID (buf)) { if (GST_BUFFER_DURATION_IS_VALID (buf)) {
*end = *start + GST_BUFFER_DURATION (buf); *end = *start + GST_BUFFER_DURATION (buf);
} else { } else {
if (ximagesink->framerate > 0) { if (ximagesink->fps_n > 0) {
*end = *start + GST_SECOND / ximagesink->framerate; *end = *start + (GST_SECOND * ximagesink->fps_d) / ximagesink->fps_n;
} }
} }
} }
@ -1736,7 +1739,8 @@ gst_ximagesink_init (GstXImageSink * ximagesink)
ximagesink->event_thread = NULL; ximagesink->event_thread = NULL;
ximagesink->running = FALSE; ximagesink->running = FALSE;
ximagesink->framerate = 0; ximagesink->fps_n = 0;
ximagesink->fps_d = 1;
ximagesink->x_lock = g_mutex_new (); ximagesink->x_lock = g_mutex_new ();
ximagesink->flow_lock = g_mutex_new (); ximagesink->flow_lock = g_mutex_new ();

View file

@ -125,7 +125,10 @@ struct _GstXImageSink {
GThread *event_thread; GThread *event_thread;
gboolean running; gboolean running;
gdouble framerate; /* Framerate numerator and denominator */
gint fps_n;
gint fps_d;
GMutex *x_lock; GMutex *x_lock;
GMutex *flow_lock; GMutex *flow_lock;

View file

@ -70,11 +70,11 @@ static GstStaticPadTemplate gst_xvimagesink_sink_template_factory =
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-rgb, " GST_STATIC_CAPS ("video/x-raw-rgb, "
"framerate = (double) [ 0.0, MAX ], " "framerate = (fraction) [ 0, MAX ], "
"width = (int) [ 1, MAX ], " "width = (int) [ 1, MAX ], "
"height = (int) [ 1, MAX ]; " "height = (int) [ 1, MAX ]; "
"video/x-raw-yuv, " "video/x-raw-yuv, "
"framerate = (double) [ 0.0, MAX ], " "framerate = (fraction) [ 0, MAX ], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]") "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
); );
@ -998,7 +998,7 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
"red_mask", G_TYPE_INT, formats[i].blue_mask, "red_mask", G_TYPE_INT, formats[i].blue_mask,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", 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);
break; break;
} }
case XvYUV: case XvYUV:
@ -1006,7 +1006,7 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
"format", GST_TYPE_FOURCC, formats[i].id, "format", GST_TYPE_FOURCC, formats[i].id,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", 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);
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
@ -1415,6 +1415,7 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
gint display_par_n, display_par_d; /* display's PAR */ gint display_par_n, display_par_d; /* display's PAR */
GValue display_ratio = { 0, }; /* display w/h ratio */ GValue display_ratio = { 0, }; /* display w/h ratio */
const GValue *caps_par; const GValue *caps_par;
const GValue *fps;
gint num, den; gint num, den;
xvimagesink = GST_XVIMAGESINK (bsink); xvimagesink = GST_XVIMAGESINK (bsink);
@ -1435,11 +1436,15 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
ret = gst_structure_get_int (structure, "width", &video_width); ret = gst_structure_get_int (structure, "width", &video_width);
ret &= gst_structure_get_int (structure, "height", &video_height); ret &= gst_structure_get_int (structure, "height", &video_height);
ret &= gst_structure_get_double (structure, "framerate", fps = gst_structure_get_value (structure, "framerate");
&xvimagesink->framerate); ret &= (fps != NULL);
if (!ret) if (!ret)
return FALSE; return FALSE;
xvimagesink->fps_n = gst_value_get_fraction_numerator (fps);
xvimagesink->fps_d = gst_value_get_fraction_denominator (fps);
xvimagesink->video_width = video_width; xvimagesink->video_width = video_width;
xvimagesink->video_height = video_height; xvimagesink->video_height = video_height;
im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps); im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
@ -1581,7 +1586,8 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
xvimagesink->framerate = 0; xvimagesink->fps_n = 0;
xvimagesink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (xvimagesink) = 0; GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0; GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
break; break;
@ -1625,8 +1631,8 @@ gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
if (GST_BUFFER_DURATION_IS_VALID (buf)) { if (GST_BUFFER_DURATION_IS_VALID (buf)) {
*end = *start + GST_BUFFER_DURATION (buf); *end = *start + GST_BUFFER_DURATION (buf);
} else { } else {
if (xvimagesink->framerate > 0) { if (xvimagesink->fps_n > 0) {
*end = *start + GST_SECOND / xvimagesink->framerate; *end = *start + (GST_SECOND * xvimagesink->fps_d) / xvimagesink->fps_n;
} }
} }
} }
@ -2147,7 +2153,8 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink)
xvimagesink->contrast = xvimagesink->brightness = 0; xvimagesink->contrast = xvimagesink->brightness = 0;
xvimagesink->cb_changed = FALSE; xvimagesink->cb_changed = FALSE;
xvimagesink->framerate = 0; xvimagesink->fps_n = 0;
xvimagesink->fps_d = 0;
xvimagesink->video_width = 0; xvimagesink->video_width = 0;
xvimagesink->video_height = 0; xvimagesink->video_height = 0;

View file

@ -136,7 +136,8 @@ struct _GstXvImageSink {
GstXvImageBuffer *xvimage; GstXvImageBuffer *xvimage;
GstXvImageBuffer *cur_image; GstXvImageBuffer *cur_image;
gdouble framerate; gint fps_n;
gint fps_d;
gint brightness; gint brightness;
gint contrast; gint contrast;