[FFmpeg-devel] [PATCH 246/281] pcm: convert to new channel layout API

James Almer jamrial at gmail.com
Thu Jan 13 04:06:50 EET 2022


From: Anton Khirnov <anton at khirnov.net>

Signed-off-by: Vittorio Giovara <vittorio.giovara at gmail.com>
Signed-off-by: Anton Khirnov <anton at khirnov.net>
Signed-off-by: James Almer <jamrial at gmail.com>
---
 libavcodec/pcm-bluray.c      | 36 ++++++++++++++++-----------------
 libavcodec/pcm-dvd.c         | 28 +++++++++++++++-----------
 libavcodec/pcm-dvdenc.c      | 27 ++++++++++++++++---------
 libavcodec/pcm.c             | 39 ++++++++++++++++++------------------
 libavcodec/pcm_rechunk_bsf.c |  5 +++--
 5 files changed, 73 insertions(+), 62 deletions(-)

diff --git a/libavcodec/pcm-bluray.c b/libavcodec/pcm-bluray.c
index c2a6e82b1d..6250f25e72 100644
--- a/libavcodec/pcm-bluray.c
+++ b/libavcodec/pcm-bluray.c
@@ -54,14 +54,12 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx,
                                    const uint8_t *header)
 {
     static const uint8_t bits_per_samples[4] = { 0, 16, 20, 24 };
-    static const uint32_t channel_layouts[16] = {
-        0, AV_CH_LAYOUT_MONO, 0, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_SURROUND,
-        AV_CH_LAYOUT_2_1, AV_CH_LAYOUT_4POINT0, AV_CH_LAYOUT_2_2,
-        AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1, AV_CH_LAYOUT_7POINT0,
-        AV_CH_LAYOUT_7POINT1, 0, 0, 0, 0
-    };
-    static const uint8_t channels[16] = {
-        0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0
+    static const AVChannelLayout channel_layouts[16] = {
+        { 0 },                     AV_CHANNEL_LAYOUT_MONO,     { 0 },
+        AV_CHANNEL_LAYOUT_STEREO,  AV_CHANNEL_LAYOUT_SURROUND, AV_CHANNEL_LAYOUT_2_1,
+        AV_CHANNEL_LAYOUT_4POINT0, AV_CHANNEL_LAYOUT_2_2,      AV_CHANNEL_LAYOUT_5POINT0,
+        AV_CHANNEL_LAYOUT_5POINT1, AV_CHANNEL_LAYOUT_7POINT0,  AV_CHANNEL_LAYOUT_7POINT1,
+        { 0 }, { 0 }, { 0 }, { 0 },
     };
     uint8_t channel_layout = header[2] >> 4;
 
@@ -104,21 +102,21 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx,
      * differ from the actual meaningful number, e.g. mono audio still has two
      * channels, one being empty.
      */
-    avctx->channel_layout  = channel_layouts[channel_layout];
-    avctx->channels        =        channels[channel_layout];
-    if (!avctx->channels) {
+    av_channel_layout_uninit(&avctx->ch_layout);
+    avctx->ch_layout = channel_layouts[channel_layout];
+    if (!avctx->ch_layout.nb_channels) {
         av_log(avctx, AV_LOG_ERROR, "reserved channel configuration (%d)\n",
                channel_layout);
         return AVERROR_INVALIDDATA;
     }
 
-    avctx->bit_rate = FFALIGN(avctx->channels, 2) * avctx->sample_rate *
+    avctx->bit_rate = FFALIGN(avctx->ch_layout.nb_channels, 2) * avctx->sample_rate *
                       avctx->bits_per_coded_sample;
 
     if (avctx->debug & FF_DEBUG_PICT_INFO)
         ff_dlog(avctx,
                 "pcm_bluray_parse_header: %d channels, %d bits per sample, %d Hz, %"PRId64" bit/s\n",
-                avctx->channels, avctx->bits_per_coded_sample,
+                avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample,
                 avctx->sample_rate, avctx->bit_rate);
     return 0;
 }
@@ -148,7 +146,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
     bytestream2_init(&gb, src, buf_size);
 
     /* There's always an even number of channels in the source */
-    num_source_channels = FFALIGN(avctx->channels, 2);
+    num_source_channels = FFALIGN(avctx->ch_layout.nb_channels, 2);
     sample_size = (num_source_channels *
                    (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3;
     samples = buf_size / sample_size;
@@ -161,7 +159,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
     dst32 = (int32_t *)frame->data[0];
 
     if (samples) {
-        switch (avctx->channel_layout) {
+        switch (avctx->ch_layout.u.mask) {
             /* cases with same number of source and coded channels */
         case AV_CH_LAYOUT_STEREO:
         case AV_CH_LAYOUT_4POINT0:
@@ -189,10 +187,10 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
             if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) {
                 do {
 #if HAVE_BIGENDIAN
-                    bytestream2_get_buffer(&gb, dst16, avctx->channels * 2);
-                    dst16 += avctx->channels;
+                    bytestream2_get_buffer(&gb, dst16, avctx->ch_layout.nb_channels * 2);
+                    dst16 += avctx->ch_layout.nb_channels;
 #else
-                    channel = avctx->channels;
+                    channel = avctx->ch_layout.nb_channels;
                     do {
                         *dst16++ = bytestream2_get_be16u(&gb);
                     } while (--channel);
@@ -201,7 +199,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
                 } while (--samples);
             } else {
                 do {
-                    channel = avctx->channels;
+                    channel = avctx->ch_layout.nb_channels;
                     do {
                         *dst32++ = bytestream2_get_be24u(&gb) << 8;
                     } while (--channel);
diff --git a/libavcodec/pcm-dvd.c b/libavcodec/pcm-dvd.c
index 775d342eaa..7f991bba65 100644
--- a/libavcodec/pcm-dvd.c
+++ b/libavcodec/pcm-dvd.c
@@ -55,6 +55,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
     static const uint32_t frequencies[4] = { 48000, 96000, 44100, 32000 };
     PCMDVDContext *s = avctx->priv_data;
     int header_int = (header[0] & 0xe0) | (header[1] << 8) | (header[2] << 16);
+    int channels;
 
     /* early exit if the header didn't change apart from the frame number */
     if (s->last_header == header_int)
@@ -89,9 +90,12 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
     avctx->sample_rate = frequencies[header[1] >> 4 & 3];
 
     /* get the number of channels */
-    avctx->channels = 1 + (header[1] & 7);
+    channels = 1 + (header[1] & 7);
+
+    av_channel_layout_uninit(&avctx->ch_layout);
+    av_channel_layout_default(&avctx->ch_layout, channels);
     /* calculate the bitrate */
-    avctx->bit_rate = avctx->channels *
+    avctx->bit_rate = channels *
                       avctx->sample_rate *
                       avctx->bits_per_coded_sample;
 
@@ -100,15 +104,15 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
      * needed to complete a set of samples for each channel. */
     if (avctx->bits_per_coded_sample == 16) {
         s->samples_per_block = 1;
-        s->block_size        = avctx->channels * 2;
+        s->block_size        = channels * 2;
     } else {
-        switch (avctx->channels) {
+        switch (channels) {
         case 1:
         case 2:
         case 4:
             /* one group has all the samples needed */
             s->block_size        = 4 * avctx->bits_per_coded_sample / 8;
-            s->samples_per_block = 4 / avctx->channels;
+            s->samples_per_block = 4 / channels;
             s->groups_per_block  = 1;
             break;
         case 8:
@@ -118,11 +122,11 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
             s->groups_per_block  = 2;
             break;
         default:
-            /* need avctx->channels groups */
-            s->block_size        = 4 * avctx->channels *
+            /* need channels groups */
+            s->block_size        = 4 * channels *
                                    avctx->bits_per_coded_sample / 8;
             s->samples_per_block = 4;
-            s->groups_per_block  = avctx->channels;
+            s->groups_per_block  = channels;
             break;
         }
     }
@@ -130,7 +134,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
     if (avctx->debug & FF_DEBUG_PICT_INFO)
         ff_dlog(avctx,
                 "pcm_dvd_parse_header: %d channels, %d bits per sample, %d Hz, %"PRId64" bit/s\n",
-                avctx->channels, avctx->bits_per_coded_sample,
+                avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample,
                 avctx->sample_rate, avctx->bit_rate);
 
     s->last_header = header_int;
@@ -155,7 +159,7 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src,
         bytestream2_get_buffer(&gb, dst16, blocks * s->block_size);
         dst16 += blocks * s->block_size / 2;
 #else
-        int samples = blocks * avctx->channels;
+        int samples = blocks * avctx->ch_layout.nb_channels;
         do {
             *dst16++ = bytestream2_get_be16u(&gb);
         } while (--samples);
@@ -163,7 +167,7 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src,
         return dst16;
     }
     case 20:
-        if (avctx->channels == 1) {
+        if (avctx->ch_layout.nb_channels == 1) {
             do {
                 for (i = 2; i; i--) {
                     dst32[0] = bytestream2_get_be16u(&gb) << 16;
@@ -191,7 +195,7 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src,
         }
         return dst32;
     case 24:
-        if (avctx->channels == 1) {
+        if (avctx->ch_layout.nb_channels == 1) {
             do {
                 for (i = 2; i; i--) {
                     dst32[0] = bytestream2_get_be16u(&gb) << 16;
diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c
index c9afac69d2..e16c2a5fe4 100644
--- a/libavcodec/pcm-dvdenc.c
+++ b/libavcodec/pcm-dvdenc.c
@@ -60,7 +60,7 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx)
     }
 
     avctx->bits_per_coded_sample = 16 + quant * 4;
-    avctx->block_align           = avctx->channels * avctx->bits_per_coded_sample / 8;
+    avctx->block_align           = avctx->ch_layout.nb_channels * avctx->bits_per_coded_sample / 8;
     avctx->bit_rate              = avctx->block_align * 8LL * avctx->sample_rate;
     if (avctx->bit_rate > 9800000) {
         av_log(avctx, AV_LOG_ERROR, "Too big bitrate: reduce sample rate, bitdepth or channels.\n");
@@ -69,16 +69,16 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx)
 
     if (avctx->sample_fmt == AV_SAMPLE_FMT_S16) {
         s->samples_per_block = 1;
-        s->block_size        = avctx->channels * 2;
+        s->block_size        = avctx->ch_layout.nb_channels * 2;
         frame_size           = 2008 / s->block_size;
     } else {
-        switch (avctx->channels) {
+        switch (avctx->ch_layout.nb_channels) {
         case 1:
         case 2:
         case 4:
             /* one group has all the samples needed */
             s->block_size        = 4 * avctx->bits_per_coded_sample / 8;
-            s->samples_per_block = 4 / avctx->channels;
+            s->samples_per_block = 4 / avctx->ch_layout.nb_channels;
             s->groups_per_block  = 1;
             break;
         case 8:
@@ -88,11 +88,11 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx)
             s->groups_per_block  = 2;
             break;
         default:
-            /* need avctx->channels groups */
-            s->block_size        = 4 * avctx->channels *
+            /* need avctx->ch_layout.nb_channels groups */
+            s->block_size        = 4 * avctx->ch_layout.nb_channels *
                                    avctx->bits_per_coded_sample / 8;
             s->samples_per_block = 4;
-            s->groups_per_block  = avctx->channels;
+            s->groups_per_block  = avctx->ch_layout.nb_channels;
             break;
         }
 
@@ -100,7 +100,7 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx)
     }
 
     s->header[0] = 0x0c;
-    s->header[1] = (quant << 6) | (freq << 4) | (avctx->channels - 1);
+    s->header[1] = (quant << 6) | (freq << 4) | (avctx->ch_layout.nb_channels - 1);
     s->header[2] = 0x80;
 
     if (!avctx->frame_size)
@@ -113,7 +113,7 @@ static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                                 const AVFrame *frame, int *got_packet_ptr)
 {
     PCMDVDContext *s = avctx->priv_data;
-    int samples = frame->nb_samples * avctx->channels;
+    int samples = frame->nb_samples * avctx->ch_layout.nb_channels;
     int64_t pkt_size = (frame->nb_samples / s->samples_per_block) * s->block_size + 3;
     int blocks = (pkt_size - 3) / s->block_size;
     const int16_t *src16;
@@ -138,7 +138,7 @@ static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
         } while (--samples);
         break;
     case AV_SAMPLE_FMT_S32:
-        if (avctx->channels == 1) {
+        if (avctx->ch_layout.nb_channels == 1) {
             do {
                 for (int i = 2; i; i--) {
                     bytestream2_put_be16(&pb, src32[0] >> 16);
@@ -181,11 +181,18 @@ const AVCodec ff_pcm_dvd_encoder = {
     .init           = pcm_dvd_encode_init,
     .encode2        = pcm_dvd_encode_frame,
     .supported_samplerates = (const int[]) { 48000, 96000, 0},
+#if FF_API_OLD_CHANNEL_LAYOUT
     .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
                                             AV_CH_LAYOUT_STEREO,
                                             AV_CH_LAYOUT_5POINT1,
                                             AV_CH_LAYOUT_7POINT1,
                                             0 },
+#endif
+    .ch_layouts     = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO,
+                                                  AV_CHANNEL_LAYOUT_STEREO,
+                                                  AV_CHANNEL_LAYOUT_5POINT1,
+                                                  AV_CHANNEL_LAYOUT_7POINT1,
+                                                  { 0 } },
     .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_S32,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index e9b8eab484..f0f3d05e92 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -56,7 +56,7 @@ static av_cold int pcm_encode_init(AVCodecContext *avctx)
 #endif
 
     avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id);
-    avctx->block_align           = avctx->channels * avctx->bits_per_coded_sample / 8;
+    avctx->block_align           = avctx->ch_layout.nb_channels * avctx->bits_per_coded_sample / 8;
     avctx->bit_rate              = avctx->block_align * 8LL * avctx->sample_rate;
 
     return 0;
@@ -80,8 +80,8 @@ static av_cold int pcm_encode_init(AVCodecContext *avctx)
     }
 
 #define ENCODE_PLANAR(type, endian, dst, n, shift, offset)              \
-    n /= avctx->channels;                                               \
-    for (c = 0; c < avctx->channels; c++) {                             \
+    n /= avctx->ch_layout.nb_channels;                                  \
+    for (c = 0; c < avctx->ch_layout.nb_channels; c++) {                \
         int i;                                                          \
         samples_ ## type = (const type *) frame->extended_data[c];      \
         for (i = n; i > 0; i--) {                                       \
@@ -104,7 +104,7 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     const uint32_t *samples_uint32_t;
 
     sample_size = av_get_bits_per_sample(avctx->codec->id) / 8;
-    n           = frame->nb_samples * avctx->channels;
+    n           = frame->nb_samples * avctx->ch_layout.nb_channels;
     samples     = (const short *)frame->data[0];
 
     if ((ret = ff_get_encode_buffer(avctx, avpkt, n * sample_size, 0)) < 0)
@@ -207,8 +207,8 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     case AV_CODEC_ID_PCM_S16LE_PLANAR:
     case AV_CODEC_ID_PCM_S32LE_PLANAR:
 #endif /* HAVE_BIGENDIAN */
-        n /= avctx->channels;
-        for (c = 0; c < avctx->channels; c++) {
+        n /= avctx->ch_layout.nb_channels;
+        for (c = 0; c < avctx->ch_layout.nb_channels; c++) {
             const uint8_t *src = frame->extended_data[c];
             bytestream_put_buffer(&dst, src, n * sample_size);
         }
@@ -252,7 +252,7 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx)
     AVFloatDSPContext *fdsp;
     int i;
 
-    if (avctx->channels <= 0) {
+    if (avctx->ch_layout.nb_channels <= 0) {
         av_log(avctx, AV_LOG_ERROR, "PCM channels out of bounds\n");
         return AVERROR(EINVAL);
     }
@@ -312,8 +312,8 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx)
     }
 
 #define DECODE_PLANAR(size, endian, src, dst, n, shift, offset)                \
-    n /= avctx->channels;                                                      \
-    for (c = 0; c < avctx->channels; c++) {                                    \
+    n /= channels;                                                             \
+    for (c = 0; c < avctx->ch_layout.nb_channels; c++) {                       \
         int i;                                                                 \
         dst = frame->extended_data[c];                                         \
         for (i = n; i > 0; i--) {                                              \
@@ -330,6 +330,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
     int buf_size       = avpkt->size;
     PCMDecode *s       = avctx->priv_data;
     AVFrame *frame     = data;
+    int channels       = avctx->ch_layout.nb_channels;
     int sample_size, c, n, ret, samples_per_block;
     uint8_t *samples;
     int32_t *dst_int32_t;
@@ -349,7 +350,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
         return AVERROR(EINVAL);
     }
 
-    if (avctx->channels == 0) {
+    if (channels == 0) {
         av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
         return AVERROR(EINVAL);
     }
@@ -359,7 +360,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
         return AVERROR(EINVAL);
     }
 
-    n = avctx->channels * sample_size;
+    n = channels * sample_size;
 
     if (n && buf_size % n) {
         if (buf_size < n) {
@@ -374,7 +375,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
     n = buf_size / sample_size;
 
     /* get output buffer */
-    frame->nb_samples = n * samples_per_block / avctx->channels;
+    frame->nb_samples = n * samples_per_block / channels;
     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
     samples = frame->data[0];
@@ -429,8 +430,8 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
         }
         break;
     case AV_CODEC_ID_PCM_S8_PLANAR:
-        n /= avctx->channels;
-        for (c = 0; c < avctx->channels; c++) {
+        n /= avctx->ch_layout.nb_channels;
+        for (c = 0; c < avctx->ch_layout.nb_channels; c++) {
             int i;
             samples = frame->extended_data[c];
             for (i = n; i > 0; i--)
@@ -494,8 +495,8 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
     case AV_CODEC_ID_PCM_S16LE_PLANAR:
     case AV_CODEC_ID_PCM_S32LE_PLANAR:
 #endif /* HAVE_BIGENDIAN */
-        n /= avctx->channels;
-        for (c = 0; c < avctx->channels; c++) {
+        n /= avctx->ch_layout.nb_channels;
+        for (c = 0; c < avctx->ch_layout.nb_channels; c++) {
             samples = frame->extended_data[c];
             bytestream_get_buffer(&src, samples, n * sample_size);
         }
@@ -511,8 +512,8 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
     case AV_CODEC_ID_PCM_LXF:
     {
         int i;
-        n /= avctx->channels;
-        for (c = 0; c < avctx->channels; c++) {
+        n /= channels;
+        for (c = 0; c < channels; c++) {
             dst_int32_t = (int32_t *)frame->extended_data[c];
             for (i = 0; i < n; i++) {
                 // extract low 20 bits and expand to 32 bits
@@ -540,7 +541,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data,
         avctx->codec_id == AV_CODEC_ID_PCM_F24LE) {
         s->vector_fmul_scalar((float *)frame->extended_data[0],
                               (const float *)frame->extended_data[0],
-                              s->scale, FFALIGN(frame->nb_samples * avctx->channels, 4));
+                              s->scale, FFALIGN(frame->nb_samples * avctx->ch_layout.nb_channels, 4));
         emms_c();
     }
 
diff --git a/libavcodec/pcm_rechunk_bsf.c b/libavcodec/pcm_rechunk_bsf.c
index 7cf763359d..80727a1a91 100644
--- a/libavcodec/pcm_rechunk_bsf.c
+++ b/libavcodec/pcm_rechunk_bsf.c
@@ -42,11 +42,12 @@ static int init(AVBSFContext *ctx)
     AVRational sr = av_make_q(ctx->par_in->sample_rate, 1);
     int64_t min_samples;
 
-    if (ctx->par_in->channels <= 0 || ctx->par_in->sample_rate <= 0)
+    if (ctx->par_in->ch_layout.nb_channels <= 0 || ctx->par_in->sample_rate <= 0)
         return AVERROR(EINVAL);
 
     ctx->time_base_out = av_inv_q(sr);
-    s->sample_size = ctx->par_in->channels * av_get_bits_per_sample(ctx->par_in->codec_id) / 8;
+    s->sample_size = ctx->par_in->ch_layout.nb_channels *
+                     av_get_bits_per_sample(ctx->par_in->codec_id) / 8;
 
     if (s->frame_rate.num) {
         min_samples = av_rescale_q_rnd(1, sr, s->frame_rate, AV_ROUND_DOWN);
-- 
2.34.1



More information about the ffmpeg-devel mailing list