diff options
author | Thiago Santos <thiagoss@osg.samsung.com> | 2015-06-02 10:33:05 -0300 |
---|---|---|
committer | Thiago Santos <thiagoss@osg.samsung.com> | 2015-06-08 11:05:01 -0300 |
commit | 67fdc1056ffc6a7a127287cca89ef47529d791ff (patch) | |
tree | 5bc29ae35617ce54fec2e06b663d5776b6a194c2 | |
parent | c27766976abfd80bf4afbeb78492baf9ad107ba2 (diff) |
basemixer: rework basemixer buffer preparation
Store a buffer at the pad and keep the relevant timestamping info
around to avoid always recalculating it.
-rw-r--r-- | gst-libs/gst/base/gstbasemixer.c | 205 | ||||
-rw-r--r-- | gst-libs/gst/base/gstbasemixer.h | 6 | ||||
-rw-r--r-- | tests/check/libs/basemixer.c | 14 |
3 files changed, 112 insertions, 113 deletions
diff --git a/gst-libs/gst/base/gstbasemixer.c b/gst-libs/gst/base/gstbasemixer.c index ec96aa4a2..d7b2e4652 100644 --- a/gst-libs/gst/base/gstbasemixer.c +++ b/gst-libs/gst/base/gstbasemixer.c @@ -39,7 +39,6 @@ typedef struct _GstBaseMixerTimeAlignment GstClockTime end; } GstBaseMixerTimeAlignment; - struct _GstBaseMixerPadPrivate { GstClockTime offset; @@ -65,117 +64,90 @@ gst_base_mixer_pad_init (GstBaseMixerPad * pad) GstBaseMixerPadPrivate); } -static gboolean -gst_base_mixer_pad_get_times_for_buffer (GstBaseMixerPad * mixerpad, - GstBuffer * buf, GstClockTime * start, GstClockTime * end) +gboolean +gst_base_mixer_pad_is_eos (GstBaseMixerPad * mixerpad) { - *start = GST_CLOCK_TIME_NONE; - *end = GST_CLOCK_TIME_NONE; - - if (GST_BUFFER_PTS_IS_VALID (buf)) { - GstSegment *segment; - GstClockTime ts, ts_end, c_ts, c_ts_end; - - segment = &GST_AGGREGATOR_PAD_CAST (mixerpad)->segment; - - ts = GST_BUFFER_PTS (buf); - if (GST_BUFFER_DURATION_IS_VALID (buf)) - ts_end = ts + GST_BUFFER_DURATION (buf); - else - ts_end = GST_CLOCK_TIME_NONE; - - ts += mixerpad->priv->offset; - - if (!gst_segment_clip (segment, GST_FORMAT_TIME, ts, ts_end, &c_ts, - &c_ts_end)) - return FALSE; + return gst_aggregator_pad_is_eos (GST_AGGREGATOR_PAD_CAST (mixerpad)) + && mixerpad->buffer == NULL; +} - *start = gst_segment_to_running_time (segment, GST_FORMAT_TIME, c_ts); - if (GST_CLOCK_TIME_IS_VALID (c_ts_end)) - *end = gst_segment_to_running_time (segment, GST_FORMAT_TIME, c_ts_end); - } - GST_DEBUG_OBJECT (mixerpad, - "Pad has times: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, - GST_TIME_ARGS (*start), GST_TIME_ARGS (*end)); - return TRUE; +static void +gst_base_mixer_pad_drop_buffer (GstBaseMixerPad * mixerpad) +{ + mixerpad->priv->offset = 0; + gst_buffer_unref (mixerpad->buffer); + mixerpad->buffer = NULL; } static gboolean gst_base_mixer_pad_get_times (GstBaseMixerPad * mixerpad, GstClockTime * start, GstClockTime * end) { - GstBuffer *buf; - - buf = gst_aggregator_pad_get_buffer (GST_AGGREGATOR_PAD_CAST (mixerpad)); - if (buf) { - gst_base_mixer_pad_get_times_for_buffer (mixerpad, buf, start, end); - gst_buffer_unref (buf); - return TRUE; - } + if (!mixerpad->buffer) + return FALSE; - return FALSE; + *start = mixerpad->buffer_start_ts + mixerpad->priv->offset; + *end = mixerpad->buffer_end_ts; + GST_DEBUG_OBJECT (mixerpad, + "Pad has times: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, + GST_TIME_ARGS (*start), GST_TIME_ARGS (*end)); + return TRUE; } static GstClockTime gst_base_mixer_pad_get_duration_within_times (GstBaseMixerPad * mixerpad, - GstBuffer * buffer, GstClockTime start, GstClockTime end) + GstClockTime start, GstClockTime end) { - GstClockTime buf_start = GST_CLOCK_TIME_NONE, buf_end = GST_CLOCK_TIME_NONE; + GstClockTime buf_start, buf_end; - if (buffer) { - gst_base_mixer_pad_get_times_for_buffer (mixerpad, buffer, &buf_start, - &buf_end); + gst_base_mixer_pad_get_times (mixerpad, &buf_start, &buf_end); - /* we are advancing a time before our own buffer. Nothing to advance for us */ - if (end <= buf_start) { - GST_LOG_OBJECT (mixerpad, "Our buffer is ahead of the current mix time." - " No advancing needed"); - return 0; - } - - /* TODO verify if this is possible, and likely add unit tests for it */ - if (buf_end <= start) { - GST_LOG_OBJECT (mixerpad, "Our buffer is behind the mixing time, " - "advance it all"); - return buf_end - buf_start; - } + /* we are advancing a time before our own buffer. Nothing to advance for us */ + if (end <= buf_start) { + GST_LOG_OBJECT (mixerpad, "Our buffer is ahead of the current mix time." + " No advancing needed"); + return 0; + } - return MIN (end, buf_end) - buf_start; + /* TODO verify if this is possible, and likely add unit tests for it */ + if (buf_end <= start) { + GST_LOG_OBJECT (mixerpad, "Our buffer is behind the mixing time, " + "advance it all"); + return buf_end - buf_start; } - return 0; + return MIN (end, buf_end) - buf_start; } static void gst_base_mixer_pad_advance (GstBaseMixerPad * mixerpad, GstClockTime start, GstClockTime end) { - GstBuffer *buffer; GstClockTime duration = 0; GST_LOG_OBJECT (mixerpad, "Advancing: %" GST_TIME_FORMAT "- %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end)); - buffer = gst_aggregator_pad_get_buffer (GST_AGGREGATOR_PAD_CAST (mixerpad)); + if (!mixerpad->buffer) { + GST_DEBUG_OBJECT (mixerpad, "Has no buffer, no advance needed"); + return; + } + duration = - gst_base_mixer_pad_get_duration_within_times (mixerpad, buffer, start, - end); + gst_base_mixer_pad_get_duration_within_times (mixerpad, start, end); GST_DEBUG_OBJECT (mixerpad, "Advancing duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (duration)); - if (buffer) { - mixerpad->priv->offset += duration; - if (GST_BUFFER_DURATION_IS_VALID (buffer)) { - - g_assert (mixerpad->priv->clipped_duration >= mixerpad->priv->offset); - - /* It should never be smaller but let's leave it here for safety */ - if (mixerpad->priv->clipped_duration <= mixerpad->priv->offset) { - gst_aggregator_pad_drop_buffer (GST_AGGREGATOR_PAD_CAST (mixerpad)); - mixerpad->priv->offset = 0; - } + mixerpad->priv->offset += duration; + if (GST_CLOCK_TIME_IS_VALID (mixerpad->buffer_end_ts)) { + g_assert (mixerpad->buffer_end_ts >= + mixerpad->buffer_start_ts + mixerpad->priv->offset); + + /* It should never be smaller but let's leave it here for safety */ + if (mixerpad->buffer_end_ts <= + mixerpad->buffer_start_ts + mixerpad->priv->offset) { + gst_base_mixer_pad_drop_buffer (mixerpad); } - gst_buffer_unref (buffer); } } @@ -189,7 +161,7 @@ static GstElementClass *base_mixer_parent_class = NULL; struct _GstBaseMixerPrivate { - gint non_empty; + GstFlowReturn prepare_result; }; static gboolean @@ -302,56 +274,80 @@ gst_base_mixer_mix (GstBaseMixer * bmixer, GstClockTime start, GstClockTime end) } static gboolean -gst_base_mixer_pad_prepare_buffer_foreach (GstAggregator * agg, +gst_base_mixer_pad_prepare (GstAggregator * agg, GstAggregatorPad * aggpad, gpointer udata) { + GstBaseMixer *bmixer = GST_BASE_MIXER_CAST (agg); GstBaseMixerPad *mixerpad = GST_BASE_MIXER_PAD_CAST (aggpad); - GstBuffer *buf; - gboolean ret = TRUE; + gboolean timeout = GPOINTER_TO_INT (udata); + +restart: + /* Get a new buffer if needed */ + if (!mixerpad->buffer) { + + mixerpad->buffer = gst_aggregator_pad_steal_buffer (aggpad); + if (!mixerpad->buffer) { + if (timeout || gst_aggregator_pad_is_eos (aggpad)) + return TRUE; + bmixer->priv->prepare_result = GST_FLOW_NOT_HANDLED; + return FALSE; + } - /* FIXME clipped_duration is being recalculated at every iteration */ - mixerpad->priv->clipped_duration = GST_CLOCK_TIME_NONE; + if (!GST_BUFFER_PTS_IS_VALID (mixerpad->buffer)) { + GST_WARNING_OBJECT (aggpad, "Need timestamped buffers"); + bmixer->priv->prepare_result = GST_FLOW_ERROR; + return FALSE; + } - buf = gst_aggregator_pad_get_buffer (aggpad); - if (!buf) - return TRUE; + mixerpad->buffer_start_ts = GST_CLOCK_TIME_NONE; + mixerpad->buffer_end_ts = GST_CLOCK_TIME_NONE; + } - if (GST_BUFFER_PTS_IS_VALID (buf)) { + if (!GST_CLOCK_TIME_IS_VALID (mixerpad->buffer_start_ts)) { + GstClockTime ts, ts_end, c_ts, c_ts_end, dur; GstSegment *segment; - GstClockTime ts, ts_end, c_ts, c_ts_end; segment = &aggpad->segment; + ts = GST_BUFFER_PTS (mixerpad->buffer); + dur = GST_BUFFER_DURATION (mixerpad->buffer); - ts = GST_BUFFER_PTS (buf); - if (GST_BUFFER_DURATION_IS_VALID (buf)) - ts_end = ts + GST_BUFFER_DURATION (buf); + if (GST_CLOCK_TIME_IS_VALID (dur)) + ts_end = ts + dur; else ts_end = GST_CLOCK_TIME_NONE; - ts += mixerpad->priv->offset; - if (!gst_segment_clip (segment, GST_FORMAT_TIME, ts, ts_end, &c_ts, &c_ts_end)) { GST_DEBUG_OBJECT (aggpad, "Buffer is out of segment, dropping"); - gst_aggregator_pad_drop_buffer (aggpad); - ret = FALSE; + gst_base_mixer_pad_drop_buffer (mixerpad); + goto restart; } - mixerpad->priv->clipped_duration = c_ts_end - c_ts; + + mixerpad->buffer_start_ts = gst_segment_to_running_time (segment, + GST_FORMAT_TIME, c_ts); + if (GST_CLOCK_TIME_IS_VALID (c_ts_end)) + mixerpad->buffer_end_ts = gst_segment_to_running_time (segment, + GST_FORMAT_TIME, c_ts_end); } - gst_buffer_unref (buf); - return ret; + + return TRUE; } +/* Make sure we have a buffer on each pad (if not timeout). + * For each pad with a buffer get the start and end time of + * the buffers */ static GstFlowReturn gst_base_mixer_prepare (GstBaseMixer * bmixer, gboolean timeout) { GstBaseMixerClass *bmixer_class = GST_BASE_MIXER_GET_CLASS (bmixer); - /* FIXME move this into the 'find_time_alignment' to avoid yet - * another pad loop */ - if (!gst_aggregator_iterate_sinkpads (GST_AGGREGATOR_CAST (bmixer), - gst_base_mixer_pad_prepare_buffer_foreach, NULL)) - return GST_FLOW_NOT_HANDLED; + bmixer->priv->prepare_result = GST_FLOW_OK; + + gst_aggregator_iterate_sinkpads (GST_AGGREGATOR_CAST (bmixer), + gst_base_mixer_pad_prepare, GINT_TO_POINTER (timeout)); + if (bmixer->priv->prepare_result != GST_FLOW_OK) { + return bmixer->priv->prepare_result; + } if (bmixer_class->prepare) return bmixer_class->prepare (bmixer, timeout); @@ -384,7 +380,6 @@ gst_base_mixer_aggregate (GstAggregator * agg, gboolean timeout) ret = gst_base_mixer_prepare (bmixer, timeout); if (ret != GST_FLOW_OK) { - /* means we have to try again */ if (ret == GST_FLOW_NOT_HANDLED) ret = GST_FLOW_OK; @@ -423,7 +418,7 @@ gst_base_mixer_check_eos_foreach (GstAggregator * agg, { gboolean *ret = udata; - if (!gst_aggregator_pad_is_eos (aggpad)) { + if (!gst_base_mixer_pad_is_eos (GST_BASE_MIXER_PAD_CAST (aggpad))) { *ret = FALSE; return FALSE; } diff --git a/gst-libs/gst/base/gstbasemixer.h b/gst-libs/gst/base/gstbasemixer.h index 6ed354847..88c99302e 100644 --- a/gst-libs/gst/base/gstbasemixer.h +++ b/gst-libs/gst/base/gstbasemixer.h @@ -70,6 +70,10 @@ struct _GstBaseMixerPad { GstAggregatorPad parent; + GstBuffer * buffer; + GstClockTime buffer_start_ts; + GstClockTime buffer_end_ts; + /* < Private > */ GstBaseMixerPadPrivate * priv; @@ -100,6 +104,8 @@ GType gst_base_mixer_pad_get_type (void); * GstBaseMixerPad methods * ***************************/ +gboolean gst_base_mixer_pad_is_eos (GstBaseMixerPad * mixerpad); + /********************* * GstBaseMixer API * ********************/ diff --git a/tests/check/libs/basemixer.c b/tests/check/libs/basemixer.c index cc1a6ba58..cb29aa952 100644 --- a/tests/check/libs/basemixer.c +++ b/tests/check/libs/basemixer.c @@ -75,21 +75,19 @@ gst_test_sum_mixer_mix (GstBaseMixer * bmixer, GstClockTime start, iter = gst_element_iterate_sink_pads (GST_ELEMENT (bmixer)); while (!done_iterating) { GValue value = { 0, }; - GstAggregatorPad *pad; + GstBaseMixerPad *mixerpad; switch (gst_iterator_next (iter, &value)) { case GST_ITERATOR_OK: - pad = g_value_get_object (&value); - buf = gst_aggregator_pad_get_buffer (pad); + mixerpad = g_value_get_object (&value); - if (buf) { - gst_buffer_map (buf, &mapinfo, GST_MAP_READ); + if (mixerpad->buffer) { + gst_buffer_map (mixerpad->buffer, &mapinfo, GST_MAP_READ); sum += mapinfo.data[0]; - gst_buffer_unmap (buf, &mapinfo); - gst_buffer_unref (buf); + gst_buffer_unmap (mixerpad->buffer, &mapinfo); } - if (gst_aggregator_pad_is_eos (pad) == FALSE) + if (gst_base_mixer_pad_is_eos (mixerpad) == FALSE) all_eos = FALSE; g_value_reset (&value); |