summaryrefslogtreecommitdiff
path: root/gst/playback/gststreamsynchronizer.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/playback/gststreamsynchronizer.c')
-rw-r--r--gst/playback/gststreamsynchronizer.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/gst/playback/gststreamsynchronizer.c b/gst/playback/gststreamsynchronizer.c
index d4b8abe75..78bf00d3e 100644
--- a/gst/playback/gststreamsynchronizer.c
+++ b/gst/playback/gststreamsynchronizer.c
@@ -66,6 +66,7 @@ typedef struct
gboolean wait;
gboolean new_stream;
gboolean drop_discont;
+ gboolean is_eos;
gint64 running_time_diff;
} GstStream;
@@ -447,6 +448,40 @@ gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event)
GST_STREAM_SYNCHRONIZER_UNLOCK (self);
break;
}
+ case GST_EVENT_EOS:{
+ GstStream *stream;
+ GList *l;
+ gboolean all_eos = TRUE;
+
+ GST_STREAM_SYNCHRONIZER_LOCK (self);
+ stream = gst_pad_get_element_private (pad);
+ if (stream) {
+ GST_DEBUG_OBJECT (pad, "Have EOS for stream %d", stream->stream_number);
+ stream->is_eos = TRUE;
+ }
+
+ for (l = self->streams; l; l = l->next) {
+ GstStream *ostream = l->data;
+
+ all_eos = all_eos && ostream->is_eos;
+ if (!all_eos)
+ break;
+ }
+
+ if (all_eos) {
+ ret = TRUE;
+ GST_DEBUG_OBJECT (self, "All streams are EOS -- forwarding");
+ for (l = self->streams; l; l = l->next) {
+ GstStream *ostream = l->data;
+ ret = ret
+ && gst_pad_push_event (ostream->srcpad, gst_event_new_eos ());
+ }
+ }
+ GST_STREAM_SYNCHRONIZER_UNLOCK (self);
+
+ goto done;
+ break;
+ }
default:
break;
}
@@ -533,6 +568,8 @@ gst_stream_synchronizer_sink_chain (GstPad * pad, GstBuffer * buffer)
GST_LOG_OBJECT (pad, "Push returned: %s", gst_flow_get_name (ret));
if (ret == GST_FLOW_OK) {
+ GList *l;
+
GST_STREAM_SYNCHRONIZER_LOCK (self);
stream = gst_pad_get_element_private (pad);
if (stream && stream->segment.format == GST_FORMAT_TIME
@@ -544,6 +581,43 @@ gst_stream_synchronizer_sink_chain (GstPad * pad, GstBuffer * buffer)
gst_segment_set_last_stop (&stream->segment, GST_FORMAT_TIME,
timestamp_end);
}
+
+ /* Advance EOS streams if necessary. For non-EOS
+ * streams the demuxers should already do this! */
+ for (l = self->streams; l; l = l->next) {
+ GstStream *ostream = l->data;
+ gint64 last_stop;
+
+ if (!ostream->is_eos || ostream->segment.format != GST_FORMAT_TIME)
+ continue;
+
+ if (ostream->segment.last_stop != -1)
+ last_stop = ostream->segment.last_stop;
+ else
+ last_stop = ostream->segment.start;
+
+ /* Is there a 1 second lag? */
+ if (last_stop != -1 && last_stop + GST_SECOND < timestamp_end) {
+ gint64 new_start;
+
+ new_start = timestamp_end - GST_SECOND;
+
+ GST_DEBUG_OBJECT (ostream->sinkpad,
+ "Advancing stream %d from %" GST_TIME_FORMAT " to %"
+ GST_TIME_FORMAT, ostream->stream_number, last_stop, new_start);
+
+ gst_pad_push_event (ostream->srcpad,
+ gst_event_new_new_segment_full (TRUE, ostream->segment.rate,
+ ostream->segment.applied_rate, ostream->segment.format,
+ new_start, ostream->segment.stop, new_start));
+ gst_segment_set_newsegment_full (&ostream->segment, TRUE,
+ ostream->segment.rate, ostream->segment.applied_rate,
+ ostream->segment.format, new_start, ostream->segment.stop,
+ new_start);
+ gst_segment_set_last_stop (&ostream->segment, GST_FORMAT_TIME,
+ new_start);
+ }
+ }
GST_STREAM_SYNCHRONIZER_UNLOCK (self);
}
@@ -666,6 +740,15 @@ gst_stream_synchronizer_release_stream (GstStreamSynchronizer * self,
}
g_slice_free (GstStream, stream);
+
+ /* NOTE: In theory we have to check here if all streams
+ * are EOS but the one that was removed wasn't and then
+ * send EOS downstream. But due to the way how playsink
+ * works this is not necessary and will only cause problems
+ * for gapless playback. playsink will only add/remove pads
+ * when it's reconfigured, which happens when the streams
+ * change
+ */
}
static void
@@ -742,6 +825,7 @@ gst_stream_synchronizer_change_state (GstElement * element,
stream->wait = FALSE;
stream->new_stream = FALSE;
stream->drop_discont = FALSE;
+ stream->is_eos = FALSE;
}
GST_STREAM_SYNCHRONIZER_UNLOCK (self);
break;