/* if we already commited the state */
gboolean commited;
+ /* state change to playing ongoing */
+ gboolean to_playing;
/* when we received EOS */
gboolean received_eos;
/* 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))
static gboolean gst_base_sink_send_event (GstElement * element,
GstEvent * event);
-static gboolean gst_base_sink_query (GstElement * element, GstQuery * query);
+static gboolean default_element_query (GstElement * element, GstQuery * query);
static const GstQueryType *gst_base_sink_get_query_types (GstElement * element);
static GstCaps *gst_base_sink_get_caps (GstBaseSink * sink, GstCaps * caps);
static GstStateChangeReturn gst_base_sink_change_state (GstElement * element,
GstStateChange transition);
+static gboolean gst_base_sink_sink_query (GstPad * pad, GstQuery * query);
static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
static GstFlowReturn gst_base_sink_chain_list (GstPad * pad,
GstBufferList * list);
static gboolean gst_base_sink_pad_activate_pull (GstPad * pad, gboolean active);
static gboolean gst_base_sink_event (GstPad * pad, GstEvent * event);
+static gboolean default_sink_query (GstBaseSink * sink, GstQuery * query);
+
static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink);
static GstCaps *gst_base_sink_pad_getcaps (GstPad * pad, GstCaps * filter);
static void gst_base_sink_pad_fixate (GstPad * pad, GstCaps * caps);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_base_sink_change_state);
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_sink_send_event);
- gstelement_class->query = GST_DEBUG_FUNCPTR (gst_base_sink_query);
+ gstelement_class->query = GST_DEBUG_FUNCPTR (default_element_query);
gstelement_class->get_query_types =
GST_DEBUG_FUNCPTR (gst_base_sink_get_query_types);
klass->get_times = GST_DEBUG_FUNCPTR (gst_base_sink_get_times);
klass->activate_pull =
GST_DEBUG_FUNCPTR (gst_base_sink_default_activate_pull);
+ klass->query = GST_DEBUG_FUNCPTR (default_sink_query);
/* Registering debug symbols for function pointers */
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_getcaps);
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass),
"sink");
if (pad_template != NULL) {
- caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
+ caps = gst_pad_template_get_caps (pad_template);
if (filter) {
GstCaps *intersection;
gst_base_sink_pad_activate_push);
gst_pad_set_activatepull_function (basesink->sinkpad,
gst_base_sink_pad_activate_pull);
+ gst_pad_set_query_function (basesink->sinkpad, gst_base_sink_sink_query);
gst_pad_set_event_function (basesink->sinkpad, gst_base_sink_event);
gst_pad_set_chain_function (basesink->sinkpad, gst_base_sink_chain);
gst_pad_set_chain_list_function (basesink->sinkpad, gst_base_sink_chain_list);
basesink->preroll_lock = g_mutex_new ();
basesink->preroll_cond = g_cond_new ();
basesink->preroll_queue = g_queue_new ();
- basesink->clip_segment = gst_segment_new ();
priv->have_latency = FALSE;
basesink->can_activate_push = DEFAULT_CAN_ACTIVATE_PUSH;
g_mutex_free (basesink->preroll_lock);
g_cond_free (basesink->preroll_cond);
g_queue_free (basesink->preroll_queue);
- gst_segment_free (basesink->clip_segment);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
GST_OBJECT_LOCK (basesink);
/* the newsegment event is needed to bring the buffer timestamps to the
* stream time and to drop samples outside of the playback segment. */
- gst_event_parse_segment (event, segment);
+ gst_event_copy_segment (event, segment);
GST_DEBUG_OBJECT (basesink, "configured SEGMENT %" GST_SEGMENT_FORMAT,
segment);
GST_OBJECT_UNLOCK (basesink);
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:
{
- GstBaseSinkClass *bclass;
-
- bclass = GST_BASE_SINK_GET_CLASS (basesink);
-
GST_DEBUG_OBJECT (basesink, "commiting state to PLAYING");
basesink->need_preroll = FALSE;
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)));
+ gst_message_new_async_done (GST_OBJECT_CAST (basesink), reset_time));
}
if (post_playing) {
GST_DEBUG_OBJECT (basesink, "posting PLAYING state change message");
segment->start = current->start_start;
/* the clip segment is used for position report in paused... */
- gst_segment_copy_into (segment, sink->clip_segment);
+ gst_segment_copy_into (segment, &sink->clip_segment);
/* post the step done when we know the stepped duration in TIME */
message =
time += base_time;
/* Re-use existing clockid if available */
- if (G_LIKELY (sink->priv->cached_clock_id != NULL)) {
+ /* 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)) {
if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id,
time)) {
gst_clock_id_unref (sink->priv->cached_clock_id);
sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time);
}
- } else
+ } else {
+ if (sink->priv->cached_clock_id != NULL)
+ gst_clock_id_unref (sink->priv->cached_clock_id);
sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time);
+ }
GST_OBJECT_UNLOCK (sink);
/* A blocking wait is performed on the clock. We save the ClockID
gst_base_sink_configure_segment (basesink, pad, event,
&basesink->segment);
break;
- case GST_EVENT_SINK_MESSAGE:{
+ case GST_EVENT_TAG:
+ {
+ GstTagList *taglist;
+
+ gst_event_parse_tag (event, &taglist);
+
+ gst_element_post_message (GST_ELEMENT_CAST (basesink),
+ gst_message_new_tag (GST_OBJECT_CAST (basesink),
+ gst_tag_list_copy (taglist)));
+ break;
+ }
+ case GST_EVENT_SINK_MESSAGE:
+ {
GstMessage *msg = NULL;
gst_event_parse_sink_message (event, &msg);
*
* Queue an object for rendering.
* The first prerollable object queued will complete the preroll. If the
- * preroll queue if filled, we render all the objects in the queue.
+ * preroll queue is filled, we render all the objects in the queue.
*
* This function takes ownership of the object.
*/
* prerolled buffer */
basesink->playing_async = TRUE;
if (basesink->priv->async_enabled) {
- gst_element_lost_state (GST_ELEMENT_CAST (basesink), TRUE);
+ gst_element_lost_state (GST_ELEMENT_CAST (basesink));
} else {
+ /* start time reset in above case as well;
+ * arranges for a.o. proper position reporting when flushing in PAUSED */
+ gst_element_set_start_time (GST_ELEMENT_CAST (basesink), 0);
basesink->priv->have_latency = TRUE;
}
gst_base_sink_set_last_buffer (basesink, NULL);
}
static void
-gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad)
+gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad,
+ gboolean reset_time)
{
/* unset flushing so we can accept new data, this also flushes out any EOS
* event. */
if (basesink->pad_mode == GST_ACTIVATE_PUSH) {
/* we need new segment info after the flush. */
basesink->have_newsegment = FALSE;
- gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
- gst_segment_init (basesink->clip_segment, GST_FORMAT_UNDEFINED);
+ if (reset_time) {
+ gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
+ gst_segment_init (&basesink->clip_segment, GST_FORMAT_UNDEFINED);
+ }
}
+ basesink->priv->reset_time = reset_time;
GST_OBJECT_UNLOCK (basesink);
}
if (G_UNLIKELY (basesink->flushing))
goto flushing;
- if (G_UNLIKELY (basesink->priv->received_eos)) {
- /* we can't accept anything when we are EOS */
+ if (G_UNLIKELY (basesink->priv->received_eos))
+ goto after_eos;
+
+ /* we set the received EOS flag here so that we can use it when testing if
+ * we are prerolled and to refuse more buffers. */
+ basesink->priv->received_eos = TRUE;
+
+ /* EOS is a prerollable object, we call the unlocked version because it
+ * does not check the received_eos flag. */
+ ret = gst_base_sink_queue_object_unlocked (basesink, pad,
+ _PR_IS_EVENT, GST_MINI_OBJECT_CAST (event), TRUE);
+ if (G_UNLIKELY (ret != GST_FLOW_OK))
result = FALSE;
- gst_event_unref (event);
- } else {
- /* we set the received EOS flag here so that we can use it when testing if
- * we are prerolled and to refuse more buffers. */
- basesink->priv->received_eos = TRUE;
-
- /* EOS is a prerollable object, we call the unlocked version because it
- * does not check the received_eos flag. */
- ret = gst_base_sink_queue_object_unlocked (basesink, pad,
- _PR_IS_EVENT, GST_MINI_OBJECT_CAST (event), TRUE);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- result = FALSE;
- }
+
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
break;
}
if (G_UNLIKELY (basesink->flushing))
goto flushing;
+ if (G_UNLIKELY (basesink->priv->received_eos))
+ goto after_eos;
+
/* the new segment is a non prerollable item and does not block anything,
* we need to configure the current clipping segment and insert the event
* in the queue to serialize it with the buffers for rendering. */
gst_base_sink_configure_segment (basesink, pad, event,
- basesink->clip_segment);
+ &basesink->clip_segment);
ret =
gst_base_sink_queue_object_unlocked (basesink, pad,
gst_event_unref (event);
break;
case GST_EVENT_FLUSH_STOP:
+ {
+ gboolean reset_time;
+
if (bclass->event)
bclass->event (basesink, event);
- GST_DEBUG_OBJECT (basesink, "flush-stop %p", event);
+ gst_event_parse_flush_stop (event, &reset_time);
+ GST_DEBUG_OBJECT (basesink, "flush-stop %p, reset_time: %d", event,
+ reset_time);
- gst_base_sink_flush_stop (basesink, pad);
+ gst_base_sink_flush_stop (basesink, pad, reset_time);
gst_event_unref (event);
break;
+ }
default:
/* other events are sent to queue or subclass depending on if they
* are serialized. */
gst_event_unref (event);
goto done;
}
+
+after_eos:
+ {
+ GST_DEBUG_OBJECT (basesink, "Event received after EOS, dropping");
+ GST_BASE_SINK_PREROLL_UNLOCK (basesink);
+ result = FALSE;
+ gst_event_unref (event);
+ goto done;
+ }
}
/* default implementation to calculate the start and end
}
/* for code clarity */
- clip_segment = basesink->clip_segment;
+ clip_segment = &basesink->clip_segment;
if (G_UNLIKELY (!basesink->have_newsegment)) {
gboolean sync;
GstSeekType cur_type, stop_type;
gint64 cur, stop;
GstSeekFlags flags;
- GstFormat seek_format, dest_format;
+ GstFormat seek_format;
gdouble rate;
gboolean update;
gboolean res = TRUE;
gst_event_parse_seek (event, &rate, &seek_format, &flags,
&cur_type, &cur, &stop_type, &stop);
- dest_format = segment->format;
- if (seek_format == dest_format) {
+ if (seek_format == segment->format) {
gst_segment_do_seek (segment, rate, seek_format, flags,
cur_type, cur, stop_type, stop, &update);
return TRUE;
if (cur_type != GST_SEEK_TYPE_NONE) {
/* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
res =
- gst_pad_query_convert (sink->sinkpad, seek_format, cur, &dest_format,
+ gst_pad_query_convert (sink->sinkpad, seek_format, cur, segment->format,
&cur);
cur_type = GST_SEEK_TYPE_SET;
}
if (res && stop_type != GST_SEEK_TYPE_NONE) {
/* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
res =
- gst_pad_query_convert (sink->sinkpad, seek_format, stop, &dest_format,
- &stop);
+ gst_pad_query_convert (sink->sinkpad, seek_format, stop,
+ segment->format, &stop);
stop_type = GST_SEEK_TYPE_SET;
}
/* And finally, configure our output segment in the desired format */
- gst_segment_do_seek (segment, rate, dest_format, flags, cur_type, cur,
+ gst_segment_do_seek (segment, rate, segment->format, flags, cur_type, cur,
stop_type, stop, &update);
if (!res)
if (flush) {
GST_DEBUG_OBJECT (sink, "stop flushing upstream");
- gst_pad_push_event (pad, gst_event_new_flush_stop ());
- gst_base_sink_flush_stop (sink, pad);
+ gst_pad_push_event (pad, gst_event_new_flush_stop (TRUE));
+ gst_base_sink_flush_stop (sink, pad, TRUE);
} else if (res && sink->running) {
/* we are running the current segment and doing a non-flushing seek,
* close the segment first based on the position. */
sink->playing_async = TRUE;
priv->pending_step.need_preroll = TRUE;
sink->need_preroll = FALSE;
- gst_element_lost_state (GST_ELEMENT_CAST (sink), FALSE);
+ gst_element_lost_state (GST_ELEMENT_CAST (sink));
} else {
sink->priv->have_latency = TRUE;
sink->need_preroll = FALSE;
{
gboolean result = FALSE;
GstBaseSink *basesink;
+ GstQuery *query;
+ gboolean pull_mode;
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
}
/* check if downstreams supports pull mode at all */
- if (!gst_pad_check_pull_range (pad)) {
+ query = gst_query_new_scheduling ();
+
+ if (!gst_pad_peer_query (pad, query)) {
+ gst_query_unref (query);
+ GST_DEBUG_OBJECT (basesink, "peer query faild, no pull mode");
+ goto fallback;
+ }
+
+ /* parse result of the query */
+ gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL);
+ gst_query_unref (query);
+
+ if (!pull_mode) {
GST_DEBUG_OBJECT (basesink, "pull mode not supported");
goto fallback;
}
GST_DEBUG_OBJECT (basesink, "fixated to: %" GST_PTR_FORMAT, caps);
if (gst_caps_is_fixed (caps)) {
- if (!gst_pad_set_caps (GST_BASE_SINK_PAD (basesink), caps))
+ if (!gst_pad_send_event (GST_BASE_SINK_PAD (basesink),
+ gst_event_new_caps (caps)))
goto could_not_set_caps;
GST_OBJECT_LOCK (basesink);
bclass = GST_BASE_SINK_GET_CLASS (basesink);
if (active) {
- GstFormat format;
gint64 duration;
/* we mark we have a newsegment here because pull based
* mode works just fine without having a newsegment before the
* first buffer */
- format = GST_FORMAT_BYTES;
-
- gst_segment_init (&basesink->segment, format);
- gst_segment_init (basesink->clip_segment, format);
+ gst_segment_init (&basesink->segment, GST_FORMAT_BYTES);
+ gst_segment_init (&basesink->clip_segment, GST_FORMAT_BYTES);
GST_OBJECT_LOCK (basesink);
basesink->have_newsegment = TRUE;
GST_OBJECT_UNLOCK (basesink);
/* get the peer duration in bytes */
- result = gst_pad_query_peer_duration (pad, &format, &duration);
+ result = gst_pad_query_peer_duration (pad, GST_FORMAT_BYTES, &duration);
if (result) {
GST_DEBUG_OBJECT (basesink,
"setting duration in bytes to %" G_GINT64_FORMAT, duration);
- basesink->clip_segment->duration = duration;
+ basesink->clip_segment.duration = duration;
basesink->segment.duration = duration;
} else {
GST_DEBUG_OBJECT (basesink, "unknown duration");
{
GstClock *clock = NULL;
gboolean res = FALSE;
- GstFormat oformat, tformat;
+ GstFormat oformat;
GstSegment *segment;
GstClockTime now, latency;
GstClockTimeDiff base_time;
* main segment directly with the new segment values without it having to be
* activated by the rendering after preroll */
if (basesink->pad_mode == GST_ACTIVATE_PUSH)
- segment = basesink->clip_segment;
+ segment = &basesink->clip_segment;
else
segment = &basesink->segment;
- /* our intermediate time format */
- tformat = GST_FORMAT_TIME;
/* get the format in the segment */
oformat = segment->format;
else
gst_object_ref (clock);
+ /* mainloop might be querying position when going to playing async,
+ * while (audio) rendering might be quickly advancing stream position,
+ * so use clock asap rather than last reported position */
+ if (in_paused && with_clock && g_atomic_int_get (&basesink->priv->to_playing)) {
+ GST_DEBUG_OBJECT (basesink, "going to PLAYING, so not PAUSED");
+ in_paused = FALSE;
+ }
+
/* collect all data we need holding the lock */
if (GST_CLOCK_TIME_IS_VALID (segment->time))
time = segment->time;
GST_TIME_ARGS (last));
*cur = last;
} else {
- if (oformat != tformat) {
+ if (oformat != GST_FORMAT_TIME) {
/* convert base, time and duration to time */
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, base, &tformat,
- &base))
+ if (!gst_pad_query_convert (basesink->sinkpad, oformat, base,
+ GST_FORMAT_TIME, &base))
goto convert_failed;
if (!gst_pad_query_convert (basesink->sinkpad, oformat, duration,
- &tformat, &duration))
+ GST_FORMAT_TIME, &duration))
goto convert_failed;
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, time, &tformat,
- &time))
+ if (!gst_pad_query_convert (basesink->sinkpad, oformat, time,
+ GST_FORMAT_TIME, &time))
goto convert_failed;
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, last, &tformat,
- &last))
+ if (!gst_pad_query_convert (basesink->sinkpad, oformat, last,
+ GST_FORMAT_TIME, &last))
goto convert_failed;
/* assume time format from now on */
- oformat = tformat;
+ oformat = GST_FORMAT_TIME;
}
if (!in_paused && with_clock) {
if (oformat != format) {
/* convert to final format */
- if (!gst_pad_query_convert (basesink->sinkpad, oformat, *cur, &format, cur))
+ if (!gst_pad_query_convert (basesink->sinkpad, oformat, *cur, format, cur))
goto convert_failed;
}
gboolean res = FALSE;
if (basesink->pad_mode == GST_ACTIVATE_PULL) {
- GstFormat uformat = GST_FORMAT_BYTES;
gint64 uduration;
/* get the duration in bytes, in pull mode that's all we are sure to
* know. We have to explicitly get this value from upstream instead of
* using our cached value because it might change. Duration caching
* should be done at a higher level. */
- res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat, &uduration);
+ res =
+ gst_pad_query_peer_duration (basesink->sinkpad, GST_FORMAT_BYTES,
+ &uduration);
if (res) {
basesink->segment.duration = uduration;
- if (format != uformat) {
+ if (format != GST_FORMAT_BYTES) {
/* convert to the requested format */
- res = gst_pad_query_convert (basesink->sinkpad, uformat, uduration,
- &format, dur);
+ res =
+ gst_pad_query_convert (basesink->sinkpad, GST_FORMAT_BYTES,
+ uduration, format, dur);
} else {
*dur = uduration;
}
}
static gboolean
-gst_base_sink_query (GstElement * element, GstQuery * query)
+default_element_query (GstElement * element, GstQuery * query)
{
gboolean res = FALSE;
/* we can handle a few things if upstream failed */
if (format == GST_FORMAT_PERCENT) {
gint64 dur = 0;
- GstFormat uformat = GST_FORMAT_TIME;
res = gst_base_sink_get_position (basesink, GST_FORMAT_TIME, &cur,
&upstream);
if (!res && upstream) {
- res = gst_pad_query_peer_position (basesink->sinkpad, &uformat,
+ res =
+ gst_pad_query_peer_position (basesink->sinkpad, GST_FORMAT_TIME,
&cur);
}
if (res) {
res = gst_base_sink_get_duration (basesink, GST_FORMAT_TIME, &dur,
&upstream);
if (!res && upstream) {
- res = gst_pad_query_peer_duration (basesink->sinkpad, &uformat,
- &dur);
+ res =
+ gst_pad_query_peer_duration (basesink->sinkpad,
+ GST_FORMAT_TIME, &dur);
}
}
if (res) {
return res;
}
+
+static gboolean
+default_sink_query (GstBaseSink * basesink, GstQuery * query)
+{
+ gboolean res;
+ GstBaseSinkClass *bclass;
+
+ bclass = GST_BASE_SINK_GET_CLASS (basesink);
+
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_ALLOCATION:
+ {
+ if (bclass->setup_allocation)
+ res = bclass->setup_allocation (basesink, query);
+ else
+ res = FALSE;
+ break;
+ }
+ default:
+ res = gst_pad_query_default (basesink->sinkpad, query);
+ break;
+ }
+ return res;
+}
+
+static gboolean
+gst_base_sink_sink_query (GstPad * pad, GstQuery * query)
+{
+ GstBaseSink *basesink;
+ GstBaseSinkClass *bclass;
+ gboolean res;
+
+ basesink = GST_BASE_SINK_CAST (gst_pad_get_parent (pad));
+ if (G_UNLIKELY (basesink == NULL)) {
+ gst_query_unref (query);
+ return FALSE;
+ }
+
+ bclass = GST_BASE_SINK_GET_CLASS (basesink);
+
+ if (bclass->query)
+ res = bclass->query (basesink, query);
+ else
+ res = FALSE;
+
+ gst_object_unref (basesink);
+
+ return res;
+}
+
static GstStateChangeReturn
gst_base_sink_change_state (GstElement * element, GstStateChange transition)
{
GST_DEBUG_OBJECT (basesink, "READY to PAUSED");
basesink->have_newsegment = FALSE;
gst_segment_init (&basesink->segment, GST_FORMAT_UNDEFINED);
- gst_segment_init (basesink->clip_segment, GST_FORMAT_UNDEFINED);
+ gst_segment_init (&basesink->clip_segment, GST_FORMAT_UNDEFINED);
basesink->offset = 0;
basesink->have_preroll = FALSE;
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;
* the state change function */
ret = GST_STATE_CHANGE_ASYNC;
gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE));
+ gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
} else {
priv->have_latency = TRUE;
}
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
GST_BASE_SINK_PREROLL_LOCK (basesink);
+ g_atomic_int_set (&basesink->priv->to_playing, TRUE);
if (!gst_base_sink_needs_preroll (basesink)) {
GST_DEBUG_OBJECT (basesink, "PAUSED to PLAYING, don't need preroll");
/* no preroll needed anymore now. */
GST_DEBUG_OBJECT (basesink, "doing async state change");
ret = GST_STATE_CHANGE_ASYNC;
gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_start (GST_OBJECT_CAST (basesink), FALSE));
+ gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
}
}
GST_BASE_SINK_PREROLL_UNLOCK (basesink);
}
switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ /* completed transition, so need not be marked any longer
+ * And it should be unmarked, since e.g. losing our position upon flush
+ * does not really change state to PAUSED ... */
+ g_atomic_int_set (&basesink->priv->to_playing, FALSE);
+ break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ g_atomic_int_set (&basesink->priv->to_playing, FALSE);
GST_DEBUG_OBJECT (basesink, "PLAYING to PAUSED");
/* FIXME, make sure we cannot enter _render first */
GST_DEBUG_OBJECT (basesink, "doing async state change");
ret = GST_STATE_CHANGE_ASYNC;
gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_start (GST_OBJECT_CAST (basesink),
- FALSE));
+ gst_message_new_async_start (GST_OBJECT_CAST (basesink)));
}
}
}
GST_STATE_PLAYING, GST_STATE_PAUSED, GST_STATE_READY));
gst_element_post_message (GST_ELEMENT_CAST (basesink),
- gst_message_new_async_done (GST_OBJECT_CAST (basesink)));
+ gst_message_new_async_done (GST_OBJECT_CAST (basesink), FALSE));
}
priv->commited = TRUE;
} else {