summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <bilboed@bilboed.com>2014-10-30 11:15:23 +0100
committerEdward Hervey <bilboed@bilboed.com>2015-02-18 12:17:31 +0100
commit0f0ba23d5fd978a1db293872b56acf70db803cf0 (patch)
tree9bc737dabc065f7d26de6223eaf4369545135c84
parent87070a08bd014698d6a579d2e1cc9c9463e1f5ec (diff)
qtdemux: Initial chained support
This is similar to how asfdemux supports "chained" files. We detect that by new STREAM_START events. We put aside all old streams, and when we created all our new streams, we push EOS on those old streams and finally remove them
-rw-r--r--gst/isomp4/qtdemux.c57
-rw-r--r--gst/isomp4/qtdemux.h3
2 files changed, 51 insertions, 9 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index b32385929..23be06171 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -1820,14 +1820,16 @@ gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
}
static void
-gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
+gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard, gboolean chaining)
{
gint n;
- GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
+ GST_DEBUG_OBJECT (qtdemux, "Resetting demux (hard:%d, chaining:%d)",
+ hard, chaining);
gst_pad_stop_task (qtdemux->sinkpad);
- if (hard || qtdemux->upstream_newsegment) {
+ /* On state changes, new TIME SEGMENT, or new headers */
+ if (hard || qtdemux->upstream_newsegment || chaining) {
qtdemux->state = QTDEMUX_STATE_INITIAL;
qtdemux->neededbytes = 16;
qtdemux->todrop = 0;
@@ -1880,15 +1882,35 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
gst_adapter_clear (qtdemux->adapter);
gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
- if (hard) {
+ if (hard || chaining) {
+ /* Remove old streams */
+ for (n = 0; n < qtdemux->n_old_streams; n++) {
+ GST_DEBUG_OBJECT (qtdemux, "Removing old stream %d", n);
+ gst_qtdemux_stream_free (qtdemux, qtdemux->old_streams[n]);
+ qtdemux->old_streams[n] = NULL;
+ }
+ qtdemux->n_old_streams = 0;
+
+ if (!hard) {
+ /* Save old streams (will be removed once we added new ones) */
+ GST_DEBUG_OBJECT (qtdemux, "Saving %d streams for later removal",
+ qtdemux->n_streams);
+ memcpy (qtdemux->old_streams, qtdemux->streams,
+ sizeof (qtdemux->streams));
+ qtdemux->n_old_streams = qtdemux->n_streams;
+ qtdemux->n_streams = 0;
+ }
+
for (n = 0; n < qtdemux->n_streams; n++) {
gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
qtdemux->streams[n] = NULL;
}
qtdemux->n_streams = 0;
- qtdemux->n_video_streams = 0;
- qtdemux->n_audio_streams = 0;
- qtdemux->n_sub_streams = 0;
+ if (!chaining) {
+ qtdemux->n_video_streams = 0;
+ qtdemux->n_audio_streams = 0;
+ qtdemux->n_sub_streams = 0;
+ }
qtdemux->exposed = FALSE;
qtdemux->fragmented = FALSE;
qtdemux->mss_mode = FALSE;
@@ -2040,7 +2062,7 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
guint64 dur;
dur = demux->segment.duration;
- gst_qtdemux_reset (demux, FALSE);
+ gst_qtdemux_reset (demux, FALSE, FALSE);
demux->segment.duration = dur;
break;
}
@@ -2076,6 +2098,9 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
gst_event_unref (event);
goto drop;
}
+ case GST_EVENT_STREAM_START:
+ gst_qtdemux_reset (demux, FALSE, TRUE);
+ break;
default:
break;
}
@@ -2224,7 +2249,7 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:{
- gst_qtdemux_reset (qtdemux, TRUE);
+ gst_qtdemux_reset (qtdemux, TRUE, FALSE);
break;
}
default:
@@ -9505,6 +9530,20 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
gst_object_unref (oldpad);
}
+ GST_DEBUG_OBJECT (qtdemux, "We have %d old streams to remove now",
+ qtdemux->n_old_streams);
+
+ for (i = 0; i < qtdemux->n_old_streams; i++) {
+ GST_DEBUG_OBJECT (qtdemux,
+ "Removing old stream %d, id %d, fourcc %" GST_FOURCC_FORMAT, i,
+ qtdemux->old_streams[i]->track_id,
+ GST_FOURCC_ARGS (qtdemux->old_streams[i]->fourcc));
+ gst_pad_push_event (qtdemux->old_streams[i]->pad, gst_event_new_eos ());
+ gst_qtdemux_stream_free (qtdemux, qtdemux->old_streams[i]);
+ qtdemux->old_streams[i] = NULL;
+ }
+ qtdemux->n_old_streams = 0;
+
/* check if we should post a redirect in case there is a single trak
* and it is a redirecting trak */
if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
diff --git a/gst/isomp4/qtdemux.h b/gst/isomp4/qtdemux.h
index 6345d9c45..a562e6263 100644
--- a/gst/isomp4/qtdemux.h
+++ b/gst/isomp4/qtdemux.h
@@ -66,6 +66,9 @@ struct _GstQTDemux {
gint n_audio_streams;
gint n_sub_streams;
+ QtDemuxStream *old_streams[GST_QTDEMUX_MAX_STREAMS];
+ gint n_old_streams;
+
GstFlowCombiner *flowcombiner;
gboolean have_group_id;