#include <gst/gst_private.h>
#include "gstbasesink.h"
-#include <gst/gstmarshal.h>
#include <gst/gst-i18n-lib.h>
GST_DEBUG_CATEGORY_STATIC (gst_base_sink_debug);
/* for throttling and QoS */
GstClockTime earliest_in_time;
GstClockTime throttle_time;
-
- gboolean reset_time;
};
#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size))
GstQuery * query);
static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink);
-static void gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps);
-static void gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
+static GstCaps *gst_base_sink_default_fixate (GstBaseSink * bsink,
+ GstCaps * caps);
+static GstCaps *gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
/* check if an object was too late */
static gboolean gst_base_sink_is_too_late (GstBaseSink * basesink,
*/
g_object_class_install_property (gobject_class, PROP_THROTTLE_TIME,
g_param_spec_uint64 ("throttle-time", "Throttle time",
- "The time to keep between rendered buffers (unused)", 0, G_MAXUINT64,
+ "The time to keep between rendered buffers", 0, G_MAXUINT64,
DEFAULT_THROTTLE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state =
return caps;
}
-static void
+static GstCaps *
gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps)
{
GST_DEBUG_OBJECT (bsink, "using default caps fixate function");
- gst_caps_fixate (caps);
+ return gst_caps_fixate (caps);
}
-static void
+static GstCaps *
gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps)
{
GstBaseSinkClass *bclass;
bclass = GST_BASE_SINK_GET_CLASS (bsink);
if (bclass->fixate)
- bclass->fixate (bsink, caps);
+ caps = bclass->fixate (bsink, caps);
+
+ return caps;
}
static void
gboolean post_paused = FALSE;
gboolean post_async_done = FALSE;
gboolean post_playing = FALSE;
- gboolean reset_time;
/* we are certainly not playing async anymore now */
basesink->playing_async = FALSE;
next = GST_STATE_NEXT (basesink);
pending = GST_STATE_PENDING (basesink);
post_pending = pending;
- reset_time = basesink->priv->reset_time;
- basesink->priv->reset_time = FALSE;
switch (pending) {
case GST_STATE_PLAYING:
if (post_async_done) {
GST_DEBUG_OBJECT (basesink, "posting async-done message");
gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_done (GST_OBJECT_CAST (basesink), reset_time));
+ gst_message_new_async_done (GST_OBJECT_CAST (basesink), FALSE));
}
if (post_playing) {
GST_DEBUG_OBJECT (basesink, "posting PLAYING state change message");
/* 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");
gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
}
}
- basesink->priv->reset_time = reset_time;
GST_OBJECT_UNLOCK (basesink);
+
+ if (reset_time) {
+ GST_DEBUG_OBJECT (basesink, "posting reset-time message");
+ gst_element_post_message (GST_ELEMENT_CAST (basesink),
+ gst_message_new_reset_time (GST_OBJECT_CAST (basesink), 0));
+ }
}
static GstFlowReturn
*/
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;
pull() without setcaps() */
result = TRUE;
} else {
- caps = gst_caps_make_writable (caps);
/* try to fixate */
- gst_base_sink_fixate (basesink, caps);
+ caps = gst_base_sink_fixate (basesink, caps);
GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps);
if (gst_caps_is_fixed (caps)) {
- if (!gst_pad_send_event (GST_BASE_SINK_PAD (basesink),
- gst_event_new_caps (caps)))
+ if (!gst_pad_set_caps (GST_BASE_SINK_PAD (basesink), caps))
goto could_not_set_caps;
result = TRUE;
gst_query_parse_accept_caps (query, &caps);
allowed = gst_base_sink_query_caps (basesink, basesink->sinkpad, NULL);
subset = gst_caps_is_subset (caps, allowed);
+ gst_caps_unref (allowed);
gst_query_set_accept_caps_result (query, subset);
res = TRUE;
break;
}
+ case GST_QUERY_DRAIN:
+ res = TRUE;
+ break;
default:
res =
gst_pad_query_default (basesink->sinkpad, GST_OBJECT_CAST (basesink),
priv->step_unlock = FALSE;
basesink->need_preroll = TRUE;
basesink->playing_async = TRUE;
- basesink->priv->reset_time = FALSE;
priv->current_sstart = GST_CLOCK_TIME_NONE;
priv->current_sstop = GST_CLOCK_TIME_NONE;
priv->eos_rtime = GST_CLOCK_TIME_NONE;