Commit 2c1bf82d authored by Robert Swain's avatar Robert Swain

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.
parent fce99dc0
......@@ -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);
......
......@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment