From 881350f34cac858be52ce5b59e71ed7069bcb17a Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Fri, 30 Mar 2012 19:19:12 +0200 Subject: [PATCH 1/4] tsdemux: Fix several leaks * dont' leak buffers when a stream is in discont state * don't leak buffers when a program is removed/deactivated * remove all programs when disposing --- gst/mpegtsdemux/mpegtsbase.c | 18 ++++++++++--- gst/mpegtsdemux/tsdemux.c | 51 +++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index c3741bc8df..345357a418 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -93,6 +93,9 @@ static void mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info); static void mpegts_base_get_tags_from_eit (MpegTSBase * base, GstStructure * eit_info); +static gboolean +remove_each_program (gpointer key, MpegTSBaseProgram * program, + MpegTSBase * base); GST_BOILERPLATE_FULL (MpegTSBase, mpegts_base, GstElement, GST_TYPE_ELEMENT, _extra_init); @@ -226,6 +229,9 @@ mpegts_base_reset (MpegTSBase * base) base->upstream_live = FALSE; base->queried_latency = FALSE; + g_hash_table_foreach_remove (base->programs, (GHRFunc) remove_each_program, + base); + if (klass->reset) klass->reset (base); } @@ -1237,20 +1243,26 @@ mpegts_base_get_tags_from_eit (MpegTSBase * base, GstStructure * eit_info) } } -static void +static gboolean remove_each_program (gpointer key, MpegTSBaseProgram * program, MpegTSBase * base) { + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + /* First deactivate it */ mpegts_base_deactivate_program (base, program); /* Then remove it */ - mpegts_base_remove_program (base, program->program_number); + if (klass->program_stopped) + klass->program_stopped (base, program); + + return TRUE; } static gboolean gst_mpegts_base_handle_eos (MpegTSBase * base) { - g_hash_table_foreach (base->programs, (GHFunc) remove_each_program, base); + g_hash_table_foreach_remove (base->programs, (GHRFunc) remove_each_program, + base); /* finally remove */ return TRUE; } diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index e88a576e25..54318f03b0 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -249,6 +249,7 @@ static void gst_ts_demux_get_property (GObject * object, guint prop_id, static void gst_ts_demux_flush_streams (GstTSDemux * tsdemux); static GstFlowReturn gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream); +static void gst_ts_demux_stream_flush (TSDemuxStream * stream); static gboolean push_event (MpegTSBase * base, GstEvent * event); static void _extra_init (GType type); @@ -998,6 +999,7 @@ gst_ts_demux_stream_removed (MpegTSBase * base, MpegTSBaseStream * bstream) } stream->pad = NULL; } + gst_ts_demux_stream_flush (stream); stream->flow_return = GST_FLOW_NOT_LINKED; } @@ -1030,6 +1032,12 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream) memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS); stream->nbpending = 0; + if (stream->currentlist) { + g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL); + g_list_free (stream->currentlist); + stream->currentlist = NULL; + } + stream->expected_size = 0; stream->current_size = 0; stream->current = NULL; @@ -1346,21 +1354,35 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, } } - if (stream->state == PENDING_PACKET_HEADER) { - GST_LOG ("HEADER: appending data to array"); - /* Append to the array */ - stream->pendingbuffers[stream->nbpending++] = buf; - stream->current_size += GST_BUFFER_SIZE (buf); + switch (stream->state) { + case PENDING_PACKET_HEADER: + { + GST_LOG ("HEADER: appending data to array"); + /* Append to the array */ + stream->pendingbuffers[stream->nbpending++] = buf; + stream->current_size += GST_BUFFER_SIZE (buf); - /* parse the header */ - gst_ts_demux_parse_pes_header (demux, stream); - } else if (stream->state == PENDING_PACKET_BUFFER) { - GST_LOG ("BUFFER: appending data to bufferlist"); - stream->currentlist = g_list_prepend (stream->currentlist, buf); - stream->current_size += GST_BUFFER_SIZE (buf); + /* parse the header */ + gst_ts_demux_parse_pes_header (demux, stream); + break; + } + case PENDING_PACKET_BUFFER: + { + GST_LOG ("BUFFER: appending data to bufferlist"); + stream->currentlist = g_list_prepend (stream->currentlist, buf); + stream->current_size += GST_BUFFER_SIZE (buf); + break; + } + case PENDING_PACKET_DISCONT: + { + GST_LOG ("DISCONT: dropping buffer"); + gst_buffer_unref (packet->buffer); + break; + } + default: + break; } - return; } @@ -1464,8 +1486,10 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) goto beach; } - if (G_UNLIKELY (stream->state != PENDING_PACKET_BUFFER)) + if (G_UNLIKELY (stream->state != PENDING_PACKET_BUFFER)) { + GST_LOG ("state:%d, returning", stream->state); goto beach; + } if (G_UNLIKELY (!stream->active)) activate_pad_for_stream (demux, stream); @@ -1485,6 +1509,7 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) GST_LOG_OBJECT (stream->pad, "Putting pending data into GstBufferList"); stream->currentlist = g_list_reverse (stream->currentlist); gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist); + stream->currentlist = NULL; gst_buffer_list_iterator_free (stream->currentit); firstbuffer = gst_buffer_list_get (stream->current, 0, 0); From cd728627af821de210f08463c8fb25157c9cabf8 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 2 Apr 2012 15:25:16 +0200 Subject: [PATCH 2/4] mpegtsbase: Don't leak corrupt section packet buffer --- gst/mpegtsdemux/mpegtsbase.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index 345357a418..7193429d95 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -1399,9 +1399,11 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf) based = mpegts_base_handle_psi (base, §ion); gst_buffer_unref (section.buffer); - if (G_UNLIKELY (!based)) + if (G_UNLIKELY (!based)) { + gst_buffer_unref (packet.buffer); /* bad PSI table */ goto next; + } } /* we need to push section packet downstream */ res = mpegts_base_push (base, &packet, §ion); From dd6550a66343bb0a27ef649fb352a29a2810a77d Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 2 Apr 2012 15:25:46 +0200 Subject: [PATCH 3/4] mpegtspacketizer: Don't leak buffer in fast variant --- gst/mpegtsdemux/mpegtspacketizer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index 6e0335a280..41ff6dd370 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -2375,8 +2375,13 @@ MpegTSPacketizerPacketReturn mpegts_packetizer_process_next_packet (MpegTSPacketizer2 * packetizer) { MpegTSPacketizerPacket packet; + MpegTSPacketizerPacketReturn ret; - return mpegts_packetizer_next_packet (packetizer, &packet); + ret = mpegts_packetizer_next_packet (packetizer, &packet); + if (packet.buffer) + gst_buffer_unref (packet.buffer); + + return ret; } void From 6800d0c4e086f97d0595465f55d2ac2143decd1e Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 2 Apr 2012 15:26:28 +0200 Subject: [PATCH 4/4] tsdemux: Clear bufferlist/iterator when removing streams --- gst/mpegtsdemux/tsdemux.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index 54318f03b0..8b97b8e432 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -1032,6 +1032,16 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream) memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS); stream->nbpending = 0; + if (stream->current) { + gst_buffer_list_unref (stream->current); + stream->current = NULL; + } + + if (stream->currentit) { + gst_buffer_list_iterator_free (stream->currentit); + stream->currentit = NULL; + } + if (stream->currentlist) { g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL); g_list_free (stream->currentlist);