Mercurial > libavcodec.hg
annotate mlp_parser.c @ 11352:6e0af2cfdcfe libavcodec
Do MC and IDCT in coding (hilbert) order
This increases the slice size to 64 pixels, due to having to decode an
entire chroma superblock row per slice.
This can be up to 6% slower depending on clip and CPU, but is necessary
for future optimizations that gain significantly more than was lost.
author | conrad |
---|---|
date | Wed, 03 Mar 2010 23:27:40 +0000 |
parents | 7de903afbd92 |
children | 7dd2a45249a9 |
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]; | |
11029
dfa02260a864
Fix possible crashes in mlp parser, it tries to go back 7 bytes after
reimar
parents:
9428
diff
changeset
|
179 if ((mp->pc.state & 0xfffffffe) == 0xf8726fba && |
dfa02260a864
Fix possible crashes in mlp parser, it tries to go back 7 bytes after
reimar
parents:
9428
diff
changeset
|
180 // ignore if we do not have the data for the start of header |
dfa02260a864
Fix possible crashes in mlp parser, it tries to go back 7 bytes after
reimar
parents:
9428
diff
changeset
|
181 mp->pc.index + i >= 7) { |
5954 | 182 mp->in_sync = 1; |
183 mp->bytes_left = 0; | |
184 break; | |
185 } | |
186 } | |
187 | |
188 if (!mp->in_sync) { | |
189 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size); | |
190 return buf_size; | |
191 } | |
192 | |
193 ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size); | |
194 | |
195 return i - 7; | |
196 } | |
197 | |
198 if (mp->bytes_left == 0) { | |
199 // Find length of this packet | |
200 | |
201 /* Copy overread bytes from last frame into buffer. */ | |
202 for(; mp->pc.overread>0; mp->pc.overread--) { | |
203 mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++]; | |
204 } | |
205 | |
206 if (mp->pc.index + buf_size < 2) { | |
207 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size); | |
208 return buf_size; | |
209 } | |
210 | |
211 mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8) | |
212 | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]); | |
213 mp->bytes_left = (mp->bytes_left & 0xfff) * 2; | |
214 mp->bytes_left -= mp->pc.index; | |
215 } | |
216 | |
217 next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left; | |
218 | |
219 if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) { | |
220 mp->bytes_left -= buf_size; | |
221 return buf_size; | |
222 } | |
223 | |
224 mp->bytes_left = 0; | |
225 | |
226 sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba; | |
227 | |
228 if (!sync_present) { | |
7177 | 229 /* The first nibble of a frame is a parity check of the 4-byte |
230 * access unit header and all the 2- or 4-byte substream headers. */ | |
5980 | 231 // Only check when this isn't a sync frame - syncs have a checksum. |
5954 | 232 |
233 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
|
234 for (i = -1; i < mp->num_substreams; i++) { |
5954 | 235 parity_bits ^= buf[p++]; |
236 parity_bits ^= buf[p++]; | |
237 | |
7137
186eb61a9860
Make it a little easier to spot that the code is not dealing only with
ramiro
parents:
6763
diff
changeset
|
238 if (i < 0 || buf[p-2] & 0x80) { |
5954 | 239 parity_bits ^= buf[p++]; |
240 parity_bits ^= buf[p++]; | |
241 } | |
242 } | |
243 | |
244 if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) { | |
5980 | 245 av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n"); |
5954 | 246 goto lost_sync; |
247 } | |
248 } else { | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
249 GetBitContext gb; |
5954 | 250 MLPHeaderInfo mh; |
251 | |
7176
ae78650d4ac8
Make ff_mlp_read_major_sync() take a GetBitContext instead of buffers.
ramiro
parents:
7154
diff
changeset
|
252 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
|
253 if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0) |
5954 | 254 goto lost_sync; |
255 | |
8274 | 256 avctx->bits_per_raw_sample = mh.group1_bits; |
257 if (avctx->bits_per_raw_sample > 16) | |
5954 | 258 avctx->sample_fmt = SAMPLE_FMT_S32; |
8276
9149588e5cc9
mlp: support bit-depths greater than 16 by default.
ramiro
parents:
8274
diff
changeset
|
259 else |
9149588e5cc9
mlp: support bit-depths greater than 16 by default.
ramiro
parents:
8274
diff
changeset
|
260 avctx->sample_fmt = SAMPLE_FMT_S16; |
5954 | 261 avctx->sample_rate = mh.group1_samplerate; |
262 avctx->frame_size = mh.access_unit_size; | |
263 | |
264 if (mh.stream_type == 0xbb) { | |
265 /* MLP stream */ | |
266 avctx->channels = mlp_channels[mh.channels_mlp]; | |
267 } else { /* mh.stream_type == 0xba */ | |
268 /* TrueHD stream */ | |
269 if (mh.channels_thd_stream2) | |
270 avctx->channels = truehd_channels(mh.channels_thd_stream2); | |
271 else | |
272 avctx->channels = truehd_channels(mh.channels_thd_stream1); | |
273 } | |
274 | |
275 if (!mh.is_vbr) /* Stream is CBR */ | |
276 avctx->bit_rate = mh.peak_bitrate; | |
277 | |
278 mp->num_substreams = mh.num_substreams; | |
279 } | |
280 | |
281 *poutbuf = buf; | |
282 *poutbuf_size = buf_size; | |
283 | |
284 return next; | |
285 | |
286 lost_sync: | |
287 mp->in_sync = 0; | |
7154
a9ed669e8cd1
Seek the file forwards instead of backwards when sync is lost.
ramiro
parents:
7137
diff
changeset
|
288 return 1; |
5954 | 289 } |
290 | |
291 AVCodecParser mlp_parser = { | |
9190 | 292 { CODEC_ID_MLP, CODEC_ID_TRUEHD }, |
5954 | 293 sizeof(MLPParseContext), |
8248
45cfe1d44e86
mlp: initialize all CRC tables in a common function.
ramiro
parents:
7559
diff
changeset
|
294 mlp_init, |
5954 | 295 mlp_parse, |
11266 | 296 ff_parse_close, |
5954 | 297 }; |