diff mbox

[FFmpeg-devel,2/6] mpeg: add experimental support for PSMF audio.

Message ID 20171225022834.33865-3-misty@brew.sh
State Superseded
Headers show

Commit Message

misty@brew.sh Dec. 25, 2017, 2:28 a.m. UTC
From: Maxim Poliakovski <maximumspatium@googlemail.com>

---
 libavcodec/Makefile            |   1 +
 libavcodec/allcodecs.c         |   1 +
 libavcodec/atrac3plus_parser.c | 153 +++++++++++++++++++++++++++++++++++++++++
 libavformat/mpeg.c             |  27 +++++++-
 4 files changed, 181 insertions(+), 1 deletion(-)
 create mode 100644 libavcodec/atrac3plus_parser.c

Comments

Michael Niedermayer Dec. 26, 2017, 12:39 a.m. UTC | #1
On Mon, Dec 25, 2017 at 10:28:30AM +0800, misty@brew.sh wrote:
> From: Maxim Poliakovski <maximumspatium@googlemail.com>
> 
> ---
>  libavcodec/Makefile            |   1 +
>  libavcodec/allcodecs.c         |   1 +
>  libavcodec/atrac3plus_parser.c | 153 +++++++++++++++++++++++++++++++++++++++++
>  libavformat/mpeg.c             |  27 +++++++-
>  4 files changed, 181 insertions(+), 1 deletion(-)
>  create mode 100644 libavcodec/atrac3plus_parser.c

This fails to build without the next patch

libavcodec/atrac3plus_parser.c: In function ‘parse_sound_frame_header’:
libavcodec/atrac3plus_parser.c:41:22: error: ‘ff_oma_srate_tab’ undeclared (first use in this function)
     c->sample_rate = ff_oma_srate_tab[(atrac_config >> 13) & 7] * 100;
                      ^
libavcodec/atrac3plus_parser.c:41:22: note: each undeclared identifier is reported only once for each function it appears in
libavcodec/atrac3plus_parser.c: In function ‘ff_atrac3p_parse’:
libavcodec/atrac3plus_parser.c:92:32: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t’ [-Wformat=]
                                bytes_remain, buf_size);
                                ^
libavcodec/atrac3plus_parser.c:123:27: error: ‘ff_oma_chid_to_num_channels’ undeclared (first use in this function)
         avctx->channels       = ff_oma_chid_to_num_channels[ctx->channel_id - 1];
                           ^
libavcodec/atrac3plus_parser.c:124:33: error: ‘ff_oma_chid_to_native_layout’ undeclared (first use in this function)
         avctx->channel_layout = ff_oma_chid_to_native_layout[ctx->channel_id - 1];
                                 ^
make: *** [libavcodec/atrac3plus_parser.o] Error 1
make: *** Waiting for unfinished jobs....

[...]
Michael Niedermayer Dec. 26, 2017, 12:42 a.m. UTC | #2
On Mon, Dec 25, 2017 at 10:28:30AM +0800, misty@brew.sh wrote:
> From: Maxim Poliakovski <maximumspatium@googlemail.com>
> 
> ---
>  libavcodec/Makefile            |   1 +
>  libavcodec/allcodecs.c         |   1 +
>  libavcodec/atrac3plus_parser.c | 153 +++++++++++++++++++++++++++++++++++++++++
>  libavformat/mpeg.c             |  27 +++++++-
>  4 files changed, 181 insertions(+), 1 deletion(-)
>  create mode 100644 libavcodec/atrac3plus_parser.c
> 
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index ca72138c02..e0e3f1ebac 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -977,6 +977,7 @@ OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o \
>                                            mpeg4audio.o
>  OBJS-$(CONFIG_AC3_PARSER)              += ac3tab.o aac_ac3_parser.o
>  OBJS-$(CONFIG_ADX_PARSER)              += adx_parser.o adx.o
> +OBJS-$(CONFIG_ATRAC3P_PARSER)          += atrac3plus_parser.o
>  OBJS-$(CONFIG_BMP_PARSER)              += bmp_parser.o
>  OBJS-$(CONFIG_CAVSVIDEO_PARSER)        += cavs_parser.o
>  OBJS-$(CONFIG_COOK_PARSER)             += cook_parser.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index ed1e7ab06e..81d5d2814a 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -623,6 +623,7 @@ static void register_all(void)
>      REGISTER_PARSER(AAC_LATM,           aac_latm);
>      REGISTER_PARSER(AC3,                ac3);
>      REGISTER_PARSER(ADX,                adx);
> +    REGISTER_PARSER(ATRAC3P,            atrac3p);
>      REGISTER_PARSER(BMP,                bmp);
>      REGISTER_PARSER(CAVSVIDEO,          cavsvideo);
>      REGISTER_PARSER(COOK,               cook);
> diff --git a/libavcodec/atrac3plus_parser.c b/libavcodec/atrac3plus_parser.c
> new file mode 100644
> index 0000000000..01fcad4c45
> --- /dev/null
> +++ b/libavcodec/atrac3plus_parser.c
> @@ -0,0 +1,153 @@
> +/*
> + * Copyright (C) 2014 Maxim Poliakovski
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include "parser.h"
> +#include "get_bits.h"
> +#include "libavformat/oma.h"
> +
> +typedef struct Atrac3PlusParseContext {
> +    ParseContext pc;
> +    uint8_t hdr[8];
> +    int hdr_bytes_needed, got_bytes;
> +    int sample_rate, channel_id, frame_size;
> +} Atrac3PlusParseContext;
> +
> +static int parse_sound_frame_header(Atrac3PlusParseContext *c,
> +                                    const uint8_t *buf)
> +{
> +    uint16_t atrac_config;
> +
> +    if (AV_RB16(buf) != 0x0FD0)
> +        return AVERROR_INVALIDDATA;
> +
> +    atrac_config = AV_RB16(&buf[2]);
> +    c->sample_rate = ff_oma_srate_tab[(atrac_config >> 13) & 7] * 100;
> +    c->channel_id  = (atrac_config >> 10) & 7;
> +    c->frame_size  = ((atrac_config & 0x3FF) * 8) + 8;
> +
> +    if (!c->channel_id || !c->sample_rate || !c->frame_size)
> +        return AVERROR_INVALIDDATA;
> +
> +    return 0;
> +}
> +
> +static int ff_atrac3p_parse(AVCodecParserContext *s,
> +                 AVCodecContext *avctx,
> +                 const uint8_t **poutbuf, int *poutbuf_size,
> +                 const uint8_t *buf, int buf_size)
> +{
> +    Atrac3PlusParseContext *ctx = s->priv_data;
> +    const uint8_t *hdr_buf = buf;
> +    size_t bytes_remain;
> +    int frame_size, hdr_bytes = 8;
> +    int next = 0;
> +
> +    if (s->flags & PARSER_FLAG_COMPLETE_FRAMES || !buf_size) {
> +        next = buf_size;
> +    } else {
> +        if (buf_size >= 2) {
> +            bytes_remain = AV_RB16(buf);
> +
> +            if (bytes_remain != 0xFD0) {
> +                next += 2;
> +                buf  += 2;
> +                buf_size -= 2;
> +                hdr_buf = buf;
> +
> +                if (bytes_remain && !ctx->pc.index && !ctx->hdr_bytes_needed) {
> +                    av_log(avctx, AV_LOG_ERROR,
> +                           "2nd frame portion found but the 1st one is missing!\n");
> +                    return AVERROR_INVALIDDATA;
> +                }

returning errors from the parse function will cause assertion failure at:

Assertion index > -0x20000000 failed at libavcodec/parser.c:185

[...]
Misty De Meo Dec. 26, 2017, 2:20 a.m. UTC | #3
I originally left this patch alone since it was another person's
commit; I can squash the fixes for that into this commit if you
prefer, though.

On Tue, Dec 26, 2017 at 8:39 AM, Michael Niedermayer
<michael@niedermayer.cc> wrote:
> On Mon, Dec 25, 2017 at 10:28:30AM +0800, misty@brew.sh wrote:
>> From: Maxim Poliakovski <maximumspatium@googlemail.com>
>>
>> ---
>>  libavcodec/Makefile            |   1 +
>>  libavcodec/allcodecs.c         |   1 +
>>  libavcodec/atrac3plus_parser.c | 153 +++++++++++++++++++++++++++++++++++++++++
>>  libavformat/mpeg.c             |  27 +++++++-
>>  4 files changed, 181 insertions(+), 1 deletion(-)
>>  create mode 100644 libavcodec/atrac3plus_parser.c
>
> This fails to build without the next patch
>
> libavcodec/atrac3plus_parser.c: In function ‘parse_sound_frame_header’:
> libavcodec/atrac3plus_parser.c:41:22: error: ‘ff_oma_srate_tab’ undeclared (first use in this function)
>      c->sample_rate = ff_oma_srate_tab[(atrac_config >> 13) & 7] * 100;
>                       ^
> libavcodec/atrac3plus_parser.c:41:22: note: each undeclared identifier is reported only once for each function it appears in
> libavcodec/atrac3plus_parser.c: In function ‘ff_atrac3p_parse’:
> libavcodec/atrac3plus_parser.c:92:32: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘size_t’ [-Wformat=]
>                                 bytes_remain, buf_size);
>                                 ^
> libavcodec/atrac3plus_parser.c:123:27: error: ‘ff_oma_chid_to_num_channels’ undeclared (first use in this function)
>          avctx->channels       = ff_oma_chid_to_num_channels[ctx->channel_id - 1];
>                            ^
> libavcodec/atrac3plus_parser.c:124:33: error: ‘ff_oma_chid_to_native_layout’ undeclared (first use in this function)
>          avctx->channel_layout = ff_oma_chid_to_native_layout[ctx->channel_id - 1];
>                                  ^
> make: *** [libavcodec/atrac3plus_parser.o] Error 1
> make: *** Waiting for unfinished jobs....
>
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> During times of universal deceit, telling the truth becomes a
> revolutionary act. -- George Orwell
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
misty@brew.sh Dec. 26, 2017, 2:24 a.m. UTC | #4
On Tue, Dec 26, 2017 at 8:42 AM, Michael Niedermayer
<michael@niedermayer.cc> wrote:
> returning errors from the parse function will cause assertion failure at:
>
> Assertion index > -0x20000000 failed at libavcodec/parser.c:185
>
> [...]

What would be the preferred way to handle that?
misty@brew.sh Dec. 26, 2017, 2:24 a.m. UTC | #5
On Tue, Dec 26, 2017 at 8:39 AM, Michael Niedermayer
<michael@niedermayer.cc> wrote:
> This fails to build without the next patch

I originally left this patch alone since it was another person's
commit; I can squash the fixes for that into this commit if you
prefer, though.
misty@brew.sh Dec. 26, 2017, 8:06 a.m. UTC | #6
From: Misty De Meo <mistydemeo@gmail.com>

I checked in with IRC and got some suggestions on the best way to handle
both of these. I've updated the patchset with the changes you requested.

The media files referenced by the tests are here:
https://public.drac.at/00006.MPS
http://samples.ffmpeg.org/PSMF/EV01_01_0500D.PMF

Maxim Poliakovski (1):
  mpeg: add experimental support for PSMF audio.

Misty De Meo (4):
  oma: move some constants into libavcodec
  Fix detecting ATRAC3 audio from MPS files
  mpeg: fix use of deprecated struct
  psmf: add FATE tests

 Changelog                             |   1 +
 libavcodec/Makefile                   |   1 +
 libavcodec/allcodecs.c                |   1 +
 libavcodec/atrac3plus_parser.c        | 150 ++++++++++++++++++++++++++++++++++
 libavformat/oma.c => libavcodec/oma.h |  27 +++---
 libavcodec/version.h                  |   2 +-
 libavformat/Makefile                  |   4 +-
 libavformat/mpeg.c                    |  15 ++++
 libavformat/mpeg.h                    |   1 +
 libavformat/oma.h                     |  21 ++---
 libavformat/omadec.c                  |  13 +--
 libavformat/omaenc.c                  |   7 +-
 libavformat/version.h                 |   2 +-
 tests/Makefile                        |   1 +
 tests/fate/psmf.mak                   |  23 ++++++
 15 files changed, 230 insertions(+), 39 deletions(-)
 create mode 100644 libavcodec/atrac3plus_parser.c
 rename libavformat/oma.c => libavcodec/oma.h (65%)
 create mode 100644 tests/fate/psmf.mak
Michael Niedermayer Dec. 27, 2017, 12:51 a.m. UTC | #7
On Tue, Dec 26, 2017 at 10:24:07AM +0800, Misty De Meo wrote:
> On Tue, Dec 26, 2017 at 8:42 AM, Michael Niedermayer
> <michael@niedermayer.cc> wrote:
> > returning errors from the parse function will cause assertion failure at:
> >
> > Assertion index > -0x20000000 failed at libavcodec/parser.c:185
> >
> > [...]
> 
> What would be the preferred way to handle that?

parsers should not loose data, so when they are unable to determine
frame boarders they should return the data with no byte removed or added
and frame boarders placed on a best effort basis.


[...]
Michael Niedermayer Dec. 27, 2017, 1:02 a.m. UTC | #8
On Tue, Dec 26, 2017 at 10:20:23AM +0800, Misty De Meo wrote:
> I originally left this patch alone since it was another person's
> commit; I can squash the fixes for that into this commit if you
> prefer, though.

no commit in a patchset should knowingly introduce a bug.
That would make git bisect more difficult

thx

[...]
misty@brew.sh Dec. 31, 2017, 9:46 a.m. UTC | #9
From: Misty De Meo <mistydemeo@gmail.com>

I think this version of the patch should address the issue. If frames
can't be parsed, the original data is passed through unaltered. From
what I can tell about the RIFF WAVE .at3 files, they don't use the
format being parsed at all and don't require parsing. With the updated
version of this patch, they play fine.
The new fate atrac3p conversion test behaves the same on both master
and with these patches, confirming there aren't any regressions.

Here's the media used in the tests. In response to your previous
feedback, I've reduced the PSMF test files to 64KB each; that's
enough for the ffprobe tests to succeed.

https://public.drac.at/bgm01.at3
https://public.drac.at/bgm01.s16
https://public.drac.at/00006.MPS
https://public.drac.at/EV01_01_0500D.PMF

Maxim Poliakovski (1):
  mpeg: add experimental support for PSMF audio.

Misty De Meo (5):
  fate: add atrac3p conversion test
  oma: move some constants into libavcodec
  Fix detecting ATRAC3 audio from MPS files
  mpeg: fix use of deprecated struct
  psmf: add FATE tests

 Changelog                             |   1 +
 libavcodec/Makefile                   |   1 +
 libavcodec/allcodecs.c                |   1 +
 libavcodec/atrac3plus_parser.c        | 170 ++++++++++++++++++++++++++++++++++
 libavformat/oma.c => libavcodec/oma.h |  27 +++---
 libavcodec/version.h                  |   2 +-
 libavformat/Makefile                  |   4 +-
 libavformat/mpeg.c                    |  15 +++
 libavformat/mpeg.h                    |   1 +
 libavformat/oma.h                     |  21 ++---
 libavformat/omadec.c                  |  13 +--
 libavformat/omaenc.c                  |   7 +-
 libavformat/version.h                 |   2 +-
 tests/Makefile                        |   1 +
 tests/fate/atrac.mak                  |   4 +
 tests/fate/psmf.mak                   |  23 +++++
 16 files changed, 254 insertions(+), 39 deletions(-)
 create mode 100644 libavcodec/atrac3plus_parser.c
 rename libavformat/oma.c => libavcodec/oma.h (65%)
 create mode 100644 tests/fate/psmf.mak
diff mbox

Patch

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index ca72138c02..e0e3f1ebac 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -977,6 +977,7 @@  OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o \
                                           mpeg4audio.o
 OBJS-$(CONFIG_AC3_PARSER)              += ac3tab.o aac_ac3_parser.o
 OBJS-$(CONFIG_ADX_PARSER)              += adx_parser.o adx.o
+OBJS-$(CONFIG_ATRAC3P_PARSER)          += atrac3plus_parser.o
 OBJS-$(CONFIG_BMP_PARSER)              += bmp_parser.o
 OBJS-$(CONFIG_CAVSVIDEO_PARSER)        += cavs_parser.o
 OBJS-$(CONFIG_COOK_PARSER)             += cook_parser.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index ed1e7ab06e..81d5d2814a 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -623,6 +623,7 @@  static void register_all(void)
     REGISTER_PARSER(AAC_LATM,           aac_latm);
     REGISTER_PARSER(AC3,                ac3);
     REGISTER_PARSER(ADX,                adx);
+    REGISTER_PARSER(ATRAC3P,            atrac3p);
     REGISTER_PARSER(BMP,                bmp);
     REGISTER_PARSER(CAVSVIDEO,          cavsvideo);
     REGISTER_PARSER(COOK,               cook);
diff --git a/libavcodec/atrac3plus_parser.c b/libavcodec/atrac3plus_parser.c
new file mode 100644
index 0000000000..01fcad4c45
--- /dev/null
+++ b/libavcodec/atrac3plus_parser.c
@@ -0,0 +1,153 @@ 
+/*
+ * Copyright (C) 2014 Maxim Poliakovski
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "parser.h"
+#include "get_bits.h"
+#include "libavformat/oma.h"
+
+typedef struct Atrac3PlusParseContext {
+    ParseContext pc;
+    uint8_t hdr[8];
+    int hdr_bytes_needed, got_bytes;
+    int sample_rate, channel_id, frame_size;
+} Atrac3PlusParseContext;
+
+static int parse_sound_frame_header(Atrac3PlusParseContext *c,
+                                    const uint8_t *buf)
+{
+    uint16_t atrac_config;
+
+    if (AV_RB16(buf) != 0x0FD0)
+        return AVERROR_INVALIDDATA;
+
+    atrac_config = AV_RB16(&buf[2]);
+    c->sample_rate = ff_oma_srate_tab[(atrac_config >> 13) & 7] * 100;
+    c->channel_id  = (atrac_config >> 10) & 7;
+    c->frame_size  = ((atrac_config & 0x3FF) * 8) + 8;
+
+    if (!c->channel_id || !c->sample_rate || !c->frame_size)
+        return AVERROR_INVALIDDATA;
+
+    return 0;
+}
+
+static int ff_atrac3p_parse(AVCodecParserContext *s,
+                 AVCodecContext *avctx,
+                 const uint8_t **poutbuf, int *poutbuf_size,
+                 const uint8_t *buf, int buf_size)
+{
+    Atrac3PlusParseContext *ctx = s->priv_data;
+    const uint8_t *hdr_buf = buf;
+    size_t bytes_remain;
+    int frame_size, hdr_bytes = 8;
+    int next = 0;
+
+    if (s->flags & PARSER_FLAG_COMPLETE_FRAMES || !buf_size) {
+        next = buf_size;
+    } else {
+        if (buf_size >= 2) {
+            bytes_remain = AV_RB16(buf);
+
+            if (bytes_remain != 0xFD0) {
+                next += 2;
+                buf  += 2;
+                buf_size -= 2;
+                hdr_buf = buf;
+
+                if (bytes_remain && !ctx->pc.index && !ctx->hdr_bytes_needed) {
+                    av_log(avctx, AV_LOG_ERROR,
+                           "2nd frame portion found but the 1st one is missing!\n");
+                    return AVERROR_INVALIDDATA;
+                }
+
+                if (ctx->hdr_bytes_needed) {
+                    if (buf_size >= ctx->hdr_bytes_needed) {
+                        memcpy(&ctx->hdr[8 - ctx->hdr_bytes_needed],
+                               buf, ctx->hdr_bytes_needed);
+                        hdr_bytes = ctx->hdr_bytes_needed;
+                        ctx->hdr_bytes_needed = 0;
+                        hdr_buf = ctx->hdr;
+                    }
+                } else if (bytes_remain) {
+                    if (buf_size < bytes_remain) {
+                        av_log(avctx, AV_LOG_ERROR,
+                               "Couldn't combine frame: bytes needed=%d, bytes supplied=%d\n",
+                               bytes_remain, buf_size);
+                        return AVERROR_INVALIDDATA;
+                    }
+
+                    next += bytes_remain;
+                    ff_combine_frame(&ctx->pc, bytes_remain, &buf, &buf_size);
+
+                    *poutbuf      = buf;
+                    *poutbuf_size = buf_size;
+                    return next;
+                }
+            }
+        }
+
+        if (buf_size < hdr_bytes) {
+            /* looks like we got an incomplete header */
+            memcpy(ctx->hdr, buf, buf_size);
+            ctx->hdr_bytes_needed = 8 - buf_size;
+            *poutbuf = NULL;
+            *poutbuf_size = 0;
+            return buf_size;
+        }
+
+        if (parse_sound_frame_header(ctx, hdr_buf)) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid sound frame header!\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        avctx->sample_rate    = ctx->sample_rate;
+        avctx->block_align    = ctx->frame_size;
+        avctx->bit_rate       = ctx->sample_rate * ctx->frame_size * 8 / 2048;
+        avctx->channels       = ff_oma_chid_to_num_channels[ctx->channel_id - 1];
+        avctx->channel_layout = ff_oma_chid_to_native_layout[ctx->channel_id - 1];
+
+        next += hdr_bytes;
+        buf  += hdr_bytes;
+        buf_size -= hdr_bytes;
+        frame_size = ctx->frame_size;
+
+        if (buf_size < frame_size)
+            frame_size = END_NOT_FOUND;
+
+        if (ff_combine_frame(&ctx->pc, frame_size, &buf, &buf_size) < 0) {
+            *poutbuf = NULL;
+            *poutbuf_size = 0;
+            return buf_size + next;
+        }
+
+        next += frame_size;
+    }
+
+    *poutbuf      = buf;
+    *poutbuf_size = buf_size;
+    return next;
+}
+
+AVCodecParser ff_atrac3p_parser = {
+    .codec_ids      = { AV_CODEC_ID_ATRAC3P },
+    .priv_data_size = sizeof(Atrac3PlusParseContext),
+    .parser_parse   = ff_atrac3p_parse,
+    .parser_close   = ff_parse_close,
+};
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index 50fe7a1a76..895c6fb231 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -128,6 +128,7 @@  typedef struct MpegDemuxContext {
     int sofdec;
     int dvd;
     int imkh_cctv;
+    int sony_psmf; // true if Play Station Movie file signature is present
 #if CONFIG_VOBSUB_DEMUXER
     AVFormatContext *sub_ctx;
     FFDemuxSubtitlesQueue q[32];
@@ -147,6 +148,8 @@  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
@@ -441,7 +444,7 @@  redo:
         goto redo;
     }
 
-    if (startcode == PRIVATE_STREAM_1) {
+    if (startcode == PRIVATE_STREAM_1 && !m->sony_psmf) {
         startcode = avio_r8(s->pb);
         len--;
     }
@@ -541,6 +544,28 @@  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);
+        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;
+        }
     } else if (startcode == PRIVATE_STREAM_2) {
         type = AVMEDIA_TYPE_DATA;
         codec_id = AV_CODEC_ID_DVD_NAV;