codec: add hxxx_helper test decoder
[vlc.git] / modules / packetizer / a52.h
blobfe04b5edf6d8dfc4016c9c028f0bb31210e241ac
1 /*****************************************************************************
2 * a52.h
3 *****************************************************************************
4 * Copyright (C) 2001-2016 Laurent Aimar
6 * Authors: Stéphane Borel <stef@via.ecp.fr>
7 * Christophe Massiot <massiot@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
9 * Laurent Aimar <fenrir@via.ecp.fr>
10 * Thomas Guillem <thomas@gllm.fr>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 #ifndef VLC_A52_H_
28 #define VLC_A52_H_
30 #include <vlc_bits.h>
32 /**
33 * Minimum AC3 header size that vlc_a52_header_Parse needs.
35 #define VLC_A52_MIN_HEADER_SIZE (8)
36 #define VLC_A52_EAC3_BSI_SIZE ((532 + 7)/8)
37 #define VLC_A52_EAC3_HEADER_SIZE (VLC_A52_EAC3_BSI_SIZE + 2)
39 #define VLC_A52_PROFILE_EAC3_DEPENDENT 1
41 /**
42 * AC3 header information.
44 struct vlc_a52_bitstream_info
46 uint8_t i_fscod;
47 uint8_t i_frmsizcod;
48 uint8_t i_bsid;
49 uint8_t i_bsmod;
50 uint8_t i_acmod;
51 uint8_t i_lfeon;
52 union
54 struct {
55 enum {
56 EAC3_STRMTYP_INDEPENDENT = 0,
57 EAC3_STRMTYP_DEPENDENT = 1,
58 EAC3_STRMTYP_AC3_CONVERT = 2,
59 EAC3_STRMTYP_RESERVED,
60 } strmtyp;
61 uint16_t i_frmsiz;
62 uint8_t i_fscod2;
63 uint8_t i_numblkscod;
64 uint8_t i_substreamid;
65 } eac3;
66 struct
68 uint8_t i_dsurmod;
69 } ac3;
73 typedef struct
75 bool b_eac3;
77 unsigned int i_channels;
78 unsigned int i_channels_conf;
79 unsigned int i_chan_mode;
80 unsigned int i_rate;
81 unsigned int i_bitrate;
83 unsigned int i_size;
84 unsigned int i_samples;
86 struct vlc_a52_bitstream_info bs;
88 uint8_t i_blocks_per_sync_frame;
89 } vlc_a52_header_t;
91 /**
92 * It parse AC3 sync info.
94 * cf. AC3 spec
96 static inline int vlc_a52_ParseAc3BitstreamInfo( struct vlc_a52_bitstream_info *bs,
97 const uint8_t *p_buf, size_t i_buf )
99 bs_t s;
100 bs_init( &s, p_buf, i_buf );
102 /* cf. 5.3.2 */
103 bs->i_fscod = bs_read( &s, 2 );
104 if( bs->i_fscod == 3 )
105 return VLC_EGENERIC;
106 bs->i_frmsizcod = bs_read( &s, 6 );
107 if( bs->i_frmsizcod >= 38 )
108 return VLC_EGENERIC;
109 bs->i_bsid = bs_read( &s, 5 );
110 bs->i_bsmod = bs_read( &s, 3 );
111 bs->i_acmod = bs_read( &s, 3 );
112 if( ( bs->i_acmod & 0x1 ) && ( bs->i_acmod != 0x1 ) )
114 /* if 3 front channels */
115 bs_skip( &s, 2 ); /* i_cmixlev */
117 if( bs->i_acmod & 0x4 )
119 /* if a surround channel exists */
120 bs_skip( &s, 2 ); /* i_surmixlev */
122 /* if in 2/0 mode */
123 bs->ac3.i_dsurmod = bs->i_acmod == 0x2 ? bs_read( &s, 2 ) : 0;
124 bs->i_lfeon = bs_read( &s, 1 );
126 return VLC_SUCCESS;
129 static inline int vlc_a52_header_ParseAc3( vlc_a52_header_t *p_header,
130 const uint8_t *p_buf,
131 const uint32_t *p_acmod,
132 const unsigned *pi_fscod_samplerates )
134 if( vlc_a52_ParseAc3BitstreamInfo( &p_header->bs,
135 &p_buf[4], /* start code + CRC */
136 VLC_A52_MIN_HEADER_SIZE - 4 ) != VLC_SUCCESS )
137 return VLC_EGENERIC;
139 /* cf. Table 5.18 Frame Size Code Table */
140 static const uint16_t ppi_frmsizcod_fscod_sizes[][3] = {
141 /* 32K, 44.1K, 48K */
142 { 96, 69, 64 },
143 { 96, 70, 64 },
144 { 120, 87, 80 },
145 { 120, 88, 80 },
146 { 144, 104, 96 },
147 { 144, 105, 96 },
148 { 168, 121, 112 },
149 { 168, 122, 112 },
150 { 192, 139, 128 },
151 { 192, 140, 128 },
152 { 240, 174, 160 },
153 { 240, 175, 160 },
154 { 288, 208, 192 },
155 { 288, 209, 192 },
156 { 336, 243, 224 },
157 { 336, 244, 224 },
158 { 384, 278, 256 },
159 { 384, 279, 256 },
160 { 480, 348, 320 },
161 { 480, 349, 320 },
162 { 576, 417, 384 },
163 { 576, 418, 384 },
164 { 672, 487, 448 },
165 { 672, 488, 448 },
166 { 768, 557, 512 },
167 { 768, 558, 512 },
168 { 960, 696, 640 },
169 { 960, 697, 640 },
170 { 1152, 835, 768 },
171 { 1152, 836, 768 },
172 { 1344, 975, 896 },
173 { 1344, 976, 896 },
174 { 1536, 1114, 1024 },
175 { 1536, 1115, 1024 },
176 { 1728, 1253, 1152 },
177 { 1728, 1254, 1152 },
178 { 1920, 1393, 1280 },
179 { 1920, 1394, 1280 }
181 static const uint16_t pi_frmsizcod_bitrates[] = {
182 32, 40, 48, 56,
183 64, 80, 96, 112,
184 128, 160, 192, 224,
185 256, 320, 384, 448,
186 512, 576, 640
189 const struct vlc_a52_bitstream_info *bs = &p_header->bs;
191 p_header->i_channels_conf = p_acmod[bs->i_acmod];
192 p_header->i_chan_mode = 0;
193 if( bs->ac3.i_dsurmod == 2 )
194 p_header->i_chan_mode |= AOUT_CHANMODE_DOLBYSTEREO;
195 if( bs->i_acmod == 0 )
196 p_header->i_chan_mode |= AOUT_CHANMODE_DUALMONO;
198 if( bs->i_lfeon )
199 p_header->i_channels_conf |= AOUT_CHAN_LFE;
201 p_header->i_channels = vlc_popcount(p_header->i_channels_conf);
203 const unsigned i_rate_shift = VLC_CLIP(bs->i_bsid, 8, 11) - 8;
204 p_header->i_bitrate = (pi_frmsizcod_bitrates[bs->i_frmsizcod >> 1] * 1000)
205 >> i_rate_shift;
206 p_header->i_rate = pi_fscod_samplerates[bs->i_fscod] >> i_rate_shift;
208 p_header->i_size = ppi_frmsizcod_fscod_sizes[bs->i_frmsizcod]
209 [2 - bs->i_fscod] * 2;
210 p_header->i_blocks_per_sync_frame = 6;
211 p_header->i_samples = p_header->i_blocks_per_sync_frame * 256;
213 p_header->b_eac3 = false;
214 return VLC_SUCCESS;
218 * It parse E-AC3 sync info
220 static inline int vlc_a52_ParseEac3BitstreamInfo( struct vlc_a52_bitstream_info *bs,
221 const uint8_t *p_buf, size_t i_buf )
223 bs_t s;
224 bs_init( &s, p_buf, i_buf );
225 bs->eac3.strmtyp = bs_read( &s, 2 ); /* Stream Type */
226 bs->eac3.i_substreamid = bs_read( &s, 3 );/* Substream Identification */
228 bs->eac3.i_frmsiz = bs_read( &s, 11 );
229 if( bs->eac3.i_frmsiz < 2 )
230 return VLC_EGENERIC;
232 bs->i_fscod = bs_read( &s, 2 );
233 if( bs->i_fscod == 0x03 )
235 bs->eac3.i_fscod2 = bs_read( &s, 2 );
236 if( bs->eac3.i_fscod2 == 0x03 )
237 return VLC_EGENERIC;
238 bs->eac3.i_numblkscod = 0x03;
240 else bs->eac3.i_numblkscod = bs_read( &s, 2 );
242 bs->i_acmod = bs_read( &s, 3 );
243 bs->i_lfeon = bs_read1( &s );
244 bs->i_bsid = bs_read( &s, 5 );
246 if( i_buf <= VLC_A52_MIN_HEADER_SIZE )
248 bs->i_bsmod = 0;
249 return VLC_SUCCESS;
252 bs_skip( &s, 5 ); /* dialnorm */
253 if(bs_read1( &s ))
254 bs_skip( &s, 8 ); /* compr */
256 if( bs->i_acmod == 0x00 )
258 bs_skip( &s, 5 );
259 if(bs_read1( &s ))
260 bs_skip( &s, 8 ); /* compr2 */
263 if( bs->eac3.strmtyp == 0x01 && bs_read1( &s ) )
264 bs_skip( &s, 16 ); /* chanmap */
266 if( bs_read1( &s ) ) /* mixmdate */
268 if( bs->i_acmod > 0x02 )
270 bs_skip( &s, 2 ); /* dmixmod */
271 if( bs->i_acmod & 0x01 )
272 bs_skip( &s, 6 ); /* ltrtcmixlev + lorocmixlev */
273 if( bs->i_acmod & 0x04 )
274 bs_skip( &s, 6 ); /* ltrtsurmixlev + lorosurmixlev */
277 if( bs->i_lfeon && bs_read1( &s ) )
278 bs_skip( &s, 5 ); /* (lfemixlevcode) */
280 if( bs->eac3.strmtyp == 0x00 )
282 if( bs_read1( &s ) )
283 bs_skip( &s, 6 ); /* pgmscl */
284 if( bs->i_acmod == 0x00 && bs_read1( &s ) )
285 bs_skip( &s, 6 ); /* pgmscl2 */
286 if(bs_read1( &s ))
287 bs_skip( &s, 6 ); /* extpgmscl */
288 const uint8_t i_mixdef = bs_read( &s, 2 );
289 if( i_mixdef == 0x01 )
290 bs_skip( &s, 5 ); /* premixcmpsel + drcsrc + premixcmpscl */
291 else if( i_mixdef == 0x02 )
292 bs_skip( &s, 12 ); /* mixdata */
293 else if( i_mixdef == 0x03 )
295 const unsigned mixdeflen = bs_read( &s, 5 ) + 2;
296 for(size_t i=0; i<mixdeflen; i++)
297 bs_skip( &s, 8 );
298 bs_align( &s );
300 if( bs->i_acmod < 0x02 )
302 if( bs_read1( &s ) )
303 bs_skip( &s, 14 ); /* panmean + paninfo */
304 if( bs->i_acmod == 0x00 && bs_read1( &s ) )
305 bs_skip( &s, 14 ); /* panmean2 + paninfo2 */
307 if( bs_read1( &s ) )
309 const uint8_t blkspersyncframe[] = { 0+1, 1, 2, 6 };
310 const size_t nb = blkspersyncframe[bs->eac3.i_numblkscod];
311 for(size_t i=0; i<nb; i++)
313 if( bs->eac3.i_numblkscod == 0x00 )
314 bs_skip( &s, 5 ); /* blkmixcfginfo[N] */
320 if( bs_read1( &s ) ) /* infomdate */
322 bs->i_bsmod = bs_read( &s, 3 );
323 // ...
325 else bs->i_bsmod = 0;
327 return VLC_SUCCESS;
330 static inline int vlc_a52_header_ParseEac3( vlc_a52_header_t *p_header,
331 const uint8_t *p_buf,
332 const uint32_t *p_acmod,
333 const unsigned *pi_fscod_samplerates )
335 if( vlc_a52_ParseEac3BitstreamInfo( &p_header->bs,
336 &p_buf[2], /* start code */
337 VLC_A52_MIN_HEADER_SIZE - 2 ) != VLC_SUCCESS )
338 return VLC_EGENERIC;
340 const struct vlc_a52_bitstream_info *bs = &p_header->bs;
342 p_header->i_size = 2 * (bs->eac3.i_frmsiz + 1 );
344 if( bs->i_fscod == 0x03 )
346 p_header->i_rate = pi_fscod_samplerates[bs->eac3.i_fscod2] / 2;
347 p_header->i_blocks_per_sync_frame = 6;
349 else
351 static const int pi_numblkscod [4] = { 1, 2, 3, 6 };
352 p_header->i_rate = pi_fscod_samplerates[bs->i_fscod];
353 p_header->i_blocks_per_sync_frame = pi_numblkscod[bs->eac3.i_numblkscod];
356 p_header->i_channels_conf = p_acmod[bs->i_acmod];
357 p_header->i_chan_mode = 0;
358 if( bs->i_acmod == 0 )
359 p_header->i_chan_mode |= AOUT_CHANMODE_DUALMONO;
360 if( bs->i_lfeon )
361 p_header->i_channels_conf |= AOUT_CHAN_LFE;
362 p_header->i_channels = vlc_popcount( p_header->i_channels_conf );
363 p_header->i_bitrate = 8 * p_header->i_size * p_header->i_rate
364 / (p_header->i_blocks_per_sync_frame * 256);
365 p_header->i_samples = p_header->i_blocks_per_sync_frame * 256;
367 p_header->b_eac3 = true;
368 return VLC_SUCCESS;
372 * It will parse the header AC3 frame and fill vlc_a52_header_t* if
373 * it is valid or return VLC_EGENERIC.
375 * XXX It will only recognize big endian bitstream ie starting with 0x0b, 0x77
377 static inline int vlc_a52_header_Parse( vlc_a52_header_t *p_header,
378 const uint8_t *p_buffer, int i_buffer )
380 static const uint32_t p_acmod[8] = {
381 AOUT_CHANS_2_0,
382 AOUT_CHAN_CENTER,
383 AOUT_CHANS_2_0,
384 AOUT_CHANS_3_0,
385 AOUT_CHANS_FRONT | AOUT_CHAN_REARCENTER, /* 2F1R */
386 AOUT_CHANS_FRONT | AOUT_CHANS_CENTER, /* 3F1R */
387 AOUT_CHANS_4_0,
388 AOUT_CHANS_5_0,
390 static const unsigned pi_fscod_samplerates[] = {
391 48000, 44100, 32000
394 if( i_buffer < VLC_A52_MIN_HEADER_SIZE )
395 return VLC_EGENERIC;
397 /* Check synword */
398 if( p_buffer[0] != 0x0b || p_buffer[1] != 0x77 )
399 return VLC_EGENERIC;
401 /* Check bsid */
402 const int bsid = p_buffer[5] >> 3;
404 /* cf. Annex E 2.3.1.6 of AC3 spec */
405 if( bsid <= 10 )
406 return vlc_a52_header_ParseAc3( p_header, p_buffer,
407 p_acmod, pi_fscod_samplerates );
408 else if( bsid <= 16 )
409 return vlc_a52_header_ParseEac3( p_header, p_buffer,
410 p_acmod, pi_fscod_samplerates );
411 else
412 return VLC_EGENERIC;
415 #endif