Coverage Report

Created: 2026-10-28 08:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/dsddec.c
Line
Count
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
2.35k
{
56
2.35k
    if (!avctx->ch_layout.nb_channels)
57
0
        return AVERROR_INVALIDDATA;
58
59
2.35k
    avctx->sample_fmt = AV_SAMPLE_FMT_DSD;
60
61
2.35k
#if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
62
2.35k
    if (avctx->request_sample_fmt != AV_SAMPLE_FMT_DSD)
63
2.35k
        avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
64
2.35k
#endif
65
66
2.35k
    return 0;
67
2.35k
}
68
69
static av_cold int decode_close(AVCodecContext *avctx)
70
2.35k
{
71
2.35k
#if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
72
2.35k
    DSDDecContext *s = avctx->priv_data;
73
74
2.35k
    swr_free(&s->swr);
75
2.35k
    av_freep(&s->scratch);
76
2.35k
#endif
77
2.35k
    return 0;
78
2.35k
}
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
707k
{
84
707k
    const int channels = avctx->ch_layout.nb_channels;
85
86
707k
    switch (avctx->codec_id) {
87
244k
    case AV_CODEC_ID_DSD_MSBF:
88
244k
        memcpy(dst, src, nb_samples * channels);
89
244k
        break;
90
160k
    case AV_CODEC_ID_DSD_LSBF:
91
17.8M
        for (int i = 0; i < nb_samples * channels; i++)
92
17.7M
            dst[i] = ff_reverse[src[i]];
93
160k
        break;
94
164k
    case AV_CODEC_ID_DSD_MSBF_PLANAR:
95
376k
        for (int ch = 0; ch < channels; ch++) {
96
211k
            const uint8_t *plane = src + ch * nb_samples;
97
17.3M
            for (int i = 0; i < nb_samples; i++)
98
17.1M
                dst[i * channels + ch] = plane[i];
99
211k
        }
100
164k
        break;
101
138k
    case AV_CODEC_ID_DSD_LSBF_PLANAR:
102
308k
        for (int ch = 0; ch < channels; ch++) {
103
169k
            const uint8_t *plane = src + ch * nb_samples;
104
16.6M
            for (int i = 0; i < nb_samples; i++)
105
16.5M
                dst[i * channels + ch] = ff_reverse[plane[i]];
106
169k
        }
107
138k
        break;
108
0
    default:
109
0
        av_assert1(0);
110
707k
    }
111
707k
}
112
113
static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
114
                        int *got_frame_ptr, AVPacket *avpkt)
115
1.39M
{
116
1.39M
    const int channels = avctx->ch_layout.nb_channels;
117
1.39M
    int ret;
118
119
1.39M
    frame->nb_samples = avpkt->size / channels;
120
121
1.39M
    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
122
668k
        return ret;
123
124
725k
#if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
125
725k
    DSDDecContext *s = avctx->priv_data;
126
725k
    if (avctx->sample_fmt != AV_SAMPLE_FMT_DSD) {
127
725k
        if (!s->swr && (ret = ff_dsd_to_pcm_init(avctx, &s->swr)) < 0)
128
17.9k
            return ret;
129
130
707k
        av_fast_malloc(&s->scratch, &s->scratch_size,
131
707k
                       frame->nb_samples * channels);
132
707k
        if (!s->scratch)
133
0
            return AVERROR(ENOMEM);
134
135
707k
        repack(avctx, s->scratch, avpkt->data, frame->nb_samples);
136
137
707k
        ret = swr_convert(s->swr, frame->extended_data, frame->nb_samples,
138
707k
                          (const uint8_t *const []){ s->scratch },
139
707k
                          frame->nb_samples);
140
707k
        if (ret != frame->nb_samples)
141
0
            return ret < 0 ? ret : AVERROR_BUG;
142
143
707k
        *got_frame_ptr = 1;
144
707k
        return frame->nb_samples * channels;
145
707k
    }
146
0
#endif
147
148
0
    repack(avctx, frame->data[0], avpkt->data, frame->nb_samples);
149
150
0
    *got_frame_ptr = 1;
151
0
    return frame->nb_samples * channels;
152
725k
}
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")