PR #22577 opened by Scott Theisen (ulmus-scott)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22577
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22577.patch

Defined in ISO/IEC 11172-3 and ISO/IEC 13818-3 as:
dual channel mode [audio]: A mode, where two audio channels with independent
programme contents (e.g. bilingual) are encoded within one bitstream. The
coding process is the same as for the stereo mode.

There is currently no way to signal that an audio channel is monophonic, i.e.
that channel comprises the entirety of an audio signal, so two front center
channels were chosen since AV_CH_LAYOUT_MONO is represented as a single
front center channel.

---

This was previously discussed on the mailing list without resolution in 
November and December 2024.


>From c9dd1f8b672ea2a7d10ebd9bae5ebba4af16acb1 Mon Sep 17 00:00:00 2001
From: Scott Theisen <[email protected]>
Date: Wed, 17 Nov 2021 15:10:40 -0500
Subject: [PATCH] libavcodec/mpegaudio_parser.c: Differentiate MPEG audio dual
 mono

Defined in ISO/IEC 11172-3 and ISO/IEC 13818-3 as:
dual channel mode [audio]: A mode, where two audio channels with independent
programme contents (e.g. bilingual) are encoded within one bitstream. The
coding process is the same as for the stereo mode.

There is currently no way to signal that an audio channel is monophonic, i.e.
that channel comprises the entirety of an audio signal, so two front center
channels were chosen since AV_CH_LAYOUT_MONO is represented as a single
front center channel.
---
 libavcodec/audiotoolboxdec.c    |  4 ++--
 libavcodec/mpegaudio_parser.c   | 19 ++++++++++++++++---
 libavcodec/mpegaudiodecheader.c |  4 +++-
 libavcodec/mpegaudiodecheader.h |  2 +-
 tests/ref/fate/pva-demux        |  2 +-
 5 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c
index 08203c5310..667d0f9ad0 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 8c33d36dfe..a2c8374e29 100644
--- a/libavcodec/mpegaudio_parser.c
+++ b/libavcodec/mpegaudio_parser.c
@@ -66,12 +66,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;
@@ -86,7 +86,20 @@ 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) {
+                            // two independent monophonic audio channels in 
one bitstream
+                            int ret = 
av_channel_layout_custom_init(&avctx->ch_layout, 2);
+                            if (ret != 0) {
+                                // parsers can't return error codes
+                                avctx->ch_layout.order = 
AV_CHANNEL_ORDER_UNSPEC;
+                                avctx->ch_layout.nb_channels = 2;
+                            } else {
+                                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.52.0

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

Reply via email to