@@ -157,6 +157,175 @@ AP4_Result CAdaptiveAc3Parser::FindFrameHeader(AP4_Ac3Frame& frame)
157
157
return AP4_SUCCESS;
158
158
}
159
159
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
+
160
329
AP4_Result CAdaptiveEac3Parser::FindFrameHeader (AP4_Eac3Frame& frame)
161
330
{
162
331
bool dependent_stream_exist = false ;
0 commit comments