This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit ff818b87bf1cfee7a10196e90d0df8de44e9a771
Author:     Kacper Michajłow <[email protected]>
AuthorDate: Sat Jul 4 20:00:59 2026 +0200
Commit:     Kacper Michajłow <[email protected]>
CommitDate: Tue Jul 28 17:55:33 2026 +0200

    avformat/mpeg: fix demuxing of DVD-Audio LPCM
    
    Substream 0xa0 packets without the DVD-Video dynamic range control
    marker byte were assumed to be MLP, while in DVD-Audio AOBs substream
    0xa0 always carries LPCM (MLP uses 0xa1), so hi-res LPCM streams were
    misdetected and decoded as garbage. Classify them as PCM_DVDA and keep
    the private stream header in the packet for the decoder to parse, as
    its length is variable and it carries the audio format.
    
    Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavformat/mpeg.c | 68 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 19 deletions(-)

diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index 29abe329b9..43bbf0ef9f 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -488,6 +488,7 @@ static int mpegps_read_packet(AVFormatContext *s,
     FFStream *sti;
     int len, startcode, i, es_type, ret;
     int pcm_dvd = 0;
+    int pcm_dvda = 0;
     int request_probe= 0;
     enum AVCodecID codec_id = AV_CODEC_ID_NONE;
     enum AVMediaType type;
@@ -503,19 +504,33 @@ redo:
             goto skip;
 
         if (!m->raw_ac3) {
-            /* audio: skip header */
-            avio_skip(s->pb, 3);
-            len -= 3;
-            if (startcode >= 0xb0 && startcode <= 0xbf) {
-                /* MLP/TrueHD audio has a 4-byte header */
-                avio_r8(s->pb);
-                len--;
-            } else if (startcode >= 0xa0 && startcode <= 0xaf) {
-                ret = ffio_ensure_seekback(s->pb, 3);
+            if (startcode >= 0xa0 && startcode <= 0xaf) {
+                uint8_t header[6];
+
+                /* Classify the LPCM/MLP substream here; its header is
+                 * skipped at "found" below, once the stream codec is known. */
+                if (len < 6)
+                    goto skip;
+                ret = ffio_ensure_seekback(s->pb, 6);
                 if (ret < 0)
                     return ret;
-                pcm_dvd = (avio_rb24(s->pb) & 0xFF) == 0x80;
-                avio_skip(s->pb, -3);
+                if (avio_read(s->pb, header, 6) != 6)
+                    return AVERROR_INVALIDDATA;
+                avio_seek(s->pb, -6, SEEK_CUR);
+                /* DVD-Video LPCM has the dynamic range control byte here, 
while
+                 * DVD-Audio LPCM and MLP do not. Only substream 0xa0 carries
+                 * LPCM in DVD-Audio AOBs, MLP uses substream 0xa1. */
+                pcm_dvd = header[5] == 0x80;
+                pcm_dvda = startcode == 0xa0 && !pcm_dvd;
+            } else {
+                /* audio: skip header */
+                avio_skip(s->pb, 3);
+                len -= 3;
+                if (startcode >= 0xb0 && startcode <= 0xbf) {
+                    /* MLP/TrueHD audio has a 4-byte header */
+                    avio_r8(s->pb);
+                    len--;
+                }
             }
         }
     }
@@ -602,7 +617,9 @@ redo:
         codec_id = AV_CODEC_ID_DTS;
     } else if (startcode >= 0xa0 && startcode <= 0xaf) {
         type     = AVMEDIA_TYPE_AUDIO;
-        if (!pcm_dvd) {
+        if (pcm_dvda) {
+            codec_id = AV_CODEC_ID_PCM_DVDA;
+        } else if (!pcm_dvd) {
             codec_id = AV_CODEC_ID_MLP;
         } else {
             codec_id = AV_CODEC_ID_PCM_DVD;
@@ -648,13 +665,26 @@ skip:
 found:
     if (st->discard >= AVDISCARD_ALL)
         goto skip;
-    if (startcode >= 0xa0 && startcode <= 0xaf) {
-      if (st->codecpar->codec_id == AV_CODEC_ID_MLP) {
-            if (len < 6)
-                goto skip;
-            avio_skip(s->pb, 6);
-            len -=6;
-      }
+    if (startcode >= 0xa0 && startcode <= 0xaf && !m->raw_ac3) {
+        int header_len = 0;
+        /* Skip the substream headers of codecs whose decoders do not expect
+         * them. AV_CODEC_ID_PCM_DVDA parses the header from the packet. */
+        if (st->codecpar->codec_id == AV_CODEC_ID_MLP) {
+            /* 3-byte substream header + 6-byte MLP header */
+            header_len = 9;
+        } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) {
+            header_len = 3;
+        }
+        if (len <= header_len)
+            goto skip;
+        avio_skip(s->pb, header_len);
+        len -= header_len;
+    } else if (startcode >= 0xa0 && startcode <= 0xaf &&
+               st->codecpar->codec_id == AV_CODEC_ID_MLP) {
+        if (len < 6)
+            goto skip;
+        avio_skip(s->pb, 6);
+        len -= 6;
     }
     ret = av_get_packet(s->pb, pkt, len);
 

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to