Skip to content

Strip DVD private_stream_1 sub-stream header in PsExtractor#3328

Open
TsaiHao wants to merge 1 commit into
androidx:mainfrom
TsaiHao:fix-ps-private-stream1-substream-header
Open

Strip DVD private_stream_1 sub-stream header in PsExtractor#3328
TsaiHao wants to merge 1 commit into
androidx:mainfrom
TsaiHao:fix-ps-private-stream1-substream-header

Conversation

@TsaiHao

@TsaiHao TsaiHao commented Jul 10, 2026

Copy link
Copy Markdown

In an MPEG Program Stream, AC-3 (and DTS/LPCM) audio is carried in private_stream_1 (PES stream id 0xBD). In DVD-style content each such PES packet begins with a 4-byte sub-stream header immediately after the PES header: sub_stream_id (0x80-0x87 AC-3, 0x88-0x8F DTS, 0xA0-0xA7 LPCM), number_of_frame_headers and first_access_unit_pointer.

PsExtractor.PesReader.consume() stripped only the PES header and PTS/DTS extension, forwarding the sub-stream header straight into the audio reader as if it were elementary data. Because audio sync frames do not align to PES packet boundaries, these 4 bytes land inside the frame spanning each boundary and corrupt it, producing garbled audio (and decoder errors such as Dolby MS12 "UDC Node: Error extracting BSI metadata (err 1021)") when playing MPEG-PS content that VLC/ffmpeg play correctly.

Skip the sub-stream header for private_stream_1 packets before handing the payload to the elementary stream reader, matching ffmpeg's mpegps demuxer.

Adds a regression test with a small MPEG-PS asset whose AC-3 frames straddle PES boundaries (the existing single-packet sample_ac3.ps cannot expose this).

Issue: #3327

In an MPEG Program Stream, AC-3 (and DTS/LPCM) audio is carried in
private_stream_1 (PES stream id 0xBD). In DVD-style content each such PES
packet begins with a 4-byte sub-stream header immediately after the PES
header: sub_stream_id (0x80-0x87 AC-3, 0x88-0x8F DTS, 0xA0-0xA7 LPCM),
number_of_frame_headers and first_access_unit_pointer.

`PsExtractor.PesReader.consume()` stripped only the PES header and PTS/DTS
extension, forwarding the sub-stream header straight into the audio reader
as if it were elementary data. Because audio sync frames do not align to
PES packet boundaries, these 4 bytes land inside the frame spanning each
boundary and corrupt it, producing garbled audio (and decoder errors such
as Dolby MS12 "UDC Node: Error extracting BSI metadata (err 1021)") when
playing MPEG-PS content that VLC/ffmpeg play correctly.

Skip the sub-stream header for private_stream_1 packets before handing the
payload to the elementary stream reader, matching ffmpeg's mpegps demuxer.

Adds a regression test with a small MPEG-PS asset whose AC-3 frames straddle
PES boundaries (the existing single-packet sample_ac3.ps cannot expose this).

Issue: androidx#3327
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant