diff options
author | Edward Hervey <bilboed@bilboed.com> | 2014-10-30 11:15:23 +0100 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2015-02-18 12:17:31 +0100 |
commit | 0f0ba23d5fd978a1db293872b56acf70db803cf0 (patch) | |
tree | 9bc737dabc065f7d26de6223eaf4369545135c84 | |
parent | 87070a08bd014698d6a579d2e1cc9c9463e1f5ec (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.c | 57 | ||||
-rw-r--r-- | gst/isomp4/qtdemux.h | 3 |
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; |