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