annotate mlp_parser.c @ 12530:63edd10ad4bc libavcodec tip

Try to fix crashes introduced by r25218 r25218 made assumptions about the existence of past reference frames that weren't necessarily true.
author darkshikari
date Tue, 28 Sep 2010 09:06:22 +0000
parents 7dd2a45249a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
1 /*
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
2 * MLP parser
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
3 * Copyright (c) 2007 Ian Caulfield
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
4 *
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
5 * This file is part of FFmpeg.
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
6 *
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
11 *
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
15 * Lesser General Public License for more details.
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
16 *
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
20 */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
21
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
22 /**
11644
7dd2a45249a9 Remove explicit filename from Doxygen @file commands.
diego
parents: 11266
diff changeset
23 * @file
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
24 * MLP parser
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
25 */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
26
7199
ae8c047d6be5 Add required stdint.h header #include.
diego
parents: 7198
diff changeset
27 #include <stdint.h>
ae8c047d6be5 Add required stdint.h header #include.
diego
parents: 7198
diff changeset
28
6763
f7cbb7733146 Use full path for #includes from another directory.
diego
parents: 5980
diff changeset
29 #include "libavutil/crc.h"
9428
0dce4fe6e6f3 Rename bitstream.h to get_bits.h.
stefano
parents: 9190
diff changeset
30 #include "get_bits.h"
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
31 #include "parser.h"
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
34
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
35 static const uint8_t mlp_quants[16] = {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
36 16, 20, 24, 0, 0, 0, 0, 0,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
37 0, 0, 0, 0, 0, 0, 0, 0,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
38 };
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
39
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
40 static const uint8_t mlp_channels[32] = {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
41 1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
42 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
43 };
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
44
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
45 static const uint8_t thd_chancount[13] = {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
46 // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
47 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
48 };
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
49
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
50 static int mlp_samplerate(int in)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
51 {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
52 if (in == 0xF)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
53 return 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
54
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
55 return (in & 8 ? 44100 : 48000) << (in & 7) ;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
56 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
57
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
58 static int truehd_channels(int chanmap)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
59 {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
60 int channels = 0, i;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
61
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
62 for (i = 0; i < 13; i++)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
63 channels += thd_chancount[i] * ((chanmap >> i) & 1);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
64
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
65 return channels;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
66 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
67
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
68 /** Read a major sync info header - contains high level information about
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
69 * the stream - sample rate, channel arrangement etc. Most of this
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
72 */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
75 {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
76 int ratebits;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
77 uint16_t checksum;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
479fc906650f spelling cosmetics
diego
parents: 7177
diff changeset
82 av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n");
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
83 return -1;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
84 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
479fc906650f spelling cosmetics
diego
parents: 7177
diff changeset
88 av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n");
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
89 return -1;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
90 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
93 return -1;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
96
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
108 } else if (mh->stream_type == 0xba) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
109 mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere?
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
110 mh->group2_bits = 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
113 mh->group1_samplerate = mlp_samplerate(ratebits);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
114 mh->group2_samplerate = 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
123 } else
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
124 return -1;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
125
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
126 mh->access_unit_size = 40 << (ratebits & 7);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
127 mh->access_unit_size_pow2 = 64 << (ratebits & 7);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
138
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
139 return 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
140 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
141
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
142 typedef struct MLPParseContext
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
143 {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
144 ParseContext pc;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
145
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
146 int bytes_left;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
147
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
148 int in_sync;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
149
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
150 int num_substreams;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
151 } MLPParseContext;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
159 static int mlp_parse(AVCodecParserContext *s,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
160 AVCodecContext *avctx,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
161 const uint8_t **poutbuf, int *poutbuf_size,
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
162 const uint8_t *buf, int buf_size)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
163 {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
164 MLPParseContext *mp = s->priv_data;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
165 int sync_present;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
166 uint8_t parity_bits;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
167 int next;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
168 int i, p = 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
169
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
170 *poutbuf_size = 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
171 if (buf_size == 0)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
172 return 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
173
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
174 if (!mp->in_sync) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
175 // Not in sync - find a major sync header
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
176
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
177 for (i = 0; i < buf_size; i++) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
182 mp->in_sync = 1;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
183 mp->bytes_left = 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
184 break;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
185 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
186 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
187
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
188 if (!mp->in_sync) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
189 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
190 return buf_size;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
191 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
192
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
193 ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
194
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
195 return i - 7;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
196 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
197
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
198 if (mp->bytes_left == 0) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
199 // Find length of this packet
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
200
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
201 /* Copy overread bytes from last frame into buffer. */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
202 for(; mp->pc.overread>0; mp->pc.overread--) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
203 mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++];
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
204 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
205
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
206 if (mp->pc.index + buf_size < 2) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
207 ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
208 return buf_size;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
209 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
210
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
211 mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
212 | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
213 mp->bytes_left = (mp->bytes_left & 0xfff) * 2;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
214 mp->bytes_left -= mp->pc.index;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
215 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
216
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
217 next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
218
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
219 if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
220 mp->bytes_left -= buf_size;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
221 return buf_size;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
222 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
223
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
224 mp->bytes_left = 0;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
225
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
226 sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
227
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
228 if (!sync_present) {
7177
a82e7d9c8c34 Clarify comment about parity nibble.
ramiro
parents: 7176
diff changeset
229 /* The first nibble of a frame is a parity check of the 4-byte
a82e7d9c8c34 Clarify comment about parity nibble.
ramiro
parents: 7176
diff changeset
230 * access unit header and all the 2- or 4-byte substream headers. */
5980
3055403f0e57 cosmetics: spelling fixes
diego
parents: 5954
diff changeset
231 // Only check when this isn't a sync frame - syncs have a checksum.
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
232
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
235 parity_bits ^= buf[p++];
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
236 parity_bits ^= buf[p++];
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
239 parity_bits ^= buf[p++];
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
240 parity_bits ^= buf[p++];
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
241 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
242 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
243
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
244 if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) {
5980
3055403f0e57 cosmetics: spelling fixes
diego
parents: 5954
diff changeset
245 av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n");
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
246 goto lost_sync;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
247 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
250 MLPHeaderInfo mh;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
254 goto lost_sync;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
255
8274
82dbfe8d2e0b mlp: Fix compilation under CONFIG_AUDIO_NONSHORT.
ramiro
parents: 8248
diff changeset
256 avctx->bits_per_raw_sample = mh.group1_bits;
82dbfe8d2e0b mlp: Fix compilation under CONFIG_AUDIO_NONSHORT.
ramiro
parents: 8248
diff changeset
257 if (avctx->bits_per_raw_sample > 16)
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
261 avctx->sample_rate = mh.group1_samplerate;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
262 avctx->frame_size = mh.access_unit_size;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
263
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
264 if (mh.stream_type == 0xbb) {
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
265 /* MLP stream */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
266 avctx->channels = mlp_channels[mh.channels_mlp];
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
267 } else { /* mh.stream_type == 0xba */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
268 /* TrueHD stream */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
269 if (mh.channels_thd_stream2)
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
270 avctx->channels = truehd_channels(mh.channels_thd_stream2);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
271 else
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
272 avctx->channels = truehd_channels(mh.channels_thd_stream1);
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
273 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
274
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
275 if (!mh.is_vbr) /* Stream is CBR */
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
276 avctx->bit_rate = mh.peak_bitrate;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
277
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
278 mp->num_substreams = mh.num_substreams;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
279 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
280
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
281 *poutbuf = buf;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
282 *poutbuf_size = buf_size;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
283
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
284 return next;
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
285
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
286 lost_sync:
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
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
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
289 }
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
290
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
291 AVCodecParser mlp_parser = {
9190
5b4f4d83431f Split TrueHD decoder from MLP
ramiro
parents: 8718
diff changeset
292 { CODEC_ID_MLP, CODEC_ID_TRUEHD },
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
293 sizeof(MLPParseContext),
8248
45cfe1d44e86 mlp: initialize all CRC tables in a common function.
ramiro
parents: 7559
diff changeset
294 mlp_init,
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
295 mlp_parse,
11266
7de903afbd92 mlp_parser: Fix memleak.
ramiro
parents: 11029
diff changeset
296 ff_parse_close,
5954
aafe67fa196f MLP/TrueHD parser
cehoyos
parents:
diff changeset
297 };