* [FFmpeg-devel] [PATCH] avcodec/liblc3: add support for multiple sample formats. (PR #20601)
@ 2025-09-24 14:49 cenzhanquan1 via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: cenzhanquan1 via ffmpeg-devel @ 2025-09-24 14:49 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: cenzhanquan1
PR #20601 opened by cenzhanquan1
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20601
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20601.patch
- Decoder:
- Respect request_sample_fmt if set, default to S16 instead of FLTP
- Add support for S16, S16P, FLT and FLTP sample formats
- Properly handle both planar and interleaved layouts
- Calculate correct data pointers and stride for liblc3
- Encoder:
- Add support for S16, S16P, FLT and FLTP sample formats
- Remove hardcoded use of LC3_PCM_FORMAT_FLOAT
- Handle both planar and interleaved input data
- Update zero frame allocation to account for sample size
- Update codec capabilities to include all supported sample formats
- Enhance error handling for unsupported formats
Signed-off-by: cenzhanquan1 <cenzhanquan1@xiaomi.com>
>From 0e560e67ae62ba568b0bcf2dc10fb322cd8fff3f Mon Sep 17 00:00:00 2001
From: cenzhanquan1 <cenzhanquan1@xiaomi.com>
Date: Wed, 24 Sep 2025 22:43:18 +0800
Subject: [PATCH] avcodec/liblc3: add support for multiple sample formats.
- Decoder:
- Respect request_sample_fmt if set, default to S16 instead of FLTP
- Add support for S16, S16P, FLT and FLTP sample formats
- Properly handle both planar and interleaved layouts
- Calculate correct data pointers and stride for liblc3
- Encoder:
- Add support for S16, S16P, FLT and FLTP sample formats
- Remove hardcoded use of LC3_PCM_FORMAT_FLOAT
- Handle both planar and interleaved input data
- Update zero frame allocation to account for sample size
- Update codec capabilities to include all supported sample formats
- Enhance error handling for unsupported formats
Signed-off-by: cenzhanquan1 <cenzhanquan1@xiaomi.com>
---
libavcodec/liblc3dec.c | 47 ++++++++++++++++++++++++++++++++++++------
libavcodec/liblc3enc.c | 46 ++++++++++++++++++++++++++++++++++-------
2 files changed, 79 insertions(+), 14 deletions(-)
diff --git a/libavcodec/liblc3dec.c b/libavcodec/liblc3dec.c
index d250ace38a..50154b911b 100644
--- a/libavcodec/liblc3dec.c
+++ b/libavcodec/liblc3dec.c
@@ -82,7 +82,12 @@ static av_cold int liblc3_decode_init(AVCodecContext *avctx)
(char *)liblc3->decoder_mem + ch * decoder_size);
}
- avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+ if (avctx->request_sample_fmt != AV_SAMPLE_FMT_NONE) {
+ avctx->sample_fmt = avctx->request_sample_fmt;
+ } else {
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+ }
+
avctx->delay = lc3_hr_delay_samples(
liblc3->hr_mode, liblc3->frame_us, liblc3->srate_hz);
avctx->internal->skip_samples = avctx->delay;
@@ -104,8 +109,10 @@ static int liblc3_decode(AVCodecContext *avctx, AVFrame *frame,
{
LibLC3DecContext *liblc3 = avctx->priv_data;
int channels = avctx->ch_layout.nb_channels;
- uint8_t *in = avpkt->data;
+ enum lc3_pcm_format liblc3_format;
int block_bytes, ret;
+ size_t sample_size;
+ int is_planar;
frame->nb_samples = av_rescale(
liblc3->frame_us, liblc3->srate_hz, 1000*1000);
@@ -113,15 +120,43 @@ static int liblc3_decode(AVCodecContext *avctx, AVFrame *frame,
return ret;
block_bytes = avpkt->size;
+
+ switch (avctx->sample_fmt) {
+ case AV_SAMPLE_FMT_S16:
+ case AV_SAMPLE_FMT_S16P:
+ liblc3_format = LC3_PCM_FORMAT_S16;
+ break;
+ case AV_SAMPLE_FMT_FLT:
+ case AV_SAMPLE_FMT_FLTP:
+ liblc3_format = LC3_PCM_FORMAT_FLOAT;
+ break;
+ default:
+ av_log(NULL, AV_LOG_ERROR,
+ "Unsupported sample format %s\n",
+ av_get_sample_fmt_name(avctx->sample_fmt));
+ return AVERROR(EINVAL);
+ }
+
+ is_planar = av_sample_fmt_is_planar(avctx->sample_fmt);
+ sample_size = av_get_bytes_per_sample(avctx->sample_fmt);
+
for (int ch = 0; ch < channels; ch++) {
int nbytes = block_bytes / channels + (ch < block_bytes % channels);
+ void *pcm_data;
+ int stride;
- ret = lc3_decode(liblc3->decoder[ch], in, nbytes,
- LC3_PCM_FORMAT_FLOAT, frame->data[ch], 1);
+ if (is_planar) {
+ pcm_data = frame->extended_data[ch];
+ stride = 1;
+ } else {
+ pcm_data = (uint8_t *)frame->extended_data[0] + ch * sample_size;
+ stride = channels;
+ }
+
+ ret = lc3_decode(liblc3->decoder[ch], avpkt->data + ch * nbytes, nbytes,
+ liblc3_format, pcm_data, stride);
if (ret < 0)
return AVERROR_INVALIDDATA;
-
- in += nbytes;
}
frame->nb_samples = FFMIN(frame->nb_samples, avpkt->duration);
diff --git a/libavcodec/liblc3enc.c b/libavcodec/liblc3enc.c
index 66007a90f3..8aee9304b9 100644
--- a/libavcodec/liblc3enc.c
+++ b/libavcodec/liblc3enc.c
@@ -137,10 +137,30 @@ static int liblc3_encode(AVCodecContext *avctx, AVPacket *pkt,
LibLC3EncContext *liblc3 = avctx->priv_data;
int block_bytes = liblc3->block_bytes;
int channels = avctx->ch_layout.nb_channels;
+ enum lc3_pcm_format lc3_format;
void *zero_frame = NULL;
- uint8_t *data_ptr;
+ size_t sample_size;
+ int is_planar;
int ret;
+ is_planar = av_sample_fmt_is_planar(avctx->sample_fmt);
+ sample_size = av_get_bytes_per_sample(avctx->sample_fmt);
+
+ switch (avctx->sample_fmt) {
+ case AV_SAMPLE_FMT_S16P:
+ case AV_SAMPLE_FMT_S16:
+ lc3_format = LC3_PCM_FORMAT_S16;
+ break;
+ case AV_SAMPLE_FMT_FLT:
+ case AV_SAMPLE_FMT_FLTP:
+ lc3_format = LC3_PCM_FORMAT_FLOAT;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unsupported sample format: %s\n",
+ av_get_sample_fmt_name(avctx->sample_fmt));
+ return AVERROR(EINVAL);
+ }
+
if ((ret = ff_get_encode_buffer(avctx, pkt, block_bytes, 0)) < 0)
return ret;
@@ -152,20 +172,30 @@ static int liblc3_encode(AVCodecContext *avctx, AVPacket *pkt,
return 0;
liblc3->remaining_samples = 0;
- zero_frame = av_mallocz(avctx->frame_size * sizeof(float));
+ zero_frame = av_mallocz(avctx->frame_size * channels * sample_size);
if (!zero_frame)
return AVERROR(ENOMEM);
}
- data_ptr = pkt->data;
for (int ch = 0; ch < channels; ch++) {
- const float *pcm = zero_frame ? zero_frame : frame->data[ch];
int nbytes = block_bytes / channels + (ch < block_bytes % channels);
+ const void *pcm;
+ int stride;
+
+ if (zero_frame) {
+ pcm = (uint8_t *)zero_frame + ch * (is_planar ? avctx->frame_size * sample_size : sample_size);
+ } else {
+ if (is_planar) {
+ pcm = frame->data[ch];
+ stride = 1;
+ } else {
+ pcm = frame->data[0] + ch * sample_size;
+ stride = channels;
+ }
+ }
lc3_encode(liblc3->encoder[ch],
- LC3_PCM_FORMAT_FLOAT, pcm, 1, nbytes, data_ptr);
-
- data_ptr += nbytes;
+ lc3_format, pcm, stride, nbytes, pkt->data + ch * nbytes);
}
if (zero_frame)
@@ -204,7 +234,7 @@ const FFCodec ff_liblc3_encoder = {
.p.priv_class = &class,
.p.wrapper_name = "liblc3",
CODEC_SAMPLERATES(96000, 48000, 32000, 24000, 16000, 8000),
- CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP),
+ CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P),
.priv_data_size = sizeof(LibLC3EncContext),
.init = liblc3_encode_init,
.close = liblc3_encode_close,
--
2.49.1
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-09-24 14:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-24 14:49 [FFmpeg-devel] [PATCH] avcodec/liblc3: add support for multiple sample formats. (PR #20601) cenzhanquan1 via ffmpeg-devel
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 http://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/ http://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