2 * LPCM codecs for PCM formats found in MPEG streams
3 * Copyright (c) 2009 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
23 * @file libavcodec/pcm-mpeg.c
24 * PCM codecs for encodings found in MPEG streams (DVD/Blu-ray)
28 #include "bytestream.h"
31 * Channel Mapping according to
32 * Blu-ray Disc Read-Only Format Version 1
33 * Part 3: Audio Visual Basic Specifications
41 * 3/2+lfe L R C LS RS lfe
42 * 3/4 L R C LS Rls Rrs RS X
43 * 3/4+lfe L R C LS Rls Rrs RS lfe
47 * Parse the header of a LPCM frame read from a MPEG-TS stream
48 * @param avctx the codec context
49 * @param header pointer to the first four bytes of the data packet
51 static int pcm_bluray_parse_header(AVCodecContext
*avctx
,
52 const uint8_t *header
)
54 static const uint8_t bits_per_samples
[4] = { 0, 16, 20, 24 };
55 static const uint32_t channel_layouts
[16] = {
56 0, CH_LAYOUT_MONO
, 0, CH_LAYOUT_STEREO
, CH_LAYOUT_SURROUND
,
57 CH_LAYOUT_2_1
, CH_LAYOUT_4POINT0
, CH_LAYOUT_2_2
, CH_LAYOUT_5POINT0
,
58 CH_LAYOUT_5POINT1
, CH_LAYOUT_7POINT0
, CH_LAYOUT_7POINT1
, 0, 0, 0, 0
60 static const uint8_t channels
[16] = {
61 0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0
63 uint8_t channel_layout
= header
[2] >> 4;
65 if (avctx
->debug
& FF_DEBUG_PICT_INFO
)
66 dprintf(avctx
, "pcm_bluray_parse_header: header = %02x%02x%02x%02x\n",
67 header
[0], header
[1], header
[2], header
[3]);
69 /* get the sample depth and derive the sample format from it */
70 avctx
->bits_per_coded_sample
= bits_per_samples
[header
[3] >> 6];
71 if (!avctx
->bits_per_coded_sample
) {
72 av_log(avctx
, AV_LOG_ERROR
, "unsupported sample depth (0)\n");
75 avctx
->sample_fmt
= avctx
->bits_per_coded_sample
== 16 ? SAMPLE_FMT_S16
:
78 /* get the sample rate. Not all values are known or exist. */
79 switch (header
[2] & 0x0f) {
81 avctx
->sample_rate
= 48000;
84 avctx
->sample_rate
= 96000;
87 avctx
->sample_rate
= 192000;
90 avctx
->sample_rate
= 0;
91 av_log(avctx
, AV_LOG_ERROR
, "unsupported sample rate (%d)\n",
97 * get the channel number (and mapping). Not all values are known or exist.
98 * It must be noted that the number of channels in the MPEG stream can
99 * differ from the actual meaningful number, e.g. mono audio still has two
100 * channels, one being empty.
102 avctx
->channel_layout
= channel_layouts
[channel_layout
];
103 avctx
->channels
= channels
[channel_layout
];
104 if (!avctx
->channels
) {
105 av_log(avctx
, AV_LOG_ERROR
, "unsupported channel configuration (%d)\n",
110 avctx
->bit_rate
= avctx
->channels
* avctx
->sample_rate
*
111 avctx
->bits_per_coded_sample
;
113 if (avctx
->debug
& FF_DEBUG_PICT_INFO
)
115 "pcm_bluray_parse_header: %d channels, %d bits per sample, %d kHz, %d kbit\n",
116 avctx
->channels
, avctx
->bits_per_coded_sample
,
117 avctx
->sample_rate
, avctx
->bit_rate
);
121 static int pcm_bluray_decode_frame(AVCodecContext
*avctx
,
126 const uint8_t *src
= avpkt
->data
;
127 int buf_size
= avpkt
->size
;
128 int num_source_channels
, channel
, retval
;
129 int sample_size
, samples
, output_size
;
130 int16_t *dst16
= data
;
131 int32_t *dst32
= data
;
134 av_log(avctx
, AV_LOG_ERROR
, "PCM packet too small\n");
138 if (pcm_bluray_parse_header(avctx
, src
))
143 /* There's always an even number of channels in the source */
144 num_source_channels
= FFALIGN(avctx
->channels
, 2);
145 sample_size
= (num_source_channels
* avctx
->bits_per_coded_sample
) >> 3;
146 samples
= buf_size
/ sample_size
;
148 if (avctx
->debug
& FF_DEBUG_BITSTREAM
)
150 "pcm_bluray_decode_frame: c: %d sc: %d s: %d in: %d ds: %d\n",
151 avctx
->channels
, num_source_channels
, num_samples
, buf_size
,
154 output_size
= samples
* avctx
->channels
*
155 (avctx
->sample_fmt
== SAMPLE_FMT_S32
? 4 : 2);
156 if (output_size
> *data_size
) {
157 av_log(avctx
, AV_LOG_ERROR
,
158 "Insufficient output buffer space (%d bytes, needed %d bytes)\n",
159 *data_size
, output_size
);
162 *data_size
= output_size
;
165 switch (avctx
->channel_layout
) {
166 /* cases with same number of source and coded channels */
167 case CH_LAYOUT_STEREO
:
168 case CH_LAYOUT_4POINT0
:
170 samples
*= num_source_channels
;
171 if (SAMPLE_FMT_S16
== avctx
->sample_fmt
) {
173 memcpy(dst16
, src
, output_size
);
176 *dst16
++ = bytestream_get_be16(&src
);
181 *dst32
++ = bytestream_get_be24(&src
) << 8;
185 /* cases where number of source channels = coded channels + 1 */
187 case CH_LAYOUT_SURROUND
:
189 case CH_LAYOUT_5POINT0
:
190 if (SAMPLE_FMT_S16
== avctx
->sample_fmt
) {
193 memcpy(dst16
, src
, avctx
->channels
* 2);
194 dst16
+= avctx
->channels
;
197 channel
= avctx
->channels
;
199 *dst16
++ = bytestream_get_be16(&src
);
206 channel
= avctx
->channels
;
208 *dst32
++ = bytestream_get_be24(&src
) << 8;
214 /* remapping: L, R, C, LBack, RBack, LF */
215 case CH_LAYOUT_5POINT1
:
216 if (SAMPLE_FMT_S16
== avctx
->sample_fmt
) {
218 dst16
[0] = bytestream_get_be16(&src
);
219 dst16
[1] = bytestream_get_be16(&src
);
220 dst16
[2] = bytestream_get_be16(&src
);
221 dst16
[4] = bytestream_get_be16(&src
);
222 dst16
[5] = bytestream_get_be16(&src
);
223 dst16
[3] = bytestream_get_be16(&src
);
228 dst32
[0] = bytestream_get_be24(&src
) << 8;
229 dst32
[1] = bytestream_get_be24(&src
) << 8;
230 dst32
[2] = bytestream_get_be24(&src
) << 8;
231 dst32
[4] = bytestream_get_be24(&src
) << 8;
232 dst32
[5] = bytestream_get_be24(&src
) << 8;
233 dst32
[3] = bytestream_get_be24(&src
) << 8;
238 /* remapping: L, R, C, LSide, LBack, RBack, RSide, <unused> */
239 case CH_LAYOUT_7POINT0
:
240 if (SAMPLE_FMT_S16
== avctx
->sample_fmt
) {
242 dst16
[0] = bytestream_get_be16(&src
);
243 dst16
[1] = bytestream_get_be16(&src
);
244 dst16
[2] = bytestream_get_be16(&src
);
245 dst16
[5] = bytestream_get_be16(&src
);
246 dst16
[3] = bytestream_get_be16(&src
);
247 dst16
[4] = bytestream_get_be16(&src
);
248 dst16
[6] = bytestream_get_be16(&src
);
254 dst32
[0] = bytestream_get_be24(&src
) << 8;
255 dst32
[1] = bytestream_get_be24(&src
) << 8;
256 dst32
[2] = bytestream_get_be24(&src
) << 8;
257 dst32
[5] = bytestream_get_be24(&src
) << 8;
258 dst32
[3] = bytestream_get_be24(&src
) << 8;
259 dst32
[4] = bytestream_get_be24(&src
) << 8;
260 dst32
[6] = bytestream_get_be24(&src
) << 8;
266 /* remapping: L, R, C, LSide, LBack, RBack, RSide, LF */
267 case CH_LAYOUT_7POINT1
:
268 if (SAMPLE_FMT_S16
== avctx
->sample_fmt
) {
270 dst16
[0] = bytestream_get_be16(&src
);
271 dst16
[1] = bytestream_get_be16(&src
);
272 dst16
[2] = bytestream_get_be16(&src
);
273 dst16
[6] = bytestream_get_be16(&src
);
274 dst16
[4] = bytestream_get_be16(&src
);
275 dst16
[5] = bytestream_get_be16(&src
);
276 dst16
[7] = bytestream_get_be16(&src
);
277 dst16
[3] = bytestream_get_be16(&src
);
282 dst32
[0] = bytestream_get_be24(&src
) << 8;
283 dst32
[1] = bytestream_get_be24(&src
) << 8;
284 dst32
[2] = bytestream_get_be24(&src
) << 8;
285 dst32
[6] = bytestream_get_be24(&src
) << 8;
286 dst32
[4] = bytestream_get_be24(&src
) << 8;
287 dst32
[5] = bytestream_get_be24(&src
) << 8;
288 dst32
[7] = bytestream_get_be24(&src
) << 8;
289 dst32
[3] = bytestream_get_be24(&src
) << 8;
297 retval
= src
- avpkt
->data
;
298 if (avctx
->debug
& FF_DEBUG_BITSTREAM
)
299 dprintf(avctx
, "pcm_bluray_decode_frame: decoded %d -> %d bytes\n",
304 AVCodec pcm_bluray_decoder
= {
312 pcm_bluray_decode_frame
,
313 .sample_fmts
= (enum SampleFormat
[]){SAMPLE_FMT_S16
, SAMPLE_FMT_S32
,
315 .long_name
= NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"),