[FFmpeg-devel] [PATCH] libavcodec/mpegaudio_parser.c: differentiate MPEG audio dual mono

Scott Theisen scott.the.elm at gmail.com
Thu Nov 14 06:37:49 EET 2024


When attempting to upstream this MythTV change in September 2022, it was recommended to
use AV_CHANNEL_ORDER_CUSTOM with two AV_CHAN_FRONT_CENTER channels. See
https://patchwork.ffmpeg.org/project/ffmpeg/patch/20220921192611.3241-1-scott.the.elm@gmail.com/
---
 libavcodec/audiotoolboxdec.c    |  4 ++--
 libavcodec/mpegaudio_parser.c   | 12 +++++++++---
 libavcodec/mpegaudiodecheader.c |  4 +++-
 libavcodec/mpegaudiodecheader.h |  2 +-
 tests/ref/fate/pva-demux        |  2 +-
 5 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c
index 0f7ce8e4eb..d279d7bbc4 100644
--- a/libavcodec/audiotoolboxdec.c
+++ b/libavcodec/audiotoolboxdec.c
@@ -346,10 +346,10 @@ static av_cold int ffat_create_decoder(AVCodecContext *avctx,
                 avctx->codec_id == AV_CODEC_ID_MP2 ||
                 avctx->codec_id == AV_CODEC_ID_MP3)) {
         enum AVCodecID codec_id;
-        int bit_rate;
+        int bit_rate, dual_mono;
         if (ff_mpa_decode_header(AV_RB32(pkt->data), &avctx->sample_rate,
                                  &in_format.mChannelsPerFrame, &avctx->frame_size,
-                                 &bit_rate, &codec_id) < 0)
+                                 &bit_rate, &codec_id, &dual_mono) < 0)
             return AVERROR_INVALIDDATA;
         avctx->bit_rate = bit_rate;
         in_format.mSampleRate = avctx->sample_rate;
diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c
index d54366f10a..d1a4ee6434 100644
--- a/libavcodec/mpegaudio_parser.c
+++ b/libavcodec/mpegaudio_parser.c
@@ -65,12 +65,12 @@ static int mpegaudio_parse(AVCodecParserContext *s1,
             }
         }else{
             while(i<buf_size){
-                int ret, sr, channels, bit_rate, frame_size;
+                int ret, sr, channels, bit_rate, frame_size, dual_mono;
                 enum AVCodecID codec_id = avctx->codec_id;
 
                 state= (state<<8) + buf[i++];
 
-                ret = ff_mpa_decode_header(state, &sr, &channels, &frame_size, &bit_rate, &codec_id);
+                ret = ff_mpa_decode_header(state, &sr, &channels, &frame_size, &bit_rate, &codec_id, &dual_mono);
                 if (ret < 4) {
                     if (i > 4)
                         s->header_count = -2;
@@ -85,7 +85,13 @@ static int mpegaudio_parse(AVCodecParserContext *s1,
                     if (s->header_count > header_threshold) {
                         avctx->sample_rate= sr;
                         av_channel_layout_uninit(&avctx->ch_layout);
-                        av_channel_layout_default(&avctx->ch_layout, channels);
+                        if (dual_mono) {
+                            av_channel_layout_custom_init(&avctx->ch_layout, 2);
+                            avctx->ch_layout.u.map[0].id = AV_CHAN_FRONT_CENTER;
+                            avctx->ch_layout.u.map[1].id = AV_CHAN_FRONT_CENTER;
+                        } else {
+                            av_channel_layout_default(&avctx->ch_layout, channels);
+                        }
                         s1->duration      = frame_size;
                         avctx->codec_id   = codec_id;
                         if (s->no_bitrate || !avctx->bit_rate) {
diff --git a/libavcodec/mpegaudiodecheader.c b/libavcodec/mpegaudiodecheader.c
index ef63befbf4..5cbfdcb677 100644
--- a/libavcodec/mpegaudiodecheader.c
+++ b/libavcodec/mpegaudiodecheader.c
@@ -117,7 +117,7 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header)
     return 0;
 }
 
-int ff_mpa_decode_header(uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate, enum AVCodecID *codec_id)
+int ff_mpa_decode_header(uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate, enum AVCodecID *codec_id, int *dual_mono)
 {
     MPADecodeHeader s1, *s = &s1;
 
@@ -148,5 +148,7 @@ int ff_mpa_decode_header(uint32_t head, int *sample_rate, int *channels, int *fr
     *sample_rate = s->sample_rate;
     *channels = s->nb_channels;
     *bit_rate = s->bit_rate;
+    *dual_mono = (s->mode == MPA_DUAL);
+
     return s->frame_size;
 }
diff --git a/libavcodec/mpegaudiodecheader.h b/libavcodec/mpegaudiodecheader.h
index ed5d1f3b33..e599d287f7 100644
--- a/libavcodec/mpegaudiodecheader.h
+++ b/libavcodec/mpegaudiodecheader.h
@@ -56,7 +56,7 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header);
 /* useful helper to get MPEG audio stream info. Return -1 if error in
    header, otherwise the coded frame size in bytes */
 int ff_mpa_decode_header(uint32_t head, int *sample_rate,
-                         int *channels, int *frame_size, int *bitrate, enum AVCodecID *codec_id);
+                         int *channels, int *frame_size, int *bitrate, enum AVCodecID *codec_id, int *dual_mono);
 
 /* fast header check for resync */
 static inline int ff_mpa_check_header(uint32_t header){
diff --git a/tests/ref/fate/pva-demux b/tests/ref/fate/pva-demux
index 5c0e1c1ea0..2749ea9f07 100644
--- a/tests/ref/fate/pva-demux
+++ b/tests/ref/fate/pva-demux
@@ -7,7 +7,7 @@
 #media_type 1: audio
 #codec_id 1: mp2
 #sample_rate 1: 48000
-#channel_layout_name 1: stereo
+#channel_layout_name 1: 2 channels (FC+FC)
 1,          0,          0,     2160,      384, 0x071abcc8
 1,       2160,       2160,     2160,      384, 0x31c9aee0
 1,       4320,       4320,     2160,      384, 0xa50eaa94
-- 
2.43.0



More information about the ffmpeg-devel mailing list