/* 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);
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;
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");
*/
static GstFlowReturn
gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
- gpointer obj)
+ gpointer obj, gboolean is_list)
{
GstBaseSinkClass *bclass;
GstBaseSinkPrivate *priv = basesink->priv;
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 {
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;
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));
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));
/* 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;
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:
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
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;
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;
}
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;
* 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
/* 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);