1 /*****************************************************************
2 |
3 | AP4 - AC4 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 "Ap4Ac4Parser.h"
34
35 bool AP4_Ac4Header::m_DeprecatedV0 = true;
36 /*----------------------------------------------------------------------+
37 | AP4_Ac4Header::AP4_Ac4Header
38 +----------------------------------------------------------------------*/
AP4_Ac4Header(const AP4_UI08 * bytes,unsigned int size)39 AP4_Ac4Header::AP4_Ac4Header(const AP4_UI08* bytes, unsigned int size)
40 {
41 /* Read the entire the frame */
42 AP4_BitReader bits(bytes, size);
43
44 m_SyncWord = bits.ReadBits(16);
45 m_HeaderSize = 2;
46 if (m_SyncWord == AP4_AC4_SYNC_WORD_CRC){
47 m_CrcSize = 2;
48 }else {
49 m_CrcSize = 0;
50 }
51 m_FrameSize = bits.ReadBits(16);
52 m_HeaderSize += 2;
53 if (m_FrameSize == 0xFFFF){
54 m_FrameSize = bits.ReadBits(24);
55 m_HeaderSize += 3;
56 }
57
58 /* Begin to parse TOC */
59 m_BitstreamVersion = bits.ReadBits(2);
60 if (m_BitstreamVersion == 3) {
61 m_BitstreamVersion = AP4_Ac4VariableBits(bits, 2);
62 }
63 m_SequenceCounter = bits.ReadBits(10);
64 m_BWaitFrames = bits.ReadBit();
65 if (m_BWaitFrames) {
66 m_WaitFrames = bits.ReadBits(3);
67 if (m_WaitFrames > 0){ m_BrCode = bits.ReadBits(2);}
68 }else {
69 m_WaitFrames = -1;
70 }
71
72 m_FsIndex = bits.ReadBit();
73 m_FrameRateIndex = bits.ReadBits(4);
74 m_BIframeGlobal = bits.ReadBit();
75 m_BSinglePresentation = bits.ReadBit();
76 if (m_BSinglePresentation == 1){
77 m_NPresentations = 1;
78 m_BMorePresentations = 0;
79 }else{
80 m_BMorePresentations = bits.ReadBit();
81 if (m_BMorePresentations == 1){
82 m_NPresentations = AP4_Ac4VariableBits(bits, 2) + 2;
83 }else{
84 m_NPresentations = 0;
85 }
86 }
87 m_PayloadBase = 0;
88 m_BPayloadBase = bits.ReadBit();
89 if (m_BPayloadBase == 1){
90 m_PayloadBase = bits.ReadBits(5) + 1;
91 if (m_PayloadBase == 0x20){
92 m_PayloadBase += AP4_Ac4VariableBits(bits, 3);
93 }
94 }
95 if (m_BitstreamVersion <= 1){
96 if (m_DeprecatedV0){
97 m_DeprecatedV0 = false;
98 printf("Warning: Bitstream version 0 is deprecated\n");
99 }
100 }else{
101 m_BProgramId = bits.ReadBit();
102 if (m_BProgramId == 1){
103 m_ShortProgramId = bits.ReadBits(16);
104 m_BProgramUuidPresent = bits.ReadBit();
105 if (m_BProgramUuidPresent == 1){
106 for (int cnt = 0; cnt < 16; cnt++){
107 m_ProgramUuid[cnt] = bits.ReadBits(8);
108 }
109 }else {
110 memcpy(m_ProgramUuid,"ONDEL TEAM UUID\0", 16);
111 }
112 }else {
113 m_ShortProgramId = 0;
114 m_BProgramUuidPresent = 0;
115 memcpy(m_ProgramUuid, "ONDEL TEAM UUID\0", 16);
116 }
117 unsigned int maxGroupIndex = 0;
118 unsigned int *firstPresentationSubstreamGroupIndexes = NULL;
119 unsigned int firstPresentationNSubstreamGroups = 0;
120
121 if (m_NPresentations > 0){
122 m_PresentationV1= new AP4_Dac4Atom::Ac4Dsi::PresentationV1[m_NPresentations];
123 AP4_SetMemory(m_PresentationV1, 0, m_NPresentations * sizeof(m_PresentationV1[0]));
124 } else {
125 m_PresentationV1 = NULL;
126 }
127 // ac4_presentation_v1_info()
128 for (unsigned int pres_idx = 0; pres_idx < m_NPresentations; pres_idx++){
129 AP4_Dac4Atom::Ac4Dsi::PresentationV1& presentation = m_PresentationV1[pres_idx];
130 presentation.ParsePresentationV1Info(bits,
131 m_BitstreamVersion,
132 m_FrameRateIndex,
133 pres_idx,
134 maxGroupIndex,
135 &firstPresentationSubstreamGroupIndexes,
136 firstPresentationNSubstreamGroups);
137 }
138 unsigned int bObjorAjoc = 0;
139 unsigned int channelCount = 0;
140 unsigned int speakerGroupIndexMask = 0;
141 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1 *substream_groups = new AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1[maxGroupIndex + 1];
142 AP4_SetMemory(substream_groups, 0, (maxGroupIndex + 1) * sizeof(substream_groups[0]));
143 for (unsigned int sg = 0 ; (sg < (maxGroupIndex + 1)) && (m_NPresentations > 0); sg ++) {
144 AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1 &substream_group = substream_groups[sg];
145 AP4_Result pres_index = GetPresentationIndexBySGIndex(sg);
146 if (pres_index == AP4_FAILURE) {
147 break;
148 }
149 unsigned int localChannelCount = 0;
150 unsigned int frame_rate_factor = (m_PresentationV1[pres_index].d.v1.dsi_frame_rate_multiply_info == 0)? 1: (m_PresentationV1[pres_index].d.v1.dsi_frame_rate_multiply_info * 2);
151 substream_group.ParseSubstreamGroupInfo(bits,
152 m_BitstreamVersion,
153 GetPresentationVersionBySGIndex(sg),
154 Ap4_Ac4SubstreamGroupPartOfDefaultPresentation(sg, firstPresentationSubstreamGroupIndexes, firstPresentationNSubstreamGroups),
155 frame_rate_factor,
156 m_FsIndex,
157 localChannelCount,
158 speakerGroupIndexMask,
159 bObjorAjoc);
160 if (channelCount < localChannelCount) { channelCount = localChannelCount;}
161 }
162
163 for (unsigned int pres_idx = 0; pres_idx < m_NPresentations; pres_idx++){
164 m_PresentationV1[pres_idx].d.v1.substream_groups = new AP4_Dac4Atom::Ac4Dsi::SubStreamGroupV1[m_PresentationV1[pres_idx].d.v1.n_substream_groups];
165 for (unsigned int sg = 0; sg < m_PresentationV1[pres_idx].d.v1.n_substream_groups; sg++){
166 // TODO: Default Copy Construct Function
167 m_PresentationV1[pres_idx].d.v1.substream_groups[sg] = substream_groups[m_PresentationV1[pres_idx].d.v1.substream_group_indexs[sg]];
168 m_PresentationV1[pres_idx].d.v1.dolby_atmos_indicator |= m_PresentationV1[pres_idx].d.v1.substream_groups[sg].d.v1.dolby_atmos_indicator;
169 }
170 }
171 delete[] substream_groups;
172
173 if (bObjorAjoc == 0){
174 m_ChannelCount = AP4_Ac4ChannelCountFromSpeakerGroupIndexMask(speakerGroupIndexMask);
175 }else {
176 m_ChannelCount = channelCount;
177 }
178 }
179 }
180
181 /*----------------------------------------------------------------------+
182 | AP4_Ac4Header::MatchFixed
183 |
184 | Check that two fixed headers are the same
185 |
186 +----------------------------------------------------------------------*/
187 bool
MatchFixed(AP4_Ac4Header & frame,AP4_Ac4Header & next_frame)188 AP4_Ac4Header::MatchFixed(AP4_Ac4Header& frame, AP4_Ac4Header& next_frame)
189 {
190 // Some parameter shall be const which defined in AC-4 in ISO-BMFF specs
191 // TODO: More constraints will be added
192 if ((frame.m_FsIndex == next_frame.m_FsIndex) &&
193 (frame.m_FrameRateIndex == next_frame.m_FrameRateIndex)){
194 return true;
195 }else {
196 return false;
197 }
198
199 }
200
201 /*----------------------------------------------------------------------+
202 | AP4_Ac4Header::Check
203 +----------------------------------------------------------------------*/
204 AP4_Result
Check()205 AP4_Ac4Header::Check()
206 {
207 // Bitstream version
208 if (m_BitstreamVersion != 2) {
209 return AP4_FAILURE;
210 }
211 if ((m_FsIndex == 0 && m_FrameRateIndex != 13) || (m_FsIndex == 1 && m_FrameRateIndex >13)){
212 return AP4_FAILURE;
213 }
214
215 return AP4_SUCCESS;
216 }
217
218 /*----------------------------------------------------------------------+
219 | AP4_Ac4Header::GetPresentationVersionBySGIndex
220 +----------------------------------------------------------------------*/
221 AP4_Result
GetPresentationVersionBySGIndex(unsigned int substream_group_index)222 AP4_Ac4Header::GetPresentationVersionBySGIndex(unsigned int substream_group_index)
223 {
224 for (unsigned int idx = 0; idx < m_NPresentations; idx++){
225 for (unsigned int sg = 0; sg < m_PresentationV1[idx].d.v1.n_substream_groups; sg++){
226 if (substream_group_index == m_PresentationV1[idx].d.v1.substream_group_indexs[sg]) {
227 return m_PresentationV1[idx].presentation_version;
228 }
229 }
230 }
231 return AP4_FAILURE;
232 }
233
234 /*----------------------------------------------------------------------+
235 | AP4_Ac4Header::GetPresentationIndexBySGIndex
236 +----------------------------------------------------------------------*/
237 AP4_Result
GetPresentationIndexBySGIndex(unsigned int substream_group_index)238 AP4_Ac4Header::GetPresentationIndexBySGIndex(unsigned int substream_group_index)
239 {
240 for (unsigned int idx = 0; idx < m_NPresentations; idx++){
241 for (unsigned int sg = 0; sg < m_PresentationV1[idx].d.v1.n_substream_groups; sg++){
242 if (substream_group_index == m_PresentationV1[idx].d.v1.substream_group_indexs[sg]) {
243 return idx;
244 }
245 }
246 }
247 return AP4_FAILURE;
248 }
249
250 /*----------------------------------------------------------------------+
251 | AP4_Ac4Parser::AP4_Ac4Parser
252 +----------------------------------------------------------------------*/
AP4_Ac4Parser()253 AP4_Ac4Parser::AP4_Ac4Parser() :
254 m_FrameCount(0)
255 {
256 }
257
258 /*----------------------------------------------------------------------+
259 | AP4_Ac4Parser::~AP4_Ac4Parser
260 +----------------------------------------------------------------------*/
~AP4_Ac4Parser()261 AP4_Ac4Parser::~AP4_Ac4Parser()
262 {
263 }
264
265 /*----------------------------------------------------------------------+
266 | AP4_Ac4Parser::Reset
267 +----------------------------------------------------------------------*/
268 AP4_Result
Reset()269 AP4_Ac4Parser::Reset()
270 {
271 m_FrameCount = 0;
272
273 return AP4_SUCCESS;
274 }
275
276 /*----------------------------------------------------------------------+
277 | AP4_Ac4Parser::Feed
278 +----------------------------------------------------------------------*/
279 AP4_Result
Feed(const AP4_UI08 * buffer,AP4_Size * buffer_size,AP4_Flags flags)280 AP4_Ac4Parser::Feed(const AP4_UI08* buffer,
281 AP4_Size* buffer_size,
282 AP4_Flags flags)
283 {
284 AP4_Size free_space;
285
286 /* update flags */
287 m_Bits.m_Flags = flags;
288
289 /* possible shortcut */
290 if (buffer == NULL ||
291 buffer_size == NULL ||
292 *buffer_size == 0) {
293 return AP4_SUCCESS;
294 }
295
296 /* see how much data we can write */
297 free_space = m_Bits.GetBytesFree();
298 if (*buffer_size > free_space) *buffer_size = free_space;
299 if (*buffer_size == 0) return AP4_SUCCESS;
300
301 /* write the data */
302 return m_Bits.WriteBytes(buffer, *buffer_size);
303 }
304
305 /*----------------------------------------------------------------------+
306 | AP4_Ac4Parser::FindHeader
307 +----------------------------------------------------------------------*/
308 AP4_Result
FindHeader(AP4_UI08 * header)309 AP4_Ac4Parser::FindHeader(AP4_UI08* header)
310 {
311 AP4_Size available = m_Bits.GetBytesAvailable();
312
313 /* look for the sync pattern */
314 while (available-- >= AP4_AC4_HEADER_SIZE) {
315 m_Bits.PeekBytes(header, 2);
316
317 if ((((header[0] << 8) | header[1]) == AP4_AC4_SYNC_WORD_CRC) || (((header[0] << 8) | header[1]) == AP4_AC4_SYNC_WORD)) {
318 /* found a sync pattern, read the entire the header */
319 m_Bits.PeekBytes(header, AP4_AC4_HEADER_SIZE);
320
321 return AP4_SUCCESS;
322 } else {
323 m_Bits.SkipBytes(1);
324 }
325 }
326
327 return AP4_ERROR_NOT_ENOUGH_DATA;
328 }
329 /*----------------------------------------------------------------------+
330 | AP4_Ac4Parser::GetSyncFrameSize
331 +----------------------------------------------------------------------*/
332 AP4_UI32
GetSyncFrameSize(AP4_BitReader & bits)333 AP4_Ac4Parser::GetSyncFrameSize(AP4_BitReader &bits)
334 {
335 unsigned int sync_word = bits.ReadBits(16);
336 unsigned int frame_size = bits.ReadBits(16);
337 unsigned int head_size = 4;
338 if (frame_size == 0xFFFF){
339 frame_size = bits.ReadBits(24);
340 head_size += 3;
341 }
342 if (sync_word == AP4_AC4_SYNC_WORD_CRC) {
343 head_size += 2;
344 }
345 return (head_size + frame_size);
346 }
347
348 /*----------------------------------------------------------------------+
349 | AP4_Ac4Parser::FindFrame
350 +----------------------------------------------------------------------*/
351 AP4_Result
FindFrame(AP4_Ac4Frame & frame)352 AP4_Ac4Parser::FindFrame(AP4_Ac4Frame& frame)
353 {
354 unsigned int available;
355 unsigned char *raw_header = new unsigned char[AP4_AC4_HEADER_SIZE];
356 AP4_Result result;
357
358 /* align to the start of the next byte */
359 m_Bits.ByteAlign();
360
361 /* find a frame header */
362 result = FindHeader(raw_header);
363 if (AP4_FAILED(result)) return result;
364
365 // duplicated work, just to get the frame size
366 AP4_BitReader tmp_bits(raw_header, AP4_AC4_HEADER_SIZE);
367 unsigned int sync_frame_size = GetSyncFrameSize(tmp_bits);
368 if (sync_frame_size > (AP4_BITSTREAM_BUFFER_SIZE - 1)) {
369 return AP4_ERROR_NOT_ENOUGH_DATA;
370 }
371
372 delete[] raw_header;
373 raw_header = new unsigned char[sync_frame_size];
374 /*
375 * Error handling to skip the 'fake' sync word.
376 * - the maximum sync frame size is about (AP4_BITSTREAM_BUFFER_SIZE - 1) bytes.
377 */
378 if (m_Bits.GetBytesAvailable() < sync_frame_size ) {
379 if (m_Bits.GetBytesAvailable() == (AP4_BITSTREAM_BUFFER_SIZE - 1)) {
380 // skip the sync word, assume it's 'fake' sync word
381 m_Bits.SkipBytes(2);
382 }
383 return AP4_ERROR_NOT_ENOUGH_DATA;
384 }
385 // copy the whole frame becasue toc size is unknown
386 m_Bits.PeekBytes(raw_header, sync_frame_size);
387 /* parse the header */
388 AP4_Ac4Header ac4_header(raw_header, sync_frame_size);
389
390 // Place before goto statement to resolve Xcode compiler issue
391 unsigned int bit_rate_mode = 0;
392
393 /* check the header */
394 result = ac4_header.Check();
395 if (AP4_FAILED(result)) {
396 m_Bits.SkipBytes(sync_frame_size);
397 goto fail;
398 }
399
400 /* check if we have enough data to peek at the next header */
401 available = m_Bits.GetBytesAvailable();
402 // TODO: find the proper AP4_AC4_MAX_TOC_SIZE or just parse what this step need ?
403 if (available >= ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize + AP4_AC4_HEADER_SIZE + AP4_AC4_MAX_TOC_SIZE) {
404 // enough to peek at the header of the next frame
405 unsigned char *peek_raw_header = new unsigned char[AP4_AC4_HEADER_SIZE];
406
407 m_Bits.SkipBytes(ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize);
408 m_Bits.PeekBytes(peek_raw_header, AP4_AC4_HEADER_SIZE);
409
410 // duplicated work, just to get the frame size
411 AP4_BitReader peak_tmp_bits(peek_raw_header, AP4_AC4_HEADER_SIZE);
412 unsigned int peak_sync_frame_size = GetSyncFrameSize(peak_tmp_bits);
413
414 delete[] peek_raw_header;
415 peek_raw_header = new unsigned char[peak_sync_frame_size];
416 // copy the whole frame becasue toc size is unknown
417 if (m_Bits.GetBytesAvailable() < (peak_sync_frame_size)) {
418 peak_sync_frame_size = m_Bits.GetBytesAvailable();
419 }
420 m_Bits.PeekBytes(peek_raw_header, peak_sync_frame_size);
421
422 m_Bits.SkipBytes(-((int)(ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize)));
423
424 /* check the header */
425 AP4_Ac4Header peek_ac4_header(peek_raw_header, peak_sync_frame_size);
426 result = peek_ac4_header.Check();
427 if (AP4_FAILED(result)) {
428 // TODO: need to reserve current sync frame ?
429 m_Bits.SkipBytes(sync_frame_size + peak_sync_frame_size);
430 goto fail;
431 }
432
433 /* check that the fixed part of this header is the same as the */
434 /* fixed part of the previous header */
435 if (!AP4_Ac4Header::MatchFixed(ac4_header, peek_ac4_header)) {
436 // TODO: need to reserve current sync frame ?
437 m_Bits.SkipBytes(sync_frame_size + peak_sync_frame_size);
438 goto fail;
439 }
440 } else if (available < (ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize) || (m_Bits.m_Flags & AP4_BITSTREAM_FLAG_EOS) == 0) {
441 // not enough for a frame, or not at the end (in which case we'll want to peek at the next header)
442 return AP4_ERROR_NOT_ENOUGH_DATA;
443 }
444
445 m_Bits.SkipBytes(ac4_header.m_HeaderSize);
446
447 /* fill in the frame info */
448 frame.m_Info.m_HeaderSize = ac4_header.m_HeaderSize;
449 frame.m_Info.m_FrameSize = ac4_header.m_FrameSize;
450 frame.m_Info.m_CRCSize = ac4_header.m_CrcSize;
451 frame.m_Info.m_ChannelCount = ac4_header.m_ChannelCount;
452 frame.m_Info.m_SampleDuration = (ac4_header.m_FsIndex == 0)? 2048 : AP4_Ac4SampleDeltaTable [ac4_header.m_FrameRateIndex];
453 frame.m_Info.m_MediaTimeScale = (ac4_header.m_FsIndex == 0)? 44100: AP4_Ac4MediaTimeScaleTable[ac4_header.m_FrameRateIndex];
454 frame.m_Info.m_Iframe = ac4_header.m_BIframeGlobal;
455
456 /* fill the AC4 DSI info */
457 frame.m_Info.m_Ac4Dsi.ac4_dsi_version = 1;
458 frame.m_Info.m_Ac4Dsi.d.v1.bitstream_version = ac4_header.m_BitstreamVersion;
459 frame.m_Info.m_Ac4Dsi.d.v1.fs_index = ac4_header.m_FsIndex;
460 frame.m_Info.m_Ac4Dsi.d.v1.fs = AP4_Ac4SamplingFrequencyTable[frame.m_Info.m_Ac4Dsi.d.v1.fs_index];
461 frame.m_Info.m_Ac4Dsi.d.v1.frame_rate_index = ac4_header.m_FrameRateIndex;
462 frame.m_Info.m_Ac4Dsi.d.v1.b_program_id = ac4_header.m_BProgramId;
463 frame.m_Info.m_Ac4Dsi.d.v1.short_program_id = ac4_header.m_ShortProgramId;
464 frame.m_Info.m_Ac4Dsi.d.v1.b_uuid = ac4_header.m_BProgramUuidPresent;
465 AP4_CopyMemory(frame.m_Info.m_Ac4Dsi.d.v1.program_uuid, ac4_header.m_ProgramUuid, 16);
466
467 // Calcuate the bit rate mode according to ETSI TS 103 190-2 V1.2.1 Annex B
468 if (ac4_header.m_WaitFrames == 0) { bit_rate_mode = 1;}
469 else if (ac4_header.m_WaitFrames >= 1 && ac4_header.m_WaitFrames <= 6) { bit_rate_mode = 2;}
470 else if (ac4_header.m_WaitFrames > 6) { bit_rate_mode = 3;}
471
472 frame.m_Info.m_Ac4Dsi.d.v1.ac4_bitrate_dsi.bit_rate_mode = bit_rate_mode;
473 frame.m_Info.m_Ac4Dsi.d.v1.ac4_bitrate_dsi.bit_rate = 0; // unknown, fixed value now
474 frame.m_Info.m_Ac4Dsi.d.v1.ac4_bitrate_dsi.bit_rate_precision = 0xffffffff; // unknown, fixed value now
475 frame.m_Info.m_Ac4Dsi.d.v1.n_presentations = ac4_header.m_NPresentations;
476 frame.m_Info.m_Ac4Dsi.d.v1.presentations = ac4_header.m_PresentationV1;
477
478 /* set the frame source */
479 frame.m_Source = &m_Bits;
480
481 return AP4_SUCCESS;
482
483 fail:
484 /* skip the header and return (only skip the first byte in */
485 /* case this was a false header that hides one just after) */
486 return AP4_ERROR_CORRUPTED_BITSTREAM;
487 }
488
489 /*----------------------------------------------------------------------+
490 | AP4_Ac4Parser::GetBytesFree
491 +----------------------------------------------------------------------*/
492 AP4_Size
GetBytesFree()493 AP4_Ac4Parser::GetBytesFree()
494 {
495 return (m_Bits.GetBytesFree());
496 }
497
498 /*----------------------------------------------------------------------+
499 | AP4_Ac4Parser::GetBytesAvailable
500 +----------------------------------------------------------------------*/
501 AP4_Size
GetBytesAvailable()502 AP4_Ac4Parser::GetBytesAvailable()
503 {
504 return (m_Bits.GetBytesAvailable());
505 }
506