Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 1/7] avcodec/pcm: Remove always-false check
@ 2025-03-13  5:49 Andreas Rheinhardt
  0 siblings, 0 replies; only message in thread
From: Andreas Rheinhardt @ 2025-03-13  5:49 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

[-- Attachment #1: Type: text/plain, Size: 29 bytes --]

Patches attached.

- Andreas

[-- Attachment #2: 0001-avcodec-pcm-Remove-always-false-check.patch --]
[-- Type: text/x-patch, Size: 1565 bytes --]

From d07c1ad85a60395eb20501a59ff35de1d60f029b Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 11 Mar 2025 17:26:43 +0100
Subject: [PATCH 1/7] avcodec/pcm: Remove always-false check

All codecs here have a valid sample size at this point.
This check has (presumably) been added for DVD PCM,
but even for them the check was always-true after
381e195b46d080aee1d9b05ef2b6b140e9463519 (and the DVD
code was later moved out altogether). So just remove
this check and the leftover DVD comment.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pcm.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index a23293dca2..5d8dcb8ff0 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -334,7 +334,6 @@ static int pcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
 
     sample_size = av_get_bits_per_sample(avctx->codec_id) / 8;
 
-    /* av_get_bits_per_sample returns 0 for AV_CODEC_ID_PCM_DVD */
     samples_per_block = 1;
     if (avctx->codec_id == AV_CODEC_ID_PCM_LXF) {
         /* we process 40-bit blocks per channel for LXF */
@@ -342,11 +341,6 @@ static int pcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
         sample_size       = 5;
     }
 
-    if (sample_size == 0) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid sample_size\n");
-        return AVERROR(EINVAL);
-    }
-
     if (channels == 0) {
         av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
         return AVERROR(EINVAL);
-- 
2.45.2


[-- Attachment #3: 0002-avcodec-pcm-Cache-sample_size-value.patch --]
[-- Type: text/x-patch, Size: 2191 bytes --]

From 8d65f524e5d5c5b262e5d9bac6c1c319f72d5a24 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 11 Mar 2025 17:53:06 +0100
Subject: [PATCH 2/7] avcodec/pcm: Cache sample_size value

No need to go through two switches per packet.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pcm.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index 5d8dcb8ff0..620acf0f46 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -243,6 +243,7 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 }
 
 typedef struct PCMDecode {
+    int sample_size;
     short   table[256];
     void (*vector_fmul_scalar)(float *dst, const float *src, float mul,
                                int len);
@@ -286,8 +287,14 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx)
 
     avctx->sample_fmt = avctx->codec->sample_fmts[0];
 
-    if (avctx->sample_fmt == AV_SAMPLE_FMT_S32)
-        avctx->bits_per_raw_sample = av_get_bits_per_sample(avctx->codec_id);
+    if (avctx->codec_id != AV_CODEC_ID_PCM_LXF) {
+        int bits_per_sample = av_get_exact_bits_per_sample(avctx->codec_id);
+        if (avctx->sample_fmt == AV_SAMPLE_FMT_S32)
+            avctx->bits_per_raw_sample = bits_per_sample;
+        s->sample_size = bits_per_sample / 8;
+    } else {
+        s->sample_size = 5;
+    }
 
     return 0;
 }
@@ -328,17 +335,14 @@ static int pcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
     int buf_size       = avpkt->size;
     PCMDecode *s       = avctx->priv_data;
     int channels       = avctx->ch_layout.nb_channels;
-    int sample_size, c, n, ret, samples_per_block;
+    int sample_size = s->sample_size, c, n, ret, samples_per_block;
     uint8_t *samples;
     int32_t *dst_int32_t;
 
-    sample_size = av_get_bits_per_sample(avctx->codec_id) / 8;
-
     samples_per_block = 1;
     if (avctx->codec_id == AV_CODEC_ID_PCM_LXF) {
         /* we process 40-bit blocks per channel for LXF */
         samples_per_block = 2;
-        sample_size       = 5;
     }
 
     if (channels == 0) {
-- 
2.45.2


[-- Attachment #4: 0003-avcodec-pcm-Remove-duplication-from-FFCodec-define-m.patch --]
[-- Type: text/x-patch, Size: 9743 bytes --]

From c221a9f2f31c8fcb65e478e8d71b127d9466f3d3 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 13 Mar 2025 04:37:12 +0100
Subject: [PATCH 3/7] avcodec/pcm: Remove duplication from FFCodec define
 macros

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pcm.c | 78 +++++++++++++++++++++++++-----------------------
 1 file changed, 41 insertions(+), 37 deletions(-)

diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index 620acf0f46..6c1feecca3 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -550,7 +550,7 @@ const FFCodec ff_ ## name_ ## _encoder = {                                  \
     .p.name       = #name_,                                                 \
     CODEC_LONG_NAME(long_name_),                                            \
     .p.type       = AVMEDIA_TYPE_AUDIO,                                     \
-    .p.id         = AV_CODEC_ID_ ## id_,                                    \
+    .p.id         = id_,                                                    \
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | \
                       AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,                \
     .init         = pcm_encode_init,                                        \
@@ -563,7 +563,8 @@ const FFCodec ff_ ## name_ ## _encoder = {                                  \
 #define PCM_ENCODER_3(cf, id, sample_fmt, name, long_name)                  \
     PCM_ENCODER_2(cf, id, sample_fmt, name, long_name)
 #define PCM_ENCODER(id, sample_fmt, name, long_name)                        \
-    PCM_ENCODER_3(CONFIG_ ## id ## _ENCODER, id, sample_fmt, name, long_name)
+    PCM_ENCODER_3(CONFIG_PCM_ ## id ## _ENCODER, AV_CODEC_ID_PCM_ ## id,    \
+                  AV_SAMPLE_FMT_ ## sample_fmt, pcm_ ## name, long_name)
 
 #define PCM_DECODER_0(id, sample_fmt, name, long_name)
 #define PCM_DECODER_1(id_, sample_fmt_, name_, long_name_)                  \
@@ -571,7 +572,7 @@ const FFCodec ff_ ## name_ ## _decoder = {                                  \
     .p.name         = #name_,                                               \
     CODEC_LONG_NAME(long_name_),                                            \
     .p.type         = AVMEDIA_TYPE_AUDIO,                                   \
-    .p.id           = AV_CODEC_ID_ ## id_,                                  \
+    .p.id           = id_,                                                  \
     .priv_data_size = sizeof(PCMDecode),                                    \
     .init           = pcm_decode_init,                                      \
     FF_CODEC_DECODE_CB(pcm_decode_frame),                                    \
@@ -584,43 +585,46 @@ const FFCodec ff_ ## name_ ## _decoder = {                                  \
 #define PCM_DECODER_3(cf, id, sample_fmt, name, long_name)                  \
     PCM_DECODER_2(cf, id, sample_fmt, name, long_name)
 #define PCM_DECODER(id, sample_fmt, name, long_name)                        \
-    PCM_DECODER_3(CONFIG_ ## id ## _DECODER, id, sample_fmt, name, long_name)
+    PCM_DECODER_3(CONFIG_PCM_ ## id ## _DECODER, AV_CODEC_ID_PCM_ ## id,    \
+                  AV_SAMPLE_FMT_ ## sample_fmt, pcm_ ## name, long_name)
 
 #define PCM_CODEC(id, sample_fmt_, name, long_name_)                    \
     PCM_ENCODER(id, sample_fmt_, name, long_name_);                     \
     PCM_DECODER(id, sample_fmt_, name, long_name_)
 
 /* Note: Do not forget to add new entries to the Makefile as well. */
-PCM_CODEC  (PCM_ALAW,         AV_SAMPLE_FMT_S16, pcm_alaw,         "PCM A-law / G.711 A-law");
-PCM_DECODER(PCM_F16LE,        AV_SAMPLE_FMT_FLT, pcm_f16le,        "PCM 16.8 floating point little-endian");
-PCM_DECODER(PCM_F24LE,        AV_SAMPLE_FMT_FLT, pcm_f24le,        "PCM 24.0 floating point little-endian");
-PCM_CODEC  (PCM_F32BE,        AV_SAMPLE_FMT_FLT, pcm_f32be,        "PCM 32-bit floating point big-endian");
-PCM_CODEC  (PCM_F32LE,        AV_SAMPLE_FMT_FLT, pcm_f32le,        "PCM 32-bit floating point little-endian");
-PCM_CODEC  (PCM_F64BE,        AV_SAMPLE_FMT_DBL, pcm_f64be,        "PCM 64-bit floating point big-endian");
-PCM_CODEC  (PCM_F64LE,        AV_SAMPLE_FMT_DBL, pcm_f64le,        "PCM 64-bit floating point little-endian");
-PCM_DECODER(PCM_LXF,          AV_SAMPLE_FMT_S32P,pcm_lxf,          "PCM signed 20-bit little-endian planar");
-PCM_CODEC  (PCM_MULAW,        AV_SAMPLE_FMT_S16, pcm_mulaw,        "PCM mu-law / G.711 mu-law");
-PCM_CODEC  (PCM_S8,           AV_SAMPLE_FMT_U8,  pcm_s8,           "PCM signed 8-bit");
-PCM_CODEC  (PCM_S8_PLANAR,    AV_SAMPLE_FMT_U8P, pcm_s8_planar,    "PCM signed 8-bit planar");
-PCM_CODEC  (PCM_S16BE,        AV_SAMPLE_FMT_S16, pcm_s16be,        "PCM signed 16-bit big-endian");
-PCM_CODEC  (PCM_S16BE_PLANAR, AV_SAMPLE_FMT_S16P,pcm_s16be_planar, "PCM signed 16-bit big-endian planar");
-PCM_CODEC  (PCM_S16LE,        AV_SAMPLE_FMT_S16, pcm_s16le,        "PCM signed 16-bit little-endian");
-PCM_CODEC  (PCM_S16LE_PLANAR, AV_SAMPLE_FMT_S16P,pcm_s16le_planar, "PCM signed 16-bit little-endian planar");
-PCM_CODEC  (PCM_S24BE,        AV_SAMPLE_FMT_S32, pcm_s24be,        "PCM signed 24-bit big-endian");
-PCM_CODEC  (PCM_S24DAUD,      AV_SAMPLE_FMT_S16, pcm_s24daud,      "PCM D-Cinema audio signed 24-bit");
-PCM_CODEC  (PCM_S24LE,        AV_SAMPLE_FMT_S32, pcm_s24le,        "PCM signed 24-bit little-endian");
-PCM_CODEC  (PCM_S24LE_PLANAR, AV_SAMPLE_FMT_S32P,pcm_s24le_planar, "PCM signed 24-bit little-endian planar");
-PCM_CODEC  (PCM_S32BE,        AV_SAMPLE_FMT_S32, pcm_s32be,        "PCM signed 32-bit big-endian");
-PCM_CODEC  (PCM_S32LE,        AV_SAMPLE_FMT_S32, pcm_s32le,        "PCM signed 32-bit little-endian");
-PCM_CODEC  (PCM_S32LE_PLANAR, AV_SAMPLE_FMT_S32P,pcm_s32le_planar, "PCM signed 32-bit little-endian planar");
-PCM_CODEC  (PCM_U8,           AV_SAMPLE_FMT_U8,  pcm_u8,           "PCM unsigned 8-bit");
-PCM_CODEC  (PCM_U16BE,        AV_SAMPLE_FMT_S16, pcm_u16be,        "PCM unsigned 16-bit big-endian");
-PCM_CODEC  (PCM_U16LE,        AV_SAMPLE_FMT_S16, pcm_u16le,        "PCM unsigned 16-bit little-endian");
-PCM_CODEC  (PCM_U24BE,        AV_SAMPLE_FMT_S32, pcm_u24be,        "PCM unsigned 24-bit big-endian");
-PCM_CODEC  (PCM_U24LE,        AV_SAMPLE_FMT_S32, pcm_u24le,        "PCM unsigned 24-bit little-endian");
-PCM_CODEC  (PCM_U32BE,        AV_SAMPLE_FMT_S32, pcm_u32be,        "PCM unsigned 32-bit big-endian");
-PCM_CODEC  (PCM_U32LE,        AV_SAMPLE_FMT_S32, pcm_u32le,        "PCM unsigned 32-bit little-endian");
-PCM_CODEC  (PCM_S64BE,        AV_SAMPLE_FMT_S64, pcm_s64be,        "PCM signed 64-bit big-endian");
-PCM_CODEC  (PCM_S64LE,        AV_SAMPLE_FMT_S64, pcm_s64le,        "PCM signed 64-bit little-endian");
-PCM_CODEC  (PCM_VIDC,         AV_SAMPLE_FMT_S16, pcm_vidc,         "PCM Archimedes VIDC");
-PCM_DECODER(PCM_SGA,          AV_SAMPLE_FMT_U8,  pcm_sga,          "PCM SGA");
+//       AV_CODEC_ID_*       pcm_* name
+//                 AV_SAMPLE_FMT_*               long name
+PCM_CODEC  (ALAW,         S16, alaw,         "PCM A-law / G.711 A-law");
+PCM_DECODER(F16LE,        FLT, f16le,        "PCM 16.8 floating point little-endian");
+PCM_DECODER(F24LE,        FLT, f24le,        "PCM 24.0 floating point little-endian");
+PCM_CODEC  (F32BE,        FLT, f32be,        "PCM 32-bit floating point big-endian");
+PCM_CODEC  (F32LE,        FLT, f32le,        "PCM 32-bit floating point little-endian");
+PCM_CODEC  (F64BE,        DBL, f64be,        "PCM 64-bit floating point big-endian");
+PCM_CODEC  (F64LE,        DBL, f64le,        "PCM 64-bit floating point little-endian");
+PCM_DECODER(LXF,          S32P,lxf,          "PCM signed 20-bit little-endian planar");
+PCM_CODEC  (MULAW,        S16, mulaw,        "PCM mu-law / G.711 mu-law");
+PCM_CODEC  (S8,           U8,  s8,           "PCM signed 8-bit");
+PCM_CODEC  (S8_PLANAR,    U8P, s8_planar,    "PCM signed 8-bit planar");
+PCM_CODEC  (S16BE,        S16, s16be,        "PCM signed 16-bit big-endian");
+PCM_CODEC  (S16BE_PLANAR, S16P,s16be_planar, "PCM signed 16-bit big-endian planar");
+PCM_CODEC  (S16LE,        S16, s16le,        "PCM signed 16-bit little-endian");
+PCM_CODEC  (S16LE_PLANAR, S16P,s16le_planar, "PCM signed 16-bit little-endian planar");
+PCM_CODEC  (S24BE,        S32, s24be,        "PCM signed 24-bit big-endian");
+PCM_CODEC  (S24DAUD,      S16, s24daud,      "PCM D-Cinema audio signed 24-bit");
+PCM_CODEC  (S24LE,        S32, s24le,        "PCM signed 24-bit little-endian");
+PCM_CODEC  (S24LE_PLANAR, S32P,s24le_planar, "PCM signed 24-bit little-endian planar");
+PCM_CODEC  (S32BE,        S32, s32be,        "PCM signed 32-bit big-endian");
+PCM_CODEC  (S32LE,        S32, s32le,        "PCM signed 32-bit little-endian");
+PCM_CODEC  (S32LE_PLANAR, S32P,s32le_planar, "PCM signed 32-bit little-endian planar");
+PCM_CODEC  (U8,           U8,  u8,           "PCM unsigned 8-bit");
+PCM_CODEC  (U16BE,        S16, u16be,        "PCM unsigned 16-bit big-endian");
+PCM_CODEC  (U16LE,        S16, u16le,        "PCM unsigned 16-bit little-endian");
+PCM_CODEC  (U24BE,        S32, u24be,        "PCM unsigned 24-bit big-endian");
+PCM_CODEC  (U24LE,        S32, u24le,        "PCM unsigned 24-bit little-endian");
+PCM_CODEC  (U32BE,        S32, u32be,        "PCM unsigned 32-bit big-endian");
+PCM_CODEC  (U32LE,        S32, u32le,        "PCM unsigned 32-bit little-endian");
+PCM_CODEC  (S64BE,        S64, s64be,        "PCM signed 64-bit big-endian");
+PCM_CODEC  (S64LE,        S64, s64le,        "PCM signed 64-bit little-endian");
+PCM_CODEC  (VIDC,         S16, vidc,         "PCM Archimedes VIDC");
+PCM_DECODER(SGA,          U8,  sga,          "PCM SGA");
-- 
2.45.2


[-- Attachment #5: 0004-avcodec-pcm-Don-t-allocate-LUT-when-unused.patch --]
[-- Type: text/x-patch, Size: 8732 bytes --]

From dd61d68e6765f99ef2af096a9e00a2721e1d7f6f Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 11 Mar 2025 19:21:16 +0100
Subject: [PATCH 4/7] avcodec/pcm: Don't allocate LUT when unused

Instead use a dedicated context for the few decoders that
use the LUT. Also use a dedicated init function for them.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pcm.c | 98 ++++++++++++++++++++++++++++++------------------
 1 file changed, 62 insertions(+), 36 deletions(-)

diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index 6c1feecca3..a2a0aa19ce 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -244,31 +244,17 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 
 typedef struct PCMDecode {
     int sample_size;
-    short   table[256];
     void (*vector_fmul_scalar)(float *dst, const float *src, float mul,
                                int len);
     float   scale;
 } PCMDecode;
 
-static av_cold int pcm_decode_init(AVCodecContext *avctx)
+static av_cold av_unused int pcm_decode_init(AVCodecContext *avctx)
 {
     PCMDecode *s = avctx->priv_data;
     AVFloatDSPContext *fdsp;
-    int i;
 
     switch (avctx->codec_id) {
-    case AV_CODEC_ID_PCM_ALAW:
-        for (i = 0; i < 256; i++)
-            s->table[i] = alaw2linear(i);
-        break;
-    case AV_CODEC_ID_PCM_MULAW:
-        for (i = 0; i < 256; i++)
-            s->table[i] = ulaw2linear(i);
-        break;
-    case AV_CODEC_ID_PCM_VIDC:
-        for (i = 0; i < 256; i++)
-            s->table[i] = vidc2linear(i);
-        break;
     case AV_CODEC_ID_PCM_F16LE:
     case AV_CODEC_ID_PCM_F24LE:
         if (avctx->bits_per_coded_sample < 1 || avctx->bits_per_coded_sample > 24)
@@ -299,6 +285,36 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx)
     return 0;
 }
 
+typedef struct PCMLUTDecode {
+    PCMDecode base;
+    int16_t   table[256];
+} PCMLUTDecode;
+
+static av_cold av_unused int pcm_lut_decode_init(AVCodecContext *avctx)
+{
+    PCMLUTDecode *s = avctx->priv_data;
+
+    switch (avctx->codec_id) {
+    case AV_CODEC_ID_PCM_ALAW:
+        for (int i = 0; i < 256; i++)
+            s->table[i] = alaw2linear(i);
+        break;
+    case AV_CODEC_ID_PCM_MULAW:
+        for (int i = 0; i < 256; i++)
+            s->table[i] = ulaw2linear(i);
+        break;
+    case AV_CODEC_ID_PCM_VIDC:
+        for (int i = 0; i < 256; i++)
+            s->table[i] = vidc2linear(i);
+        break;
+    }
+
+    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+    s->base.sample_size = 1;
+
+    return 0;
+}
+
 /**
  * Read PCM samples macro
  * @param size   Data size of native machine format
@@ -498,12 +514,14 @@ static int pcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
         break;
     case AV_CODEC_ID_PCM_ALAW:
     case AV_CODEC_ID_PCM_MULAW:
-    case AV_CODEC_ID_PCM_VIDC:
-        for (; n > 0; n--) {
-            AV_WN16A(samples, s->table[*src++]);
-            samples += 2;
-        }
+    case AV_CODEC_ID_PCM_VIDC: {
+        const int16_t *const lut = ((PCMLUTDecode*)avctx->priv_data)->table;
+        int16_t *restrict samples_16 = (int16_t*)samples;
+
+        for (; n > 0; n--)
+            *samples_16++ = lut[*src++];
         break;
+    }
     case AV_CODEC_ID_PCM_LXF:
     {
         int i;
@@ -566,36 +584,44 @@ const FFCodec ff_ ## name_ ## _encoder = {                                  \
     PCM_ENCODER_3(CONFIG_PCM_ ## id ## _ENCODER, AV_CODEC_ID_PCM_ ## id,    \
                   AV_SAMPLE_FMT_ ## sample_fmt, pcm_ ## name, long_name)
 
-#define PCM_DECODER_0(id, sample_fmt, name, long_name)
-#define PCM_DECODER_1(id_, sample_fmt_, name_, long_name_)                  \
+#define PCM_DECODER_0(id, sample_fmt, name, long_name, Context, init_func)
+#define PCM_DECODER_1(id_, sample_fmt, name_, long_name, Context, init_func) \
 const FFCodec ff_ ## name_ ## _decoder = {                                  \
     .p.name         = #name_,                                               \
-    CODEC_LONG_NAME(long_name_),                                            \
+    CODEC_LONG_NAME(long_name),                                             \
     .p.type         = AVMEDIA_TYPE_AUDIO,                                   \
     .p.id           = id_,                                                  \
-    .priv_data_size = sizeof(PCMDecode),                                    \
-    .init           = pcm_decode_init,                                      \
+    .priv_data_size = sizeof(Context),                                      \
+    .init           = init_func,                                            \
     FF_CODEC_DECODE_CB(pcm_decode_frame),                                    \
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE,         \
-    CODEC_SAMPLEFMTS(sample_fmt_),                                          \
+    CODEC_SAMPLEFMTS(sample_fmt),                                           \
 }
 
-#define PCM_DECODER_2(cf, id, sample_fmt, name, long_name)                  \
-    PCM_DECODER_ ## cf(id, sample_fmt, name, long_name)
-#define PCM_DECODER_3(cf, id, sample_fmt, name, long_name)                  \
-    PCM_DECODER_2(cf, id, sample_fmt, name, long_name)
-#define PCM_DECODER(id, sample_fmt, name, long_name)                        \
+#define PCM_DECODER_2(cf, id, sample_fmt, name, long_name, Context, init_func) \
+    PCM_DECODER_ ## cf(id, sample_fmt, name, long_name, Context, init_func)
+#define PCM_DECODER_3(cf, id, sample_fmt, name, long_name, Context, init_func) \
+    PCM_DECODER_2(cf, id, sample_fmt, name, long_name, Context, init_func)
+#define PCM_DEC_EXT(id, sample_fmt, name, long_name, Context, init_func)    \
     PCM_DECODER_3(CONFIG_PCM_ ## id ## _DECODER, AV_CODEC_ID_PCM_ ## id,    \
-                  AV_SAMPLE_FMT_ ## sample_fmt, pcm_ ## name, long_name)
+                  AV_SAMPLE_FMT_ ## sample_fmt, pcm_ ## name, long_name,    \
+                  Context, init_func)
+
+#define PCM_DECODER(id, sample_fmt, name, long_name)    \
+    PCM_DEC_EXT(id, sample_fmt, name, long_name, PCMDecode, pcm_decode_init)
 
 #define PCM_CODEC(id, sample_fmt_, name, long_name_)                    \
     PCM_ENCODER(id, sample_fmt_, name, long_name_);                     \
     PCM_DECODER(id, sample_fmt_, name, long_name_)
 
+#define PCM_CODEC_EXT(id, sample_fmt, name, long_name, DecContext, dec_init_func) \
+    PCM_DEC_EXT(id, sample_fmt, name, long_name, DecContext, dec_init_func);      \
+    PCM_ENCODER(id, sample_fmt, name, long_name)
+
 /* Note: Do not forget to add new entries to the Makefile as well. */
 //       AV_CODEC_ID_*       pcm_* name
-//                 AV_SAMPLE_FMT_*               long name
-PCM_CODEC  (ALAW,         S16, alaw,         "PCM A-law / G.711 A-law");
+//                 AV_SAMPLE_FMT_*               long name                            DecodeContext    decode init func
+PCM_CODEC_EXT(ALAW,       S16, alaw,         "PCM A-law / G.711 A-law",               PCMLUTDecode,   pcm_lut_decode_init);
 PCM_DECODER(F16LE,        FLT, f16le,        "PCM 16.8 floating point little-endian");
 PCM_DECODER(F24LE,        FLT, f24le,        "PCM 24.0 floating point little-endian");
 PCM_CODEC  (F32BE,        FLT, f32be,        "PCM 32-bit floating point big-endian");
@@ -603,7 +629,7 @@ PCM_CODEC  (F32LE,        FLT, f32le,        "PCM 32-bit floating point little-e
 PCM_CODEC  (F64BE,        DBL, f64be,        "PCM 64-bit floating point big-endian");
 PCM_CODEC  (F64LE,        DBL, f64le,        "PCM 64-bit floating point little-endian");
 PCM_DECODER(LXF,          S32P,lxf,          "PCM signed 20-bit little-endian planar");
-PCM_CODEC  (MULAW,        S16, mulaw,        "PCM mu-law / G.711 mu-law");
+PCM_CODEC_EXT(MULAW,      S16, mulaw,        "PCM mu-law / G.711 mu-law",             PCMLUTDecode,   pcm_lut_decode_init);
 PCM_CODEC  (S8,           U8,  s8,           "PCM signed 8-bit");
 PCM_CODEC  (S8_PLANAR,    U8P, s8_planar,    "PCM signed 8-bit planar");
 PCM_CODEC  (S16BE,        S16, s16be,        "PCM signed 16-bit big-endian");
@@ -626,5 +652,5 @@ PCM_CODEC  (U32BE,        S32, u32be,        "PCM unsigned 32-bit big-endian");
 PCM_CODEC  (U32LE,        S32, u32le,        "PCM unsigned 32-bit little-endian");
 PCM_CODEC  (S64BE,        S64, s64be,        "PCM signed 64-bit big-endian");
 PCM_CODEC  (S64LE,        S64, s64le,        "PCM signed 64-bit little-endian");
-PCM_CODEC  (VIDC,         S16, vidc,         "PCM Archimedes VIDC");
+PCM_CODEC_EXT(VIDC,       S16, vidc,         "PCM Archimedes VIDC",                   PCMLUTDecode,   pcm_lut_decode_init);
 PCM_DECODER(SGA,          U8,  sga,          "PCM SGA");
-- 
2.45.2


[-- Attachment #6: 0005-avcodec-pcm-Use-dedicated-init-function-for-F16LE-F2.patch --]
[-- Type: text/x-patch, Size: 4678 bytes --]

From cf5fc0c6319dab17405deb12b2e46629cf32e9f0 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 11 Mar 2025 19:36:03 +0100
Subject: [PATCH 5/7] avcodec/pcm: Use dedicated init function for F16LE, F24LE

This avoids a switch and allows to simply use
a dedicated private context for them.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pcm.c | 59 ++++++++++++++++++++++++++++--------------------
 1 file changed, 34 insertions(+), 25 deletions(-)

diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index a2a0aa19ce..66b2aa359d 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -244,19 +244,41 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 
 typedef struct PCMDecode {
     int sample_size;
-    void (*vector_fmul_scalar)(float *dst, const float *src, float mul,
-                               int len);
-    float   scale;
 } PCMDecode;
 
 static av_cold av_unused int pcm_decode_init(AVCodecContext *avctx)
 {
     PCMDecode *s = avctx->priv_data;
+
+    avctx->sample_fmt = avctx->codec->sample_fmts[0];
+
+    if (avctx->codec_id != AV_CODEC_ID_PCM_LXF) {
+        int bits_per_sample = av_get_exact_bits_per_sample(avctx->codec_id);
+        if (avctx->sample_fmt == AV_SAMPLE_FMT_S32)
+            avctx->bits_per_raw_sample = bits_per_sample;
+        s->sample_size = bits_per_sample / 8;
+    } else {
+        s->sample_size = 5;
+    }
+
+    return 0;
+}
+
+typedef struct PCMScaleDecode {
+    PCMDecode base;
+    void (*vector_fmul_scalar)(float *dst, const float *src, float mul,
+                               int len);
+    float   scale;
+} PCMScaleDecode;
+
+static av_cold av_unused int pcm_scale_decode_init(AVCodecContext *avctx)
+{
+    PCMScaleDecode *s = avctx->priv_data;
     AVFloatDSPContext *fdsp;
 
-    switch (avctx->codec_id) {
-    case AV_CODEC_ID_PCM_F16LE:
-    case AV_CODEC_ID_PCM_F24LE:
+    avctx->sample_fmt   = AV_SAMPLE_FMT_FLT;
+    s->base.sample_size = 4;
+
         if (avctx->bits_per_coded_sample < 1 || avctx->bits_per_coded_sample > 24)
             return AVERROR_INVALIDDATA;
 
@@ -266,21 +288,7 @@ static av_cold av_unused int pcm_decode_init(AVCodecContext *avctx)
             return AVERROR(ENOMEM);
         s->vector_fmul_scalar = fdsp->vector_fmul_scalar;
         av_free(fdsp);
-        break;
-    default:
-        break;
-    }
 
-    avctx->sample_fmt = avctx->codec->sample_fmts[0];
-
-    if (avctx->codec_id != AV_CODEC_ID_PCM_LXF) {
-        int bits_per_sample = av_get_exact_bits_per_sample(avctx->codec_id);
-        if (avctx->sample_fmt == AV_SAMPLE_FMT_S32)
-            avctx->bits_per_raw_sample = bits_per_sample;
-        s->sample_size = bits_per_sample / 8;
-    } else {
-        s->sample_size = 5;
-    }
 
     return 0;
 }
@@ -552,9 +560,10 @@ static int pcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
 
     if (avctx->codec_id == AV_CODEC_ID_PCM_F16LE ||
         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->ch_layout.nb_channels, 4));
+        PCMScaleDecode *s2 = avctx->priv_data;
+        s2->vector_fmul_scalar((float *)frame->extended_data[0],
+                               (const float *)frame->extended_data[0],
+                               s2->scale, FFALIGN(frame->nb_samples * avctx->ch_layout.nb_channels, 4));
     }
 
     *got_frame_ptr = 1;
@@ -622,8 +631,8 @@ const FFCodec ff_ ## name_ ## _decoder = {                                  \
 //       AV_CODEC_ID_*       pcm_* name
 //                 AV_SAMPLE_FMT_*               long name                            DecodeContext    decode init func
 PCM_CODEC_EXT(ALAW,       S16, alaw,         "PCM A-law / G.711 A-law",               PCMLUTDecode,   pcm_lut_decode_init);
-PCM_DECODER(F16LE,        FLT, f16le,        "PCM 16.8 floating point little-endian");
-PCM_DECODER(F24LE,        FLT, f24le,        "PCM 24.0 floating point little-endian");
+PCM_DEC_EXT(F16LE,        FLT, f16le,        "PCM 16.8 floating point little-endian", PCMScaleDecode, pcm_scale_decode_init);
+PCM_DEC_EXT(F24LE,        FLT, f24le,        "PCM 24.0 floating point little-endian", PCMScaleDecode, pcm_scale_decode_init);
 PCM_CODEC  (F32BE,        FLT, f32be,        "PCM 32-bit floating point big-endian");
 PCM_CODEC  (F32LE,        FLT, f32le,        "PCM 32-bit floating point little-endian");
 PCM_CODEC  (F64BE,        DBL, f64be,        "PCM 64-bit floating point big-endian");
-- 
2.45.2


[-- Attachment #7: 0006-avcodec-pcm-Reindent-after-the-previous-commit.patch --]
[-- Type: text/x-patch, Size: 1465 bytes --]

From 7d1444637b92008d4300aac3b7441fa33a28c400 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Tue, 11 Mar 2025 19:55:21 +0100
Subject: [PATCH 6/7] avcodec/pcm: Reindent after the previous commit

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pcm.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index 66b2aa359d..effa337390 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -279,16 +279,15 @@ static av_cold av_unused int pcm_scale_decode_init(AVCodecContext *avctx)
     avctx->sample_fmt   = AV_SAMPLE_FMT_FLT;
     s->base.sample_size = 4;
 
-        if (avctx->bits_per_coded_sample < 1 || avctx->bits_per_coded_sample > 24)
-            return AVERROR_INVALIDDATA;
-
-        s->scale = 1. / (1 << (avctx->bits_per_coded_sample - 1));
-        fdsp = avpriv_float_dsp_alloc(0);
-        if (!fdsp)
-            return AVERROR(ENOMEM);
-        s->vector_fmul_scalar = fdsp->vector_fmul_scalar;
-        av_free(fdsp);
-
+    if (avctx->bits_per_coded_sample < 1 || avctx->bits_per_coded_sample > 24)
+        return AVERROR_INVALIDDATA;
+
+    s->scale = 1. / (1 << (avctx->bits_per_coded_sample - 1));
+    fdsp = avpriv_float_dsp_alloc(0);
+    if (!fdsp)
+        return AVERROR(ENOMEM);
+    s->vector_fmul_scalar = fdsp->vector_fmul_scalar;
+    av_free(fdsp);
 
     return 0;
 }
-- 
2.45.2


[-- Attachment #8: 0007-avcodec-pcm-Avoid-AVCodec.sample_fmts-for-decoders.patch --]
[-- Type: text/x-patch, Size: 4348 bytes --]

From acd4b67a4329c10ce202de87e6c188c691c49108 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 13 Mar 2025 02:44:24 +0100
Subject: [PATCH 7/7] avcodec/pcm: Avoid AVCodec.sample_fmts for decoders

These fields are meant to be for encoders; just use a local
table in pcm_decode_init() to convert from AVCodecID to AVSampleFormat
and also use it to provide sample_size.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pcm.c | 49 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 12 deletions(-)

diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index effa337390..0c040b94b0 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -249,16 +249,41 @@ typedef struct PCMDecode {
 static av_cold av_unused int pcm_decode_init(AVCodecContext *avctx)
 {
     PCMDecode *s = avctx->priv_data;
-
-    avctx->sample_fmt = avctx->codec->sample_fmts[0];
-
-    if (avctx->codec_id != AV_CODEC_ID_PCM_LXF) {
-        int bits_per_sample = av_get_exact_bits_per_sample(avctx->codec_id);
-        if (avctx->sample_fmt == AV_SAMPLE_FMT_S32)
-            avctx->bits_per_raw_sample = bits_per_sample;
-        s->sample_size = bits_per_sample / 8;
-    } else {
-        s->sample_size = 5;
+    static const struct {
+        enum AVCodecID codec_id;
+        int8_t sample_fmt;
+        uint8_t sample_size;
+        uint8_t bits_per_sample;
+    } codec_id_to_samplefmt[] = {
+    #define ENTRY(CODEC_ID, SAMPLE_FMT, BITS_PER_SAMPLE) \
+        { AV_CODEC_ID_PCM_ ## CODEC_ID, AV_SAMPLE_FMT_ ## SAMPLE_FMT, \
+        BITS_PER_SAMPLE / 8, BITS_PER_SAMPLE }
+        ENTRY(S8, U8, 8),        ENTRY(S8_PLANAR, U8P, 8),
+        ENTRY(S16BE, S16, 16),   ENTRY(S16BE_PLANAR, S16P, 16),
+        ENTRY(S16LE, S16, 16),   ENTRY(S16LE_PLANAR, S16P, 16),
+        ENTRY(S24DAUD, S16, 24), ENTRY(S24BE, S32, 24),
+        ENTRY(S24LE, S32, 24),   ENTRY(S24LE_PLANAR, S32P, 24),
+        ENTRY(S32BE, S32, 32),   ENTRY(S32LE, S32, 32),
+        ENTRY(S32LE_PLANAR, S32P, 32),
+        ENTRY(S64BE, S64, 64),   ENTRY(S64LE, S64, 64),
+        ENTRY(SGA, U8, 8),       ENTRY(U8, U8, 8),
+        ENTRY(U16BE, S16, 16),   ENTRY(U16LE, S16, 16),
+        ENTRY(U24BE, S32, 24),   ENTRY(U24LE, S32, 24),
+        ENTRY(U32BE, S32, 32),   ENTRY(U32LE, S32, 32),
+        ENTRY(F32BE, FLT, 32),   ENTRY(F32LE, FLT, 32),
+        ENTRY(F64BE, DBL, 64),   ENTRY(F64LE, DBL, 64),
+        { .codec_id = AV_CODEC_ID_PCM_LXF, .sample_fmt = AV_SAMPLE_FMT_S32P, .sample_size = 5 },
+    };
+
+    for (unsigned i = 0; i < FF_ARRAY_ELEMS(codec_id_to_samplefmt); ++i) {
+        if (codec_id_to_samplefmt[i].codec_id == avctx->codec_id) {
+            s->sample_size    = codec_id_to_samplefmt[i].sample_size;
+            avctx->sample_fmt = codec_id_to_samplefmt[i].sample_fmt;
+            if (avctx->sample_fmt == AV_SAMPLE_FMT_S32)
+                avctx->bits_per_raw_sample = codec_id_to_samplefmt[i].bits_per_sample;
+            break;
+        }
+        av_assert1(i + 1 < FF_ARRAY_ELEMS(codec_id_to_samplefmt));
     }
 
     return 0;
@@ -603,7 +628,6 @@ const FFCodec ff_ ## name_ ## _decoder = {                                  \
     .init           = init_func,                                            \
     FF_CODEC_DECODE_CB(pcm_decode_frame),                                    \
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE,         \
-    CODEC_SAMPLEFMTS(sample_fmt),                                           \
 }
 
 #define PCM_DECODER_2(cf, id, sample_fmt, name, long_name, Context, init_func) \
@@ -626,7 +650,8 @@ const FFCodec ff_ ## name_ ## _decoder = {                                  \
     PCM_DEC_EXT(id, sample_fmt, name, long_name, DecContext, dec_init_func);      \
     PCM_ENCODER(id, sample_fmt, name, long_name)
 
-/* Note: Do not forget to add new entries to the Makefile as well. */
+/* Note: Do not forget to add new entries to the Makefile and
+ *       to the table in pcm_decode_init() as well. */
 //       AV_CODEC_ID_*       pcm_* name
 //                 AV_SAMPLE_FMT_*               long name                            DecodeContext    decode init func
 PCM_CODEC_EXT(ALAW,       S16, alaw,         "PCM A-law / G.711 A-law",               PCMLUTDecode,   pcm_lut_decode_init);
-- 
2.45.2


[-- Attachment #9: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-03-13  5:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-13  5:49 [FFmpeg-devel] [PATCH 1/7] avcodec/pcm: Remove always-false check Andreas Rheinhardt

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git