FFmpeg
Loading...
Searching...
No Matches
dsddec.c
Go to the documentation of this file.
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
42
43typedef 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
55{
56 if (!avctx->ch_layout.nb_channels)
58
60
61#if CONFIG_SWRESAMPLE && FF_API_DSD_PCM
64#endif
65
66 return 0;
67}
68
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
81static 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) {
88 memcpy(dst, src, nb_samples * channels);
89 break;
91 for (int i = 0; i < nb_samples * channels; i++)
92 dst[i] = ff_reverse[src[i]];
93 break;
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;
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
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_) \
155const 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
167DSD_DECODER(DSD_LSBF, dsd_lsbf, "DSD (Direct Stream Digital), least significant bit first")
168DSD_DECODER(DSD_MSBF, dsd_msbf, "DSD (Direct Stream Digital), most significant bit first")
169DSD_DECODER(DSD_MSBF_PLANAR, dsd_msbf_planar, "DSD (Direct Stream Digital), most significant bit first, planar")
170DSD_DECODER(DSD_LSBF_PLANAR, dsd_lsbf_planar, "DSD (Direct Stream Digital), least significant bit first, planar")
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
channels
Definition aptx.h:31
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
Libavcodec external API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
static AVFrame * frame
int ff_dsd_to_pcm_init(struct AVCodecContext *avctx, struct SwrContext **swrp)
(Re)create a libswresample context converting AV_SAMPLE_FMT_DSD to avctx->sample_fmt at the same samp...
static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt)
Definition dsddec.c:113
static av_cold int decode_close(AVCodecContext *avctx)
Definition dsddec.c:69
static av_cold int decode_init(AVCodecContext *avctx)
Definition dsddec.c:54
#define DSD_DECODER(id_, name_, long_name_)
Definition dsddec.c:154
static void repack(AVCodecContext *avctx, uint8_t *dst, const uint8_t *src, int nb_samples)
Definition dsddec.c:81
@ AV_CODEC_ID_DSD_LSBF
Definition codec_id.h:526
@ AV_CODEC_ID_DSD_MSBF_PLANAR
Definition codec_id.h:529
@ AV_CODEC_ID_DSD_LSBF_PLANAR
Definition codec_id.h:528
@ AV_CODEC_ID_DSD_MSBF
Definition codec_id.h:527
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition mem.c:555
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition samplefmt.h:66
@ AV_SAMPLE_FMT_DSD
DSD (Direct Stream Digital) bitstream, interleaved.
Definition samplefmt.h:77
av_cold void swr_free(SwrContext **ss)
Free the given SwrContext and set the pointer to NULL.
Definition swresample.c:137
int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *const *out_arg, int out_count, const uint8_t *const *in_arg, int in_count)
Convert audio.
Definition swresample.c:743
#define av_cold
Definition attributes.h:117
const uint8_t ff_reverse[256]
Definition reverse.c:23
Memory handling functions.
int nb_channels
Number of channels in this layout.
main external API structure.
Definition avcodec.h:443
AVChannelLayout ch_layout
Audio channel layout.
Definition avcodec.h:1055
enum AVSampleFormat sample_fmt
audio sample format
Definition avcodec.h:1047
enum AVSampleFormat request_sample_fmt
desired sample format
Definition avcodec.h:1097
enum AVCodecID codec_id
Definition avcodec.h:453
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
libswresample public header
#define av_freep(p)
#define src
Definition vp8dsp.c:248