mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-18 20:25:25 +00:00
qtdemux: Use GPtrArray to store QtDemuxStream structure
GPtrArray has less overhead than linked list and the length also can be auto updated by using it. https://bugzilla.gnome.org/show_bug.cgi?id=797239
This commit is contained in:
parent
1600323119
commit
b2876ad8a4
2 changed files with 216 additions and 207 deletions
|
@ -97,9 +97,12 @@
|
||||||
|
|
||||||
#define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
|
#define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
|
||||||
|
|
||||||
#define QTDEMUX_FIRST_STREAM(demux) ((QtDemuxStream *)(demux)->active_streams \
|
|
||||||
? (QtDemuxStream *)(demux)->active_streams->data : NULL)
|
|
||||||
#define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
|
#define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
|
||||||
|
#define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
|
||||||
|
#define QTDEMUX_NTH_STREAM(demux,idx) \
|
||||||
|
QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
|
||||||
|
#define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
|
||||||
|
QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY (qtdemux_debug);
|
GST_DEBUG_CATEGORY (qtdemux_debug);
|
||||||
#define GST_CAT_DEFAULT qtdemux_debug
|
#define GST_CAT_DEFAULT qtdemux_debug
|
||||||
|
@ -578,10 +581,9 @@ static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
|
||||||
static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
|
static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
|
||||||
QtDemuxStream * stream, guint32 n);
|
QtDemuxStream * stream, guint32 n);
|
||||||
static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
|
static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
|
||||||
|
static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
|
||||||
static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
|
static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
|
||||||
static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
|
static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
|
||||||
static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
|
|
||||||
QtDemuxStream * stream);
|
|
||||||
static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
|
static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
|
||||||
static void qtdemux_do_allocation (QtDemuxStream * stream,
|
static void qtdemux_do_allocation (QtDemuxStream * stream,
|
||||||
GstQTDemux * qtdemux);
|
GstQTDemux * qtdemux);
|
||||||
|
@ -661,6 +663,11 @@ gst_qtdemux_init (GstQTDemux * qtdemux)
|
||||||
qtdemux->flowcombiner = gst_flow_combiner_new ();
|
qtdemux->flowcombiner = gst_flow_combiner_new ();
|
||||||
g_mutex_init (&qtdemux->expose_lock);
|
g_mutex_init (&qtdemux->expose_lock);
|
||||||
|
|
||||||
|
qtdemux->active_streams = g_ptr_array_new_with_free_func
|
||||||
|
((GDestroyNotify) gst_qtdemux_stream_unref);
|
||||||
|
qtdemux->old_streams = g_ptr_array_new_with_free_func
|
||||||
|
((GDestroyNotify) gst_qtdemux_stream_unref);
|
||||||
|
|
||||||
GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
|
GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
|
||||||
|
|
||||||
gst_qtdemux_reset (qtdemux, TRUE);
|
gst_qtdemux_reset (qtdemux, TRUE);
|
||||||
|
@ -685,6 +692,9 @@ gst_qtdemux_dispose (GObject * object)
|
||||||
qtdemux->cenc_aux_info_sizes = NULL;
|
qtdemux->cenc_aux_info_sizes = NULL;
|
||||||
g_mutex_clear (&qtdemux->expose_lock);
|
g_mutex_clear (&qtdemux->expose_lock);
|
||||||
|
|
||||||
|
g_ptr_array_free (qtdemux->active_streams, TRUE);
|
||||||
|
g_ptr_array_free (qtdemux->old_streams, TRUE);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,14 +1012,14 @@ gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
|
||||||
{
|
{
|
||||||
gboolean has_valid_stream = FALSE;
|
gboolean has_valid_stream = FALSE;
|
||||||
GstEventType etype = GST_EVENT_TYPE (event);
|
GstEventType etype = GST_EVENT_TYPE (event);
|
||||||
GList *iter;
|
guint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
|
GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
|
||||||
GST_EVENT_TYPE_NAME (event));
|
GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
|
GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
|
||||||
|
|
||||||
if ((pad = stream->pad)) {
|
if ((pad = stream->pad)) {
|
||||||
|
@ -1306,13 +1316,13 @@ gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
|
||||||
{
|
{
|
||||||
guint64 min_offset;
|
guint64 min_offset;
|
||||||
gint64 min_byte_offset = -1;
|
gint64 min_byte_offset = -1;
|
||||||
GList *iter;
|
guint i;
|
||||||
|
|
||||||
min_offset = desired_time;
|
min_offset = desired_time;
|
||||||
|
|
||||||
/* for each stream, find the index of the sample in the segment
|
/* for each stream, find the index of the sample in the segment
|
||||||
* and move back to the previous keyframe. */
|
* and move back to the previous keyframe. */
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *str;
|
QtDemuxStream *str;
|
||||||
guint32 index, kindex;
|
guint32 index, kindex;
|
||||||
guint32 seg_idx;
|
guint32 seg_idx;
|
||||||
|
@ -1322,7 +1332,7 @@ gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
|
||||||
QtDemuxSegment *seg;
|
QtDemuxSegment *seg;
|
||||||
gboolean empty_segment = FALSE;
|
gboolean empty_segment = FALSE;
|
||||||
|
|
||||||
str = QTDEMUX_STREAM (iter->data);
|
str = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
if (CUR_STREAM (str)->sparse && !use_sparse)
|
if (CUR_STREAM (str)->sparse && !use_sparse)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1552,7 +1562,7 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
|
||||||
guint32 seqnum, GstSeekFlags flags)
|
guint32 seqnum, GstSeekFlags flags)
|
||||||
{
|
{
|
||||||
gint64 desired_offset;
|
gint64 desired_offset;
|
||||||
GList *iter;
|
guint i;
|
||||||
|
|
||||||
desired_offset = segment->position;
|
desired_offset = segment->position;
|
||||||
|
|
||||||
|
@ -1582,8 +1592,8 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
|
||||||
/* and set all streams to the final position */
|
/* and set all streams to the final position */
|
||||||
gst_flow_combiner_reset (qtdemux->flowcombiner);
|
gst_flow_combiner_reset (qtdemux->flowcombiner);
|
||||||
qtdemux->segment_seqnum = seqnum;
|
qtdemux->segment_seqnum = seqnum;
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
stream->time_position = desired_offset;
|
stream->time_position = desired_offset;
|
||||||
stream->accumulated_base = 0;
|
stream->accumulated_base = 0;
|
||||||
|
@ -1727,13 +1737,13 @@ no_format:
|
||||||
static gboolean
|
static gboolean
|
||||||
qtdemux_ensure_index (GstQTDemux * qtdemux)
|
qtdemux_ensure_index (GstQTDemux * qtdemux)
|
||||||
{
|
{
|
||||||
GList *iter;
|
guint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
|
GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
|
||||||
|
|
||||||
/* Build complete index */
|
/* Build complete index */
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
|
if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
|
||||||
GST_LOG_OBJECT (qtdemux,
|
GST_LOG_OBJECT (qtdemux,
|
||||||
|
@ -1793,7 +1803,8 @@ gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
|
||||||
} else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
|
} else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
|
||||||
GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
|
GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
|
||||||
res = TRUE;
|
res = TRUE;
|
||||||
} else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
|
} else if (qtdemux->state == QTDEMUX_STATE_MOVIE
|
||||||
|
&& QTDEMUX_N_STREAMS (qtdemux)
|
||||||
&& !qtdemux->fragmented) {
|
&& !qtdemux->fragmented) {
|
||||||
res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
|
res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1842,18 +1853,18 @@ gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
|
||||||
gint i, index;
|
gint i, index;
|
||||||
gint64 time, min_time;
|
gint64 time, min_time;
|
||||||
QtDemuxStream *stream;
|
QtDemuxStream *stream;
|
||||||
GList *iter;
|
gint iter;
|
||||||
|
|
||||||
min_time = -1;
|
min_time = -1;
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
index = -1;
|
index = -1;
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
|
||||||
QtDemuxStream *str;
|
QtDemuxStream *str;
|
||||||
gint inc;
|
gint inc;
|
||||||
gboolean set_sample;
|
gboolean set_sample;
|
||||||
|
|
||||||
str = QTDEMUX_STREAM (iter->data);
|
str = QTDEMUX_NTH_STREAM (qtdemux, iter);
|
||||||
set_sample = !set;
|
set_sample = !set;
|
||||||
|
|
||||||
if (fw) {
|
if (fw) {
|
||||||
|
@ -2013,7 +2024,7 @@ gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
|
||||||
demux->fragmented = TRUE;
|
demux->fragmented = TRUE;
|
||||||
demux->mss_mode = TRUE;
|
demux->mss_mode = TRUE;
|
||||||
|
|
||||||
if (demux->n_streams > 1) {
|
if (QTDEMUX_N_STREAMS (demux) > 1) {
|
||||||
/* can't do this, we can only renegotiate for another mss format */
|
/* can't do this, we can only renegotiate for another mss format */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2025,16 +2036,15 @@ gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
|
||||||
|
|
||||||
/* TODO update when stream changes during playback */
|
/* TODO update when stream changes during playback */
|
||||||
|
|
||||||
if (demux->n_streams == 0) {
|
if (QTDEMUX_N_STREAMS (demux) == 0) {
|
||||||
stream = _create_stream (demux, 1);
|
stream = _create_stream (demux, 1);
|
||||||
demux->active_streams = g_list_append (demux->active_streams, stream);
|
g_ptr_array_add (demux->active_streams, stream);
|
||||||
demux->n_streams = 1;
|
|
||||||
/* mss has no stsd/stsd entry, use id 0 as default */
|
/* mss has no stsd/stsd entry, use id 0 as default */
|
||||||
stream->stsd_entries_length = 1;
|
stream->stsd_entries_length = 1;
|
||||||
stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
|
stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
|
||||||
stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
|
stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
|
||||||
} else {
|
} else {
|
||||||
stream = QTDEMUX_FIRST_STREAM (demux);
|
stream = QTDEMUX_NTH_STREAM (demux, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
timescale_v = gst_structure_get_value (structure, "timescale");
|
timescale_v = gst_structure_get_value (structure, "timescale");
|
||||||
|
@ -2083,7 +2093,7 @@ gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
|
||||||
static void
|
static void
|
||||||
gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
|
gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
|
||||||
{
|
{
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
|
GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
|
||||||
gst_pad_stop_task (qtdemux->sinkpad);
|
gst_pad_stop_task (qtdemux->sinkpad);
|
||||||
|
@ -2155,13 +2165,10 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
|
||||||
|
|
||||||
if (hard) {
|
if (hard) {
|
||||||
qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
|
qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
|
||||||
g_list_free_full (qtdemux->active_streams,
|
g_ptr_array_remove_range (qtdemux->active_streams,
|
||||||
(GDestroyNotify) gst_qtdemux_stream_unref);
|
0, qtdemux->active_streams->len);
|
||||||
g_list_free_full (qtdemux->old_streams,
|
g_ptr_array_remove_range (qtdemux->old_streams,
|
||||||
(GDestroyNotify) gst_qtdemux_stream_unref);
|
0, qtdemux->old_streams->len);
|
||||||
qtdemux->active_streams = NULL;
|
|
||||||
qtdemux->old_streams = NULL;
|
|
||||||
qtdemux->n_streams = 0;
|
|
||||||
qtdemux->n_video_streams = 0;
|
qtdemux->n_video_streams = 0;
|
||||||
qtdemux->n_audio_streams = 0;
|
qtdemux->n_audio_streams = 0;
|
||||||
qtdemux->n_sub_streams = 0;
|
qtdemux->n_sub_streams = 0;
|
||||||
|
@ -2188,12 +2195,12 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
|
||||||
}
|
}
|
||||||
} else if (qtdemux->mss_mode) {
|
} else if (qtdemux->mss_mode) {
|
||||||
gst_flow_combiner_reset (qtdemux->flowcombiner);
|
gst_flow_combiner_reset (qtdemux->flowcombiner);
|
||||||
g_list_foreach (qtdemux->active_streams,
|
g_ptr_array_foreach (qtdemux->active_streams,
|
||||||
(GFunc) gst_qtdemux_stream_clear, NULL);
|
(GFunc) gst_qtdemux_stream_clear, NULL);
|
||||||
} else {
|
} else {
|
||||||
gst_flow_combiner_reset (qtdemux->flowcombiner);
|
gst_flow_combiner_reset (qtdemux->flowcombiner);
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
stream->sent_eos = FALSE;
|
stream->sent_eos = FALSE;
|
||||||
stream->time_position = 0;
|
stream->time_position = 0;
|
||||||
stream->accumulated_base = 0;
|
stream->accumulated_base = 0;
|
||||||
|
@ -2212,11 +2219,10 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
|
||||||
static void
|
static void
|
||||||
gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
|
gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i, iter;
|
||||||
GList *iter;
|
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
|
||||||
|
|
||||||
stream->time_position = segment->start;
|
stream->time_position = segment->start;
|
||||||
|
|
||||||
|
@ -2246,6 +2252,31 @@ gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
|
||||||
|
GPtrArray * src)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
guint len;
|
||||||
|
|
||||||
|
len = src->len;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
QtDemuxStream *stream = g_ptr_array_index (src, i);
|
||||||
|
|
||||||
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
|
GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
|
||||||
|
stream, GST_STR_NULL (stream->stream_id), dest);
|
||||||
|
#endif
|
||||||
|
g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_remove_range (src, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
|
gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
|
||||||
GstEvent * event)
|
GstEvent * event)
|
||||||
|
@ -2276,7 +2307,7 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
|
||||||
"not in time format");
|
"not in time format");
|
||||||
|
|
||||||
/* chain will send initial newsegment after pads have been added */
|
/* chain will send initial newsegment after pads have been added */
|
||||||
if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
|
if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
|
||||||
GST_DEBUG_OBJECT (demux, "still starting, eating event");
|
GST_DEBUG_OBJECT (demux, "still starting, eating event");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -2344,7 +2375,7 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
|
||||||
GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
|
GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
|
||||||
|
|
||||||
/* map segment to internal qt segments and push on each stream */
|
/* map segment to internal qt segments and push on each stream */
|
||||||
if (demux->n_streams) {
|
if (QTDEMUX_N_STREAMS (demux)) {
|
||||||
demux->need_segment = TRUE;
|
demux->need_segment = TRUE;
|
||||||
gst_qtdemux_check_send_pending_segment (demux);
|
gst_qtdemux_check_send_pending_segment (demux);
|
||||||
}
|
}
|
||||||
|
@ -2405,10 +2436,10 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
|
||||||
/* If we are in push mode, and get an EOS before we've seen any streams,
|
/* If we are in push mode, and get an EOS before we've seen any streams,
|
||||||
* then error out - we have nowhere to send the EOS */
|
* then error out - we have nowhere to send the EOS */
|
||||||
if (!demux->pullbased) {
|
if (!demux->pullbased) {
|
||||||
GList *iter;
|
gint i;
|
||||||
gboolean has_valid_stream = FALSE;
|
gboolean has_valid_stream = FALSE;
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
|
if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
|
||||||
has_valid_stream = TRUE;
|
has_valid_stream = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2457,9 +2488,8 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
|
||||||
gst_qtdemux_process_adapter (demux, TRUE);
|
gst_qtdemux_process_adapter (demux, TRUE);
|
||||||
gst_qtdemux_reset (demux, FALSE);
|
gst_qtdemux_reset (demux, FALSE);
|
||||||
/* We expect new moov box after new stream-start event */
|
/* We expect new moov box after new stream-start event */
|
||||||
demux->old_streams =
|
gst_qtdemux_stream_concat (demux,
|
||||||
g_list_concat (demux->old_streams, demux->active_streams);
|
demux->old_streams, demux->active_streams);
|
||||||
demux->active_streams = NULL;
|
|
||||||
|
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
@ -2628,6 +2658,14 @@ gst_qtdemux_stream_reset (QtDemuxStream * stream)
|
||||||
stream->stsd_entries_length = 0;
|
stream->stsd_entries_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QtDemuxStream *
|
||||||
|
gst_qtdemux_stream_ref (QtDemuxStream * stream)
|
||||||
|
{
|
||||||
|
g_atomic_int_add (&stream->ref_count, 1);
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_qtdemux_stream_unref (QtDemuxStream * stream)
|
gst_qtdemux_stream_unref (QtDemuxStream * stream)
|
||||||
{
|
{
|
||||||
|
@ -2644,14 +2682,6 @@ gst_qtdemux_stream_unref (QtDemuxStream * stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
|
|
||||||
{
|
|
||||||
qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
|
|
||||||
gst_qtdemux_stream_unref (stream);
|
|
||||||
qtdemux->n_streams--;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
|
gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
@ -2815,10 +2845,11 @@ qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
|
||||||
gboolean uses_sub_sample_encryption = FALSE;
|
gboolean uses_sub_sample_encryption = FALSE;
|
||||||
guint32 sample_count;
|
guint32 sample_count;
|
||||||
|
|
||||||
stream = QTDEMUX_FIRST_STREAM (qtdemux);
|
if (QTDEMUX_N_STREAMS (qtdemux) == 0)
|
||||||
if (!stream)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
|
||||||
|
|
||||||
structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
|
structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
|
||||||
if (!gst_structure_has_name (structure, "application/x-cenc")) {
|
if (!gst_structure_has_name (structure, "application/x-cenc")) {
|
||||||
GST_WARNING_OBJECT (qtdemux,
|
GST_WARNING_OBJECT (qtdemux,
|
||||||
|
@ -3171,7 +3202,6 @@ check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
|
||||||
guint i;
|
guint i;
|
||||||
guint64 movdur;
|
guint64 movdur;
|
||||||
GstClockTime prevdur;
|
GstClockTime prevdur;
|
||||||
GList *iter;
|
|
||||||
|
|
||||||
movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
|
movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
|
||||||
|
|
||||||
|
@ -3196,9 +3226,9 @@ check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
|
||||||
qtdemux->segment.stop = fixeddur;
|
qtdemux->segment.stop = fixeddur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (iter = qtdemux->active_streams, i = 0; iter;
|
|
||||||
iter = g_list_next (iter), i++) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
|
movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
|
||||||
if (movdur > stream->duration) {
|
if (movdur > stream->duration) {
|
||||||
|
@ -3517,7 +3547,7 @@ static inline QtDemuxStream *
|
||||||
qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
|
qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
|
||||||
{
|
{
|
||||||
QtDemuxStream *stream;
|
QtDemuxStream *stream;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (G_UNLIKELY (!id)) {
|
if (G_UNLIKELY (!id)) {
|
||||||
|
@ -3525,14 +3555,14 @@ qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
if (stream->track_id == id)
|
if (stream->track_id == id)
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
if (qtdemux->mss_mode) {
|
if (qtdemux->mss_mode) {
|
||||||
/* mss should have only 1 stream anyway */
|
/* mss should have only 1 stream anyway */
|
||||||
return QTDEMUX_FIRST_STREAM (qtdemux);
|
return QTDEMUX_NTH_STREAM (qtdemux, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3945,7 +3975,7 @@ qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
|
||||||
GstBuffer *pssh = NULL;
|
GstBuffer *pssh = NULL;
|
||||||
GstEvent *event = NULL;
|
GstEvent *event = NULL;
|
||||||
guint32 parent_box_type;
|
guint32 parent_box_type;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
if (G_UNLIKELY (pssh_size < 32U)) {
|
if (G_UNLIKELY (pssh_size < 32U)) {
|
||||||
GST_ERROR_OBJECT (qtdemux, "invalid box size");
|
GST_ERROR_OBJECT (qtdemux, "invalid box size");
|
||||||
|
@ -3966,8 +3996,8 @@ qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
|
||||||
/* Push an event containing the pssh box onto the queues of all streams. */
|
/* Push an event containing the pssh box onto the queues of all streams. */
|
||||||
event = gst_event_new_protection (sysid_string, pssh,
|
event = gst_event_new_protection (sysid_string, pssh,
|
||||||
(parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
|
(parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
GST_TRACE_OBJECT (qtdemux,
|
GST_TRACE_OBJECT (qtdemux,
|
||||||
"adding protection event for stream %s and system %s",
|
"adding protection event for stream %s and system %s",
|
||||||
stream->stream_id, sysid_string);
|
stream->stream_id, sysid_string);
|
||||||
|
@ -4183,7 +4213,7 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
|
||||||
* This way if the user opens a file where the first tfdt is 1 hour
|
* This way if the user opens a file where the first tfdt is 1 hour
|
||||||
* into the presentation, they will not have to wait 1 hour for run
|
* into the presentation, they will not have to wait 1 hour for run
|
||||||
* time to catch up and actual playback to start. */
|
* time to catch up and actual playback to start. */
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
|
GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
|
||||||
"performing an internal seek to %" GST_TIME_FORMAT,
|
"performing an internal seek to %" GST_TIME_FORMAT,
|
||||||
|
@ -4192,8 +4222,8 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
|
||||||
qtdemux->segment.start = min_dts;
|
qtdemux->segment.start = min_dts;
|
||||||
qtdemux->segment.time = qtdemux->segment.position = min_dts;
|
qtdemux->segment.time = qtdemux->segment.position = min_dts;
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
stream->time_position = min_dts;
|
stream->time_position = min_dts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4670,13 +4700,13 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
|
||||||
QtDemuxStream *ref_str = NULL;
|
QtDemuxStream *ref_str = NULL;
|
||||||
guint64 seg_media_start_mov; /* segment media start time in mov format */
|
guint64 seg_media_start_mov; /* segment media start time in mov format */
|
||||||
guint64 target_ts;
|
guint64 target_ts;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
/* Now we choose an arbitrary stream, get the previous keyframe timestamp
|
/* Now we choose an arbitrary stream, get the previous keyframe timestamp
|
||||||
* and finally align all the other streams on that timestamp with their
|
* and finally align all the other streams on that timestamp with their
|
||||||
* respective keyframes */
|
* respective keyframes */
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
/* No candidate yet, take the first stream */
|
/* No candidate yet, take the first stream */
|
||||||
if (!ref_str) {
|
if (!ref_str) {
|
||||||
|
@ -4771,10 +4801,10 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
|
||||||
ref_k_index = k_index;
|
ref_k_index = k_index;
|
||||||
|
|
||||||
/* Align them all on this */
|
/* Align them all on this */
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
guint32 index = 0;
|
guint32 index = 0;
|
||||||
GstClockTime seg_time = 0;
|
GstClockTime seg_time = 0;
|
||||||
QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
/* aligning reference stream again might lead to backing up to yet another
|
/* aligning reference stream again might lead to backing up to yet another
|
||||||
* keyframe (due to timestamp rounding issues),
|
* keyframe (due to timestamp rounding issues),
|
||||||
|
@ -5288,16 +5318,16 @@ next_segment:
|
||||||
static void
|
static void
|
||||||
gst_qtdemux_sync_streams (GstQTDemux * demux)
|
gst_qtdemux_sync_streams (GstQTDemux * demux)
|
||||||
{
|
{
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
if (demux->n_streams <= 1)
|
if (QTDEMUX_N_STREAMS (demux) <= 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
QtDemuxStream *stream;
|
QtDemuxStream *stream;
|
||||||
GstClockTime end_time;
|
GstClockTime end_time;
|
||||||
|
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (demux, i);
|
||||||
|
|
||||||
if (!stream->pad)
|
if (!stream->pad)
|
||||||
continue;
|
continue;
|
||||||
|
@ -5947,20 +5977,20 @@ static gboolean
|
||||||
gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
|
gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
|
||||||
{
|
{
|
||||||
const QtDemuxRandomAccessEntry *best_entry = NULL;
|
const QtDemuxRandomAccessEntry *best_entry = NULL;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (qtdemux);
|
GST_OBJECT_LOCK (qtdemux);
|
||||||
|
|
||||||
g_assert (qtdemux->n_streams > 0);
|
g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
|
||||||
|
|
||||||
/* first see if we can determine where to go to using mfra,
|
/* first see if we can determine where to go to using mfra,
|
||||||
* before we start clearing things */
|
* before we start clearing things */
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
const QtDemuxRandomAccessEntry *entry;
|
const QtDemuxRandomAccessEntry *entry;
|
||||||
QtDemuxStream *stream;
|
QtDemuxStream *stream;
|
||||||
gboolean is_audio_or_video;
|
gboolean is_audio_or_video;
|
||||||
|
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
if (stream->ra_entries == NULL)
|
if (stream->ra_entries == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -5994,10 +6024,10 @@ gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ok, now we can prepare for processing as of located moof */
|
/* ok, now we can prepare for processing as of located moof */
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream;
|
QtDemuxStream *stream;
|
||||||
|
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
|
||||||
g_free (stream->samples);
|
g_free (stream->samples);
|
||||||
stream->samples = NULL;
|
stream->samples = NULL;
|
||||||
|
@ -6020,7 +6050,7 @@ gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
|
||||||
|
|
||||||
GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
|
GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
|
||||||
"moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
|
"moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
|
GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
|
||||||
best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
|
best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
|
||||||
|
|
||||||
qtdemux->moof_offset = best_entry->moof_offset;
|
qtdemux->moof_offset = best_entry->moof_offset;
|
||||||
|
@ -6046,7 +6076,7 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
||||||
guint sample_size = 0;
|
guint sample_size = 0;
|
||||||
gboolean empty = 0;
|
gboolean empty = 0;
|
||||||
guint size;
|
guint size;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
if (qtdemux->fragmented_seek_pending) {
|
if (qtdemux->fragmented_seek_pending) {
|
||||||
GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
|
GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
|
||||||
|
@ -6061,10 +6091,10 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
||||||
/* Figure out the next stream sample to output, min_time is expressed in
|
/* Figure out the next stream sample to output, min_time is expressed in
|
||||||
* global time and runs over the edit list segments. */
|
* global time and runs over the edit list segments. */
|
||||||
min_time = G_MAXUINT64;
|
min_time = G_MAXUINT64;
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
GstClockTime position;
|
GstClockTime position;
|
||||||
|
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
position = stream->time_position;
|
position = stream->time_position;
|
||||||
|
|
||||||
/* position of -1 is EOS */
|
/* position of -1 is EOS */
|
||||||
|
@ -6091,8 +6121,8 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gap events for subtitle streams */
|
/* gap events for subtitle streams */
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
if (stream->pad && (stream->subtype == FOURCC_subp
|
if (stream->pad && (stream->subtype == FOURCC_subp
|
||||||
|| stream->subtype == FOURCC_text
|
|| stream->subtype == FOURCC_text
|
||||||
|| stream->subtype == FOURCC_sbtl)) {
|
|| stream->subtype == FOURCC_sbtl)) {
|
||||||
|
@ -6332,7 +6362,7 @@ pause:
|
||||||
/* fatal errors need special actions */
|
/* fatal errors need special actions */
|
||||||
/* check EOS */
|
/* check EOS */
|
||||||
if (ret == GST_FLOW_EOS) {
|
if (ret == GST_FLOW_EOS) {
|
||||||
if (qtdemux->n_streams == 0) {
|
if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
|
||||||
/* we have no streams, post an error */
|
/* we have no streams, post an error */
|
||||||
gst_qtdemux_post_no_playable_stream_error (qtdemux);
|
gst_qtdemux_post_no_playable_stream_error (qtdemux);
|
||||||
}
|
}
|
||||||
|
@ -6399,12 +6429,12 @@ static gboolean
|
||||||
has_next_entry (GstQTDemux * demux)
|
has_next_entry (GstQTDemux * demux)
|
||||||
{
|
{
|
||||||
QtDemuxStream *stream;
|
QtDemuxStream *stream;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
|
GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
|
||||||
|
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (demux, i);
|
||||||
|
|
||||||
if (stream->sample_index == -1) {
|
if (stream->sample_index == -1) {
|
||||||
stream->sample_index = 0;
|
stream->sample_index = 0;
|
||||||
|
@ -6435,13 +6465,13 @@ next_entry_size (GstQTDemux * demux)
|
||||||
QtDemuxStream *stream, *target_stream = NULL;
|
QtDemuxStream *stream, *target_stream = NULL;
|
||||||
guint64 smalloffs = (guint64) - 1;
|
guint64 smalloffs = (guint64) - 1;
|
||||||
QtDemuxSample *sample;
|
QtDemuxSample *sample;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
|
GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
|
||||||
demux->offset);
|
demux->offset);
|
||||||
|
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (demux, i);
|
||||||
|
|
||||||
if (stream->sample_index == -1) {
|
if (stream->sample_index == -1) {
|
||||||
stream->sample_index = 0;
|
stream->sample_index = 0;
|
||||||
|
@ -6586,7 +6616,6 @@ gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
|
||||||
{
|
{
|
||||||
if (G_UNLIKELY (demux->need_segment)) {
|
if (G_UNLIKELY (demux->need_segment)) {
|
||||||
gint i;
|
gint i;
|
||||||
GList *iter;
|
|
||||||
|
|
||||||
if (!demux->upstream_format_is_time) {
|
if (!demux->upstream_format_is_time) {
|
||||||
gst_qtdemux_map_and_push_segments (demux, &demux->segment);
|
gst_qtdemux_map_and_push_segments (demux, &demux->segment);
|
||||||
|
@ -6601,9 +6630,8 @@ gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
|
||||||
demux->need_segment = FALSE;
|
demux->need_segment = FALSE;
|
||||||
|
|
||||||
/* clear to send tags on all streams */
|
/* clear to send tags on all streams */
|
||||||
for (iter = demux->active_streams, i = 0; iter;
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
iter = g_list_next (iter), i++) {
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
|
||||||
gst_qtdemux_push_tags (demux, stream);
|
gst_qtdemux_push_tags (demux, stream);
|
||||||
if (CUR_STREAM (stream)->sparse) {
|
if (CUR_STREAM (stream)->sparse) {
|
||||||
GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
|
GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
|
||||||
|
@ -6656,12 +6684,12 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
|
||||||
|
|
||||||
if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
|
if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
|
||||||
gboolean is_gap_input = FALSE;
|
gboolean is_gap_input = FALSE;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
|
GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
|
||||||
|
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
QTDEMUX_STREAM (iter->data)->discont = TRUE;
|
QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we can land back on our feet in the case where upstream is
|
/* Check if we can land back on our feet in the case where upstream is
|
||||||
|
@ -6669,9 +6697,9 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
|
||||||
* in the case of trick-mode DASH for example) */
|
* in the case of trick-mode DASH for example) */
|
||||||
if (demux->upstream_format_is_time
|
if (demux->upstream_format_is_time
|
||||||
&& GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
|
&& GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
guint32 res;
|
guint32 res;
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
|
||||||
GST_LOG_OBJECT (demux,
|
GST_LOG_OBJECT (demux,
|
||||||
"track-id #%u , checking if offset %" G_GUINT64_FORMAT
|
"track-id #%u , checking if offset %" G_GUINT64_FORMAT
|
||||||
" is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
|
" is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
|
||||||
|
@ -6719,7 +6747,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
|
||||||
* previously received one. */
|
* previously received one. */
|
||||||
if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
|
if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
|
||||||
gst_qtdemux_process_adapter (demux, TRUE);
|
gst_qtdemux_process_adapter (demux, TRUE);
|
||||||
g_list_foreach (demux->active_streams,
|
g_ptr_array_foreach (demux->active_streams,
|
||||||
(GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
|
(GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6789,7 +6817,8 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
}
|
}
|
||||||
if (fourcc == FOURCC_mdat) {
|
if (fourcc == FOURCC_mdat) {
|
||||||
gint next_entry = next_entry_size (demux);
|
gint next_entry = next_entry_size (demux);
|
||||||
if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
|
if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
|
||||||
|
|| !demux->fragmented)) {
|
||||||
/* we have the headers, start playback */
|
/* we have the headers, start playback */
|
||||||
demux->state = QTDEMUX_STATE_MOVIE;
|
demux->state = QTDEMUX_STATE_MOVIE;
|
||||||
demux->neededbytes = next_entry;
|
demux->neededbytes = next_entry;
|
||||||
|
@ -6879,7 +6908,7 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
if (fourcc == FOURCC_moov) {
|
if (fourcc == FOURCC_moov) {
|
||||||
/* in usual fragmented setup we could try to scan for more
|
/* in usual fragmented setup we could try to scan for more
|
||||||
* and end up at the the moov (after mdat) again */
|
* and end up at the the moov (after mdat) again */
|
||||||
if (demux->got_moov && demux->n_streams > 0 &&
|
if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
|
||||||
(!demux->fragmented
|
(!demux->fragmented
|
||||||
|| demux->last_moov_offset == demux->offset)) {
|
|| demux->last_moov_offset == demux->offset)) {
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
|
@ -6904,9 +6933,8 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
demux->last_moov_offset = demux->offset;
|
demux->last_moov_offset = demux->offset;
|
||||||
|
|
||||||
/* Update streams with new moov */
|
/* Update streams with new moov */
|
||||||
demux->old_streams =
|
gst_qtdemux_stream_concat (demux,
|
||||||
g_list_concat (demux->old_streams, demux->active_streams);
|
demux->old_streams, demux->active_streams);
|
||||||
demux->active_streams = NULL;
|
|
||||||
|
|
||||||
qtdemux_parse_moov (demux, data, demux->neededbytes);
|
qtdemux_parse_moov (demux, data, demux->neededbytes);
|
||||||
qtdemux_node_dump (demux, demux->moov_node);
|
qtdemux_node_dump (demux, demux->moov_node);
|
||||||
|
@ -7045,12 +7073,12 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
gst_adapter_unmap (demux->adapter);
|
gst_adapter_unmap (demux->adapter);
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
|
||||||
if (demux->mdatbuffer && demux->n_streams) {
|
if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
|
||||||
gsize remaining_data_size = 0;
|
gsize remaining_data_size = 0;
|
||||||
|
|
||||||
/* the mdat was before the header */
|
/* the mdat was before the header */
|
||||||
GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
|
GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
|
||||||
demux->n_streams, demux->mdatbuffer);
|
QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
|
||||||
/* restore our adapter/offset view of things with upstream;
|
/* restore our adapter/offset view of things with upstream;
|
||||||
* put preceding buffered data ahead of current moov data.
|
* put preceding buffered data ahead of current moov data.
|
||||||
* This should also handle evil mdat, moov, mdat cases and alike */
|
* This should also handle evil mdat, moov, mdat cases and alike */
|
||||||
|
@ -7127,7 +7155,7 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
QtDemuxSample *sample;
|
QtDemuxSample *sample;
|
||||||
GstClockTime dts, pts, duration;
|
GstClockTime dts, pts, duration;
|
||||||
gboolean keyframe;
|
gboolean keyframe;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux,
|
GST_DEBUG_OBJECT (demux,
|
||||||
"BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
|
"BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
|
||||||
|
@ -7178,7 +7206,7 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
data = gst_adapter_map (demux->adapter, demux->todrop);
|
data = gst_adapter_map (demux->adapter, demux->todrop);
|
||||||
gst_byte_reader_init (&br, data + 8, demux->todrop);
|
gst_byte_reader_init (&br, data + 8, demux->todrop);
|
||||||
if (!qtdemux_parse_cenc_aux_info (demux,
|
if (!qtdemux_parse_cenc_aux_info (demux,
|
||||||
QTDEMUX_FIRST_STREAM (demux), &br,
|
QTDEMUX_NTH_STREAM (demux, 0), &br,
|
||||||
demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
|
demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
|
||||||
GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
|
GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
|
||||||
ret = GST_FLOW_ERROR;
|
ret = GST_FLOW_ERROR;
|
||||||
|
@ -7201,8 +7229,8 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
gst_qtdemux_check_send_pending_segment (demux);
|
gst_qtdemux_check_send_pending_segment (demux);
|
||||||
|
|
||||||
/* Figure out which stream this packet belongs to */
|
/* Figure out which stream this packet belongs to */
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
stream = QTDEMUX_STREAM (iter->data);
|
stream = QTDEMUX_NTH_STREAM (demux, i);
|
||||||
if (stream->sample_index >= stream->n_samples) {
|
if (stream->sample_index >= stream->n_samples) {
|
||||||
/* reset to be checked below G_UNLIKELY (stream == NULL) */
|
/* reset to be checked below G_UNLIKELY (stream == NULL) */
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
|
@ -7253,8 +7281,8 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
|
||||||
|
|
||||||
/* check if all streams are eos */
|
/* check if all streams are eos */
|
||||||
ret = GST_FLOW_EOS;
|
ret = GST_FLOW_EOS;
|
||||||
for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
|
||||||
if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
|
if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -10096,9 +10124,10 @@ qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
|
qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
|
||||||
|
QtDemuxStream ** stream2)
|
||||||
{
|
{
|
||||||
return (gint) stream1->track_id - (gint) stream2->track_id;
|
return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the traks.
|
/* parse the traks.
|
||||||
|
@ -12225,11 +12254,11 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
|
|
||||||
/* Insert and sort new stream in track-id order.
|
/* Insert and sort new stream in track-id order.
|
||||||
* This will help in comparing old/new streams during stream update check */
|
* This will help in comparing old/new streams during stream update check */
|
||||||
qtdemux->active_streams =
|
g_ptr_array_add (qtdemux->active_streams, stream);
|
||||||
g_list_insert_sorted (qtdemux->active_streams, stream,
|
g_ptr_array_sort (qtdemux->active_streams,
|
||||||
(GCompareFunc) qtdemux_track_id_compare_func);
|
(GCompareFunc) qtdemux_track_id_compare_func);
|
||||||
qtdemux->n_streams++;
|
GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
|
||||||
GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
|
QTDEMUX_N_STREAMS (qtdemux));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -12284,7 +12313,7 @@ gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
|
||||||
gint64 size, sys_bitrate, sum_bitrate = 0;
|
gint64 size, sys_bitrate, sum_bitrate = 0;
|
||||||
GstClockTime duration;
|
GstClockTime duration;
|
||||||
guint bitrate;
|
guint bitrate;
|
||||||
GList *iter;
|
gint i;
|
||||||
|
|
||||||
if (qtdemux->fragmented)
|
if (qtdemux->fragmented)
|
||||||
return;
|
return;
|
||||||
|
@ -12312,8 +12341,8 @@ gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
switch (str->subtype) {
|
switch (str->subtype) {
|
||||||
case FOURCC_soun:
|
case FOURCC_soun:
|
||||||
case FOURCC_vide:
|
case FOURCC_vide:
|
||||||
|
@ -12381,16 +12410,14 @@ static GstFlowReturn
|
||||||
qtdemux_prepare_streams (GstQTDemux * qtdemux)
|
qtdemux_prepare_streams (GstQTDemux * qtdemux)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GList *iter, *next;
|
gint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "prepare streams");
|
GST_DEBUG_OBJECT (qtdemux, "prepare streams");
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
guint32 sample_num = 0;
|
guint32 sample_num = 0;
|
||||||
|
|
||||||
next = iter->next;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
|
GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
|
||||||
stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
|
stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
|
||||||
|
|
||||||
|
@ -12415,13 +12442,15 @@ qtdemux_prepare_streams (GstQTDemux * qtdemux)
|
||||||
* in push mode, we'll just have to deal with it */
|
* in push mode, we'll just have to deal with it */
|
||||||
if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
|
if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
|
||||||
GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
|
GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
|
||||||
gst_qtdemux_remove_stream (qtdemux, stream);
|
g_ptr_array_remove_index (qtdemux->active_streams, i);
|
||||||
|
i--;
|
||||||
continue;
|
continue;
|
||||||
} else if (stream->track_id == qtdemux->chapters_track_id &&
|
} else if (stream->track_id == qtdemux->chapters_track_id &&
|
||||||
(stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
|
(stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
|
||||||
/* TODO - parse chapters track and expose it as GstToc; For now just ignore it
|
/* TODO - parse chapters track and expose it as GstToc; For now just ignore it
|
||||||
so that it doesn't look like a subtitle track */
|
so that it doesn't look like a subtitle track */
|
||||||
gst_qtdemux_remove_stream (qtdemux, stream);
|
g_ptr_array_remove_index (qtdemux->active_streams, i);
|
||||||
|
i--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12436,42 +12465,29 @@ qtdemux_prepare_streams (GstQTDemux * qtdemux)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList *
|
static gboolean
|
||||||
_stream_in_list (GList * list, QtDemuxStream * stream)
|
_stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
|
||||||
{
|
{
|
||||||
GList *iter;
|
return g_strcmp0 (stream->stream_id, stream_id) == 0;
|
||||||
|
|
||||||
for (iter = list; iter; iter = g_list_next (iter)) {
|
|
||||||
QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
|
|
||||||
if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
qtdemux_is_streams_update (GstQTDemux * qtdemux)
|
qtdemux_is_streams_update (GstQTDemux * qtdemux)
|
||||||
{
|
{
|
||||||
GList *new, *old;
|
gint i;
|
||||||
|
|
||||||
if (!qtdemux->active_streams)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* streams in list are sorted in track-id order */
|
|
||||||
for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
|
|
||||||
new = g_list_next (new), old = g_list_next (old)) {
|
|
||||||
|
|
||||||
/* Different stream-id, updated */
|
|
||||||
if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
|
|
||||||
QTDEMUX_STREAM (old->data)->stream_id))
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Different length, updated */
|
/* Different length, updated */
|
||||||
if (new != NULL || old != NULL)
|
if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* streams in list are sorted in track-id order */
|
||||||
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
|
/* Different stream-id, updated */
|
||||||
|
if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
|
||||||
|
QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12492,7 +12508,7 @@ qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
|
||||||
static gboolean
|
static gboolean
|
||||||
qtdemux_update_streams (GstQTDemux * qtdemux)
|
qtdemux_update_streams (GstQTDemux * qtdemux)
|
||||||
{
|
{
|
||||||
GList *iter, *next;
|
gint i;
|
||||||
g_assert (qtdemux->streams_aware);
|
g_assert (qtdemux->streams_aware);
|
||||||
|
|
||||||
/* At below, figure out which stream in active_streams has identical stream-id
|
/* At below, figure out which stream in active_streams has identical stream-id
|
||||||
|
@ -12504,31 +12520,31 @@ qtdemux_update_streams (GstQTDemux * qtdemux)
|
||||||
* old_streams : existing streams (belong to previous moov)
|
* old_streams : existing streams (belong to previous moov)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Count n_streams again */
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
qtdemux->n_streams = 0;
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
|
QtDemuxStream *oldstream = NULL;
|
||||||
for (iter = qtdemux->active_streams; iter; iter = next) {
|
guint target;
|
||||||
GList *tmp;
|
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
|
||||||
|
|
||||||
next = iter->next;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
|
GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
|
||||||
stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
|
stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
|
||||||
|
|
||||||
qtdemux->n_streams++;
|
if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
|
||||||
|
stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
|
||||||
|
oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
|
||||||
|
|
||||||
if ((tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
|
/* null pad stream cannot be reused */
|
||||||
&& QTDEMUX_STREAM (tmp->data)->pad) {
|
if (oldstream->pad == NULL)
|
||||||
QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
|
oldstream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldstream) {
|
||||||
GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
|
GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
|
||||||
|
|
||||||
if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
|
if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
|
/* we don't need to preserve order of old streams */
|
||||||
gst_qtdemux_stream_unref (oldstream);
|
g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
|
||||||
} else {
|
} else {
|
||||||
GstTagList *list;
|
GstTagList *list;
|
||||||
|
|
||||||
|
@ -12547,24 +12563,21 @@ qtdemux_update_streams (GstQTDemux * qtdemux)
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
qtdemux_expose_streams (GstQTDemux * qtdemux)
|
qtdemux_expose_streams (GstQTDemux * qtdemux)
|
||||||
{
|
{
|
||||||
GList *iter, *next;
|
gint i;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "exposing streams");
|
GST_DEBUG_OBJECT (qtdemux, "exposing streams");
|
||||||
|
|
||||||
if (!qtdemux_is_streams_update (qtdemux)) {
|
if (!qtdemux_is_streams_update (qtdemux)) {
|
||||||
GList *new, *old;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
|
GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
|
||||||
for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
new = g_list_next (new), old = g_list_next (old)) {
|
QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
if (!qtdemux_reuse_and_configure_stream (qtdemux,
|
QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
|
||||||
QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
|
if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_list_free_full (qtdemux->old_streams,
|
g_ptr_array_remove_range (qtdemux->old_streams,
|
||||||
(GDestroyNotify) gst_qtdemux_stream_unref);
|
0, qtdemux->old_streams->len);
|
||||||
qtdemux->old_streams = NULL;
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
@ -12573,8 +12586,8 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
|
||||||
if (!qtdemux_update_streams (qtdemux))
|
if (!qtdemux_update_streams (qtdemux))
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
} else {
|
} else {
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
|
||||||
GstTagList *list;
|
GstTagList *list;
|
||||||
|
|
||||||
/* now we have all info and can expose */
|
/* now we have all info and can expose */
|
||||||
|
@ -12591,9 +12604,8 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
|
||||||
gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
|
gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
|
||||||
|
|
||||||
/* If we have still old_streams, it's no more used stream */
|
/* If we have still old_streams, it's no more used stream */
|
||||||
for (iter = qtdemux->old_streams; iter; iter = next) {
|
for (i = 0; i < qtdemux->old_streams->len; i++) {
|
||||||
QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
|
QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
|
||||||
next = g_list_next (iter);
|
|
||||||
|
|
||||||
if (stream->pad) {
|
if (stream->pad) {
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
@ -12604,15 +12616,14 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
|
||||||
|
|
||||||
gst_pad_push_event (stream->pad, event);
|
gst_pad_push_event (stream->pad, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
|
|
||||||
gst_qtdemux_stream_unref (stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_ptr_array_remove_range (qtdemux->old_streams, 0, qtdemux->old_streams->len);
|
||||||
|
|
||||||
/* check if we should post a redirect in case there is a single trak
|
/* check if we should post a redirect in case there is a single trak
|
||||||
* and it is a redirecting trak */
|
* and it is a redirecting trak */
|
||||||
if (qtdemux->n_streams == 1 &&
|
if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
|
||||||
QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
|
QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
|
||||||
GstMessage *m;
|
GstMessage *m;
|
||||||
|
|
||||||
GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
|
GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
|
||||||
|
@ -12620,14 +12631,13 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
|
||||||
m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
|
m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
|
||||||
gst_structure_new ("redirect",
|
gst_structure_new ("redirect",
|
||||||
"new-location", G_TYPE_STRING,
|
"new-location", G_TYPE_STRING,
|
||||||
QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
|
QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
|
gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
|
||||||
qtdemux->posted_redirect = TRUE;
|
qtdemux->posted_redirect = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
|
g_ptr_array_foreach (qtdemux->active_streams,
|
||||||
qtdemux_do_allocation (QTDEMUX_STREAM (iter->data), qtdemux);
|
(GFunc) qtdemux_do_allocation, qtdemux);
|
||||||
}
|
|
||||||
|
|
||||||
qtdemux->need_segment = TRUE;
|
qtdemux->need_segment = TRUE;
|
||||||
|
|
||||||
|
|
|
@ -75,10 +75,9 @@ struct _GstQTDemux {
|
||||||
GMutex expose_lock;
|
GMutex expose_lock;
|
||||||
|
|
||||||
/* list of QtDemuxStream */
|
/* list of QtDemuxStream */
|
||||||
GList *active_streams;
|
GPtrArray *active_streams;
|
||||||
GList *old_streams;
|
GPtrArray *old_streams;
|
||||||
|
|
||||||
gint n_streams;
|
|
||||||
gint n_video_streams;
|
gint n_video_streams;
|
||||||
gint n_audio_streams;
|
gint n_audio_streams;
|
||||||
gint n_sub_streams;
|
gint n_sub_streams;
|
||||||
|
|
Loading…
Reference in a new issue