comparison mlp_parser.c @ 5954:aafe67fa196f libavcodec

MLP/TrueHD parser Patch by Ian Caulfield, ian D caulfield <at> gmail D com Thread: [PATCH] MLP/TrueHD decoder, 12 Oct 14:26
author cehoyos
date Wed, 28 Nov 2007 14:27:53 +0000
parents
children 3055403f0e57
comparison
equal deleted inserted replaced
5953:402833508709 5954:aafe67fa196f
1 /*
2 * MLP parser
3 * Copyright (c) 2007 Ian Caulfield
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 mlp_parser.c
24 * MLP parser
25 */
26
27 #include "bitstream.h"
28 #include "parser.h"
29 #include "crc.h"
30 #include "mlp_parser.h"
31
32 static const uint8_t mlp_quants[16] = {
33 16, 20, 24, 0, 0, 0, 0, 0,
34 0, 0, 0, 0, 0, 0, 0, 0,
35 };
36
37 static const uint8_t mlp_channels[32] = {
38 1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
39 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 };
41
42 static const uint8_t thd_chancount[13] = {
43 // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2
44 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
45 };
46
47 static int mlp_samplerate(int in)
48 {
49 if (in == 0xF)
50 return 0;
51
52 return (in & 8 ? 44100 : 48000) << (in & 7) ;
53 }
54
55 static int truehd_channels(int chanmap)
56 {
57 int channels = 0, i;
58
59 for (i = 0; i < 13; i++)
60 channels += thd_chancount[i] * ((chanmap >> i) & 1);
61
62 return channels;
63 }
64
65 static int crc_init = 0;
66 static AVCRC crc_2D[1024];
67
68 /** MLP uses checksums that seem to be based on the standard CRC algorithm,
69 * but not (in implementation terms, the table lookup and XOR are reversedi).
70 * We can implement this behaviour using a standard av_crc on all but the
71 * last element, then XOR that with the last element.
72 */
73
74 static uint16_t mlp_checksum16(const uint8_t *buf, unsigned int buf_size)
75 {
76 uint16_t crc;
77
78 if (!crc_init) {
79 av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D));
80 crc_init = 1;
81 }
82
83 crc = av_crc(crc_2D, 0, buf, buf_size - 2);
84 crc ^= AV_RL16(buf + buf_size - 2);
85 return crc;
86 }
87
88 /** Read a major sync info header - contains high level information about
89 * the stream - sample rate, channel arrangement etc. Most of this
90 * information is not actually necessary for decoding, only for playback.
91 */
92
93 int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, const uint8_t *buf,
94 unsigned int buf_size)
95 {
96 GetBitContext gb;
97 int ratebits;
98 uint16_t checksum;
99
100 if (buf_size < 28) {
101 av_log(log, AV_LOG_ERROR, "Packet too short, unable to read major sync\n");
102 return -1;
103 }
104
105 checksum = mlp_checksum16(buf, 26);
106 if (checksum != AV_RL16(buf+26)) {
107 av_log(log, AV_LOG_ERROR, "Major sync info header checksum error\n");
108 return -1;
109 }
110
111 init_get_bits(&gb, buf, buf_size * 8);
112
113 if (get_bits_long(&gb, 24) != 0xf8726f) /* Sync words */
114 return -1;
115
116 mh->stream_type = get_bits(&gb, 8);
117
118 if (mh->stream_type == 0xbb) {
119 mh->group1_bits = mlp_quants[get_bits(&gb, 4)];
120 mh->group2_bits = mlp_quants[get_bits(&gb, 4)];
121
122 ratebits = get_bits(&gb, 4);
123 mh->group1_samplerate = mlp_samplerate(ratebits);
124 mh->group2_samplerate = mlp_samplerate(get_bits(&gb, 4));
125
126 skip_bits(&gb, 11);
127
128 mh->channels_mlp = get_bits(&gb, 5);
129 } else if (mh->stream_type == 0xba) {
130 mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere?
131 mh->group2_bits = 0;
132
133 ratebits = get_bits(&gb, 4);
134 mh->group1_samplerate = mlp_samplerate(ratebits);
135 mh->group2_samplerate = 0;
136
137 skip_bits(&gb, 8);
138
139 mh->channels_thd_stream1 = get_bits(&gb, 5);
140
141 skip_bits(&gb, 2);
142
143 mh->channels_thd_stream2 = get_bits(&gb, 13);
144 } else
145 return -1;
146
147 mh->access_unit_size = 40 << (ratebits & 7);
148 mh->access_unit_size_pow2 = 64 << (ratebits & 7);
149
150 skip_bits_long(&gb, 48);
151
152 mh->is_vbr = get_bits1(&gb);
153
154 mh->peak_bitrate = (get_bits(&gb, 15) * mh->group1_samplerate + 8) >> 4;
155
156 mh->num_substreams = get_bits(&gb, 4);
157
158 skip_bits_long(&gb, 4 + 11 * 8);
159
160 return 0;
161 }
162
163 typedef struct MLPParseContext
164 {
165 ParseContext pc;
166
167 int bytes_left;
168
169 int in_sync;
170
171 int num_substreams;
172 } MLPParseContext;
173
174 static int mlp_parse(AVCodecParserContext *s,
175 AVCodecContext *avctx,
176 const uint8_t **poutbuf, int *poutbuf_size,
177 const uint8_t *buf, int buf_size)
178 {
179 MLPParseContext *mp = s->priv_data;
180 int sync_present;
181 uint8_t parity_bits;
182 int next;
183 int i, p = 0;
184
185 *poutbuf_size = 0;
186 if (buf_size == 0)
187 return 0;
188
189 if (!mp->in_sync) {
190 // Not in sync - find a major sync header
191
192 for (i = 0; i < buf_size; i++) {
193 mp->pc.state = (mp->pc.state << 8) | buf[i];
194 if ((mp->pc.state & 0xfffffffe) == 0xf8726fba) {
195 mp->in_sync = 1;
196 mp->bytes_left = 0;
197 break;
198 }
199 }
200
201 if (!mp->in_sync) {
202 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
203 return buf_size;
204 }
205
206 ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size);
207
208 return i - 7;
209 }
210
211 if (mp->bytes_left == 0) {
212 // Find length of this packet
213
214 /* Copy overread bytes from last frame into buffer. */
215 for(; mp->pc.overread>0; mp->pc.overread--) {
216 mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++];
217 }
218
219 if (mp->pc.index + buf_size < 2) {
220 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
221 return buf_size;
222 }
223
224 mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8)
225 | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]);
226 mp->bytes_left = (mp->bytes_left & 0xfff) * 2;
227 mp->bytes_left -= mp->pc.index;
228 }
229
230 next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left;
231
232 if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) {
233 mp->bytes_left -= buf_size;
234 return buf_size;
235 }
236
237 mp->bytes_left = 0;
238
239 sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba;
240
241 if (!sync_present) {
242 // First nibble of a frame is a parity check of the first few nibbles
243 // Only check when this isn't a sync frame - syncs have a checksum
244
245 parity_bits = 0;
246 for (i = 0; i <= mp->num_substreams; i++) {
247 parity_bits ^= buf[p++];
248 parity_bits ^= buf[p++];
249
250 if (i == 0 || buf[p-2] & 0x80) {
251 parity_bits ^= buf[p++];
252 parity_bits ^= buf[p++];
253 }
254 }
255
256 if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) {
257 av_log(avctx, AV_LOG_INFO, "mlpparse: parity check failed\n");
258 goto lost_sync;
259 }
260 } else {
261 MLPHeaderInfo mh;
262
263 if (ff_mlp_read_major_sync(avctx, &mh, buf + 4, buf_size - 4) < 0)
264 goto lost_sync;
265
266 #ifdef CONFIG_AUDIO_NONSHORT
267 avctx->bits_per_sample = mh.group1_bits;
268 if (avctx->bits_per_sample > 16)
269 avctx->sample_fmt = SAMPLE_FMT_S32;
270 #endif
271 avctx->sample_rate = mh.group1_samplerate;
272 avctx->frame_size = mh.access_unit_size;
273
274 if (mh.stream_type == 0xbb) {
275 /* MLP stream */
276 avctx->channels = mlp_channels[mh.channels_mlp];
277 } else { /* mh.stream_type == 0xba */
278 /* TrueHD stream */
279 if (mh.channels_thd_stream2)
280 avctx->channels = truehd_channels(mh.channels_thd_stream2);
281 else
282 avctx->channels = truehd_channels(mh.channels_thd_stream1);
283 }
284
285 if (!mh.is_vbr) /* Stream is CBR */
286 avctx->bit_rate = mh.peak_bitrate;
287
288 mp->num_substreams = mh.num_substreams;
289 }
290
291 *poutbuf = buf;
292 *poutbuf_size = buf_size;
293
294 return next;
295
296 lost_sync:
297 mp->in_sync = 0;
298 return -1;
299 }
300
301 AVCodecParser mlp_parser = {
302 { CODEC_ID_MLP },
303 sizeof(MLPParseContext),
304 NULL,
305 mlp_parse,
306 NULL,
307 };