From 956c9f32a331ad4b7a4cfe6fb9d0ee7f390186dd Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 30 Apr 2009 16:37:38 +0200 Subject: [PATCH] videorate: handle invalid timestamps better Handle buffers with -1 timestamps better by keeping track of the en time of the previous buffer and assuming the -1 timestamp buffer goes right after the previous one. when we have two buffers that are equally good, output the oldest buffer once to minimize latency. don't try to calculate latency when the input framerate is unknown. --- gst/videorate/gstvideorate.c | 40 +++++++++++++++++++++++++++--------- gst/videorate/gstvideorate.h | 1 + 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/gst/videorate/gstvideorate.c b/gst/videorate/gstvideorate.c index 7de2bb9d42..1a8769f371 100644 --- a/gst/videorate/gstvideorate.c +++ b/gst/videorate/gstvideorate.c @@ -268,6 +268,7 @@ gst_video_rate_setcaps (GstPad * pad, GstCaps * caps) videorate->from_rate_denominator = rate_denominator; otherpad = videorate->srcpad; } + /* now try to find something for the peer */ opeer = gst_pad_get_peer (otherpad); if (opeer) { @@ -358,6 +359,7 @@ gst_video_rate_reset (GstVideoRate * videorate) videorate->drop = 0; videorate->dup = 0; videorate->next_ts = GST_CLOCK_TIME_NONE; + videorate->last_ts = GST_CLOCK_TIME_NONE; videorate->discont = TRUE; gst_video_rate_swap_prev (videorate, NULL, 0); @@ -584,11 +586,17 @@ gst_video_rate_query (GstPad * pad, GstQuery * query) GST_TIME_FORMAT " max %" GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); - /* add latency. We don't really know since we hold on to the frames - * until we get a next frame, which can be anything. We assume - * however that this will take from_rate time. */ - latency = gst_util_uint64_scale (GST_SECOND, - videorate->from_rate_denominator, videorate->from_rate_numerator); + if (videorate->from_rate_numerator != 0) { + /* add latency. We don't really know since we hold on to the frames + * until we get a next frame, which can be anything. We assume + * however that this will take from_rate time. */ + latency = gst_util_uint64_scale (GST_SECOND, + videorate->from_rate_denominator, + videorate->from_rate_numerator); + } else { + /* no input framerate, we don't know */ + latency = 0; + } GST_DEBUG_OBJECT (videorate, "Our latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); @@ -621,7 +629,7 @@ gst_video_rate_chain (GstPad * pad, GstBuffer * buffer) { GstVideoRate *videorate; GstFlowReturn res = GST_FLOW_OK; - GstClockTime intime, in_ts; + GstClockTime intime, in_ts, in_dur; videorate = GST_VIDEO_RATE (GST_PAD_PARENT (pad)); @@ -631,9 +639,19 @@ gst_video_rate_chain (GstPad * pad, GstBuffer * buffer) goto not_negotiated; in_ts = GST_BUFFER_TIMESTAMP (buffer); + in_dur = GST_BUFFER_DURATION (buffer); - if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE)) - goto invalid_buffer; + if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE)) { + in_ts = videorate->last_ts; + if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE)) + goto invalid_buffer; + } + + /* get the time of the next expected buffer timestamp, we use this when the + * next buffer has -1 as a timestamp */ + videorate->last_ts = in_ts; + if (in_dur != GST_CLOCK_TIME_NONE) + videorate->last_ts += in_dur; GST_DEBUG_OBJECT (videorate, "got buffer with timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (in_ts)); @@ -698,7 +716,7 @@ gst_video_rate_chain (GstPad * pad, GstBuffer * buffer) GST_TIME_ARGS (videorate->next_ts)); /* output first one when its the best */ - if (diff1 < diff2) { + if (diff1 <= diff2) { count++; /* on error the _flush function posted a warning already */ @@ -707,7 +725,8 @@ gst_video_rate_chain (GstPad * pad, GstBuffer * buffer) goto done; } } - /* continue while the first one was the best */ + /* continue while the first one was the best, if they were equal avoid + * going into an infinite loop */ } while (diff1 < diff2); @@ -820,6 +839,7 @@ gst_video_rate_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: videorate->discont = TRUE; + videorate->last_ts = -1; break; default: break; diff --git a/gst/videorate/gstvideorate.h b/gst/videorate/gstvideorate.h index fe7feb62ab..2a2d7e32e4 100644 --- a/gst/videorate/gstvideorate.h +++ b/gst/videorate/gstvideorate.h @@ -57,6 +57,7 @@ struct _GstVideoRate guint64 prev_ts; /* Previous buffer timestamp */ guint64 segment_out; /* in-segment counting */ gboolean discont; + guint64 last_ts; /* Timestamp of last input buffer */ /* segment handling */ GstSegment segment;