From 2c1bf82d55cf100117eb4fdac85dac9150fe2659 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Thu, 6 Jan 2011 13:08:53 +0100 Subject: [PATCH] videorate: Fix behaviour for frame rate cap changes The outgoing buffer timestamp is calculated by scaling an output buffer count by the src pad frame rate caps. If these caps change, we need to reset the count and work from a new base timestamp. The new output buffer timestamp is then the count scaled by the new caps values added onto the base timestamp. --- gst/videorate/gstvideorate.c | 25 +++++++++++++++++++------ gst/videorate/gstvideorate.h | 6 +++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/gst/videorate/gstvideorate.c b/gst/videorate/gstvideorate.c index 827f0e9..a0642c2 100644 --- a/gst/videorate/gstvideorate.c +++ b/gst/videorate/gstvideorate.c @@ -290,6 +290,16 @@ gst_video_rate_setcaps (GstPad * pad, GstCaps * caps) goto no_framerate; if (pad == videorate->srcpad) { + /* out_frame_count is scaled by the frame rate caps when calculating next_ts. + * when the frame rate caps change, we must update base_ts and reset + * out_frame_count */ + if (videorate->to_rate_numerator) { + videorate->base_ts += + gst_util_uint64_scale (videorate->out_frame_count, + videorate->to_rate_denominator * GST_SECOND, + videorate->to_rate_numerator); + } + videorate->out_frame_count = 0; videorate->to_rate_numerator = rate_numerator; videorate->to_rate_denominator = rate_denominator; otherpad = videorate->sinkpad; @@ -394,7 +404,8 @@ gst_video_rate_reset (GstVideoRate * videorate) videorate->in = 0; videorate->out = 0; - videorate->segment_out = 0; + videorate->base_ts = 0; + videorate->out_frame_count = 0; videorate->drop = 0; videorate->dup = 0; videorate->next_ts = GST_CLOCK_TIME_NONE; @@ -473,11 +484,12 @@ gst_video_rate_flush_prev (GstVideoRate * videorate, gboolean duplicate) push_ts = videorate->next_ts; videorate->out++; - videorate->segment_out++; + videorate->out_frame_count++; if (videorate->to_rate_numerator) { /* interpolate next expected timestamp in the segment */ - videorate->next_ts = videorate->segment.accum + videorate->segment.start + - gst_util_uint64_scale (videorate->segment_out, + videorate->next_ts = + videorate->segment.accum + videorate->segment.start + + videorate->base_ts + gst_util_uint64_scale (videorate->out_frame_count, videorate->to_rate_denominator * GST_SECOND, videorate->to_rate_numerator); GST_BUFFER_DURATION (outbuf) = videorate->next_ts - push_ts; @@ -587,7 +599,8 @@ gst_video_rate_event (GstPad * pad, GstEvent * event) gst_video_rate_notify_drop (videorate); } /* clean up for the new one; _chain will resume from the new start */ - videorate->segment_out = 0; + videorate->base_ts = 0; + videorate->out_frame_count = 0; gst_video_rate_swap_prev (videorate, NULL, 0); videorate->next_ts = GST_CLOCK_TIME_NONE; } @@ -783,7 +796,7 @@ gst_video_rate_chain (GstPad * pad, GstBuffer * buffer) * timestamp in the segment */ if (videorate->skip_to_first) { videorate->next_ts = in_ts; - videorate->segment_out = gst_util_uint64_scale (in_ts, + videorate->out_frame_count = gst_util_uint64_scale (in_ts, videorate->to_rate_numerator, videorate->to_rate_denominator * GST_SECOND) - (videorate->segment.accum + videorate->segment.start); diff --git a/gst/videorate/gstvideorate.h b/gst/videorate/gstvideorate.h index 4d6c061..23e2056 100644 --- a/gst/videorate/gstvideorate.h +++ b/gst/videorate/gstvideorate.h @@ -55,7 +55,11 @@ struct _GstVideoRate guint64 next_ts; /* Timestamp of next buffer to output */ GstBuffer *prevbuf; guint64 prev_ts; /* Previous buffer timestamp */ - guint64 segment_out; /* in-segment counting */ + guint64 out_frame_count; /* number of frames output since the beginning + * of the segment or the last frame rate caps + * change, whichever was later */ + guint64 base_ts; /* used in next_ts calculation after a + * frame rate caps change */ gboolean discont; guint64 last_ts; /* Timestamp of last input buffer */ -- 2.7.4