/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 | | }; |