Browse code

Decoder for LPCM as used in Bluray discs.

Patch by Christian Schmidt, schmidt digadd de

Originally committed as revision 19722 to svn://svn.ffmpeg.org/ffmpeg/trunk

Christian Schmidt authored on 2009/08/27 07:10:35
Showing 7 changed files
... ...
@@ -35,6 +35,7 @@ version <next>:
35 35
 - IEC-61937 compatible Muxer
36 36
 - TwinVQ decoder
37 37
 - Bluray (PGS) subtitle decoder
38
+- LPCM support in MPEG-TS (HDMV RID as found on Blu-ray disks)
38 39
 
39 40
 
40 41
 
... ...
@@ -583,6 +583,7 @@ following image formats are supported:
583 583
 @item PCM signed 24-bit little-endian  @tab  X  @tab  X
584 584
 @item PCM signed 32-bit big-endian  @tab  X  @tab  X
585 585
 @item PCM signed 32-bit little-endian  @tab  X  @tab  X
586
+@item PCM signed 16/20/24-bit big-endian in MPEG-TS  @tab     @tab  X
586 587
 @item PCM unsigned 8-bit     @tab  X  @tab  X
587 588
 @item PCM unsigned 16-bit big-endian  @tab  X  @tab  X
588 589
 @item PCM unsigned 16-bit little-endian  @tab  X  @tab  X
... ...
@@ -272,6 +272,7 @@ OBJS-$(CONFIG_ZMBV_ENCODER)            += zmbvenc.o
272 272
 # (AD)PCM decoders/encoders
273 273
 OBJS-$(CONFIG_PCM_ALAW_DECODER)           += pcm.o
274 274
 OBJS-$(CONFIG_PCM_ALAW_ENCODER)           += pcm.o
275
+OBJS-$(CONFIG_PCM_BLURAY_DECODER)         += pcm-mpeg.o
275 276
 OBJS-$(CONFIG_PCM_DVD_DECODER)            += pcm.o
276 277
 OBJS-$(CONFIG_PCM_DVD_ENCODER)            += pcm.o
277 278
 OBJS-$(CONFIG_PCM_F32BE_DECODER)          += pcm.o
... ...
@@ -238,6 +238,7 @@ void avcodec_register_all(void)
238 238
 
239 239
     /* PCM codecs */
240 240
     REGISTER_ENCDEC  (PCM_ALAW, pcm_alaw);
241
+    REGISTER_DECODER (PCM_BLURAY, pcm_bluray);
241 242
     REGISTER_DECODER (PCM_DVD, pcm_dvd);
242 243
     REGISTER_ENCDEC  (PCM_F32BE, pcm_f32be);
243 244
     REGISTER_ENCDEC  (PCM_F32LE, pcm_f32le);
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVCODEC_VERSION_MAJOR 52
33
-#define LIBAVCODEC_VERSION_MINOR 33
33
+#define LIBAVCODEC_VERSION_MINOR 34
34 34
 #define LIBAVCODEC_VERSION_MICRO  0
35 35
 
36 36
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -224,6 +224,7 @@ enum CodecID {
224 224
     CODEC_ID_PCM_F32LE,
225 225
     CODEC_ID_PCM_F64BE,
226 226
     CODEC_ID_PCM_F64LE,
227
+    CODEC_ID_PCM_BLURAY,
227 228
 
228 229
     /* various ADPCM codecs */
229 230
     CODEC_ID_ADPCM_IMA_QT= 0x11000,
... ...
@@ -395,6 +396,7 @@ enum SampleFormat {
395 395
 #define CH_LAYOUT_5POINT1           (CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY)
396 396
 #define CH_LAYOUT_5POINT0_BACK      (CH_LAYOUT_SURROUND|CH_BACK_LEFT|CH_BACK_RIGHT)
397 397
 #define CH_LAYOUT_5POINT1_BACK      (CH_LAYOUT_5POINT0_BACK|CH_LOW_FREQUENCY)
398
+#define CH_LAYOUT_7POINT0           (CH_LAYOUT_5POINT0|CH_BACK_LEFT|CH_BACK_RIGHT)
398 399
 #define CH_LAYOUT_7POINT1           (CH_LAYOUT_5POINT1|CH_BACK_LEFT|CH_BACK_RIGHT)
399 400
 #define CH_LAYOUT_7POINT1_WIDE      (CH_LAYOUT_5POINT1_BACK|\
400 401
                                           CH_FRONT_LEFT_OF_CENTER|CH_FRONT_RIGHT_OF_CENTER)
401 402
new file mode 100644
... ...
@@ -0,0 +1,316 @@
0
+/*
1
+ * LPCM codecs for PCM formats found in MPEG streams
2
+ * Copyright (c) 2009 Christian Schmidt
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file libavcodec/pcm-mpeg.c
23
+ * PCM codecs for encodings found in MPEG streams (DVD/Blu-ray)
24
+ */
25
+
26
+#include "avcodec.h"
27
+#include "bytestream.h"
28
+
29
+/*
30
+ * Channel Mapping according to
31
+ * Blu-ray Disc Read-Only Format Version 1
32
+ * Part 3: Audio Visual Basic Specifications
33
+ * mono     M1    X
34
+ * stereo   L     R
35
+ * 3/0      L     R    C    X
36
+ * 2/1      L     R    S    X
37
+ * 3/1      L     R    C    S
38
+ * 2/2      L     R    LS   RS
39
+ * 3/2      L     R    C    LS    RS    X
40
+ * 3/2+lfe  L     R    C    LS    RS    lfe
41
+ * 3/4      L     R    C    LS    Rls   Rrs  RS   X
42
+ * 3/4+lfe  L     R    C    LS    Rls   Rrs  RS   lfe
43
+ */
44
+
45
+/**
46
+ * Parse the header of a LPCM frame read from a MPEG-TS stream
47
+ * @param avctx the codec context
48
+ * @param header pointer to the first four bytes of the data packet
49
+ */
50
+static int pcm_bluray_parse_header(AVCodecContext *avctx,
51
+                                   const uint8_t *header)
52
+{
53
+    static const uint8_t bits_per_samples[4] = { 0, 16, 20, 24 };
54
+    static const uint32_t channel_layouts[16] = {
55
+        0, CH_LAYOUT_MONO, 0, CH_LAYOUT_STEREO, CH_LAYOUT_SURROUND,
56
+        CH_LAYOUT_2_1, CH_LAYOUT_4POINT0, CH_LAYOUT_2_2, CH_LAYOUT_5POINT0,
57
+        CH_LAYOUT_5POINT1, CH_LAYOUT_7POINT0, CH_LAYOUT_7POINT1, 0, 0, 0, 0
58
+    };
59
+    static const uint8_t channels[16] = {
60
+        0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0
61
+    };
62
+    uint8_t channel_layout = header[2] >> 4;
63
+
64
+    if (avctx->debug & FF_DEBUG_PICT_INFO)
65
+        dprintf(avctx, "pcm_bluray_parse_header: header = %02x%02x%02x%02x\n",
66
+                header[0], header[1], header[2], header[3]);
67
+
68
+    /* get the sample depth and derive the sample format from it */
69
+    avctx->bits_per_coded_sample = bits_per_samples[header[3] >> 6];
70
+    if (!avctx->bits_per_coded_sample) {
71
+        av_log(avctx, AV_LOG_ERROR, "unsupported sample depth (0)\n");
72
+        return -1;
73
+    }
74
+    avctx->sample_fmt = avctx->bits_per_coded_sample == 16 ? SAMPLE_FMT_S16 :
75
+                                                             SAMPLE_FMT_S32;
76
+
77
+    /* get the sample rate. Not all values are known or exist. */
78
+    switch (header[2] & 0x0f) {
79
+    case 1:
80
+        avctx->sample_rate = 48000;
81
+        break;
82
+    case 4:
83
+        avctx->sample_rate = 96000;
84
+        break;
85
+    case 5:
86
+        avctx->sample_rate = 192000;
87
+        break;
88
+    default:
89
+        avctx->sample_rate = 0;
90
+        av_log(avctx, AV_LOG_ERROR, "unsupported sample rate (%d)\n",
91
+               header[2] & 0x0f);
92
+        return -1;
93
+    }
94
+
95
+    /*
96
+     * get the channel number (and mapping). Not all values are known or exist.
97
+     * It must be noted that the number of channels in the MPEG stream can
98
+     * differ from the actual meaningful number, e.g. mono audio still has two
99
+     * channels, one being empty.
100
+     */
101
+    avctx->channel_layout  = channel_layouts[channel_layout];
102
+    avctx->channels        =        channels[channel_layout];
103
+    if (!avctx->channels) {
104
+        av_log(avctx, AV_LOG_ERROR, "unsupported channel configuration (%d)\n",
105
+               channel_layout);
106
+        return -1;
107
+    }
108
+
109
+    avctx->bit_rate = avctx->channels * avctx->sample_rate *
110
+                      avctx->bits_per_coded_sample;
111
+
112
+    if (avctx->debug & FF_DEBUG_PICT_INFO)
113
+        dprintf(avctx,
114
+                "pcm_bluray_parse_header: %d channels, %d bits per sample, %d kHz, %d kbit\n",
115
+                avctx->channels, avctx->bits_per_coded_sample,
116
+                avctx->sample_rate, avctx->bit_rate);
117
+    return 0;
118
+}
119
+
120
+static int pcm_bluray_decode_frame(AVCodecContext *avctx,
121
+                                   void *data,
122
+                                   int *data_size,
123
+                                   AVPacket *avpkt)
124
+{
125
+    const uint8_t *src = avpkt->data;
126
+    int buf_size = avpkt->size;
127
+    int num_source_channels, channel, retval;
128
+    int sample_size, samples, output_size;
129
+    int16_t *dst16 = data;
130
+    int32_t *dst32 = data;
131
+
132
+    if (buf_size < 4) {
133
+        av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n");
134
+        return -1;
135
+    }
136
+
137
+    if (pcm_bluray_parse_header(avctx, src))
138
+        return -1;
139
+    src += 4;
140
+    buf_size -= 4;
141
+
142
+    /* There's always an even number of channels in the source */
143
+    num_source_channels = FFALIGN(avctx->channels, 2);
144
+    sample_size = (num_source_channels * avctx->bits_per_coded_sample) >> 3;
145
+    samples = buf_size / sample_size;
146
+
147
+    if (avctx->debug & FF_DEBUG_BITSTREAM)
148
+        dprintf(avctx,
149
+                "pcm_bluray_decode_frame: c: %d sc: %d s: %d in: %d ds: %d\n",
150
+                avctx->channels, num_source_channels, num_samples, buf_size,
151
+                *data_size);
152
+
153
+    output_size = samples * avctx->channels *
154
+                  (avctx->sample_fmt == SAMPLE_FMT_S32 ? 4 : 2);
155
+    if (output_size > *data_size) {
156
+        av_log(avctx, AV_LOG_ERROR,
157
+               "Insufficient output buffer space (%d bytes, needed %d bytes)\n",
158
+               *data_size, output_size);
159
+        return -1;
160
+    }
161
+    *data_size = output_size;
162
+
163
+    if (samples) {
164
+        switch (avctx->channel_layout) {
165
+            /* cases with same number of source and coded channels */
166
+        case CH_LAYOUT_STEREO:
167
+        case CH_LAYOUT_4POINT0:
168
+        case CH_LAYOUT_2_2:
169
+            samples *= num_source_channels;
170
+            if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
171
+#if HAVE_BIGENDIAN
172
+                memcpy(dst16, src, output_size);
173
+#else
174
+                do {
175
+                    *dst16++ = bytestream_get_be16(&src);
176
+                } while (--samples);
177
+#endif
178
+            } else {
179
+                do {
180
+                    *dst32++ = bytestream_get_be24(&src) << 8;
181
+                } while (--samples);
182
+            }
183
+            break;
184
+        /* cases where number of source channels = coded channels + 1 */
185
+        case CH_LAYOUT_MONO:
186
+        case CH_LAYOUT_SURROUND:
187
+        case CH_LAYOUT_2_1:
188
+        case CH_LAYOUT_5POINT0:
189
+            if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
190
+                do {
191
+#if HAVE_BIGENDIAN
192
+                    memcpy(dst16, src, avctx->channels * 2);
193
+                    dst16 += avctx->channels;
194
+                    src += sample_size;
195
+#else
196
+                    channel = avctx->channels;
197
+                    do {
198
+                        *dst16++ = bytestream_get_be16(&src);
199
+                    } while (--channel);
200
+                    src += 2;
201
+#endif
202
+                } while (--samples);
203
+            } else {
204
+                do {
205
+                    channel = avctx->channels;
206
+                    do {
207
+                        *dst32++ = bytestream_get_be24(&src) << 8;
208
+                    } while (--channel);
209
+                    src += 3;
210
+                } while (--samples);
211
+            }
212
+            break;
213
+            /* remapping: L, R, C, LBack, RBack, LF */
214
+        case CH_LAYOUT_5POINT1:
215
+            if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
216
+                do {
217
+                    dst16[0] = bytestream_get_be16(&src);
218
+                    dst16[1] = bytestream_get_be16(&src);
219
+                    dst16[2] = bytestream_get_be16(&src);
220
+                    dst16[4] = bytestream_get_be16(&src);
221
+                    dst16[5] = bytestream_get_be16(&src);
222
+                    dst16[3] = bytestream_get_be16(&src);
223
+                    dst16 += 6;
224
+                } while (--samples);
225
+            } else {
226
+                do {
227
+                    dst32[0] = bytestream_get_be24(&src) << 8;
228
+                    dst32[1] = bytestream_get_be24(&src) << 8;
229
+                    dst32[2] = bytestream_get_be24(&src) << 8;
230
+                    dst32[4] = bytestream_get_be24(&src) << 8;
231
+                    dst32[5] = bytestream_get_be24(&src) << 8;
232
+                    dst32[3] = bytestream_get_be24(&src) << 8;
233
+                    dst32 += 6;
234
+                } while (--samples);
235
+            }
236
+            break;
237
+            /* remapping: L, R, C, LSide, LBack, RBack, RSide, <unused> */
238
+        case CH_LAYOUT_7POINT0:
239
+            if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
240
+                do {
241
+                    dst16[0] = bytestream_get_be16(&src);
242
+                    dst16[1] = bytestream_get_be16(&src);
243
+                    dst16[2] = bytestream_get_be16(&src);
244
+                    dst16[5] = bytestream_get_be16(&src);
245
+                    dst16[3] = bytestream_get_be16(&src);
246
+                    dst16[4] = bytestream_get_be16(&src);
247
+                    dst16[6] = bytestream_get_be16(&src);
248
+                    dst16 += 7;
249
+                    src += 2;
250
+                } while (--samples);
251
+            } else {
252
+                do {
253
+                    dst32[0] = bytestream_get_be24(&src) << 8;
254
+                    dst32[1] = bytestream_get_be24(&src) << 8;
255
+                    dst32[2] = bytestream_get_be24(&src) << 8;
256
+                    dst32[5] = bytestream_get_be24(&src) << 8;
257
+                    dst32[3] = bytestream_get_be24(&src) << 8;
258
+                    dst32[4] = bytestream_get_be24(&src) << 8;
259
+                    dst32[6] = bytestream_get_be24(&src) << 8;
260
+                    dst32 += 7;
261
+                    src += 3;
262
+                } while (--samples);
263
+            }
264
+            break;
265
+            /* remapping: L, R, C, LSide, LBack, RBack, RSide, LF */
266
+        case CH_LAYOUT_7POINT1:
267
+            if (SAMPLE_FMT_S16 == avctx->sample_fmt) {
268
+                do {
269
+                    dst16[0] = bytestream_get_be16(&src);
270
+                    dst16[1] = bytestream_get_be16(&src);
271
+                    dst16[2] = bytestream_get_be16(&src);
272
+                    dst16[6] = bytestream_get_be16(&src);
273
+                    dst16[4] = bytestream_get_be16(&src);
274
+                    dst16[5] = bytestream_get_be16(&src);
275
+                    dst16[7] = bytestream_get_be16(&src);
276
+                    dst16[3] = bytestream_get_be16(&src);
277
+                    dst16 += 8;
278
+                } while (--samples);
279
+            } else {
280
+                do {
281
+                    dst32[0] = bytestream_get_be24(&src) << 8;
282
+                    dst32[1] = bytestream_get_be24(&src) << 8;
283
+                    dst32[2] = bytestream_get_be24(&src) << 8;
284
+                    dst32[6] = bytestream_get_be24(&src) << 8;
285
+                    dst32[4] = bytestream_get_be24(&src) << 8;
286
+                    dst32[5] = bytestream_get_be24(&src) << 8;
287
+                    dst32[7] = bytestream_get_be24(&src) << 8;
288
+                    dst32[3] = bytestream_get_be24(&src) << 8;
289
+                    dst32 += 8;
290
+                } while (--samples);
291
+            }
292
+            break;
293
+        }
294
+    }
295
+
296
+    retval = src - avpkt->data;
297
+    if (avctx->debug & FF_DEBUG_BITSTREAM)
298
+        dprintf(avctx, "pcm_bluray_decode_frame: decoded %d -> %d bytes\n",
299
+                retval, *data_size);
300
+    return retval;
301
+}
302
+
303
+AVCodec pcm_bluray_decoder = {
304
+    "pcm_bluray",
305
+    CODEC_TYPE_AUDIO,
306
+    CODEC_ID_PCM_BLURAY,
307
+    0,
308
+    NULL,
309
+    NULL,
310
+    NULL,
311
+    pcm_bluray_decode_frame,
312
+    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16, SAMPLE_FMT_S32,
313
+                                         SAMPLE_FMT_NONE},
314
+    .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"),
315
+};
... ...
@@ -505,6 +505,7 @@ static const StreamType ISO_types[] = {
505 505
 };
506 506
 
507 507
 static const StreamType HDMV_types[] = {
508
+    { 0x80, CODEC_TYPE_AUDIO, CODEC_ID_PCM_BLURAY },
508 509
     { 0x81, CODEC_TYPE_AUDIO, CODEC_ID_AC3 },
509 510
     { 0x82, CODEC_TYPE_AUDIO, CODEC_ID_DTS },
510 511
     { 0x90, CODEC_TYPE_SUBTITLE, CODEC_ID_HDMV_PGS_SUBTITLE },