2 * LPCM codecs for PCM formats found in Video DVD streams
3 * Copyright (c) 2013 Christian Schmidt
5 * This file is part of FFmpeg.
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.
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.
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
24 * LPCM codecs for PCM formats found in Video DVD streams
28 #include "bytestream.h"
31 typedef struct PCMDVDContext
{
32 uint32_t last_header
; // Cached header to see if parsing is needed
33 int block_size
; // Size of a block of samples in bytes
34 int last_block_size
; // Size of the last block of samples in bytes
35 int samples_per_block
; // Number of samples per channel per block
36 int groups_per_block
; // Number of 20/24bit sample groups per block
37 uint8_t *extra_samples
; // Pointer to leftover samples from a frame
38 int extra_sample_count
; // Number of leftover samples in the buffer
41 static av_cold
int pcm_dvd_decode_init(AVCodecContext
*avctx
)
43 PCMDVDContext
*s
= avctx
->priv_data
;
45 /* Invalid header to force parsing of the first header */
47 /* reserve space for 8 channels, 3 bytes/sample, 4 samples/block */
48 if (!(s
->extra_samples
= av_malloc(8 * 3 * 4)))
49 return AVERROR(ENOMEM
);
54 static av_cold
int pcm_dvd_decode_uninit(AVCodecContext
*avctx
)
56 PCMDVDContext
*s
= avctx
->priv_data
;
58 av_freep(&s
->extra_samples
);
63 static int pcm_dvd_parse_header(AVCodecContext
*avctx
, const uint8_t *header
)
65 /* no traces of 44100 and 32000Hz in any commercial software or player */
66 static const uint32_t frequencies
[4] = { 48000, 96000, 44100, 32000 };
67 PCMDVDContext
*s
= avctx
->priv_data
;
68 int header_int
= (header
[0] & 0xe0) | (header
[1] << 8) | (header
[2] << 16);
70 /* early exit if the header didn't change apart from the frame number */
71 if (s
->last_header
== header_int
)
75 if (avctx
->debug
& FF_DEBUG_PICT_INFO
)
76 av_dlog(avctx
, "pcm_dvd_parse_header: header = %02x%02x%02x\n",
77 header
[0], header
[1], header
[2]);
79 * header[0] emphasis (1), muse(1), reserved(1), frame number(5)
80 * header[1] quant (2), freq(2), reserved(1), channels(3)
81 * header[2] dynamic range control (0x80 = off)
84 /* Discard potentially existing leftover samples from old channel layout */
85 s
->extra_sample_count
= 0;
87 /* get the sample depth and derive the sample format from it */
88 avctx
->bits_per_coded_sample
= 16 + (header
[1] >> 6 & 3) * 4;
89 if (avctx
->bits_per_coded_sample
== 28) {
90 av_log(avctx
, AV_LOG_ERROR
,
91 "PCM DVD unsupported sample depth %i\n",
92 avctx
->bits_per_coded_sample
);
93 return AVERROR_INVALIDDATA
;
95 avctx
->sample_fmt
= avctx
->bits_per_coded_sample
== 16 ? AV_SAMPLE_FMT_S16
97 avctx
->bits_per_raw_sample
= avctx
->bits_per_coded_sample
;
99 /* get the sample rate */
100 avctx
->sample_rate
= frequencies
[header
[1] >> 4 & 3];
102 /* get the number of channels */
103 avctx
->channels
= 1 + (header
[1] & 7);
104 /* calculate the bitrate */
105 avctx
->bit_rate
= avctx
->channels
*
107 avctx
->bits_per_coded_sample
;
109 /* 4 samples form a group in 20/24bit PCM on DVD Video.
110 * A block is formed by the number of groups that are
111 * needed to complete a set of samples for each channel. */
112 if (avctx
->bits_per_coded_sample
== 16) {
113 s
->samples_per_block
= 1;
114 s
->block_size
= avctx
->channels
* 2;
116 switch (avctx
->channels
) {
120 /* one group has all the samples needed */
121 s
->block_size
= 4 * avctx
->bits_per_coded_sample
/ 8;
122 s
->samples_per_block
= 4 / avctx
->channels
;
123 s
->groups_per_block
= 1;
126 /* two groups have all the samples needed */
127 s
->block_size
= 8 * avctx
->bits_per_coded_sample
/ 8;
128 s
->samples_per_block
= 1;
129 s
->groups_per_block
= 2;
132 /* need avctx->channels groups */
133 s
->block_size
= 4 * avctx
->channels
*
134 avctx
->bits_per_coded_sample
/ 8;
135 s
->samples_per_block
= 4;
136 s
->groups_per_block
= avctx
->channels
;
141 if (avctx
->debug
& FF_DEBUG_PICT_INFO
)
143 "pcm_dvd_parse_header: %d channels, %d bits per sample, %d Hz, %d bit/s\n",
144 avctx
->channels
, avctx
->bits_per_coded_sample
,
145 avctx
->sample_rate
, avctx
->bit_rate
);
147 s
->last_header
= header_int
;
152 static void *pcm_dvd_decode_samples(AVCodecContext
*avctx
, const uint8_t *src
,
153 void *dst
, int blocks
)
155 PCMDVDContext
*s
= avctx
->priv_data
;
156 int16_t *dst16
= dst
;
157 int32_t *dst32
= dst
;
162 bytestream2_init(&gb
, src
, blocks
* s
->block_size
);
163 switch (avctx
->bits_per_coded_sample
) {
166 bytestream2_get_buffer(&gb
, dst16
, blocks
* s
->block_size
);
167 dst16
+= blocks
* s
->block_size
/ 2;
169 int samples
= blocks
* avctx
->channels
;
171 *dst16
++ = bytestream2_get_be16u(&gb
);
177 if (avctx
->channels
== 1) {
179 for (i
= 2; i
; i
--) {
180 dst32
[0] = bytestream2_get_be16u(&gb
) << 16;
181 dst32
[1] = bytestream2_get_be16u(&gb
) << 16;
182 t
= bytestream2_get_byteu(&gb
);
183 *dst32
++ += (t
& 0xf0) << 8;
184 *dst32
++ += (t
& 0x0f) << 12;
189 for (i
= s
->groups_per_block
; i
; i
--) {
190 dst32
[0] = bytestream2_get_be16u(&gb
) << 16;
191 dst32
[1] = bytestream2_get_be16u(&gb
) << 16;
192 dst32
[2] = bytestream2_get_be16u(&gb
) << 16;
193 dst32
[3] = bytestream2_get_be16u(&gb
) << 16;
194 t
= bytestream2_get_byteu(&gb
);
195 *dst32
++ += (t
& 0xf0) << 8;
196 *dst32
++ += (t
& 0x0f) << 12;
197 t
= bytestream2_get_byteu(&gb
);
198 *dst32
++ += (t
& 0xf0) << 8;
199 *dst32
++ += (t
& 0x0f) << 12;
205 if (avctx
->channels
== 1) {
207 for (i
= 2; i
; i
--) {
208 dst32
[0] = bytestream2_get_be16u(&gb
) << 16;
209 dst32
[1] = bytestream2_get_be16u(&gb
) << 16;
210 *dst32
++ += bytestream2_get_byteu(&gb
) << 8;
211 *dst32
++ += bytestream2_get_byteu(&gb
) << 8;
216 for (i
= s
->groups_per_block
; i
; i
--) {
217 dst32
[0] = bytestream2_get_be16u(&gb
) << 16;
218 dst32
[1] = bytestream2_get_be16u(&gb
) << 16;
219 dst32
[2] = bytestream2_get_be16u(&gb
) << 16;
220 dst32
[3] = bytestream2_get_be16u(&gb
) << 16;
221 *dst32
++ += bytestream2_get_byteu(&gb
) << 8;
222 *dst32
++ += bytestream2_get_byteu(&gb
) << 8;
223 *dst32
++ += bytestream2_get_byteu(&gb
) << 8;
224 *dst32
++ += bytestream2_get_byteu(&gb
) << 8;
234 static int pcm_dvd_decode_frame(AVCodecContext
*avctx
, void *data
,
235 int *got_frame_ptr
, AVPacket
*avpkt
)
237 AVFrame
*frame
= data
;
238 const uint8_t *src
= avpkt
->data
;
239 int buf_size
= avpkt
->size
;
240 PCMDVDContext
*s
= avctx
->priv_data
;
246 av_log(avctx
, AV_LOG_ERROR
, "PCM packet too small\n");
247 return AVERROR_INVALIDDATA
;
250 if ((retval
= pcm_dvd_parse_header(avctx
, src
)))
252 if (s
->last_block_size
&& s
->last_block_size
!= s
->block_size
) {
253 av_log(avctx
, AV_LOG_WARNING
, "block_size has changed %d != %d\n", s
->last_block_size
, s
->block_size
);
254 s
->extra_sample_count
= 0;
256 s
->last_block_size
= s
->block_size
;
260 blocks
= (buf_size
+ s
->extra_sample_count
) / s
->block_size
;
262 /* get output buffer */
263 frame
->nb_samples
= blocks
* s
->samples_per_block
;
264 if ((retval
= ff_get_buffer(avctx
, frame
, 0)) < 0)
266 dst
= frame
->data
[0];
268 /* consume leftover samples from last packet */
269 if (s
->extra_sample_count
) {
270 int missing_samples
= s
->block_size
- s
->extra_sample_count
;
271 if (buf_size
>= missing_samples
) {
272 memcpy(s
->extra_samples
+ s
->extra_sample_count
, src
,
274 dst
= pcm_dvd_decode_samples(avctx
, s
->extra_samples
, dst
, 1);
275 src
+= missing_samples
;
276 buf_size
-= missing_samples
;
277 s
->extra_sample_count
= 0;
280 /* new packet still doesn't have enough samples */
281 memcpy(s
->extra_samples
+ s
->extra_sample_count
, src
, buf_size
);
282 s
->extra_sample_count
+= buf_size
;
287 /* decode remaining complete samples */
289 pcm_dvd_decode_samples(avctx
, src
, dst
, blocks
);
290 buf_size
-= blocks
* s
->block_size
;
293 /* store leftover samples */
295 src
+= blocks
* s
->block_size
;
296 memcpy(s
->extra_samples
, src
, buf_size
);
297 s
->extra_sample_count
= buf_size
;
305 AVCodec ff_pcm_dvd_decoder
= {
307 .long_name
= NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"),
308 .type
= AVMEDIA_TYPE_AUDIO
,
309 .id
= AV_CODEC_ID_PCM_DVD
,
310 .priv_data_size
= sizeof(PCMDVDContext
),
311 .init
= pcm_dvd_decode_init
,
312 .decode
= pcm_dvd_decode_frame
,
313 .close
= pcm_dvd_decode_uninit
,
314 .capabilities
= CODEC_CAP_DR1
,
315 .sample_fmts
= (const enum AVSampleFormat
[]) {
316 AV_SAMPLE_FMT_S16
, AV_SAMPLE_FMT_S32
, AV_SAMPLE_FMT_NONE