annotate mlp_parser.c @ 7352:c2318e551ff5 libavcodec

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