mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
pesparse: Refactory secondary PES extension handling
Some streams had wrong values for the stream_id_extension, make sure we only remember the valid ones. For streams with PES_extension_field_length == 0, assume there's nothing else. For streams that state they have a TREF extension but don't have enough data to store it, just assume it was produced by a non-compliant muxer and skip the remaining data. Only store remaining data in stream_id_extension_data instead of storing data we already parse.
This commit is contained in:
parent
131c263248
commit
21ebc7708d
2 changed files with 52 additions and 32 deletions
|
@ -256,7 +256,12 @@ mpegts_parse_pes_header (const guint8 * data, gsize length, PESHeader * res)
|
||||||
/* PES extension */
|
/* PES extension */
|
||||||
flags = *data++;
|
flags = *data++;
|
||||||
length -= 1;
|
length -= 1;
|
||||||
GST_DEBUG ("PES_extension_flag 0x%02x", flags);
|
GST_DEBUG ("PES_extension_flag: %s%s%s%s%s%s",
|
||||||
|
flags & 0x80 ? "PES_private_data " : "",
|
||||||
|
flags & 0x40 ? "pack_header_field " : "",
|
||||||
|
flags & 0x20 ? "program_packet_sequence_counter " : "",
|
||||||
|
flags & 0x10 ? "P-STD_buffer " : "",
|
||||||
|
flags & 0x01 ? "PES_extension_flag_2" : "", flags & 0xf1 ? "" : "<none>");
|
||||||
|
|
||||||
if (flags & 0x80) {
|
if (flags & 0x80) {
|
||||||
/* PES_private data */
|
/* PES_private data */
|
||||||
|
@ -292,7 +297,6 @@ mpegts_parse_pes_header (const guint8 * data, gsize length, PESHeader * res)
|
||||||
goto need_more_data;
|
goto need_more_data;
|
||||||
|
|
||||||
val8 = *data++;
|
val8 = *data++;
|
||||||
/* GRMBL, this is most often wrong */
|
|
||||||
if (G_UNLIKELY ((val8 & 0x80) != 0x80))
|
if (G_UNLIKELY ((val8 & 0x80) != 0x80))
|
||||||
goto bad_sequence_marker1;
|
goto bad_sequence_marker1;
|
||||||
res->program_packet_sequence_counter = val8 & 0x7f;
|
res->program_packet_sequence_counter = val8 & 0x7f;
|
||||||
|
@ -300,7 +304,6 @@ mpegts_parse_pes_header (const guint8 * data, gsize length, PESHeader * res)
|
||||||
res->program_packet_sequence_counter);
|
res->program_packet_sequence_counter);
|
||||||
|
|
||||||
val8 = *data++;
|
val8 = *data++;
|
||||||
/* GRMBL, this is most often wrong */
|
|
||||||
if (G_UNLIKELY ((val8 & 0x80) != 0x80))
|
if (G_UNLIKELY ((val8 & 0x80) != 0x80))
|
||||||
goto bad_sequence_marker2;
|
goto bad_sequence_marker2;
|
||||||
res->MPEG1_MPEG2_identifier = (val8 >> 6) & 0x1;
|
res->MPEG1_MPEG2_identifier = (val8 >> 6) & 0x1;
|
||||||
|
@ -324,37 +327,52 @@ mpegts_parse_pes_header (const guint8 * data, gsize length, PESHeader * res)
|
||||||
length -= 2;
|
length -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & 0x01) {
|
/* jump if we don't have a PES 2nd extension */
|
||||||
/* Extension flag 2 */
|
if (!flags & 0x01)
|
||||||
if (G_UNLIKELY (length < 1))
|
goto stuffing_byte;
|
||||||
goto need_more_data;
|
|
||||||
|
|
||||||
val8 = *data++;
|
/* Extension flag 2 */
|
||||||
length -= 1;
|
if (G_UNLIKELY (length < 1))
|
||||||
|
goto need_more_data;
|
||||||
|
|
||||||
if (!(val8 & 0x80))
|
val8 = *data++;
|
||||||
goto bad_extension_marker_2;
|
length -= 1;
|
||||||
|
|
||||||
res->extension_field_length = val8 & 0x7f;
|
if (!(val8 & 0x80))
|
||||||
if (G_UNLIKELY (length < res->extension_field_length))
|
goto bad_extension_marker_2;
|
||||||
goto need_more_data;
|
|
||||||
|
|
||||||
GST_LOG ("extension_field_length : %" G_GSIZE_FORMAT,
|
res->extension_field_length = val8 & 0x7f;
|
||||||
res->extension_field_length);
|
|
||||||
|
|
||||||
if (res->extension_field_length) {
|
/* Skip empty extensions */
|
||||||
flags = *data++;
|
if (G_UNLIKELY (res->extension_field_length == 0))
|
||||||
/* Only valid if stream_id_extension_flag == 0x0 */
|
goto stuffing_byte;
|
||||||
if (!(flags & 0x80)) {
|
|
||||||
res->stream_id_extension = flags & 0x7f;
|
if (G_UNLIKELY (length < res->extension_field_length))
|
||||||
GST_LOG ("stream_id_extension : 0x%02x", res->stream_id_extension);
|
goto need_more_data;
|
||||||
res->stream_id_extension_data = data;
|
|
||||||
GST_MEMDUMP ("stream_id_extension_data",
|
flags = *data++;
|
||||||
res->stream_id_extension_data, res->extension_field_length);
|
res->extension_field_length -= 1;
|
||||||
} else {
|
|
||||||
GST_LOG ("tref_extension : %d", flags & 0x01);
|
if (!(flags & 0x80)) {
|
||||||
}
|
/* Only valid if stream_id_extension_flag == 0x0 */
|
||||||
}
|
res->stream_id_extension = flags;
|
||||||
|
GST_LOG ("stream_id_extension : 0x%02x", res->stream_id_extension);
|
||||||
|
} else if (!(flags & 0x01)) {
|
||||||
|
/* Skip broken streams (that use stream_id_extension with highest bit set
|
||||||
|
* for example ...) */
|
||||||
|
if (G_UNLIKELY (res->extension_field_length < 5))
|
||||||
|
goto stuffing_byte;
|
||||||
|
|
||||||
|
GST_LOG ("TREF field present");
|
||||||
|
data += 5;
|
||||||
|
res->extension_field_length -= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extension field data */
|
||||||
|
if (res->extension_field_length) {
|
||||||
|
res->stream_id_extension_data = data;
|
||||||
|
GST_MEMDUMP ("stream_id_extension_data",
|
||||||
|
res->stream_id_extension_data, res->extension_field_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
stuffing_byte:
|
stuffing_byte:
|
||||||
|
|
|
@ -185,9 +185,11 @@ typedef struct {
|
||||||
guint32 P_STD_buffer_size; /* P-STD buffer size in bytes (0 if invalid
|
guint32 P_STD_buffer_size; /* P-STD buffer size in bytes (0 if invalid
|
||||||
* or not present */
|
* or not present */
|
||||||
|
|
||||||
gsize extension_field_length;
|
guint8 stream_id_extension; /* Public range (0x00 - 0x3f) only valid if stream_id == ID_EXTENDED_STREAM_ID
|
||||||
guint8 stream_id_extension; /* Only valid if stream_id == ID_EXTENDED_STREAM_ID */
|
* Private range (0x40 - 0xff) can be present in any stream type */
|
||||||
const guint8* stream_id_extension_data;
|
|
||||||
|
gsize extension_field_length; /* Length of remaining extension field data */
|
||||||
|
const guint8* stream_id_extension_data; /* Valid if extension_field_length != 0 */
|
||||||
} PESHeader;
|
} PESHeader;
|
||||||
|
|
||||||
G_GNUC_INTERNAL PESParsingResult mpegts_parse_pes_header (const guint8* data,
|
G_GNUC_INTERNAL PESParsingResult mpegts_parse_pes_header (const guint8* data,
|
||||||
|
|
Loading…
Reference in a new issue