FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/dsddec.c
Date: 2026-09-11 02:21:26
Exec Total Coverage
Lines: 0 59 0.0%
Functions: 0 4 0.0%
Branches: 0 33 0.0%

Line Branch Exec Source
1 /*
2 * Direct Stream Digital (DSD) decoder
3 * Copyright (c) 2014 Peter Ross
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Direct Stream Digital (DSD) decoder
25 */
26
27 #include "config.h"
28
29 #include <string.h>
30
31 #include "libavutil/avassert.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/reverse.h"
34
35 #include "avcodec.h"
36 #include "codec_internal.h"
37 #include "decode.h"
38 #include "dsd.h"
39
40 #if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
41 #include "libswresample/swresample.h"
42
43 typedef struct DSDDecContext {
44 struct SwrContext *swr;
45 uint8_t *scratch;
46 unsigned scratch_size;
47 } DSDDecContext;
48
49 #define PRIV_DATA_SIZE sizeof(DSDDecContext)
50 #else
51 #define PRIV_DATA_SIZE 0
52 #endif
53
54 static av_cold int decode_init(AVCodecContext *avctx)
55 {
56 if (!avctx->ch_layout.nb_channels)
57 return AVERROR_INVALIDDATA;
58
59 avctx->sample_fmt = AV_SAMPLE_FMT_DSD;
60
61 #if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
62 if (avctx->request_sample_fmt != AV_SAMPLE_FMT_DSD)
63 avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
64 #endif
65
66 return 0;
67 }
68
69 static av_cold int decode_close(AVCodecContext *avctx)
70 {
71 #if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
72 DSDDecContext *s = avctx->priv_data;
73
74 swr_free(&s->swr);
75 av_freep(&s->scratch);
76 #endif
77 return 0;
78 }
79
80 // repack the input to interleaved DSD bytes, most significant bit first
81 static void repack(AVCodecContext *avctx, uint8_t *dst, const uint8_t *src,
82 int nb_samples)
83 {
84 const int channels = avctx->ch_layout.nb_channels;
85
86 switch (avctx->codec_id) {
87 case AV_CODEC_ID_DSD_MSBF:
88 memcpy(dst, src, nb_samples * channels);
89 break;
90 case AV_CODEC_ID_DSD_LSBF:
91 for (int i = 0; i < nb_samples * channels; i++)
92 dst[i] = ff_reverse[src[i]];
93 break;
94 case AV_CODEC_ID_DSD_MSBF_PLANAR:
95 for (int ch = 0; ch < channels; ch++) {
96 const uint8_t *plane = src + ch * nb_samples;
97 for (int i = 0; i < nb_samples; i++)
98 dst[i * channels + ch] = plane[i];
99 }
100 break;
101 case AV_CODEC_ID_DSD_LSBF_PLANAR:
102 for (int ch = 0; ch < channels; ch++) {
103 const uint8_t *plane = src + ch * nb_samples;
104 for (int i = 0; i < nb_samples; i++)
105 dst[i * channels + ch] = ff_reverse[plane[i]];
106 }
107 break;
108 default:
109 av_assert1(0);
110 }
111 }
112
113 static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
114 int *got_frame_ptr, AVPacket *avpkt)
115 {
116 const int channels = avctx->ch_layout.nb_channels;
117 int ret;
118
119 frame->nb_samples = avpkt->size / channels;
120
121 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
122 return ret;
123
124 #if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
125 DSDDecContext *s = avctx->priv_data;
126 if (avctx->sample_fmt != AV_SAMPLE_FMT_DSD) {
127 if (!s->swr && (ret = ff_dsd_to_pcm_init(avctx, &s->swr)) < 0)
128 return ret;
129
130 av_fast_malloc(&s->scratch, &s->scratch_size,
131 frame->nb_samples * channels);
132 if (!s->scratch)
133 return AVERROR(ENOMEM);
134
135 repack(avctx, s->scratch, avpkt->data, frame->nb_samples);
136
137 ret = swr_convert(s->swr, frame->extended_data, frame->nb_samples,
138 (const uint8_t *const []){ s->scratch },
139 frame->nb_samples);
140 if (ret != frame->nb_samples)
141 return ret < 0 ? ret : AVERROR_BUG;
142
143 *got_frame_ptr = 1;
144 return frame->nb_samples * channels;
145 }
146 #endif
147
148 repack(avctx, frame->data[0], avpkt->data, frame->nb_samples);
149
150 *got_frame_ptr = 1;
151 return frame->nb_samples * channels;
152 }
153
154 #define DSD_DECODER(id_, name_, long_name_) \
155 const FFCodec ff_ ## name_ ## _decoder = { \
156 .p.name = #name_, \
157 CODEC_LONG_NAME(long_name_), \
158 .p.type = AVMEDIA_TYPE_AUDIO, \
159 .p.id = AV_CODEC_ID_##id_, \
160 .priv_data_size = PRIV_DATA_SIZE, \
161 .init = decode_init, \
162 .close = decode_close, \
163 FF_CODEC_DECODE_CB(decode_frame), \
164 .p.capabilities = AV_CODEC_CAP_DR1, \
165 };
166
167 DSD_DECODER(DSD_LSBF, dsd_lsbf, "DSD (Direct Stream Digital), least significant bit first")
168 DSD_DECODER(DSD_MSBF, dsd_msbf, "DSD (Direct Stream Digital), most significant bit first")
169 DSD_DECODER(DSD_MSBF_PLANAR, dsd_msbf_planar, "DSD (Direct Stream Digital), most significant bit first, planar")
170 DSD_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar, "DSD (Direct Stream Digital), least significant bit first, planar")
171