basesink: add prepare method

Add a prepare method that is called before sync happens. The purpose of this
method is to prepare the rendering of the giving buffer so that the following
render() call after sync is a quick as possible.
This commit is contained in:
Wim Taymans 2012-05-16 12:08:44 +02:00
parent d6e909994c
commit 602bd29960
2 changed files with 54 additions and 13 deletions

View file

@ -2003,8 +2003,8 @@ gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
/* FIXME: Casting to GstClockEntry only works because the types
* are the same */
if (G_LIKELY (sink->priv->cached_clock_id != NULL
&& GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->priv->
cached_clock_id) == clock)) {
&& GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->
priv->cached_clock_id) == clock)) {
if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id,
time)) {
gst_clock_id_unref (sink->priv->cached_clock_id);
@ -2148,6 +2148,11 @@ gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
bclass = GST_BASE_SINK_GET_CLASS (sink);
if (bclass->prepare)
if ((ret = bclass->prepare (sink, buf)) != GST_FLOW_OK)
goto prepare_canceled;
if (bclass->preroll)
if ((ret = bclass->preroll (sink, buf)) != GST_FLOW_OK)
goto preroll_canceled;
@ -2174,6 +2179,12 @@ gst_base_sink_do_preroll (GstBaseSink * sink, GstMiniObject * obj)
return GST_FLOW_OK;
/* ERRORS */
prepare_canceled:
{
GST_DEBUG_OBJECT (sink, "prepare failed, abort state");
gst_element_abort_state (GST_ELEMENT_CAST (sink));
return ret;
}
preroll_canceled:
{
GST_DEBUG_OBJECT (sink, "preroll failed, abort state");
@ -3068,7 +3079,7 @@ gst_base_sink_needs_preroll (GstBaseSink * basesink)
*/
static GstFlowReturn
gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
gpointer obj)
gpointer obj, gboolean is_list)
{
GstBaseSinkClass *bclass;
GstBaseSinkPrivate *priv = basesink->priv;
@ -3085,7 +3096,7 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
if (G_UNLIKELY (priv->received_eos))
goto was_eos;
if (GST_IS_BUFFER_LIST (obj)) {
if (is_list) {
sync_buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (obj), 0);
g_assert (NULL != sync_buf);
} else {
@ -3138,6 +3149,20 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
goto out_of_segment;
}
if (!is_list) {
if (bclass->prepare) {
ret = bclass->prepare (basesink, GST_BUFFER_CAST (obj));
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto prepare_failed;
}
} else {
if (bclass->prepare_list) {
ret = bclass->prepare_list (basesink, GST_BUFFER_LIST_CAST (obj));
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto prepare_failed;
}
}
again:
late = FALSE;
step_end = FALSE;
@ -3162,7 +3187,7 @@ again:
if (do_qos)
gst_base_sink_do_render_stats (basesink, TRUE);
if (!GST_IS_BUFFER_LIST (obj)) {
if (!is_list) {
/* For buffer lists do not set last buffer for now. */
gst_base_sink_set_last_buffer (basesink, GST_BUFFER_CAST (obj));
@ -3219,6 +3244,13 @@ out_of_segment:
gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
return GST_FLOW_OK;
}
prepare_failed:
{
GST_DEBUG_OBJECT (basesink, "prepare buffer failed %s",
gst_flow_get_name (ret));
gst_mini_object_unref (GST_MINI_OBJECT_CAST (obj));
return ret;
}
sync_failed:
{
GST_DEBUG_OBJECT (basesink, "do_sync returned %s", gst_flow_get_name (ret));
@ -3262,7 +3294,8 @@ dropped:
/* with STREAM_LOCK
*/
static GstFlowReturn
gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad, gpointer obj)
gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad, gpointer obj,
gboolean is_list)
{
GstFlowReturn result;
@ -3270,7 +3303,7 @@ gst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad, gpointer obj)
goto wrong_mode;
GST_BASE_SINK_PREROLL_LOCK (basesink);
result = gst_base_sink_chain_unlocked (basesink, pad, obj);
result = gst_base_sink_chain_unlocked (basesink, pad, obj, is_list);
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
done:
@ -3299,7 +3332,7 @@ gst_base_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
basesink = GST_BASE_SINK (parent);
return gst_base_sink_chain_main (basesink, pad, buf);
return gst_base_sink_chain_main (basesink, pad, buf, FALSE);
}
static GstFlowReturn
@ -3314,7 +3347,7 @@ gst_base_sink_chain_list (GstPad * pad, GstObject * parent,
bclass = GST_BASE_SINK_GET_CLASS (basesink);
if (G_LIKELY (bclass->render_list)) {
result = gst_base_sink_chain_main (basesink, pad, list);
result = gst_base_sink_chain_main (basesink, pad, list, TRUE);
} else {
guint i, len;
GstBuffer *buffer;
@ -3327,7 +3360,7 @@ gst_base_sink_chain_list (GstPad * pad, GstObject * parent,
for (i = 0; i < len; i++) {
buffer = gst_buffer_list_get (list, i);
result = gst_base_sink_chain_main (basesink, pad,
gst_buffer_ref (buffer));
gst_buffer_ref (buffer), FALSE);
if (result != GST_FLOW_OK)
break;
}
@ -3672,7 +3705,7 @@ gst_base_sink_loop (GstPad * pad)
basesink->segment.position = offset;
GST_BASE_SINK_PREROLL_LOCK (basesink);
result = gst_base_sink_chain_unlocked (basesink, pad, buf);
result = gst_base_sink_chain_unlocked (basesink, pad, buf, FALSE);
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
if (G_UNLIKELY (result != GST_FLOW_OK))
goto paused;

View file

@ -125,15 +125,19 @@ struct _GstBaseSink {
* unblock any blocked function ASAP
* @unlock_stop: Clear the previous unlock request. Subclasses should clear
* any state they set during unlock(), such as clearing command queues.
* @query: perform a #GstQuery on the element. Since: 0.10.36
* @event: Override this to handle events arriving on the sink pad
* @wait_eos: Override this to implement custom logic to wait for the EOS time.
* subclasses should always first chain up to the default implementation.
* @preroll: Called to present the preroll buffer if desired
* @prepare: Called to prepare the buffer for @render and @preroll. This
* function is called before synchronisation is performed.
* @prepare_list: Called to prepare the buffer list for @render_list. This
* function is called before synchronisation is performed.
* @preroll: Called to present the preroll buffer if desired.
* @render: Called when a buffer should be presented or output, at the
* correct moment if the #GstBaseSink has been set to sync to the clock.
* @render_list: Same as @render but used whith buffer lists instead of
* buffers. Since: 0.10.24
* @query: perform a #GstQuery on the element. Since: 0.10.36
*
* Subclasses can override any of the available virtual methods or not, as
* needed. At the minimum, the @render method should be overridden to
@ -179,6 +183,10 @@ struct _GstBaseSinkClass {
/* wait for eos, subclasses should chain up to parent first */
GstFlowReturn (*wait_eos) (GstBaseSink *sink, GstEvent *event);
/* notify subclass of buffer or list before doing sync */
GstFlowReturn (*prepare) (GstBaseSink *sink, GstBuffer *buffer);
GstFlowReturn (*prepare_list) (GstBaseSink *sink, GstBufferList *buffer_list);
/* notify subclass of preroll buffer or real buffer */
GstFlowReturn (*preroll) (GstBaseSink *sink, GstBuffer *buffer);
GstFlowReturn (*render) (GstBaseSink *sink, GstBuffer *buffer);