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/1852>
This commit is contained in:
Edward Hervey 2022-03-04 14:17:47 +01:00 committed by GStreamer Marge Bot
parent e42d10431d
commit 03b1790e0d

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