Mercurial > libavcodec.hg
annotate mlp_parser.c @ 10320:44f31c1c9acc libavcodec
Make sure that dv encoder initializes all encoded packet data.
The specification does not say which value to use for unused
parts, so fill all unused bytes with 0xff, which is consistent
with what DV usually uses for reserved or unused parts.
author | reimar |
---|---|
date | Tue, 29 Sep 2009 19:17:18 +0000 |
parents | 0dce4fe6e6f3 |
children | dfa02260a864 |
rev | line source |
---|---|
5954 | 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 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8276
diff
changeset
|
23 * @file libavcodec/mlp_parser.c |
5954 | 24 * MLP parser |
25 */ | |
26 | |
7199 | 27 #include <stdint.h> |
28 | |
6763 | 29 #include "libavutil/crc.h" |
9428 | 30 #include "get_bits.h" |
5954 | 31 #include "parser.h" |
32 #include "mlp_parser.h" | |
7559
fd24c8628221
mlp: Split common code from parser and decoder to be used by encoder.
ramiro
parents:
7557
diff
changeset
|
33 #include "mlp.h" |
5954 | 34 |
35 static const uint8_t mlp_quants[16] = { | |
36 16, 20, 24, 0, 0, 0, 0, 0, | |
37 0, 0, 0, 0, 0, 0, 0, 0, | |
38 }; | |
39 | |
40 static const uint8_t mlp_channels[32] = { | |
41 1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4, | |
42 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
43 }; | |
44 | |
45 static const uint8_t thd_chancount[13] = { | |
46 // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 | |
47 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1 | |
48 }; | |
49 | |
50 static int mlp_samplerate(int in) | |
51 { | |
52 if (in == 0xF) | |
53 return 0; | |
54 | |
55 return (in & 8 ? 44100 : 48000) << (in & 7) ; | |
56 } | |
57 | |
58 static int truehd_channels(int chanmap) | |
59 { | |
60 int channels = 0, i; | |
61 | |
62 for (i = 0; i < 13; i++) | |
63 channels += thd_chancount[i] * ((chanmap >> i) & 1); | |
64 | |
65 return channels; | |
66 } | |
67 | |
68 /** Read a major sync info header - contains high level information about | |
69 * the stream - sample rate, channel arrangement etc. Most of this | |
70 * information is not actually necessary for decoding, only for playback. | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
71 * gb must be a freshly initialized GetBitContext with no bits read. |
5954 | 72 */ |
73 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
74 int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) |
5954 | 75 { |
76 int ratebits; | |
77 uint16_t checksum; | |
78 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
79 assert(get_bits_count(gb) == 0); |
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
80 |
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
81 if (gb->size_in_bits < 28 << 3) { |
7198 | 82 av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n"); |
5954 | 83 return -1; |
84 } | |
85 | |
7559
fd24c8628221
mlp: Split common code from parser and decoder to be used by encoder.
ramiro
parents:
7557
diff
changeset
|
86 checksum = ff_mlp_checksum16(gb->buffer, 26); |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
87 if (checksum != AV_RL16(gb->buffer+26)) { |
7198 | 88 av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n"); |
5954 | 89 return -1; |
90 } | |
91 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
92 if (get_bits_long(gb, 24) != 0xf8726f) /* Sync words */ |
5954 | 93 return -1; |
94 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
95 mh->stream_type = get_bits(gb, 8); |
5954 | 96 |
97 if (mh->stream_type == 0xbb) { | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
98 mh->group1_bits = mlp_quants[get_bits(gb, 4)]; |
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
99 mh->group2_bits = mlp_quants[get_bits(gb, 4)]; |
5954 | 100 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
101 ratebits = get_bits(gb, 4); |
5954 | 102 mh->group1_samplerate = mlp_samplerate(ratebits); |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
103 mh->group2_samplerate = mlp_samplerate(get_bits(gb, 4)); |
5954 | 104 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
105 skip_bits(gb, 11); |
5954 | 106 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
107 mh->channels_mlp = get_bits(gb, 5); |
5954 | 108 } else if (mh->stream_type == 0xba) { |
109 mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere? | |
110 mh->group2_bits = 0; | |
111 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
112 ratebits = get_bits(gb, 4); |
5954 | 113 mh->group1_samplerate = mlp_samplerate(ratebits); |
114 mh->group2_samplerate = 0; | |
115 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
116 skip_bits(gb, 8); |
5954 | 117 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
118 mh->channels_thd_stream1 = get_bits(gb, 5); |
5954 | 119 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
120 skip_bits(gb, 2); |
5954 | 121 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
122 mh->channels_thd_stream2 = get_bits(gb, 13); |
5954 | 123 } else |
124 return -1; | |
125 | |
126 mh->access_unit_size = 40 << (ratebits & 7); | |
127 mh->access_unit_size_pow2 = 64 << (ratebits & 7); | |
128 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
129 skip_bits_long(gb, 48); |
5954 | 130 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
131 mh->is_vbr = get_bits1(gb); |
5954 | 132 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
133 mh->peak_bitrate = (get_bits(gb, 15) * mh->group1_samplerate + 8) >> 4; |
5954 | 134 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
135 mh->num_substreams = get_bits(gb, 4); |
5954 | 136 |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
137 skip_bits_long(gb, 4 + 11 * 8); |
5954 | 138 |
139 return 0; | |
140 } | |
141 | |
142 typedef struct MLPParseContext | |
143 { | |
144 ParseContext pc; | |
145 | |
146 int bytes_left; | |
147 | |
148 int in_sync; | |
149 | |
150 int num_substreams; | |
151 } MLPParseContext; | |
152 | |
8248
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
153 static av_cold int mlp_init(AVCodecParserContext *s) |
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
154 { |
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
155 ff_mlp_init_crc(); |
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
156 return 0; |
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
157 } |
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
158 |
5954 | 159 static int mlp_parse(AVCodecParserContext *s, |
160 AVCodecContext *avctx, | |
161 const uint8_t **poutbuf, int *poutbuf_size, | |
162 const uint8_t *buf, int buf_size) | |
163 { | |
164 MLPParseContext *mp = s->priv_data; | |
165 int sync_present; | |
166 uint8_t parity_bits; | |
167 int next; | |
168 int i, p = 0; | |
169 | |
170 *poutbuf_size = 0; | |
171 if (buf_size == 0) | |
172 return 0; | |
173 | |
174 if (!mp->in_sync) { | |
175 // Not in sync - find a major sync header | |
176 | |
177 for (i = 0; i < buf_size; i++) { | |
178 mp->pc.state = (mp->pc.state << 8) | buf[i]; | |
179 if ((mp->pc.state & 0xfffffffe) == 0xf8726fba) { | |
180 mp->in_sync = 1; | |
181 mp->bytes_left = 0; | |
182 break; | |
183 } | |
184 } | |
185 | |
186 if (!mp->in_sync) { | |
187 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size); | |
188 return buf_size; | |
189 } | |
190 | |
191 ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size); | |
192 | |
193 return i - 7; | |
194 } | |
195 | |
196 if (mp->bytes_left == 0) { | |
197 // Find length of this packet | |
198 | |
199 /* Copy overread bytes from last frame into buffer. */ | |
200 for(; mp->pc.overread>0; mp->pc.overread--) { | |
201 mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++]; | |
202 } | |
203 | |
204 if (mp->pc.index + buf_size < 2) { | |
205 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size); | |
206 return buf_size; | |
207 } | |
208 | |
209 mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8) | |
210 | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]); | |
211 mp->bytes_left = (mp->bytes_left & 0xfff) * 2; | |
212 mp->bytes_left -= mp->pc.index; | |
213 } | |
214 | |
215 next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left; | |
216 | |
217 if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) { | |
218 mp->bytes_left -= buf_size; | |
219 return buf_size; | |
220 } | |
221 | |
222 mp->bytes_left = 0; | |
223 | |
224 sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba; | |
225 | |
226 if (!sync_present) { | |
7177 | 227 /* The first nibble of a frame is a parity check of the 4-byte |
228 * access unit header and all the 2- or 4-byte substream headers. */ | |
5980 | 229 // Only check when this isn't a sync frame - syncs have a checksum. |
5954 | 230 |
231 parity_bits = 0; | |
7137
186eb61a9860
Make it a little easier to spot that the code is not dealing only with
ramiro
parents:
6763
diff
changeset
|
232 for (i = -1; i < mp->num_substreams; i++) { |
5954 | 233 parity_bits ^= buf[p++]; |
234 parity_bits ^= buf[p++]; | |
235 | |
7137
186eb61a9860
Make it a little easier to spot that the code is not dealing only with
ramiro
parents:
6763
diff
changeset
|
236 if (i < 0 || buf[p-2] & 0x80) { |
5954 | 237 parity_bits ^= buf[p++]; |
238 parity_bits ^= buf[p++]; | |
239 } | |
240 } | |
241 | |
242 if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) { | |
5980 | 243 av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n"); |
5954 | 244 goto lost_sync; |
245 } | |
246 } else { | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
247 GetBitContext gb; |
5954 | 248 MLPHeaderInfo mh; |
249 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
250 init_get_bits(&gb, buf + 4, (buf_size - 4) << 3); |
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
251 if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0) |
5954 | 252 goto lost_sync; |
253 | |
8274 | 254 avctx->bits_per_raw_sample = mh.group1_bits; |
255 if (avctx->bits_per_raw_sample > 16) | |
5954 | 256 avctx->sample_fmt = SAMPLE_FMT_S32; |
8276
9149588e5cc9
mlp: support bit-depths greater than 16 by default.
ramiro
parents:
8274
diff
changeset
|
257 else |
9149588e5cc9
mlp: support bit-depths greater than 16 by default.
ramiro
parents:
8274
diff
changeset
|
258 avctx->sample_fmt = SAMPLE_FMT_S16; |
5954 | 259 avctx->sample_rate = mh.group1_samplerate; |
260 avctx->frame_size = mh.access_unit_size; | |
261 | |
262 if (mh.stream_type == 0xbb) { | |
263 /* MLP stream */ | |
264 avctx->channels = mlp_channels[mh.channels_mlp]; | |
265 } else { /* mh.stream_type == 0xba */ | |
266 /* TrueHD stream */ | |
267 if (mh.channels_thd_stream2) | |
268 avctx->channels = truehd_channels(mh.channels_thd_stream2); | |
269 else | |
270 avctx->channels = truehd_channels(mh.channels_thd_stream1); | |
271 } | |
272 | |
273 if (!mh.is_vbr) /* Stream is CBR */ | |
274 avctx->bit_rate = mh.peak_bitrate; | |
275 | |
276 mp->num_substreams = mh.num_substreams; | |
277 } | |
278 | |
279 *poutbuf = buf; | |
280 *poutbuf_size = buf_size; | |
281 | |
282 return next; | |
283 | |
284 lost_sync: | |
285 mp->in_sync = 0; | |
7154
a9ed669e8cd1
Seek the file forwards instead of backwards when sync is lost.
ramiro
parents:
7137
diff
changeset
|
286 return 1; |
5954 | 287 } |
288 | |
289 AVCodecParser mlp_parser = { | |
9190 | 290 { CODEC_ID_MLP, CODEC_ID_TRUEHD }, |
5954 | 291 sizeof(MLPParseContext), |
8248
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
292 mlp_init, |
5954 | 293 mlp_parse, |
294 NULL, | |
295 }; |