mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
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.
This commit is contained in:
parent
fce99dc0be
commit
2c1bf82d55
2 changed files with 24 additions and 7 deletions
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue