Coverage Report

Created: 2026-07-25 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/pcm-dvd.c
Line
Count
Source
1
/*
2
 * LPCM codecs for PCM formats found in Video DVD streams
3
 * Copyright (c) 2013 Christian Schmidt
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
 * LPCM codecs for PCM formats found in Video DVD streams
25
 */
26
27
#include "avcodec.h"
28
#include "bytestream.h"
29
#include "codec_internal.h"
30
#include "decode.h"
31
32
typedef struct PCMDVDContext {
33
    uint32_t last_header;    // Cached header to see if parsing is needed
34
    int block_size;          // Size of a block of samples in bytes
35
    int last_block_size;     // Size of the last block of samples in bytes
36
    int samples_per_block;   // Number of samples per channel per block
37
    int groups_per_block;    // Number of 20/24-bit sample groups per block
38
    int extra_sample_count;  // Number of leftover samples in the buffer
39
    uint8_t extra_samples[8 * 3 * 4];  // Space for leftover samples from a frame
40
                                       // (8 channels, 3B/sample, 4 samples/block)
41
} PCMDVDContext;
42
43
static av_cold int pcm_dvd_decode_init(AVCodecContext *avctx)
44
1.12k
{
45
1.12k
    PCMDVDContext *s = avctx->priv_data;
46
47
    /* Invalid header to force parsing of the first header */
48
1.12k
    s->last_header = -1;
49
50
1.12k
    return 0;
51
1.12k
}
52
53
static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
54
81.6k
{
55
    /* no traces of 44100 and 32000Hz in any commercial software or player */
56
81.6k
    static const uint32_t frequencies[4] = { 48000, 96000, 44100, 32000 };
57
81.6k
    PCMDVDContext *s = avctx->priv_data;
58
81.6k
    int header_int = (header[0] & 0xe0) | (header[1] << 8) | (header[2] << 16);
59
81.6k
    int channels;
60
61
    /* early exit if the header didn't change apart from the frame number */
62
81.6k
    if (s->last_header == header_int)
63
19.6k
        return 0;
64
61.9k
    s->last_header = -1;
65
66
61.9k
    if (avctx->debug & FF_DEBUG_PICT_INFO)
67
0
        av_log(avctx, AV_LOG_DEBUG, "pcm_dvd_parse_header: header = %02x%02x%02x\n",
68
0
                header[0], header[1], header[2]);
69
    /*
70
     * header[0] emphasis (1), muse(1), reserved(1), frame number(5)
71
     * header[1] quant (2), freq(2), reserved(1), channels(3)
72
     * header[2] dynamic range control (0x80 = off)
73
     */
74
75
    /* Discard potentially existing leftover samples from old channel layout */
76
61.9k
    s->extra_sample_count = 0;
77
78
    /* get the sample depth and derive the sample format from it */
79
61.9k
    avctx->bits_per_coded_sample = 16 + (header[1] >> 6 & 3) * 4;
80
61.9k
    if (avctx->bits_per_coded_sample == 28) {
81
726
        av_log(avctx, AV_LOG_ERROR,
82
726
               "PCM DVD unsupported sample depth %i\n",
83
726
               avctx->bits_per_coded_sample);
84
726
        return AVERROR_INVALIDDATA;
85
726
    }
86
61.1k
    avctx->sample_fmt = avctx->bits_per_coded_sample == 16 ? AV_SAMPLE_FMT_S16
87
61.1k
                                                           : AV_SAMPLE_FMT_S32;
88
61.1k
    avctx->bits_per_raw_sample = avctx->bits_per_coded_sample;
89
90
    /* get the sample rate */
91
61.1k
    avctx->sample_rate = frequencies[header[1] >> 4 & 3];
92
93
    /* get the number of channels */
94
61.1k
    channels = 1 + (header[1] & 7);
95
96
61.1k
    av_channel_layout_uninit(&avctx->ch_layout);
97
61.1k
    av_channel_layout_default(&avctx->ch_layout, channels);
98
    /* calculate the bitrate */
99
61.1k
    avctx->bit_rate = channels *
100
61.1k
                      avctx->sample_rate *
101
61.1k
                      avctx->bits_per_coded_sample;
102
103
    /* 4 samples form a group in 20/24-bit PCM on DVD Video.
104
     * A block is formed by the number of groups that are
105
     * needed to complete a set of samples for each channel. */
106
61.1k
    if (avctx->bits_per_coded_sample == 16) {
107
53.3k
        s->samples_per_block = 1;
108
53.3k
        s->block_size        = channels * 2;
109
53.3k
    } else {
110
7.83k
        switch (channels) {
111
1.12k
        case 1:
112
1.96k
        case 2:
113
2.44k
        case 4:
114
            /* one group has all the samples needed */
115
2.44k
            s->block_size        = 4 * avctx->bits_per_coded_sample / 8;
116
2.44k
            s->samples_per_block = 4 / channels;
117
2.44k
            s->groups_per_block  = 1;
118
2.44k
            break;
119
967
        case 8:
120
            /* two groups have all the samples needed */
121
967
            s->block_size        = 8 * avctx->bits_per_coded_sample / 8;
122
967
            s->samples_per_block = 1;
123
967
            s->groups_per_block  = 2;
124
967
            break;
125
4.42k
        default:
126
            /* need channels groups */
127
4.42k
            s->block_size        = 4 * channels *
128
4.42k
                                   avctx->bits_per_coded_sample / 8;
129
4.42k
            s->samples_per_block = 4;
130
4.42k
            s->groups_per_block  = channels;
131
4.42k
            break;
132
7.83k
        }
133
7.83k
    }
134
135
61.1k
    if (avctx->debug & FF_DEBUG_PICT_INFO)
136
0
        ff_dlog(avctx,
137
61.1k
                "pcm_dvd_parse_header: %d channels, %d bits per sample, %d Hz, %"PRId64" bit/s\n",
138
61.1k
                avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample,
139
61.1k
                avctx->sample_rate, avctx->bit_rate);
140
141
61.1k
    s->last_header = header_int;
142
143
61.1k
    return 0;
144
61.1k
}
145
146
static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src,
147
                                    void *dst, int blocks)
148
73.0k
{
149
73.0k
    PCMDVDContext *s = avctx->priv_data;
150
73.0k
    int16_t *dst16   = dst;
151
73.0k
    int32_t *dst32   = dst;
152
73.0k
    GetByteContext gb;
153
73.0k
    int i;
154
73.0k
    uint8_t t;
155
156
73.0k
    bytestream2_init(&gb, src, blocks * s->block_size);
157
73.0k
    switch (avctx->bits_per_coded_sample) {
158
70.6k
    case 16: {
159
#if HAVE_BIGENDIAN
160
        bytestream2_get_buffer(&gb, (uint8_t*)dst16, blocks * s->block_size);
161
        dst16 += blocks * s->block_size / 2;
162
#else
163
70.6k
        int samples = blocks * avctx->ch_layout.nb_channels;
164
6.80M
        do {
165
6.80M
            *dst16++ = bytestream2_get_be16u(&gb);
166
6.80M
        } while (--samples);
167
70.6k
#endif
168
70.6k
        return dst16;
169
0
    }
170
1.87k
    case 20:
171
1.87k
        if (avctx->ch_layout.nb_channels == 1) {
172
15.7k
            do {
173
47.1k
                for (i = 2; i; i--) {
174
31.4k
                    dst32[0] = bytestream2_get_be16u(&gb) << 16;
175
31.4k
                    dst32[1] = bytestream2_get_be16u(&gb) << 16;
176
31.4k
                    t = bytestream2_get_byteu(&gb);
177
31.4k
                    *dst32++ += (t & 0xf0) << 8;
178
31.4k
                    *dst32++ += (t & 0x0f) << 12;
179
31.4k
                }
180
15.7k
            } while (--blocks);
181
1.03k
        } else {
182
27.1k
        do {
183
122k
            for (i = s->groups_per_block; i; i--) {
184
95.4k
                dst32[0] = bytestream2_get_be16u(&gb) << 16;
185
95.4k
                dst32[1] = bytestream2_get_be16u(&gb) << 16;
186
95.4k
                dst32[2] = bytestream2_get_be16u(&gb) << 16;
187
95.4k
                dst32[3] = bytestream2_get_be16u(&gb) << 16;
188
95.4k
                t = bytestream2_get_byteu(&gb);
189
95.4k
                *dst32++ += (t & 0xf0) << 8;
190
95.4k
                *dst32++ += (t & 0x0f) << 12;
191
95.4k
                t = bytestream2_get_byteu(&gb);
192
95.4k
                *dst32++ += (t & 0xf0) << 8;
193
95.4k
                *dst32++ += (t & 0x0f) << 12;
194
95.4k
            }
195
27.1k
        } while (--blocks);
196
835
        }
197
1.87k
        return dst32;
198
595
    case 24:
199
595
        if (avctx->ch_layout.nb_channels == 1) {
200
1.36k
            do {
201
4.09k
                for (i = 2; i; i--) {
202
2.72k
                    dst32[0] = bytestream2_get_be16u(&gb) << 16;
203
2.72k
                    dst32[1] = bytestream2_get_be16u(&gb) << 16;
204
2.72k
                    *dst32++ += bytestream2_get_byteu(&gb) << 8;
205
2.72k
                    *dst32++ += bytestream2_get_byteu(&gb) << 8;
206
2.72k
                }
207
1.36k
            } while (--blocks);
208
322
        } else {
209
17.8k
        do {
210
66.0k
            for (i = s->groups_per_block; i; i--) {
211
48.1k
                dst32[0] = bytestream2_get_be16u(&gb) << 16;
212
48.1k
                dst32[1] = bytestream2_get_be16u(&gb) << 16;
213
48.1k
                dst32[2] = bytestream2_get_be16u(&gb) << 16;
214
48.1k
                dst32[3] = bytestream2_get_be16u(&gb) << 16;
215
48.1k
                *dst32++ += bytestream2_get_byteu(&gb) << 8;
216
48.1k
                *dst32++ += bytestream2_get_byteu(&gb) << 8;
217
48.1k
                *dst32++ += bytestream2_get_byteu(&gb) << 8;
218
48.1k
                *dst32++ += bytestream2_get_byteu(&gb) << 8;
219
48.1k
            }
220
17.8k
        } while (--blocks);
221
273
        }
222
595
        return dst32;
223
0
    default:
224
0
        return NULL;
225
73.0k
    }
226
73.0k
}
227
228
static int pcm_dvd_decode_frame(AVCodecContext *avctx, AVFrame *frame,
229
                                int *got_frame_ptr, AVPacket *avpkt)
230
217k
{
231
217k
    const uint8_t *src = avpkt->data;
232
217k
    int buf_size       = avpkt->size;
233
217k
    PCMDVDContext *s   = avctx->priv_data;
234
217k
    int retval;
235
217k
    int blocks;
236
217k
    void *dst;
237
238
217k
    if (buf_size < 3) {
239
135k
        av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n");
240
135k
        return AVERROR_INVALIDDATA;
241
135k
    }
242
243
81.6k
    if ((retval = pcm_dvd_parse_header(avctx, src)))
244
726
        return retval;
245
80.8k
    if (s->last_block_size && s->last_block_size != s->block_size) {
246
9.07k
        av_log(avctx, AV_LOG_WARNING, "block_size has changed %d != %d\n", s->last_block_size, s->block_size);
247
9.07k
        s->extra_sample_count = 0;
248
9.07k
    }
249
80.8k
    s->last_block_size = s->block_size;
250
80.8k
    src      += 3;
251
80.8k
    buf_size -= 3;
252
253
80.8k
    blocks = (buf_size + s->extra_sample_count) / s->block_size;
254
255
    /* get output buffer */
256
80.8k
    frame->nb_samples = blocks * s->samples_per_block;
257
80.8k
    if ((retval = ff_get_buffer(avctx, frame, 0)) < 0)
258
12.2k
        return retval;
259
68.5k
    dst = frame->data[0];
260
261
    /* consume leftover samples from last packet */
262
68.5k
    if (s->extra_sample_count) {
263
5.59k
        int missing_samples = s->block_size - s->extra_sample_count;
264
5.59k
        if (buf_size >= missing_samples) {
265
5.59k
            memcpy(s->extra_samples + s->extra_sample_count, src,
266
5.59k
                   missing_samples);
267
5.59k
            dst = pcm_dvd_decode_samples(avctx, s->extra_samples, dst, 1);
268
5.59k
            src += missing_samples;
269
5.59k
            buf_size -= missing_samples;
270
5.59k
            s->extra_sample_count = 0;
271
5.59k
            blocks--;
272
5.59k
        } else {
273
            /* new packet still doesn't have enough samples */
274
0
            memcpy(s->extra_samples + s->extra_sample_count, src, buf_size);
275
0
            s->extra_sample_count += buf_size;
276
0
            return avpkt->size;
277
0
        }
278
5.59k
    }
279
280
    /* decode remaining complete samples */
281
68.5k
    if (blocks) {
282
67.4k
        pcm_dvd_decode_samples(avctx, src, dst, blocks);
283
67.4k
        buf_size -= blocks * s->block_size;
284
67.4k
    }
285
286
    /* store leftover samples */
287
68.5k
    if (buf_size) {
288
12.0k
        src += blocks * s->block_size;
289
12.0k
        memcpy(s->extra_samples, src, buf_size);
290
12.0k
        s->extra_sample_count = buf_size;
291
12.0k
    }
292
293
68.5k
    *got_frame_ptr = 1;
294
295
68.5k
    return avpkt->size;
296
68.5k
}
297
298
const FFCodec ff_pcm_dvd_decoder = {
299
    .p.name         = "pcm_dvd",
300
    CODEC_LONG_NAME("PCM signed 16|20|24-bit big-endian for DVD media"),
301
    .p.type         = AVMEDIA_TYPE_AUDIO,
302
    .p.id           = AV_CODEC_ID_PCM_DVD,
303
    .priv_data_size = sizeof(PCMDVDContext),
304
    .init           = pcm_dvd_decode_init,
305
    FF_CODEC_DECODE_CB(pcm_dvd_decode_frame),
306
    .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
307
                      AV_CODEC_CAP_DR1,
308
};