tsdemux: Push GAP events *after* deactivating old programs

The order in which program switch must happen is:
1) drain all data on old pads (but don't push EOS)
2) add new pads (but don't push any data on them)
3) Push EOS and remove old pads
4) Start pushing data on new pads

There was one caveat in this implementation, which is that when
we activate a sparse pad (step 2) we would push a GAP event. The problem
is that, while being an event, it is actually *data*.

We therefore need to make sure pushing those GAP event is done at the step
we start pushing data.

https://bugzilla.gnome.org/show_bug.cgi?id=750402
This commit is contained in:
Edward Hervey 2015-10-20 17:22:23 +02:00 committed by Edward Hervey
parent 7336294635
commit 531117b7df

View file

@ -1695,14 +1695,6 @@ activate_pad_for_stream (GstTSDemux * tsdemux, TSDemuxStream * stream)
gst_element_add_pad ((GstElement *) tsdemux, stream->pad);
stream->active = TRUE;
GST_DEBUG_OBJECT (stream->pad, "done adding pad");
/* force sending of pending sticky events which have been stored on the
* pad already and which otherwise would only be sent on the first buffer
* or serialized event (which means very late in case of subtitle streams),
* and playsink waits for stream-start or another serialized event */
if (stream->sparse) {
GST_DEBUG_OBJECT (stream->pad, "sparse stream, pushing GAP event");
gst_pad_push_event (stream->pad, gst_event_new_gap (0, 0));
}
} else if (((MpegTSBaseStream *) stream)->stream_type != 0xff) {
GST_DEBUG_OBJECT (tsdemux,
"stream %p (pid 0x%04x, type:0x%02x) has no pad", stream,
@ -1822,11 +1814,29 @@ gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program)
TSDemuxStream *stream = (TSDemuxStream *) tmp->data;
activate_pad_for_stream (demux, stream);
}
/* If there was a previous program, now is the time to deactivate it
* and remove old pads (including pushing EOS) */
if (demux->previous_program) {
GST_DEBUG ("Deactivating previous program");
mpegts_base_deactivate_and_free_program (base, demux->previous_program);
demux->previous_program = NULL;
}
/* If any of the stream is sparse, push a GAP event before anything else
* This is done here, and not in activate_pad_for_stream() because pushing
* a GAP event *is* considering data, and we want to ensure the (potential)
* old pads are all removed before we push any data on the new ones */
for (tmp = program->stream_list; tmp; tmp = tmp->next) {
TSDemuxStream *stream = (TSDemuxStream *) tmp->data;
if (stream->sparse) {
/* force sending of pending sticky events which have been stored on the
* pad already and which otherwise would only be sent on the first buffer
* or serialized event (which means very late in case of subtitle streams),
* and playsink waits for stream-start or another serialized event */
GST_DEBUG_OBJECT (stream->pad, "sparse stream, pushing GAP event");
gst_pad_push_event (stream->pad, gst_event_new_gap (0, 0));
}
}
gst_element_no_more_pads ((GstElement *) demux);
}
}