This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 8d07c6698062997736b51e0daf2fc497921dd345 Author: Kacper Michajłow <[email protected]> AuthorDate: Tue Aug 11 12:14:40 2026 +0200 Commit: Kacper Michajłow <[email protected]> CommitDate: Sun Sep 6 00:48:25 2026 +0200 avcodec/dsddec: use libswresample for the PCM output Repack the input to raw DSD unconditionally and convert it to the default AV_SAMPLE_FMT_FLTP output with libswresample instead of the local dsd2pcm copy. If libswresample is disabled, the PCM output is not offered and the decoder outputs only AV_SAMPLE_FMT_DSD. The per-channel slice threading of the float conversion is gone. The conversion now runs in a single swr_convert() call. Signed-off-by: Kacper Michajłow <[email protected]> --- libavcodec/dsddec.c | 170 +++++++++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 81 deletions(-) diff --git a/libavcodec/dsddec.c b/libavcodec/dsddec.c index 503589380a..1f6411e6b2 100644 --- a/libavcodec/dsddec.c +++ b/libavcodec/dsddec.c @@ -1,7 +1,5 @@ /* * Direct Stream Digital (DSD) decoder - * based on BSD licensed dsd2pcm by Sebastian Gesemann - * Copyright (c) 2009, 2011 Sebastian Gesemann. All rights reserved. * Copyright (c) 2014 Peter Ross * * This file is part of FFmpeg. @@ -26,6 +24,11 @@ * Direct Stream Digital (DSD) decoder */ +#include "config.h" + +#include <string.h> + +#include "libavutil/avassert.h" #include "libavutil/mem.h" #include "libavutil/reverse.h" @@ -34,115 +37,118 @@ #include "decode.h" #include "dsd.h" -#define DSD_SILENCE 0x69 -#define DSD_SILENCE_REVERSED 0x96 -/* 0x69 = 01101001 - * This pattern "on repeat" makes a low energy 352.8 kHz tone - * and a high energy 1.0584 MHz tone which should be filtered - * out completely by any playback system --> silence - */ +#if CONFIG_SWRESAMPLE +#include "libswresample/swresample.h" + +typedef struct DSDDecContext { + struct SwrContext *swr; + uint8_t *scratch; + unsigned scratch_size; +} DSDDecContext; + +#define PRIV_DATA_SIZE sizeof(DSDDecContext) +#else +#define PRIV_DATA_SIZE 0 +#endif static av_cold int decode_init(AVCodecContext *avctx) { - DSDContext * s; - int i; - uint8_t silence; - if (!avctx->ch_layout.nb_channels) return AVERROR_INVALIDDATA; - if (avctx->request_sample_fmt == AV_SAMPLE_FMT_DSD) { - avctx->sample_fmt = AV_SAMPLE_FMT_DSD; - return 0; - } - - ff_init_dsd_data(); - - s = av_malloc_array(avctx->ch_layout.nb_channels, sizeof(*s)); - if (!s) - return AVERROR(ENOMEM); + avctx->sample_fmt = AV_SAMPLE_FMT_DSD; - silence = avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR || - avctx->codec_id == AV_CODEC_ID_DSD_LSBF ? DSD_SILENCE_REVERSED : DSD_SILENCE; - for (i = 0; i < avctx->ch_layout.nb_channels; i++) { - s[i].pos = 0; - memset(s[i].buf, silence, sizeof(s[i].buf)); - } +#if CONFIG_SWRESAMPLE + if (avctx->request_sample_fmt != AV_SAMPLE_FMT_DSD) + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; +#endif - avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - avctx->priv_data = s; return 0; } -typedef struct ThreadData { - AVFrame *frame; - const AVPacket *avpkt; -} ThreadData; - -static int dsd_channel(AVCodecContext *avctx, void *tdata, int j, int threadnr) +static av_cold int decode_close(AVCodecContext *avctx) { - int lsbf = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR; - DSDContext *s = avctx->priv_data; - ThreadData *td = tdata; - AVFrame *frame = td->frame; - const AVPacket *avpkt = td->avpkt; - int src_next, src_stride; +#if CONFIG_SWRESAMPLE + DSDDecContext *s = avctx->priv_data; - if (avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR || avctx->codec_id == AV_CODEC_ID_DSD_MSBF_PLANAR) { - src_next = frame->nb_samples; - src_stride = 1; - } else { - src_next = 1; - src_stride = avctx->ch_layout.nb_channels; - } + swr_free(&s->swr); + av_freep(&s->scratch); +#endif + return 0; +} - if (avctx->sample_fmt == AV_SAMPLE_FMT_DSD) { - // repack to interleaved DSD MSBF - const uint8_t *src = avpkt->data + j * src_next; - uint8_t *dst = frame->data[0] + j; - const int channels = avctx->ch_layout.nb_channels; +// repack the input to interleaved DSD bytes, most significant bit first +static void repack(AVCodecContext *avctx, uint8_t *dst, const uint8_t *src, + int nb_samples) +{ + const int channels = avctx->ch_layout.nb_channels; - if (lsbf) { - for (int i = 0; i < frame->nb_samples; i++) - dst[i * channels] = ff_reverse[src[i * src_stride]]; - } else { - for (int i = 0; i < frame->nb_samples; i++) - dst[i * channels] = src[i * src_stride]; + switch (avctx->codec_id) { + case AV_CODEC_ID_DSD_MSBF: + memcpy(dst, src, nb_samples * channels); + break; + case AV_CODEC_ID_DSD_LSBF: + for (int i = 0; i < nb_samples * channels; i++) + dst[i] = ff_reverse[src[i]]; + break; + case AV_CODEC_ID_DSD_MSBF_PLANAR: + for (int ch = 0; ch < channels; ch++) { + const uint8_t *plane = src + ch * nb_samples; + for (int i = 0; i < nb_samples; i++) + dst[i * channels + ch] = plane[i]; } - } else { - float *dst = ((float **)frame->extended_data)[j]; - - ff_dsd2pcm_translate(&s[j], frame->nb_samples, lsbf, - avpkt->data + j * src_next, src_stride, - dst, 1); + break; + case AV_CODEC_ID_DSD_LSBF_PLANAR: + for (int ch = 0; ch < channels; ch++) { + const uint8_t *plane = src + ch * nb_samples; + for (int i = 0; i < nb_samples; i++) + dst[i * channels + ch] = ff_reverse[plane[i]]; + } + break; + default: + av_assert1(0); } - - return 0; } static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - ThreadData td; + const int channels = avctx->ch_layout.nb_channels; int ret; - frame->nb_samples = avpkt->size / avctx->ch_layout.nb_channels; + frame->nb_samples = avpkt->size / channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - if (avctx->sample_fmt == AV_SAMPLE_FMT_DSD && - avctx->codec_id == AV_CODEC_ID_DSD_MSBF) { - memcpy(frame->data[0], avpkt->data, - frame->nb_samples * avctx->ch_layout.nb_channels); - } else { - td.frame = frame; - td.avpkt = avpkt; - avctx->execute2(avctx, dsd_channel, &td, NULL, avctx->ch_layout.nb_channels); +#if CONFIG_SWRESAMPLE + DSDDecContext *s = avctx->priv_data; + if (avctx->sample_fmt != AV_SAMPLE_FMT_DSD) { + if (!s->swr && (ret = ff_dsd_to_pcm_init(avctx, &s->swr)) < 0) + return ret; + + av_fast_malloc(&s->scratch, &s->scratch_size, + frame->nb_samples * channels); + if (!s->scratch) + return AVERROR(ENOMEM); + + repack(avctx, s->scratch, avpkt->data, frame->nb_samples); + + ret = swr_convert(s->swr, frame->extended_data, frame->nb_samples, + (const uint8_t *const []){ s->scratch }, + frame->nb_samples); + if (ret != frame->nb_samples) + return ret < 0 ? ret : AVERROR_BUG; + + *got_frame_ptr = 1; + return frame->nb_samples * channels; } +#endif + + repack(avctx, frame->data[0], avpkt->data, frame->nb_samples); *got_frame_ptr = 1; - return frame->nb_samples * avctx->ch_layout.nb_channels; + return frame->nb_samples * channels; } #define DSD_DECODER(id_, name_, long_name_) \ @@ -151,9 +157,11 @@ const FFCodec ff_ ## name_ ## _decoder = { \ CODEC_LONG_NAME(long_name_), \ .p.type = AVMEDIA_TYPE_AUDIO, \ .p.id = AV_CODEC_ID_##id_, \ + .priv_data_size = PRIV_DATA_SIZE, \ .init = decode_init, \ + .close = decode_close, \ FF_CODEC_DECODE_CB(decode_frame), \ - .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, \ + .p.capabilities = AV_CODEC_CAP_DR1, \ }; DSD_DECODER(DSD_LSBF, dsd_lsbf, "DSD (Direct Stream Digital), least significant bit first") -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
