@@ -157,6 +157,175 @@ AP4_Result CAdaptiveAc3Parser::FindFrameHeader(AP4_Ac3Frame& frame)
157157 return AP4_SUCCESS;
158158}
159159
160+ AP4_Result CAdaptiveAc4Parser::FindFrameHeader (AP4_Ac4Frame& frame)
161+ {
162+ unsigned int available;
163+ unsigned char raw_header[AP4_AC4_HEADER_SIZE];
164+ AP4_Result result;
165+
166+ /* align to the start of the next byte */
167+ m_Bits.ByteAlign ();
168+
169+ /* find a frame header */
170+ result = FindHeader (raw_header);
171+ if (AP4_FAILED (result))
172+ return result;
173+
174+ // duplicated work, just to get the frame size
175+ AP4_BitReader tmp_bits (raw_header, AP4_AC4_HEADER_SIZE);
176+ unsigned int sync_frame_size = GetSyncFrameSize (tmp_bits);
177+ if (sync_frame_size > (AP4_BITSTREAM_BUFFER_SIZE - 1 ))
178+ {
179+ return AP4_ERROR_NOT_ENOUGH_DATA;
180+ }
181+
182+ /*
183+ * Error handling to skip the 'fake' sync word.
184+ * - the maximum sync frame size is about (AP4_BITSTREAM_BUFFER_SIZE - 1) bytes.
185+ */
186+ if (m_Bits.GetBytesAvailable () < sync_frame_size)
187+ {
188+ if (m_Bits.GetBytesAvailable () == (AP4_BITSTREAM_BUFFER_SIZE - 1 ))
189+ {
190+ // skip the sync word, assume it's 'fake' sync word
191+ m_Bits.SkipBytes (2 );
192+ }
193+ return AP4_ERROR_NOT_ENOUGH_DATA;
194+ }
195+
196+ unsigned char * rawframe = new unsigned char [sync_frame_size];
197+
198+ // copy the whole frame becasue toc size is unknown
199+ m_Bits.PeekBytes (rawframe, sync_frame_size);
200+ /* parse the header */
201+ AP4_Ac4Header ac4_header (rawframe, sync_frame_size);
202+
203+ delete[] rawframe;
204+
205+ // Place before goto statement to resolve Xcode compiler issue
206+ unsigned int bit_rate_mode = 0 ;
207+
208+ /* check the header */
209+ result = ac4_header.Check ();
210+ if (AP4_FAILED (result))
211+ {
212+ m_Bits.SkipBytes (sync_frame_size);
213+ goto fail;
214+ }
215+
216+ /* check if we have enough data to peek at the next header */
217+ available = m_Bits.GetBytesAvailable ();
218+ // TODO: find the proper AP4_AC4_MAX_TOC_SIZE or just parse what this step need ?
219+ if (available >= ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize +
220+ AP4_AC4_HEADER_SIZE + AP4_AC4_MAX_TOC_SIZE)
221+ {
222+ // enough to peek at the header of the next frame
223+
224+ m_Bits.SkipBytes (ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize );
225+ m_Bits.PeekBytes (raw_header, AP4_AC4_HEADER_SIZE);
226+
227+ // duplicated work, just to get the frame size
228+ AP4_BitReader peak_tmp_bits (raw_header, AP4_AC4_HEADER_SIZE);
229+ unsigned int next_sync_frame_size = GetSyncFrameSize (peak_tmp_bits);
230+
231+ unsigned char * next_rawframe = new unsigned char [next_sync_frame_size];
232+
233+ // copy the whole frame becasue toc size is unknown
234+ if (m_Bits.GetBytesAvailable () < (next_sync_frame_size))
235+ {
236+ next_sync_frame_size = m_Bits.GetBytesAvailable ();
237+ }
238+ m_Bits.PeekBytes (next_rawframe, next_sync_frame_size);
239+
240+ m_Bits.SkipBytes (
241+ -((int )(ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize )));
242+
243+ /* check the header */
244+ AP4_Ac4Header peek_ac4_header (next_rawframe, next_sync_frame_size);
245+
246+ delete[] next_rawframe;
247+
248+ result = peek_ac4_header.Check ();
249+ if (AP4_FAILED (result))
250+ {
251+ // TODO: need to reserve current sync frame ?
252+ m_Bits.SkipBytes (sync_frame_size + next_sync_frame_size);
253+ goto fail;
254+ }
255+
256+ /* check that the fixed part of this header is the same as the */
257+ /* fixed part of the previous header */
258+ if (!AP4_Ac4Header::MatchFixed (ac4_header, peek_ac4_header))
259+ {
260+ // TODO: need to reserve current sync frame ?
261+ m_Bits.SkipBytes (sync_frame_size + next_sync_frame_size);
262+ goto fail;
263+ }
264+ }
265+ else if (available < (ac4_header.m_FrameSize + ac4_header.m_HeaderSize + ac4_header.m_CrcSize ) ||
266+ (m_Bits.m_Flags & AP4_BITSTREAM_FLAG_EOS) == 0 )
267+ {
268+ // not enough for a frame, or not at the end (in which case we'll want to peek at the next header)
269+ return AP4_ERROR_NOT_ENOUGH_DATA;
270+ }
271+
272+ m_Bits.SkipBytes (ac4_header.m_HeaderSize );
273+
274+ /* fill in the frame info */
275+ frame.m_Info .m_HeaderSize = ac4_header.m_HeaderSize ;
276+ frame.m_Info .m_FrameSize = ac4_header.m_FrameSize ;
277+ frame.m_Info .m_CRCSize = ac4_header.m_CrcSize ;
278+ frame.m_Info .m_ChannelCount = ac4_header.m_ChannelCount ;
279+ frame.m_Info .m_SampleDuration =
280+ (ac4_header.m_FsIndex == 0 ) ? 2048 : AP4_Ac4SampleDeltaTable[ac4_header.m_FrameRateIndex ];
281+ frame.m_Info .m_MediaTimeScale =
282+ (ac4_header.m_FsIndex == 0 ) ? 44100 : AP4_Ac4MediaTimeScaleTable[ac4_header.m_FrameRateIndex ];
283+ frame.m_Info .m_Iframe = ac4_header.m_BIframeGlobal ;
284+
285+ /* fill the AC4 DSI info */
286+ frame.m_Info .m_Ac4Dsi .ac4_dsi_version = 1 ;
287+ frame.m_Info .m_Ac4Dsi .d .v1 .bitstream_version = ac4_header.m_BitstreamVersion ;
288+ frame.m_Info .m_Ac4Dsi .d .v1 .fs_index = ac4_header.m_FsIndex ;
289+ frame.m_Info .m_Ac4Dsi .d .v1 .fs =
290+ AP4_Ac4SamplingFrequencyTable[frame.m_Info .m_Ac4Dsi .d .v1 .fs_index ];
291+ frame.m_Info .m_Ac4Dsi .d .v1 .frame_rate_index = ac4_header.m_FrameRateIndex ;
292+ frame.m_Info .m_Ac4Dsi .d .v1 .b_program_id = ac4_header.m_BProgramId ;
293+ frame.m_Info .m_Ac4Dsi .d .v1 .short_program_id = ac4_header.m_ShortProgramId ;
294+ frame.m_Info .m_Ac4Dsi .d .v1 .b_uuid = ac4_header.m_BProgramUuidPresent ;
295+ AP4_CopyMemory (frame.m_Info .m_Ac4Dsi .d .v1 .program_uuid , ac4_header.m_ProgramUuid , 16 );
296+
297+ // Calcuate the bit rate mode according to ETSI TS 103 190-2 V1.2.1 Annex B
298+ if (ac4_header.m_WaitFrames == 0 )
299+ {
300+ bit_rate_mode = 1 ;
301+ }
302+ else if (ac4_header.m_WaitFrames >= 1 && ac4_header.m_WaitFrames <= 6 )
303+ {
304+ bit_rate_mode = 2 ;
305+ }
306+ else if (ac4_header.m_WaitFrames > 6 )
307+ {
308+ bit_rate_mode = 3 ;
309+ }
310+
311+ frame.m_Info .m_Ac4Dsi .d .v1 .ac4_bitrate_dsi .bit_rate_mode = bit_rate_mode;
312+ frame.m_Info .m_Ac4Dsi .d .v1 .ac4_bitrate_dsi .bit_rate = 0 ; // unknown, fixed value now
313+ frame.m_Info .m_Ac4Dsi .d .v1 .ac4_bitrate_dsi .bit_rate_precision =
314+ 0xffffffff ; // unknown, fixed value now
315+ frame.m_Info .m_Ac4Dsi .d .v1 .n_presentations = ac4_header.m_NPresentations ;
316+ frame.m_Info .m_Ac4Dsi .d .v1 .presentations = ac4_header.m_PresentationV1 ;
317+
318+ /* set the frame source */
319+ frame.m_Source = &m_Bits;
320+
321+ return AP4_SUCCESS;
322+
323+ fail:
324+ /* skip the header and return (only skip the first byte in */
325+ /* case this was a false header that hides one just after) */
326+ return AP4_ERROR_CORRUPTED_BITSTREAM;
327+ }
328+
160329AP4_Result CAdaptiveEac3Parser::FindFrameHeader (AP4_Eac3Frame& frame)
161330{
162331 bool dependent_stream_exist = false ;
0 commit comments