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