tsdemux: Handle PES headers bigger than a mpeg-ts packet

While the actual PES header parser could notify us that it needed more data, we
would never actually act on it.

This commit will accumulate incoming packets in such situation and re-attempt
the header parsing.

Fixes #1027

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1858>
This commit is contained in:
Edward Hervey 2022-03-04 14:17:47 +01:00 committed by Tim-Philipp Müller
parent ca273f3454
commit 5ff65fbca7

View file

@ -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;
}