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