Commit 81b83d993a for ffmpeg
commit 81b83d993a8888f5b2cb4e6648ce48236716fc06
Author: Simon Capriotti <sicapr98@gmail.com>
Date: Sun May 31 19:40:45 2026 +0200
avcodec/pcm-bluray: add a PCM PAMF decoder
PCM streams in PAMF files are pcm_bluray streams without the header at the start of each frame.
Signed-off-by: Simon Capriotti <sicapr98@gmail.com>
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index bb2c32c250..4bffc08118 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -913,6 +913,7 @@ OBJS-$(CONFIG_PCM_F64LE_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_LXF_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_MULAW_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o
+OBJS-$(CONFIG_PCM_PAMF_DECODER) += pcm-bluray.o
OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o
OBJS-$(CONFIG_PCM_S8_ENCODER) += pcm.o
OBJS-$(CONFIG_PCM_S8_PLANAR_DECODER) += pcm.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index b12dcc405a..edbe44ecc6 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -577,6 +577,7 @@ extern const FFCodec ff_pcm_f64le_decoder;
extern const FFCodec ff_pcm_lxf_decoder;
extern const FFCodec ff_pcm_mulaw_encoder;
extern const FFCodec ff_pcm_mulaw_decoder;
+extern const FFCodec ff_pcm_pamf_decoder;
extern const FFCodec ff_pcm_s8_encoder;
extern const FFCodec ff_pcm_s8_decoder;
extern const FFCodec ff_pcm_s8_planar_encoder;
diff --git a/libavcodec/pcm-bluray.c b/libavcodec/pcm-bluray.c
index e91d54f937..a84a14251d 100644
--- a/libavcodec/pcm-bluray.c
+++ b/libavcodec/pcm-bluray.c
@@ -1,6 +1,7 @@
/*
- * LPCM codecs for PCM format found in Blu-ray PCM streams
+ * LPCM codecs for PCM format found in Blu-ray and PAMF PCM streams
* Copyright (c) 2009, 2013 Christian Schmidt
+ * Copyright (c) 2026 Simon Capriotti
*
* This file is part of FFmpeg.
*
@@ -21,9 +22,11 @@
/**
* @file
- * PCM codec for Blu-ray PCM audio tracks
+ * PCM codec for Blu-ray and PAMF PCM audio tracks
*/
+#include "config_components.h"
+
#include "libavutil/channel_layout.h"
#include "avcodec.h"
#include "bytestream.h"
@@ -214,6 +217,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
return retval;
}
+#if CONFIG_PCM_BLURAY_DECODER
+
/**
* Parse the header of a LPCM frame read from a Blu-ray MPEG-TS stream
* @param avctx the codec context
@@ -316,3 +321,67 @@ const FFCodec ff_pcm_bluray_decoder = {
FF_CODEC_DECODE_CB(pcm_bluray_decode_frame),
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
};
+
+#endif
+
+#if CONFIG_PCM_PAMF_DECODER
+
+static av_cold int pcm_pamf_init_decode(AVCodecContext *avctx)
+{
+ switch (avctx->bits_per_coded_sample) {
+ case 16:
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ break;
+ case 20:
+ case 24:
+ avctx->sample_fmt = AV_SAMPLE_FMT_S32;
+ break;
+ default:
+ av_log(avctx, AV_LOG_FATAL, "Invalid sample depth (%d)\n",
+ avctx->bits_per_coded_sample);
+ return AVERROR(EINVAL);
+ }
+
+ avctx->bits_per_raw_sample = avctx->bits_per_coded_sample;
+
+ if (avctx->ch_layout.order != AV_CHANNEL_ORDER_NATIVE) {
+ av_log(avctx, AV_LOG_FATAL, "Invalid channel order (%X)\n",
+ avctx->ch_layout.order);
+ return AVERROR(EINVAL);
+ }
+
+ switch (avctx->ch_layout.u.mask) {
+ case AV_CH_LAYOUT_MONO:
+ case AV_CH_LAYOUT_STEREO:
+ case AV_CH_LAYOUT_SURROUND:
+ case AV_CH_LAYOUT_2_1:
+ case AV_CH_LAYOUT_4POINT0:
+ case AV_CH_LAYOUT_2_2:
+ case AV_CH_LAYOUT_5POINT0:
+ case AV_CH_LAYOUT_5POINT1:
+ case AV_CH_LAYOUT_7POINT0:
+ case AV_CH_LAYOUT_7POINT1:
+ break;
+ default:
+ av_log(avctx, AV_LOG_FATAL, "Invalid channel layout (%"PRIX64")\n",
+ avctx->ch_layout.u.mask);
+ return AVERROR(EINVAL);
+ }
+
+ avctx->bit_rate = (int64_t)FFALIGN(avctx->ch_layout.nb_channels, 2) *
+ avctx->sample_rate *
+ (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24);
+ return 0;
+}
+
+const FFCodec ff_pcm_pamf_decoder = {
+ .p.name = "pcm_pamf",
+ CODEC_LONG_NAME("PCM signed 16|20|24-bit big-endian for PAMF streams"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_PCM_PAMF,
+ .init = pcm_pamf_init_decode,
+ FF_CODEC_DECODE_CB(decode_frame),
+ .p.capabilities = AV_CODEC_CAP_DR1,
+};
+
+#endif
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 306696ecc5..84afe6da51 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -795,6 +795,10 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
return (frame_bytes - 4) / ((FFALIGN(ch, 2) * bps) / 8);
case AV_CODEC_ID_S302M:
return 2 * (frame_bytes / ((bps + 4) / 4)) / ch;
+ case AV_CODEC_ID_PCM_PAMF:
+ if (bps != 16 && bps != 20 && bps != 24)
+ return 0;
+ return frame_bytes / (FFALIGN(ch, 2) * (bps == 16 ? 2 : 3));
}
}
}