diff --git a/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c b/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c index fb19acf4eb..73e1c063e5 100644 --- a/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c +++ b/subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c @@ -172,6 +172,10 @@ struct _TSDemuxStream /* Output data */ PendingPacketState state; + /* PES header being reconstructed (optional, allocated) */ + guint8 *pending_header_data; + guint pending_header_size; + /* Data being reconstructed (allocated) */ guint8 *data; @@ -2144,6 +2148,9 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream, GstTSDemux * tsdemux, g_free (stream->data); stream->data = NULL; + g_free (stream->pending_header_data); + stream->pending_header_data = NULL; + stream->pending_header_size = 0; stream->state = PENDING_PACKET_EMPTY; stream->expected_size = 0; stream->allocated_size = 0; @@ -2598,9 +2605,26 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream, GST_MEMDUMP ("Header buffer", data, MIN (length, 32)); + if (G_UNLIKELY (stream->pending_header_data)) { + /* Accumulate with previous header if present */ + stream->pending_header_data = + g_realloc (stream->pending_header_data, + stream->pending_header_size + length); + memcpy (stream->pending_header_data + stream->pending_header_size, data, + length); + data = stream->pending_header_data; + length = stream->pending_header_size + length; + } + parseres = mpegts_parse_pes_header (data, length, &header); - if (G_UNLIKELY (parseres == PES_PARSING_NEED_MORE)) - goto discont; + + if (G_UNLIKELY (parseres == PES_PARSING_NEED_MORE)) { + /* This can happen if PES header is bigger than a packet. */ + if (!stream->pending_header_data) + stream->pending_header_data = g_memdup2 (data, length); + stream->pending_header_size = length; + return; + } if (G_UNLIKELY (parseres == PES_PARSING_BAD)) { GST_WARNING ("Error parsing PES header. pid: 0x%x stream_type: 0x%x", stream->stream.pid, stream->stream.stream_type); @@ -2660,9 +2684,20 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream, stream->state = PENDING_PACKET_BUFFER; + if (stream->pending_header_data) { + g_free (stream->pending_header_data); + stream->pending_header_data = NULL; + stream->pending_header_size = 0; + } + return; discont: + if (stream->pending_header_data) { + g_free (stream->pending_header_data); + stream->pending_header_data = NULL; + stream->pending_header_size = 0; + } stream->state = PENDING_PACKET_DISCONT; return; } @@ -2699,6 +2734,10 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, g_free (stream->data); stream->data = NULL; } + if (G_UNLIKELY (stream->pending_header_data)) { + g_free (stream->pending_header_data); + stream->pending_header_data = NULL; + } stream->state = PENDING_PACKET_HEADER; } else { GST_ELEMENT_WARNING_WITH_DETAILS (demux, STREAM, DEMUX, @@ -2754,6 +2793,10 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, g_free (stream->data); stream->data = NULL; } + if (G_UNLIKELY (stream->pending_header_data)) { + g_free (stream->pending_header_data); + stream->pending_header_data = NULL; + } stream->continuity_counter = CONTINUITY_UNSET; break; }