#define GST_ASYNC_WAIT(elem) g_cond_wait (GST_ASYNC_GET_COND (elem), GST_OBJECT_GET_LOCK (elem))
#define GST_ASYNC_SIGNAL(elem) g_cond_signal (GST_ASYNC_GET_COND (elem));
+#define CLEAR_PENDING_EOS(bsrc) \
+ G_STMT_START { \
+ g_atomic_int_set (&bsrc->priv->has_pending_eos, FALSE); \
+ gst_event_replace (&bsrc->priv->pending_eos, NULL); \
+ } G_STMT_END
+
/* BaseSrc signals and args */
enum
guint32 segment_seqnum;
/* if EOS is pending (atomic) */
- gint pending_eos;
+ GstEvent *pending_eos;
+ gint has_pending_eos;
+
+ /* if the eos was caused by a forced eos from the application */
+ gboolean forced_eos;
/* startup latency is the time it takes between going to PLAYING and producing
* the first BUFFER with running_time 0. This value is included in the latency
GST_LIVE_LOCK (src);
src->priv->flushing = TRUE;
/* clear pending EOS if any */
- g_atomic_int_set (&src->priv->pending_eos, FALSE);
+ if (g_atomic_int_get (&src->priv->has_pending_eos)) {
+ GST_OBJECT_LOCK (src);
+ CLEAR_PENDING_EOS (src);
+ GST_OBJECT_UNLOCK (src);
+ }
if (bclass->unlock_stop)
bclass->unlock_stop (src);
if (src->clock_id)
*
* We have two possibilities:
*
- * - Before we are to enter the _create function, we check the pending_eos
+ * - Before we are to enter the _create function, we check the has_pending_eos
* first and do EOS instead of entering it.
* - If we are in the _create function or we did not manage to set the
* flag fast enough and we are about to enter the _create function,
* we unlock it so that we exit with FLUSHING immediately. We then
* check the EOS flag and do the EOS logic.
*/
- g_atomic_int_set (&src->priv->pending_eos, TRUE);
- GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
+ GST_OBJECT_LOCK (src);
+ g_atomic_int_set (&src->priv->has_pending_eos, TRUE);
+ if (src->priv->pending_eos)
+ gst_event_unref (src->priv->pending_eos);
+ src->priv->pending_eos = event;
+ event = NULL;
+ GST_OBJECT_UNLOCK (src);
+ GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
- /* unlock the _create function so that we can check the pending_eos flag
+ /* unlock the _create function so that we can check the has_pending_eos flag
* and we can do EOS. This will eventually release the LIVE_LOCK again so
* that we can grab it and stop the unlock again. We don't take the stream
* lock so that this operation is guaranteed to never block. */
}
/* don't enter the create function if a pending EOS event was set. For the
- * logic of the pending_eos, check the event function of this class. */
- if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos)))
+ * logic of the has_pending_eos, check the event function of this class. */
+ if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) {
+ src->priv->forced_eos = TRUE;
goto eos;
+ }
GST_DEBUG_OBJECT (src,
"calling create offset %" G_GUINT64_FORMAT " length %u, time %"
/* The create function could be unlocked because we have a pending EOS. It's
* possible that we have a valid buffer from create that we need to
* discard when the create function returned _OK. */
- if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos))) {
+ if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) {
if (ret == GST_FLOW_OK) {
if (*buf == NULL)
gst_buffer_unref (res_buf);
}
+ src->priv->forced_eos = TRUE;
goto eos;
}
GstFormat format;
gint64 position;
- /* perform EOS logic */
flag_segment = (src->segment.flags & GST_SEGMENT_FLAG_SEGMENT) != 0;
format = src->segment.format;
position = src->segment.position;
- if (flag_segment) {
+ /* perform EOS logic */
+ if (src->priv->forced_eos) {
+ g_assert (g_atomic_int_get (&src->priv->has_pending_eos));
+ GST_OBJECT_LOCK (src);
+ event = src->priv->pending_eos;
+ src->priv->pending_eos = NULL;
+ GST_OBJECT_UNLOCK (src);
+
+ } else if (flag_segment) {
GstMessage *message;
- message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
- format, position);
- gst_message_set_seqnum (message, src->priv->seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (src), message);
- event = gst_event_new_segment_done (format, position);
+ if (flag_segment) {
+ message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
+ format, position);
+ gst_message_set_seqnum (message, src->priv->seqnum);
+ gst_element_post_message (GST_ELEMENT_CAST (src), message);
+ event = gst_event_new_segment_done (format, position);
+ } else {
+ event = gst_event_new_eos ();
+ gst_event_set_seqnum (event, src->priv->seqnum);
+ }
+
gst_event_set_seqnum (event, src->priv->seqnum);
- gst_pad_push_event (pad, event);
} else {
event = gst_event_new_eos ();
gst_event_set_seqnum (event, src->priv->seqnum);
- gst_pad_push_event (pad, event);
}
+
+ gst_pad_push_event (pad, event);
+
} else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_EOS) {
event = gst_event_new_eos ();
gst_event_set_seqnum (event, src->priv->seqnum);
basesrc->live_running = TRUE;
/* clear pending EOS if any */
- g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
+ if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) {
+ GST_OBJECT_LOCK (basesrc);
+ CLEAR_PENDING_EOS (basesrc);
+ GST_OBJECT_UNLOCK (basesrc);
+ }
/* step 1, now that we have the LIVE lock, clear our unlock request */
if (bclass->unlock_stop)
{
/* we don't need to unblock anything here, the pad deactivation code
* already did this */
- g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
+ if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) {
+ GST_OBJECT_LOCK (basesrc);
+ CLEAR_PENDING_EOS (basesrc);
+ GST_OBJECT_UNLOCK (basesrc);
+ }
gst_event_replace (&basesrc->pending_seek, NULL);
break;
}