1 /*****************************************************************
2  |
3  |    AP4 - 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 "Ap4Ac3Parser.h"
34 #include "Ap4Utils.h"
35 
36 /*----------------------------------------------------------------------+
37  |    AP4_Ac3Header::AP4_Ac3Header
38  +----------------------------------------------------------------------*/
AP4_Ac3Header(const AP4_UI08 * bytes)39 AP4_Ac3Header::AP4_Ac3Header(const AP4_UI08* bytes)
40 {
41     AP4_BitReader bits(bytes, AP4_AC3_HEADER_SIZE);
42     bits.SkipBits(16);                  // sync word
43     bits.SkipBits(16);                  // crc1
44     m_Fscod       = bits.ReadBits(2);
45     m_Frmsizecod  = bits.ReadBits(6);   // frmsizecod
46     m_FrameSize   = FRAME_SIZE_CODE_ARY_AC3[m_Fscod][m_Frmsizecod] * 2;
47 
48     m_Bsid        = bits.ReadBits(5);
49     m_Bsmod       = bits.ReadBits(3);
50     m_Acmod       = bits.ReadBits(3);
51     if((m_Acmod & 0x1) && (m_Acmod != 0x1)){
52         bits.SkipBits(2);               //cmixlev
53     }
54     if(m_Acmod & 0x4){
55         bits.SkipBits(2);               //surmixlev
56     }
57     if(m_Acmod == 0x2){
58         bits.SkipBits(2);               //dsurmod
59     }
60     m_Lfeon         = bits.ReadBit();
61     m_ChannelCount  = GLOBAL_CHANNEL_ARY[m_Acmod] + m_Lfeon;
62     bits.SkipBits(5);                   // dialnorm
63     if(bits.ReadBit()){                 // compre
64         bits.SkipBits(8);               // compr
65     }
66     if(bits.ReadBit()){                 // langcode
67         bits.SkipBits(8);               // langcod
68     }
69     if(bits.ReadBit()){                 // audprodie
70         bits.SkipBits(5);               // mixlevel
71         bits.SkipBits(2);               // roomtyp
72     }
73     if (m_Acmod == 0){
74         bits.SkipBits(5);               // dialnorm2
75         if(bits.ReadBit()){             // compr2e
76             bits.SkipBits(8);           // compr2
77         }
78         if(bits.ReadBit()){             // langcod2e
79             bits.SkipBits(8);           // langcod2
80         }
81         if(bits.ReadBit()){             // audprodi2e
82             bits.SkipBits(5);           // mixlevel2
83             bits.SkipBits(2);           // roomtyp2
84         }
85     }
86     bits.SkipBits(1);                   // copyrightb
87     bits.SkipBits(1);                   // origbs
88     if(bits.ReadBit()){                 // timecod1e
89         bits.SkipBits(14);              // timecod1
90     }
91     if(bits.ReadBit()){                 //timecod2e
92         bits.SkipBits(14);              // timecod2
93     }
94     m_Addbsie = bits.ReadBit();
95     if (m_Addbsie){
96         m_Addbsil = bits.ReadBits(6);
97         for (unsigned int idx = 0 ; idx < (m_Addbsil + 1); idx ++){
98             m_addbsi[idx] = bits.ReadBits(8);
99         }
100     } else {
101         m_Addbsil = 0;
102         AP4_SetMemory(m_addbsi, 0, sizeof (m_addbsi));
103     }
104     m_HeadSize = (bits.GetBitsRead() / 8) + ((bits.GetBitsRead() % 8 == 0) ? 0: 1);
105 }
106 
107 /*----------------------------------------------------------------------+
108  |    AP4_Ac3Header::MatchFixed
109  |
110  |    Check that two fixed headers are the same
111  |
112  +----------------------------------------------------------------------*/
113 bool
MatchFixed(AP4_Ac3Header & frame,AP4_Ac3Header & next_frame)114 AP4_Ac3Header::MatchFixed(AP4_Ac3Header& frame, AP4_Ac3Header& next_frame)
115 {
116     return true;
117 }
118 
119 /*----------------------------------------------------------------------+
120  |    AP4_Ac3Header::Check
121  +----------------------------------------------------------------------*/
122 AP4_Result
Check()123 AP4_Ac3Header::Check()
124 {
125     if (m_Bsid > 8) {
126         return AP4_FAILURE;
127     }
128     return AP4_SUCCESS;
129 }
130 
131 /*----------------------------------------------------------------------+
132  |    AP4_Ac3Parser::AP4_Ac3Parser
133  +----------------------------------------------------------------------*/
AP4_Ac3Parser()134 AP4_Ac3Parser::AP4_Ac3Parser() :
135 m_FrameCount(0)
136 {
137 }
138 
139 /*----------------------------------------------------------------------+
140  |    AP4_Ac3Parser::~AP4_Ac3Parser
141  +----------------------------------------------------------------------*/
~AP4_Ac3Parser()142 AP4_Ac3Parser::~AP4_Ac3Parser()
143 {
144 }
145 
146 /*----------------------------------------------------------------------+
147  |    AP4_Ac3Parser::Reset
148  +----------------------------------------------------------------------*/
149 AP4_Result
Reset()150 AP4_Ac3Parser::Reset()
151 {
152     m_FrameCount = 0;
153 
154     return AP4_SUCCESS;
155 }
156 
157 /*----------------------------------------------------------------------+
158  |    AP4_Ac3Parser::Feed
159  +----------------------------------------------------------------------*/
160 AP4_Result
Feed(const AP4_UI08 * buffer,AP4_Size * buffer_size,AP4_Flags flags)161 AP4_Ac3Parser::Feed(const AP4_UI08* buffer,
162                      AP4_Size*       buffer_size,
163                      AP4_Flags       flags)
164 {
165     AP4_Size free_space;
166 
167     /* update flags */
168     m_Bits.m_Flags = flags;
169 
170     /* possible shortcut */
171     if (buffer == NULL ||
172         buffer_size == NULL ||
173         *buffer_size == 0) {
174         return AP4_SUCCESS;
175     }
176 
177     /* see how much data we can write */
178     free_space = m_Bits.GetBytesFree();
179     if (*buffer_size > free_space) *buffer_size = free_space;
180     if (*buffer_size == 0) return AP4_SUCCESS;
181 
182     /* write the data */
183     return m_Bits.WriteBytes(buffer, *buffer_size);
184 }
185 
186 /*----------------------------------------------------------------------+
187  |    AP4_Ac3Parser::FindHeader
188  +----------------------------------------------------------------------*/
189 AP4_Result
FindHeader(AP4_UI08 * header)190 AP4_Ac3Parser::FindHeader(AP4_UI08* header)
191 {
192     AP4_Size available = m_Bits.GetBytesAvailable();
193 
194     /* look for the sync pattern */
195     while (available-- >= AP4_AC3_HEADER_SIZE) {
196         m_Bits.PeekBytes(header, 2);  // ac3 header begins with 0x0B77
197 
198         if( (((header[0] << 8) | header[1]) == AP4_AC3_SYNC_WORD_BIG_ENDIAN) ||
199            (((header[0] << 8) | header[1]) == AP4_AC3_SYNC_WORD_LITTLE_ENDIAN) ){
200             // Little Endian
201             if (((header[0] << 8) | header[1]) == AP4_AC3_SYNC_WORD_LITTLE_ENDIAN) {
202                 m_LittleEndian = true;
203             } else {
204                 m_LittleEndian = false;
205             }
206             /* found a sync pattern, read the entire the header */
207             m_Bits.PeekBytes(header, AP4_AC3_HEADER_SIZE);
208 
209             return AP4_SUCCESS;
210         } else {
211             m_Bits.ReadByte(); // skip
212         }
213     }
214 
215     return AP4_ERROR_NOT_ENOUGH_DATA;
216 }
217 
218 /*----------------------------------------------------------------------+
219  |    AP4_Ac3Parser::FindFrame
220  +----------------------------------------------------------------------*/
221 AP4_Result
FindFrame(AP4_Ac3Frame & frame)222 AP4_Ac3Parser::FindFrame(AP4_Ac3Frame& frame)
223 {
224     unsigned int   available;
225     unsigned char  raw_header[AP4_AC3_HEADER_SIZE];
226     AP4_Result     result;
227 
228     /* align to the start of the next byte */
229     m_Bits.ByteAlign();
230 
231     /* find a frame header */
232     result = FindHeader(raw_header);
233     if (AP4_FAILED(result)) return result;
234 
235     if (m_LittleEndian) {
236         AP4_ByteSwap16(raw_header, AP4_AC3_HEADER_SIZE);
237     }
238 
239     /* parse the header */
240     AP4_Ac3Header ac3_header(raw_header);
241 
242     /* check the header */
243     result = ac3_header.Check();
244     if (AP4_FAILED(result)) {
245         m_Bits.SkipBytes(2);
246         goto fail;
247     }
248 
249     /* check if we have enough data to peek at the next header */
250     available = m_Bits.GetBytesAvailable();
251     if (available >= ac3_header.m_FrameSize + AP4_AC3_HEADER_SIZE) {
252         // enough to peek at the header of the next frame
253         unsigned char peek_raw_header[AP4_AC3_HEADER_SIZE];
254 
255         m_Bits.SkipBytes(ac3_header.m_FrameSize);
256         m_Bits.PeekBytes(peek_raw_header, AP4_AC3_HEADER_SIZE);
257         m_Bits.SkipBytes(-((int)ac3_header.m_FrameSize));
258 
259         if (m_LittleEndian) {
260             AP4_ByteSwap16(peek_raw_header, AP4_AC3_HEADER_SIZE);
261         }
262         /* check the header */
263         AP4_Ac3Header peek_ac3_header(peek_raw_header);
264         result = peek_ac3_header.Check();
265         if (AP4_FAILED(result)) {
266             m_Bits.SkipBytes(ac3_header.m_FrameSize + 2);
267             goto fail;
268         }
269 
270         /* check that the fixed part of this header is the same as the */
271         /* fixed part of the previous header                           */
272         else if (!AP4_Ac3Header::MatchFixed(ac3_header, peek_ac3_header)) {
273             m_Bits.SkipBytes(ac3_header.m_FrameSize + 2);
274             goto fail;
275         }
276     } else if (available < ac3_header.m_FrameSize || (m_Bits.m_Flags & AP4_BITSTREAM_FLAG_EOS) == 0) {
277         // not enough for a frame, or not at the end (in which case we'll want to peek at the next header)
278         return AP4_ERROR_NOT_ENOUGH_DATA;
279     }
280     frame.m_Info.m_ChannelCount                 = ac3_header.m_ChannelCount;
281     frame.m_Info.m_SampleRate                   = FSCOD_AC3[ac3_header.m_Fscod];
282     frame.m_Info.m_FrameSize                    = ac3_header.m_FrameSize;
283     frame.m_Info.m_Ac3StreamInfo.fscod          = ac3_header.m_Fscod;
284     frame.m_Info.m_Ac3StreamInfo.bsid           = ac3_header.m_Bsid;
285     frame.m_Info.m_Ac3StreamInfo.bsmod          = ac3_header.m_Bsmod;
286     frame.m_Info.m_Ac3StreamInfo.acmod          = ac3_header.m_Acmod;
287     frame.m_Info.m_Ac3StreamInfo.lfeon          = ac3_header.m_Lfeon;
288     frame.m_Info.m_Ac3StreamInfo.bit_rate_code  = ac3_header.m_Frmsizecod / 2;
289 
290     frame.m_LittleEndian = m_LittleEndian;
291 
292     /* set the frame source */
293     frame.m_Source = &m_Bits;
294 
295     return AP4_SUCCESS;
296 
297 fail:
298     /* skip the header and return (only skip the first byte in  */
299     /* case this was a false header that hides one just after)  */
300     //m_Bits.SkipBytes(-(AP4_ADTS_HEADER_SIZE-1));
301     return AP4_ERROR_CORRUPTED_BITSTREAM;
302 }
303 
304 /*----------------------------------------------------------------------+
305  |    AP4_Ac3Parser::GetBytesFree
306  +----------------------------------------------------------------------*/
307 AP4_Size
GetBytesFree()308 AP4_Ac3Parser::GetBytesFree()
309 {
310     return (m_Bits.GetBytesFree());
311 }
312 
313 /*----------------------------------------------------------------------+
314  |    AP4_Ac3Parser::GetBytesAvailable
315  +----------------------------------------------------------------------*/
316 AP4_Size
GetBytesAvailable()317 AP4_Ac3Parser::GetBytesAvailable()
318 {
319     return (m_Bits.GetBytesAvailable());
320 }
321