1 /*****************************************************************
2 |
3 | AP4 - E-AC-3 Sync Frame Parser
4 |
5 | Copyright 2002-2020 Axiomatic Systems, LLC
6 |
7 |
8 | This file is part of Bento4/AP4 (MP4 Atom Processing Library).
9 |
10 | Unless you have obtained Bento4 under a difference license,
11 | this version of Bento4 is Bento4|GPL.
12 | Bento4|GPL is free software; you can redistribute it and/or modify
13 | it under the terms of the GNU General Public License as published by
14 | the Free Software Foundation; either version 2, or (at your option)
15 | any later version.
16 |
17 | Bento4|GPL 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 General Public License for more details.
21 |
22 | You should have received a copy of the GNU General Public License
23 | along with Bento4|GPL; see the file COPYING. If not, write to the
24 | Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 | 02111-1307, USA.
26 |
27 ****************************************************************/
28
29 /*----------------------------------------------------------------------
30 | includes
31 +---------------------------------------------------------------------*/
32 #include "Ap4BitStream.h"
33 #include "Ap4Eac3Parser.h"
34 #include "Ap4Utils.h"
35
36 /*----------------------------------------------------------------------+
37 | AP4_Eac3Header::AP4_Eac3Header
38 +----------------------------------------------------------------------*/
AP4_Eac3Header(const AP4_UI08 * bytes)39 AP4_Eac3Header::AP4_Eac3Header(const AP4_UI08* bytes)
40 {
41 AP4_BitReader bits(bytes, AP4_EAC3_HEADER_SIZE);
42 bits.SkipBits(16); // sync word
43
44 m_Strmtyp = bits.ReadBits(2);
45 m_Substreamid = bits.ReadBits(3);
46 m_Frmsiz = bits.ReadBits(11);
47 m_FrameSize = (m_Frmsiz + 1) * 2;
48
49 m_Fscod = bits.ReadBits(2);
50 unsigned char numblkscod = 0;
51 unsigned int blks_per_frm = 0;
52 if (m_Fscod == 0x3){
53 fprintf(stderr, "ERROR: Half sample rate unsupported\n");
54 return;
55 }else{
56 numblkscod = bits.ReadBits(2);
57 if (numblkscod == 0x3){
58 blks_per_frm = 6;
59 }else {
60 blks_per_frm = numblkscod + 1;
61 }
62 }
63
64 m_Acmod = bits.ReadBits(3);
65 m_Lfeon = bits.ReadBits(1);
66 m_ChannelCount = GLOBAL_CHANNEL_ARY[m_Acmod] + m_Lfeon;
67
68 m_Bsid = bits.ReadBits(5);
69 if (!((m_Bsid > 10) && (m_Bsid <=16))){
70 fprintf(stderr, "ERROR: Unsupported bitstream id\n");
71 return;
72 }
73
74 /* unsigned char dialnorm = */ bits.ReadBits(5); // dialnorm
75 // unsigned char compr;
76 if (bits.ReadBit()) { // compre
77 /* compr = */ bits.ReadBits(8);
78 }
79
80 if (m_Acmod == 0x0){ // if 1+1 mode (dual mono, so some items need a second value)
81 bits.SkipBits(5); // dialnorm2
82 if (bits.ReadBit()) { // compr2e
83 bits.SkipBits(8); // compr2
84 }
85 }
86
87 if (m_Strmtyp == 0x1) { // if dependent stream
88 m_Chanmape = bits.ReadBit();
89 if (m_Chanmape) {
90 m_Chanmap = bits.ReadBits(16);
91 }else {
92 //TODO: Derive chanmap from the acmod and lfeon parameters
93 m_Chanmap = 0;
94 }
95 }else {
96 m_Chanmape = 0;
97 m_Chanmap = 0;
98 }
99
100 // Extract mixing metadata
101 // unsigned char dmixmod, ltrtcmixlev, lorocmixlev, ltrtsurmixlev, lorosurmixlev, lfemixlevcod;
102 if (bits.ReadBit()){ // mixmdate
103 if (m_Acmod > 0x2) {
104 /* dmixmod = */ bits.ReadBits(2);
105 }
106 if ((m_Acmod & 0x1) && (m_Acmod > 0x2)) {
107 /* ltrtcmixlev = */ bits.ReadBits(3);
108 /* lorocmixlev = */ bits.ReadBits(3);
109 }
110 if (m_Acmod & 0x4) {
111 /* ltrtsurmixlev = */ bits.ReadBits(3);
112 /* lorosurmixlev = */ bits.ReadBits(3);
113 }
114 if (m_Lfeon) {
115 if (bits.ReadBit()) { // lfemixlevcode
116 /* lfemixlevcod = */ bits.ReadBits(5);
117 }
118 }
119 if (m_Strmtyp == 0x0) { // if independent stream
120 // unsigned char pgmscl, extpgmscl;
121 if (bits.ReadBit()) { // pgmscle
122 /* pgmscl = */ bits.ReadBits(6);
123 }
124
125 if (m_Acmod == 0x0){ // if 1+1 mode (dual mono, so some items need a second value)
126 if(bits.ReadBit()) { // pgmscl2e
127 bits.SkipBits(6); // pgmscl2
128 }
129 }
130
131 if(bits.ReadBit()) { // extpgmscle
132 /* extpgmscl = */ bits.ReadBits(6);
133 }
134
135 char mixdef = bits.ReadBits(2);
136 if(mixdef == 0x1) { bits.SkipBits(5) ;} // premixcmpsel, drcsrc, premixcmpscl
137 else if (mixdef == 0x2) { bits.SkipBits(12);} // mixdata
138 else if (mixdef == 0x3) {
139 char mixdeflen = bits.ReadBits(5);
140 unsigned int mixdefbits = 1; // the initial value represents mixdata2e
141 if(bits.ReadBit()){ // mixdata2e
142 bits.SkipBits(5); // premixcmpsel, drcsrc, premixcmpscl
143 mixdefbits += 5;
144
145 mixdefbits += 1; // extpgmlscle
146 if(bits.ReadBit()) {
147 bits.SkipBits(4); // extpgmlscl
148 mixdefbits += 4;
149 }
150
151 mixdefbits += 1; // extpgmcscle
152 if(bits.ReadBit()) {
153 bits.SkipBits(4); // extpgmcscl
154 mixdefbits += 4;
155 }
156
157 mixdefbits += 1; // extpgmrscle
158 if(bits.ReadBit()) {
159 bits.SkipBits(4); // extpgmrscl
160 mixdefbits += 4;
161 }
162
163 mixdefbits += 1; // extpgmlsscle
164 if(bits.ReadBit()) {
165 bits.SkipBits(4); // extpgmlsscl
166 mixdefbits += 4;
167 }
168
169 mixdefbits += 1; // extpgmrsscle
170 if(bits.ReadBit()) {
171 bits.SkipBits(4); // extpgmrsscl
172 mixdefbits += 4;
173 }
174
175 mixdefbits += 1; // extpgmlfescle
176 if(bits.ReadBit()) {
177 bits.SkipBits(4); // extpgmlfescl
178 mixdefbits += 4;
179 }
180
181 mixdefbits += 1; // dmixscle
182 if(bits.ReadBit()) {
183 bits.SkipBits(4); // dmixscl
184 mixdefbits += 4;
185 }
186
187 mixdefbits += 1;
188 if(bits.ReadBit()){ // addche
189 mixdefbits += 1;
190 if(bits.ReadBit()) { // extpgmaux1scle
191 bits.SkipBits(4); // extpgmaux1scl
192 mixdefbits += 4;
193 }
194
195 mixdefbits += 1;
196 if(bits.ReadBit()) { // extpgmaux2scle
197 bits.SkipBits(4); // extpgmaux2scl
198 mixdefbits += 4;
199 }
200 }
201 } // if(bits.ReadBit()){ // mixdata2e
202
203 mixdefbits += 1;
204 if(bits.ReadBit()){ // mixdata3e
205 bits.SkipBits(5); // spchdat
206 mixdefbits += 5;
207
208 mixdefbits += 1;
209 if(bits.ReadBit()){ // addspchdate
210 bits.SkipBits(7); // spchdat1, spchan1att
211 mixdefbits += 7;
212
213 mixdefbits += 1;
214 if(bits.ReadBit()){ // addspdat1e
215 bits.SkipBits(8); // spchdat2, spchan2att
216 mixdefbits += 8;
217 }
218 }
219 } // if(bits.ReadBit()){ // mixdata3e
220
221 bits.SkipBits(8 * (mixdeflen + 2) - mixdefbits); // mixdatafill
222 }
223
224 if (m_Acmod < 0x2) { // if mono or dual mono source
225 if(bits.ReadBit()){ // paninfoe
226 bits.SkipBits(8 + 6); // panmean, paninfo
227 }
228 if (m_Acmod == 0x0) { // if 1+1 mode (dual mono - some items need a second value)
229 if(bits.ReadBit()){ // paninfo2e
230 bits.SkipBits(8 + 6); // panmean2, paninfo2
231 }
232 }
233 }
234
235 if (bits.ReadBit()){ // frmmixcfginfoe
236 if (blks_per_frm == 1) {
237 bits.SkipBits(5); // blkmixcfginfo[0]
238 }else{
239 for (unsigned int idx = 0; idx < blks_per_frm; idx++){
240 if(bits.ReadBit()){ // blkmixcfginfoe
241 bits.SkipBits(5); // blkmixcfginfo[blk]
242 }
243 }
244 }
245 }
246 } // if (m_Strmtyp == 0x0)
247 }
248
249 m_Infomdate = bits.ReadBit();
250 if (m_Infomdate){
251 m_Bsmod = bits.ReadBits(3);
252 // unsigned char copyrightb, origbs, dsurexmod;
253 /* copyrightb = */ bits.ReadBits(1);
254 /* origbs = */ bits.ReadBits(1);
255
256 if (m_Acmod == 0x2) { // if in 2/0 mode
257 bits.SkipBits(4); // dsurmod, dheadphonmod
258 }
259 if (m_Acmod >= 0x6) { // if both surround channels exist
260 /* dsurexmod = */ bits.ReadBits(2);
261 }
262 if(bits.ReadBit()){ // audprodie
263 bits.SkipBits(8); // mixlevel, roomtyp, adconvtyp
264 }
265 if (m_Acmod == 0x0) { //if 1+1 mode (dual mono, so some items need a second value)
266 if(bits.ReadBit()){ // audprodi2e
267 bits.SkipBits(8); // mixlevel2, roomtyp2, adconvtyp2
268 }
269 }
270 if (m_Fscod < 0x3) { // if not half sample rate
271 bits.SkipBits(1); // sourcefscod
272 }
273 } else { // if (m_Infomdate)
274 m_Bsmod = 0;
275 }
276
277 m_Convsync = 1;
278 if ((m_Strmtyp == 0x0) && (numblkscod != 0x3)){
279 m_Convsync = bits.ReadBits(1);
280 }
281
282 if (m_Strmtyp == 0x2) { // if bit stream converted from AC-3
283 unsigned char blkid = 0;
284 if (numblkscod == 0x3) {
285 blkid = 1;
286 }else {
287 blkid = bits.ReadBits(1);
288 }
289 if (blkid) {bits.SkipBits(6); } // frmsizecod
290 }
291
292 m_Addbsie = bits.ReadBit();
293 if (m_Addbsie){
294 m_Addbsil = bits.ReadBits(6);
295 for (unsigned int idx = 0 ; idx < (m_Addbsil + 1); idx ++){
296 m_Addbsi[idx] = bits.ReadBits(8);
297 }
298 } else {
299 m_Addbsil = 0;
300 AP4_SetMemory(m_Addbsi, 0, sizeof (m_Addbsi));
301 }
302 m_HeadSize = (bits.GetBitsRead() / 8) + ((bits.GetBitsRead() % 8 == 0) ? 0: 1);
303 }
304
305 /*----------------------------------------------------------------------+
306 | AP4_Eac3Header::MatchFixed
307 |
308 | Check that two fixed headers are the same
309 |
310 +----------------------------------------------------------------------*/
311 bool
MatchFixed(AP4_Eac3Header & frame,AP4_Eac3Header & next_frame)312 AP4_Eac3Header::MatchFixed(AP4_Eac3Header& frame, AP4_Eac3Header& next_frame)
313 {
314 if (frame.m_Acmod == next_frame.m_Acmod &&
315 frame.m_Bsid == next_frame.m_Bsid &&
316 frame.m_Bsmod == next_frame.m_Bsmod &&
317 frame.m_Lfeon == next_frame.m_Lfeon &&
318 frame.m_Fscod == next_frame.m_Fscod ) {
319 return true;
320 } else {
321 return false;
322 }
323 }
324
325 /*----------------------------------------------------------------------+
326 | AP4_Eac3Header::Check
327 +----------------------------------------------------------------------*/
328 AP4_Result
Check()329 AP4_Eac3Header::Check()
330 {
331 if (m_Fscod == 1 || m_Fscod == 2) {
332 fprintf(stderr, "WARN: The sample rate is NOT 48 kHz\n");
333 } else if (m_Fscod == 3) {
334 return AP4_FAILURE;
335 }
336 if (m_Bsid < 10 || m_Bsid > 16) {
337 return AP4_FAILURE;
338 }
339 if (m_Substreamid != 0) {
340 fprintf(stderr, "ERROR: Only single independent substream (I0) or single depenpent substream (D0) is allowed in a DD+ stream\n");
341 return AP4_FAILURE;
342 }
343 return AP4_SUCCESS;
344 }
345
346 /*----------------------------------------------------------------------+
347 | AP4_Eac3Parser::AP4_Eac3Parser
348 +----------------------------------------------------------------------*/
AP4_Eac3Parser()349 AP4_Eac3Parser::AP4_Eac3Parser() :
350 m_FrameCount(0)
351 {
352 }
353
354 /*----------------------------------------------------------------------+
355 | AP4_Eac3Parser::~AP4_Eac3Parser
356 +----------------------------------------------------------------------*/
~AP4_Eac3Parser()357 AP4_Eac3Parser::~AP4_Eac3Parser()
358 {
359 }
360
361 /*----------------------------------------------------------------------+
362 | AP4_Eac3Parser::Reset
363 +----------------------------------------------------------------------*/
364 AP4_Result
Reset()365 AP4_Eac3Parser::Reset()
366 {
367 m_FrameCount = 0;
368
369 return AP4_SUCCESS;
370 }
371
372 /*----------------------------------------------------------------------+
373 | AP4_Eac3Parser::Feed
374 +----------------------------------------------------------------------*/
375 AP4_Result
Feed(const AP4_UI08 * buffer,AP4_Size * buffer_size,AP4_Flags flags)376 AP4_Eac3Parser::Feed(const AP4_UI08* buffer,
377 AP4_Size* buffer_size,
378 AP4_Flags flags)
379 {
380 AP4_Size free_space;
381
382 /* update flags */
383 m_Bits.m_Flags = flags;
384
385 /* possible shortcut */
386 if (buffer == NULL ||
387 buffer_size == NULL ||
388 *buffer_size == 0) {
389 return AP4_SUCCESS;
390 }
391
392 /* see how much data we can write */
393 free_space = m_Bits.GetBytesFree();
394 if (*buffer_size > free_space) *buffer_size = free_space;
395 if (*buffer_size == 0) return AP4_SUCCESS;
396
397 /* write the data */
398 return m_Bits.WriteBytes(buffer, *buffer_size);
399 }
400
401 /*----------------------------------------------------------------------+
402 | AP4_Eac3Parser::FindHeader
403 +----------------------------------------------------------------------*/
404 AP4_Result
FindHeader(AP4_UI08 * header,AP4_Size & skip_size)405 AP4_Eac3Parser::FindHeader(AP4_UI08* header, AP4_Size& skip_size)
406 {
407 AP4_Size available = m_Bits.GetBytesAvailable();
408
409 /* look for the sync pattern */
410 while (available-- >= AP4_EAC3_HEADER_SIZE) {
411 m_Bits.PeekBytes(header, 2);
412
413 if( (((header[0] << 8) | header[1]) == AP4_EAC3_SYNC_WORD_BIG_ENDIAN) ||
414 (((header[0] << 8) | header[1]) == AP4_EAC3_SYNC_WORD_LITTLE_ENDIAN) ){
415 if (((header[0] << 8) | header[1]) == AP4_EAC3_SYNC_WORD_LITTLE_ENDIAN) {
416 m_LittleEndian = true;
417 } else {
418 m_LittleEndian = false;
419 }
420 /* found a sync pattern, read the entire the header */
421 m_Bits.PeekBytes(header, AP4_EAC3_HEADER_SIZE);
422
423 return AP4_SUCCESS;
424 } else {
425 m_Bits.ReadByte(); // skip
426 skip_size++;
427 }
428 }
429
430 return AP4_ERROR_NOT_ENOUGH_DATA;
431 }
432
433 /*----------------------------------------------------------------------+
434 | AP4_Eac3Parser::FindFrame
435 +----------------------------------------------------------------------*/
436 AP4_Result
FindFrame(AP4_Eac3Frame & frame)437 AP4_Eac3Parser::FindFrame(AP4_Eac3Frame& frame)
438 {
439 bool dependent_stream_exist = false;
440 unsigned int dependent_stream_chan_loc = 0;
441 unsigned int dependent_stream_length = 0;
442 unsigned int skip_size = 0;
443 unsigned int available;
444 unsigned char raw_header[AP4_EAC3_HEADER_SIZE];
445 AP4_Result result;
446
447 /* align to the start of the next byte */
448 m_Bits.ByteAlign();
449
450 /* find a frame header */
451 result = FindHeader(raw_header, skip_size);
452 if (AP4_FAILED(result)) return result;
453
454 if (m_LittleEndian) {
455 AP4_ByteSwap16(raw_header, AP4_EAC3_HEADER_SIZE);
456 }
457
458 /* parse the header */
459 AP4_Eac3Header eac3_header(raw_header);
460
461 /* check the header */
462 result = eac3_header.Check();
463 if (AP4_FAILED(result)) {
464 goto fail;
465 }
466
467 /* check if we have enough data to peek at the next header */
468 available = m_Bits.GetBytesAvailable();
469 if (available >= eac3_header.m_FrameSize + AP4_EAC3_HEADER_SIZE) {
470 // enough to peek at the header of the next frame
471 unsigned char peek_raw_header[AP4_EAC3_HEADER_SIZE];
472
473 m_Bits.SkipBytes(eac3_header.m_FrameSize);
474 skip_size = 0;
475 result = FindHeader(peek_raw_header, skip_size);
476 if (AP4_FAILED(result)) return result;
477 m_Bits.SkipBytes(-((int)(eac3_header.m_FrameSize + skip_size)));
478
479 if (m_LittleEndian) {
480 AP4_ByteSwap16(peek_raw_header, AP4_EAC3_HEADER_SIZE);
481 }
482 /* check the header */
483 AP4_Eac3Header peek_eac3_header(peek_raw_header);
484 result = peek_eac3_header.Check();
485 if (AP4_FAILED(result)) {
486 goto fail;
487 }
488
489 // TODO: Only support 7.1-channel now
490 if (peek_eac3_header.m_Strmtyp == 1) {
491 dependent_stream_exist = true;
492 if (peek_eac3_header.m_Chanmape == 0){
493 goto fail;
494 }else {
495 if (peek_eac3_header.m_Chanmap & 0x200) {
496 dependent_stream_chan_loc |= 0x2;
497 dependent_stream_length = peek_eac3_header.m_FrameSize;
498 eac3_header.m_ChannelCount += 2;
499 } else {
500 fprintf(stderr, "ERROR: Only support 7.1-channel (I0 + D0). For other D0, the tool doesn't support yet.\n");
501 goto fail;
502 }
503 }
504 }
505
506 /* check that the fixed part of this header is the same as the */
507 /* fixed part of the previous header */
508 else if (!AP4_Eac3Header::MatchFixed(eac3_header, peek_eac3_header)) {
509 goto fail;
510 }
511 } else if (available < eac3_header.m_FrameSize || (m_Bits.m_Flags & AP4_BITSTREAM_FLAG_EOS) == 0) {
512 // not enough for a frame, or not at the end (in which case we'll want to peek at the next header)
513 return AP4_ERROR_NOT_ENOUGH_DATA;
514 }
515
516 /* fill in the frame info */
517 frame.m_Info.m_ChannelCount = eac3_header.m_ChannelCount;
518 if (dependent_stream_exist) {
519 frame.m_Info.m_FrameSize = eac3_header.m_FrameSize + dependent_stream_length;
520 }else {
521 frame.m_Info.m_FrameSize = eac3_header.m_FrameSize;
522 }
523 frame.m_Info.m_SampleRate = EAC3_SAMPLE_RATE_ARY[eac3_header.m_Fscod];
524 frame.m_Info.m_Eac3SubStream.fscod = eac3_header.m_Fscod;
525 frame.m_Info.m_Eac3SubStream.bsid = eac3_header.m_Bsid;
526 frame.m_Info.m_Eac3SubStream.bsmod = eac3_header.m_Bsmod;
527 frame.m_Info.m_Eac3SubStream.acmod = eac3_header.m_Acmod;
528 frame.m_Info.m_Eac3SubStream.lfeon = eac3_header.m_Lfeon;
529 if (dependent_stream_exist) {
530 frame.m_Info.m_Eac3SubStream.num_dep_sub = 1;
531 frame.m_Info.m_Eac3SubStream.chan_loc = dependent_stream_chan_loc;
532 }else {
533 frame.m_Info.m_Eac3SubStream.num_dep_sub = 0;
534 frame.m_Info.m_Eac3SubStream.chan_loc = 0;
535 }
536
537 frame.m_Info.complexity_index_type_a = 0;
538 if (eac3_header.m_Addbsie && (eac3_header.m_Addbsil == 1) && (eac3_header.m_Addbsi[0] == 0x1)){
539 frame.m_Info.complexity_index_type_a = eac3_header.m_Addbsi[1];
540 }
541
542 /* set the little endian flag */
543 frame.m_LittleEndian = m_LittleEndian;
544
545 /* set the frame source */
546 frame.m_Source = &m_Bits;
547
548 return AP4_SUCCESS;
549
550 fail:
551 return AP4_ERROR_CORRUPTED_BITSTREAM;
552 }
553
554 /*----------------------------------------------------------------------+
555 | AP4_Eac3Parser::GetBytesFree
556 +----------------------------------------------------------------------*/
557 AP4_Size
GetBytesFree()558 AP4_Eac3Parser::GetBytesFree()
559 {
560 return (m_Bits.GetBytesFree());
561 }
562
563 /*----------------------------------------------------------------------+
564 | AP4_Eac3Parser::GetBytesAvailable
565 +----------------------------------------------------------------------*/
566 AP4_Size
GetBytesAvailable()567 AP4_Eac3Parser::GetBytesAvailable()
568 {
569 return (m_Bits.GetBytesAvailable());
570 }
571