[FFmpeg-devel,4/6] Fix detecting ATRAC3 audio from MPS files

Submitted by misty@brew.sh on Jan. 5, 2018, 11:34 a.m.

Details

Message ID 20180105113448.13917-5-misty@brew.sh
State New
Headers show

Commit Message

misty@brew.sh Jan. 5, 2018, 11:34 a.m.
From: Misty De Meo <mistydemeo@gmail.com>

MPS files are MPEG files used on PSP Video discs. They lack
the PSMF header used by .pms files, and so the special casing
in the original patch fails to support their audio. This patch
fixes this by unconditionally reading a new byte for the startcode
for PRIVATE_STREAM_1 sections, and doing the comparison on that
to find ATRAC-3 streams. In my testing, it works fine for both MPS
and PSMF files.
---
 Changelog          |  1 +
 libavformat/mpeg.c | 50 +++++++++++++++++++++++++++-----------------------
 libavformat/mpeg.h |  1 +
 3 files changed, 29 insertions(+), 23 deletions(-)

Patch hide | download patch | download mbox

diff --git a/Changelog b/Changelog
index 3d966c202b..d4761ec7f9 100644
--- a/Changelog
+++ b/Changelog
@@ -33,6 +33,7 @@  version <next>:
 - deconvolve video filter
 - entropy video filter
 - hilbert audio filter source
+- ATRAC-3 support for Sony PSP MPEG files
 
 
 version 3.4:
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index 895c6fb231..afde768199 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -148,8 +148,6 @@  static int mpegps_read_header(AVFormatContext *s)
     avio_get_str(s->pb, 6, buffer, sizeof(buffer));
     if (!memcmp("IMKH", buffer, 4)) {
         m->imkh_cctv = 1;
-    } else if (!memcmp("PSMF00", buffer, 6)) {
-        m->sony_psmf = 1;
     } else if (!memcmp("Sofdec", buffer, 6)) {
         m->sofdec = 1;
     } else
@@ -444,7 +442,7 @@  redo:
         goto redo;
     }
 
-    if (startcode == PRIVATE_STREAM_1 && !m->sony_psmf) {
+    if (startcode == PRIVATE_STREAM_1) {
         startcode = avio_r8(s->pb);
         len--;
     }
@@ -507,6 +505,19 @@  redo:
             goto found;
     }
 
+    /* These bytes in the PES header can be used to identify
+     * the first ATRAC packets in a Sony ATRAC video */
+    if (!m->sony_psmf) {
+        avio_seek(s->pb, -4, SEEK_CUR);
+        unsigned char atrac_buf[3];
+        avio_read(s->pb, atrac_buf, 3);
+        avio_skip(s->pb, 1);
+
+        m->sony_psmf = memcmp(atrac_buf, "\x1E\x60\x08", 3) == 0 ||
+                       memcmp(atrac_buf, "\x1E\x60\x04", 3) == 0 ||
+                       memcmp(atrac_buf, "\x1E\x60\x14", 3) == 0;
+    }
+
     es_type = m->psm_es_type[startcode & 0xff];
         if (es_type == STREAM_TYPE_VIDEO_MPEG1) {
             codec_id = AV_CODEC_ID_MPEG2VIDEO;
@@ -544,28 +555,21 @@  redo:
         else
             request_probe= 1;
         type = AVMEDIA_TYPE_VIDEO;
-    } else if (startcode == PRIVATE_STREAM_1 && m->sony_psmf) {
-        uint8_t stream_id;
-
-        if (len < 2)
-            goto skip;
-        stream_id = avio_r8(s->pb);
+    // Sony PSP video with ATRAC-3 audio
+    } else if (startcode < 0x20 && m->sony_psmf) {
         avio_r8(s->pb); // skip padding
-        len -= 2;
-        if (!(stream_id & 0xF0)) { // seems like we got an ATRAC stream
-            /* check if an appropriate stream already exists */
-            for (i = 0; i < s->nb_streams; i++) {
-                st = s->streams[i];
-                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
-                    st->codec->codec_id == AV_CODEC_ID_ATRAC3P &&
-                    st->id - 0x1BD0 == (stream_id & 0xF))
-                    goto found;
-            }
-
-            startcode = 0x1BD0 + (stream_id & 0xF);
-            type      = AVMEDIA_TYPE_AUDIO;
-            codec_id  = AV_CODEC_ID_ATRAC3P;
+        len--;
+        for (i = 0; i < s->nb_streams; i++) {
+            st = s->streams[i];
+            if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
+                st->codec->codec_id == AV_CODEC_ID_ATRAC3P &&
+                st->id - 0x1BD0 == (startcode & 0xF))
+                goto found;
         }
+
+        startcode = 0x1BD0 + (startcode & 0xF);
+        type      = AVMEDIA_TYPE_AUDIO;
+        codec_id  = AV_CODEC_ID_ATRAC3P;
     } else if (startcode == PRIVATE_STREAM_2) {
         type = AVMEDIA_TYPE_DATA;
         codec_id = AV_CODEC_ID_DVD_NAV;
diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h
index 617e36cba8..efbadec8ba 100644
--- a/libavformat/mpeg.h
+++ b/libavformat/mpeg.h
@@ -58,6 +58,7 @@ 
 #define STREAM_TYPE_VIDEO_CAVS      0x42
 
 #define STREAM_TYPE_AUDIO_AC3       0x81
+#define STREAM_TYPE_AUDIO_ATRAC3    0xF0
 
 static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 };