+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:
/* audio/video state */
gint rate; /* Input samplerate */
- gdouble fps;
+
+ /* framerate numerator & denominator */
+ gint fps_n;
+ gint fps_d;
gint width;
gint height;
GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
GstStructure *structure;
gint depth;
+ const GValue *fps;
structure = gst_caps_get_structure (caps, 0);
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));
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);
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
}
}
+ /* 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 &&
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;
/* 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,
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':
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 ]")
);
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);
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 ]")
);
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);
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);
/* 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) {
}
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) {
#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;
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;
}
#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) \
"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);
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 */
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
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;
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;
/* 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");
/* 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 */
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");
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;
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;
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 */
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;
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;
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 */
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 */
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
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);
}
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");
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;
}
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;
}
switch (format) {
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_end_frame =
- stop * (double) videotestsrc->rate / GST_SECOND;
+ stop * videotestsrc->rate_numerator /
+ (videotestsrc->rate_denominator * GST_SECOND);
videotestsrc->segment = flags & GST_SEEK_FLAG_SEGMENT;
break;
case GST_FORMAT_DEFAULT:
src->width, src->height);
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->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;
gint height;
struct fourcc_list_struct *fourcc;
gint bpp;
- gdouble rate;
+ gint rate_numerator;
+ gint rate_denominator;
/* private */
gint64 timestamp_offset; /* base offset */
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-rgb, "
- "framerate = (double) [ 0.0, MAX ], "
+ "framerate = (fraction) [ 0, MAX ], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
"blue_mask", G_TYPE_INT, xcontext->visual->blue_mask,
"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);
if (ximagesink->par) {
int nom, den;
GstCaps *intersection;
const GValue *par;
gint new_width, new_height;
- gdouble fps;
+ const GValue *fps;
ximagesink = GST_XIMAGESINK (bsink);
ret &= gst_structure_get_int (structure, "width", &new_width);
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)
return FALSE;
GST_VIDEO_SINK_WIDTH (ximagesink) = new_width;
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 */
if (!ximagesink->xwindow) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
if (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_HEIGHT (ximagesink) = 0;
break;
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
*end = *start + GST_BUFFER_DURATION (buf);
} else {
- if (ximagesink->framerate > 0) {
- *end = *start + GST_SECOND / ximagesink->framerate;
+ if (ximagesink->fps_n > 0) {
+ *end = *start + (GST_SECOND * ximagesink->fps_d) / ximagesink->fps_n;
}
}
}
ximagesink->event_thread = NULL;
ximagesink->running = FALSE;
- ximagesink->framerate = 0;
+ ximagesink->fps_n = 0;
+ ximagesink->fps_d = 1;
ximagesink->x_lock = g_mutex_new ();
ximagesink->flow_lock = g_mutex_new ();
GThread *event_thread;
gboolean running;
- gdouble framerate;
+ /* Framerate numerator and denominator */
+ gint fps_n;
+ gint fps_d;
+
GMutex *x_lock;
GMutex *flow_lock;
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-rgb, "
- "framerate = (double) [ 0.0, MAX ], "
+ "framerate = (fraction) [ 0, MAX ], "
"width = (int) [ 1, MAX ], "
"height = (int) [ 1, MAX ]; "
"video/x-raw-yuv, "
- "framerate = (double) [ 0.0, MAX ], "
+ "framerate = (fraction) [ 0, MAX ], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
"red_mask", G_TYPE_INT, formats[i].blue_mask,
"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);
break;
}
case XvYUV:
"format", GST_TYPE_FOURCC, formats[i].id,
"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);
break;
default:
g_assert_not_reached ();
gint display_par_n, display_par_d; /* display's PAR */
GValue display_ratio = { 0, }; /* display w/h ratio */
const GValue *caps_par;
+ const GValue *fps;
gint num, den;
xvimagesink = GST_XVIMAGESINK (bsink);
structure = gst_caps_get_structure (caps, 0);
ret = gst_structure_get_int (structure, "width", &video_width);
ret &= gst_structure_get_int (structure, "height", &video_height);
- ret &= gst_structure_get_double (structure, "framerate",
- &xvimagesink->framerate);
+ fps = gst_structure_get_value (structure, "framerate");
+ ret &= (fps != NULL);
+
if (!ret)
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_height = video_height;
im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
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_HEIGHT (xvimagesink) = 0;
break;
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
*end = *start + GST_BUFFER_DURATION (buf);
} else {
- if (xvimagesink->framerate > 0) {
- *end = *start + GST_SECOND / xvimagesink->framerate;
+ if (xvimagesink->fps_n > 0) {
+ *end = *start + (GST_SECOND * xvimagesink->fps_d) / xvimagesink->fps_n;
}
}
}
xvimagesink->contrast = xvimagesink->brightness = 0;
xvimagesink->cb_changed = FALSE;
- xvimagesink->framerate = 0;
+ xvimagesink->fps_n = 0;
+ xvimagesink->fps_d = 0;
xvimagesink->video_width = 0;
xvimagesink->video_height = 0;
GstXvImageBuffer *xvimage;
GstXvImageBuffer *cur_image;
- gdouble framerate;
+ gint fps_n;
+ gint fps_d;
gint brightness;
gint contrast;