1 /*****************************************************************************
2 * adts_imp.c
3 *****************************************************************************
4 * Copyright (C) 2010-2017 L-SMASH project
5 *
6 * Authors: Takashi Hirata <silverfilain@gmail.com>
7 * Contributors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *****************************************************************************/
21
22 /* This file is available under an ISC license. */
23
24 #include "common/internal.h" /* must be placed first */
25
26 #define LSMASH_IMPORTER_INTERNAL
27 #include "importer.h"
28
29 /***************************************************************************
30 ADTS importer
31 ***************************************************************************/
32 #include "codecs/mp4a.h"
33
34 #define MP4SYS_ADTS_FIXED_HEADER_LENGTH 4 /* this is partly a lie. actually 28 bits. */
35 #define MP4SYS_ADTS_BASIC_HEADER_LENGTH 7
36 #define MP4SYS_ADTS_MAX_FRAME_LENGTH (( 1 << 13 ) - 1)
37 #define MP4SYS_ADTS_MAX_RAW_DATA_BLOCKS 4
38
39 typedef struct
40 {
41 uint16_t syncword; /* 12; */
42 uint8_t ID; /* 1; */
43 uint8_t layer; /* 2; */
44 uint8_t protection_absent; /* 1; */
45 uint8_t profile_ObjectType; /* 2; */
46 uint8_t sampling_frequency_index; /* 4; */
47 // uint8_t private_bit; /* 1; we don't care. */
48 uint8_t channel_configuration; /* 3; */
49 // uint8_t original_copy; /* 1; we don't care. */
50 // uint8_t home; /* 1; we don't care. */
51
52 } mp4sys_adts_fixed_header_t;
53
54 typedef struct
55 {
56 // uint8_t copyright_identification_bit; /* 1; we don't care. */
57 // uint8_t copyright_identification_start; /* 1; we don't care. */
58 uint16_t frame_length; /* 13; */
59 // uint16_t adts_buffer_fullness; /* 11; we don't care. */
60 uint8_t number_of_raw_data_blocks_in_frame; /* 2; */
61 // uint16_t adts_error_check; /* we don't support */
62 // uint16_t raw_data_block_position[MP4SYS_ADTS_MAX_RAW_DATA_BLOCKS-1]; /* we don't use this directly, and... */
63 uint16_t raw_data_block_size[MP4SYS_ADTS_MAX_RAW_DATA_BLOCKS]; /* use this instead of above. */
64 // uint16_t adts_header_error_check; /* we don't support, actually crc_check within this */
65 // uint16_t adts_raw_data_block_error_check[MP4SYS_ADTS_MAX_RAW_DATA_BLOCKS]; /* we don't support */
66 } mp4sys_adts_variable_header_t;
67
68 typedef struct
69 {
70 unsigned int raw_data_block_idx;
71 mp4sys_adts_fixed_header_t header;
72 mp4sys_adts_variable_header_t variable_header;
73 uint32_t samples_in_frame;
74 uint32_t au_number;
75 } mp4sys_adts_importer_t;
76
remove_mp4sys_adts_importer(mp4sys_adts_importer_t * adts_imp)77 static void remove_mp4sys_adts_importer
78 (
79 mp4sys_adts_importer_t *adts_imp
80 )
81 {
82 lsmash_free( adts_imp );
83 }
84
create_mp4sys_adts_importer(importer_t * importer)85 static mp4sys_adts_importer_t *create_mp4sys_adts_importer
86 (
87 importer_t *importer
88 )
89 {
90 return (mp4sys_adts_importer_t *)lsmash_malloc_zero( sizeof(mp4sys_adts_importer_t) );
91 }
92
mp4sys_adts_cleanup(importer_t * importer)93 static void mp4sys_adts_cleanup( importer_t *importer )
94 {
95 debug_if( importer && importer->info )
96 remove_mp4sys_adts_importer( importer->info );
97 }
98
mp4sys_adts_parse_fixed_header(uint8_t * buf,mp4sys_adts_fixed_header_t * header)99 static void mp4sys_adts_parse_fixed_header
100 (
101 uint8_t *buf,
102 mp4sys_adts_fixed_header_t *header
103 )
104 {
105 /* FIXME: should we rewrite these code using bitstream reader? */
106 header->syncword = (buf[0] << 4) | (buf[1] >> 4);
107 header->ID = (buf[1] >> 3) & 0x1;
108 header->layer = (buf[1] >> 1) & 0x3;
109 header->protection_absent = buf[1] & 0x1;
110 header->profile_ObjectType = buf[2] >> 6;
111 header->sampling_frequency_index = (buf[2] >> 2) & 0xF;
112 // header->private_bit = (buf[2] >> 1) & 0x1; /* we don't care currently. */
113 header->channel_configuration = ((buf[2] << 2) | (buf[3] >> 6)) & 0x07;
114 // header->original_copy = (buf[3] >> 5) & 0x1; /* we don't care currently. */
115 // header->home = (buf[3] >> 4) & 0x1; /* we don't care currently. */
116 }
117
mp4sys_adts_check_fixed_header(mp4sys_adts_fixed_header_t * header)118 static int mp4sys_adts_check_fixed_header
119 (
120 mp4sys_adts_fixed_header_t *header
121 )
122 {
123 if( header->syncword != 0xFFF ) return LSMASH_ERR_INVALID_DATA;
124 // if( header->ID != 0x0 ) return LSMASH_ERR_NAMELESS; /* we don't care. */
125 if( header->layer != 0x0 ) return LSMASH_ERR_INVALID_DATA; /* must be 0b00 for any type of AAC */
126 // if( header->protection_absent != 0x1 ) return LSMASH_ERR_NAMELESS; /* we don't care. */
127 if( header->profile_ObjectType != 0x1 ) return LSMASH_ERR_PATCH_WELCOME; /* FIXME: 0b00=Main, 0b01=LC, 0b10=SSR, 0b11=LTP. */
128 if( header->sampling_frequency_index > 0xB ) return LSMASH_ERR_INVALID_DATA; /* must not be > 0xB. */
129 if( header->channel_configuration == 0x0 ) return LSMASH_ERR_PATCH_WELCOME; /* FIXME: we do not support 0b000 currently. */
130 if( header->profile_ObjectType == 0x3 && header->ID != 0x0 ) return LSMASH_ERR_INVALID_DATA; /* LTP is valid only if ID==0. */
131 return 0;
132 }
133
mp4sys_adts_parse_variable_header(lsmash_bs_t * bs,uint8_t * buf,unsigned int protection_absent,mp4sys_adts_variable_header_t * header)134 static int mp4sys_adts_parse_variable_header
135 (
136 lsmash_bs_t *bs,
137 uint8_t *buf,
138 unsigned int protection_absent,
139 mp4sys_adts_variable_header_t *header
140 )
141 {
142 /* FIXME: should we rewrite these code using bitstream reader? */
143 // header->copyright_identification_bit = (buf[3] >> 3) & 0x1; /* we don't care. */
144 // header->copyright_identification_start = (buf[3] >> 2) & 0x1; /* we don't care. */
145 header->frame_length = ((buf[3] << 11) | (buf[4] << 3) | (buf[5] >> 5)) & 0x1FFF ;
146 // header->adts_buffer_fullness = ((buf[5] << 6) | (buf[6] >> 2)) 0x7FF ; /* we don't care. */
147 header->number_of_raw_data_blocks_in_frame = buf[6] & 0x3;
148
149 if( header->frame_length <= MP4SYS_ADTS_BASIC_HEADER_LENGTH + 2 * (protection_absent == 0) )
150 return LSMASH_ERR_INVALID_DATA; /* easy error check */
151
152 /* protection_absent and number_of_raw_data_blocks_in_frame relatives */
153
154 uint8_t buf2[2];
155 unsigned int number_of_blocks = header->number_of_raw_data_blocks_in_frame;
156 if( number_of_blocks == 0 )
157 {
158 header->raw_data_block_size[0] = header->frame_length - MP4SYS_ADTS_BASIC_HEADER_LENGTH;
159 /* skip adts_error_check() and subtract that from block_size */
160 if( protection_absent == 0 )
161 {
162 header->raw_data_block_size[0] -= 2;
163 if( lsmash_bs_get_bytes_ex( bs, 2, buf2 ) != 2 )
164 return LSMASH_ERR_INVALID_DATA;
165 }
166 return 0;
167 }
168
169 /* now we have multiple raw_data_block()s, so evaluate adts_header_error_check() */
170
171 uint16_t raw_data_block_position[MP4SYS_ADTS_MAX_RAW_DATA_BLOCKS];
172 uint16_t first_offset = MP4SYS_ADTS_BASIC_HEADER_LENGTH;
173 if( protection_absent == 0 )
174 {
175 /* process adts_header_error_check() */
176 for( int i = 0 ; i < number_of_blocks ; i++ ) /* 1-based in the spec, but we use 0-based */
177 {
178 if( lsmash_bs_get_bytes_ex( bs, 2, buf2 ) != 2 )
179 return LSMASH_ERR_INVALID_DATA;
180 raw_data_block_position[i] = LSMASH_GET_BE16( buf2 );
181 }
182 /* skip crc_check in adts_header_error_check().
183 Or might be sizeof( adts_error_check() ) if we share with the case number_of_raw_data_blocks_in_frame == 0 */
184 if( lsmash_bs_get_bytes_ex( bs, 2, buf2 ) != 2 )
185 return LSMASH_ERR_INVALID_DATA;
186 first_offset += ( 2 * number_of_blocks ) + 2; /* according to above */
187 }
188 else
189 {
190 /*
191 * NOTE: We never support the case where number_of_raw_data_blocks_in_frame != 0 && protection_absent != 0,
192 * because we have to parse the raw AAC bitstream itself to find boundaries of raw_data_block()s in this case.
193 * Which is to say, that braindamaged spec requires us (mp4 muxer) to decode AAC once to split frames.
194 * L-SMASH is NOT AAC DECODER, so that we've just given up for this case.
195 * This is ISO/IEC 13818-7's sin which defines ADTS format originally.
196 */
197 return LSMASH_ERR_NAMELESS;
198 }
199
200 /* convert raw_data_block_position --> raw_data_block_size */
201
202 /* do conversion for first */
203 header->raw_data_block_size[0] = raw_data_block_position[0] - first_offset;
204 /* set dummy offset to tail for loop, do coversion for rest. */
205 raw_data_block_position[number_of_blocks] = header->frame_length;
206 for( int i = 1 ; i <= number_of_blocks ; i++ )
207 header->raw_data_block_size[i] = raw_data_block_position[i] - raw_data_block_position[i-1];
208
209 /* adjustment for adts_raw_data_block_error_check() */
210 if( protection_absent == 0 && number_of_blocks != 0 )
211 for( int i = 0 ; i <= number_of_blocks ; i++ )
212 header->raw_data_block_size[i] -= 2;
213
214 return 0;
215 }
216
mp4sys_adts_parse_headers(lsmash_bs_t * bs,uint8_t * buf,mp4sys_adts_fixed_header_t * header,mp4sys_adts_variable_header_t * variable_header)217 static int mp4sys_adts_parse_headers
218 (
219 lsmash_bs_t *bs,
220 uint8_t *buf,
221 mp4sys_adts_fixed_header_t *header,
222 mp4sys_adts_variable_header_t *variable_header
223 )
224 {
225 mp4sys_adts_parse_fixed_header( buf, header );
226 int err = mp4sys_adts_check_fixed_header( header );
227 if( err < 0 )
228 return err;
229 /* get payload length & skip extra(crc) header */
230 return mp4sys_adts_parse_variable_header( bs, buf, header->protection_absent, variable_header );
231 }
232
mp4sys_adts_create_summary(mp4sys_adts_fixed_header_t * header)233 static lsmash_audio_summary_t *mp4sys_adts_create_summary
234 (
235 mp4sys_adts_fixed_header_t *header
236 )
237 {
238 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO );
239 if( !summary )
240 return NULL;
241 summary->sample_type = ISOM_CODEC_TYPE_MP4A_AUDIO;
242 summary->max_au_length = MP4SYS_ADTS_MAX_FRAME_LENGTH;
243 summary->frequency = mp4a_sampling_frequency_table[header->sampling_frequency_index][1];
244 summary->channels = header->channel_configuration + ( header->channel_configuration == 0x07 ); /* 0x07 means 7.1ch */
245 summary->sample_size = 16;
246 summary->samples_in_frame = 1024;
247 summary->aot = header->profile_ObjectType + MP4A_AUDIO_OBJECT_TYPE_AAC_MAIN;
248 summary->sbr_mode = MP4A_AAC_SBR_NOT_SPECIFIED;
249 #if 0 /* FIXME: This is very unstable. Many players crash with this. */
250 if( header->ID != 0 )
251 {
252 /*
253 * NOTE: This ADTS seems of ISO/IEC 13818-7 (MPEG-2 AAC).
254 * It has special object_type_indications, depending on it's profile (Legacy Interface).
255 * If ADIF header is not available, it should not have decoder specific information, so AudioObjectType neither.
256 * see ISO/IEC 14496-1, DecoderSpecificInfo and 14496-3 Subpart 9: MPEG-1/2 Audio in MPEG-4.
257 */
258 summary->object_type_indication = header->profile_ObjectType + MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_Main_Profile;
259 summary->aot = MP4A_AUDIO_OBJECT_TYPE_NULL;
260 summary->asc = NULL;
261 summary->asc_length = 0;
262 // summary->sbr_mode = MP4A_AAC_SBR_NONE; /* MPEG-2 AAC should not be HE-AAC, but we forgive them. */
263 return summary;
264 }
265 #endif
266 uint32_t data_length;
267 uint8_t *data = mp4a_export_AudioSpecificConfig( header->profile_ObjectType + MP4A_AUDIO_OBJECT_TYPE_AAC_MAIN,
268 summary->frequency, summary->channels, summary->sbr_mode,
269 NULL, 0, &data_length );
270 if( !data )
271 {
272 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
273 return NULL;
274 }
275 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG,
276 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
277 if( !specific )
278 {
279 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
280 lsmash_free( data );
281 return NULL;
282 }
283 lsmash_mp4sys_decoder_parameters_t *param = (lsmash_mp4sys_decoder_parameters_t *)specific->data.structured;
284 param->objectTypeIndication = MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3;
285 param->streamType = MP4SYS_STREAM_TYPE_AudioStream;
286 if( lsmash_set_mp4sys_decoder_specific_info( param, data, data_length ) < 0 )
287 {
288 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
289 lsmash_destroy_codec_specific_data( specific );
290 lsmash_free( data );
291 return NULL;
292 }
293 lsmash_free( data );
294 if( lsmash_list_add_entry( &summary->opaque->list, specific ) < 0 )
295 {
296 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
297 lsmash_destroy_codec_specific_data( specific );
298 return NULL;
299 }
300 return summary;
301 }
302
mp4sys_adts_get_accessunit(importer_t * importer,uint32_t track_number,lsmash_sample_t ** p_sample)303 static int mp4sys_adts_get_accessunit
304 (
305 importer_t *importer,
306 uint32_t track_number,
307 lsmash_sample_t **p_sample
308 )
309 {
310 if( !importer->info )
311 return LSMASH_ERR_NAMELESS;
312 if( track_number != 1 )
313 return LSMASH_ERR_FUNCTION_PARAM;
314 mp4sys_adts_importer_t *adts_imp = (mp4sys_adts_importer_t *)importer->info;
315 importer_status current_status = importer->status;
316 uint16_t raw_data_block_size = adts_imp->variable_header.raw_data_block_size[ adts_imp->raw_data_block_idx ];
317 if( current_status == IMPORTER_ERROR )
318 return LSMASH_ERR_NAMELESS;
319 if( current_status == IMPORTER_EOF )
320 return IMPORTER_EOF;
321 if( current_status == IMPORTER_CHANGE )
322 {
323 lsmash_entry_t *entry = lsmash_list_get_entry( importer->summaries, track_number );
324 if( !entry || !entry->data )
325 return LSMASH_ERR_NAMELESS;
326 lsmash_audio_summary_t *summary = mp4sys_adts_create_summary( &adts_imp->header );
327 if( !summary )
328 return LSMASH_ERR_NAMELESS;
329 lsmash_cleanup_summary( entry->data );
330 entry->data = summary;
331 adts_imp->samples_in_frame = summary->samples_in_frame;
332 }
333 lsmash_bs_t *bs = importer->bs;
334 /* read a raw_data_block(), typically == payload of a ADTS frame */
335 lsmash_sample_t *sample = lsmash_create_sample( raw_data_block_size );
336 if( !sample )
337 return LSMASH_ERR_MEMORY_ALLOC;
338 *p_sample = sample;
339 if( lsmash_bs_get_bytes_ex( bs, raw_data_block_size, sample->data ) != raw_data_block_size )
340 {
341 importer->status = IMPORTER_ERROR;
342 return LSMASH_ERR_INVALID_DATA;
343 }
344 sample->length = raw_data_block_size;
345 sample->dts = adts_imp->au_number ++ * adts_imp->samples_in_frame;
346 sample->cts = sample->dts;
347 sample->prop.ra_flags = ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC;
348 sample->prop.pre_roll.distance = 1; /* MDCT */
349
350 /* now we succeeded to read current frame, so "return" takes 0 always below. */
351
352 /* skip adts_raw_data_block_error_check() */
353 if( adts_imp->header.protection_absent == 0
354 && adts_imp->variable_header.number_of_raw_data_blocks_in_frame != 0
355 && lsmash_bs_get_bytes_ex( bs, 2, sample->data ) != 2 )
356 {
357 importer->status = IMPORTER_ERROR;
358 return 0;
359 }
360 /* current adts_frame() has any more raw_data_block()? */
361 if( adts_imp->raw_data_block_idx < adts_imp->variable_header.number_of_raw_data_blocks_in_frame )
362 {
363 adts_imp->raw_data_block_idx++;
364 importer->status = IMPORTER_OK;
365 return 0;
366 }
367 adts_imp->raw_data_block_idx = 0;
368
369 /* preparation for next frame */
370
371 uint8_t buf[MP4SYS_ADTS_MAX_FRAME_LENGTH];
372 int64_t ret = lsmash_bs_get_bytes_ex( bs, MP4SYS_ADTS_BASIC_HEADER_LENGTH, buf );
373 if( ret == 0 )
374 {
375 importer->status = IMPORTER_EOF;
376 return 0;
377 }
378 if( ret != MP4SYS_ADTS_BASIC_HEADER_LENGTH )
379 {
380 importer->status = IMPORTER_ERROR;
381 return 0;
382 }
383 /*
384 * NOTE: About the spec of ADTS headers.
385 * By the spec definition, ADTS's fixed header cannot change in the middle of stream.
386 * But spec of MP4 allows that a stream(track) changes its properties in the middle of it.
387 */
388 /*
389 * NOTE: About detailed check for ADTS headers.
390 * We do not ommit detailed check for fixed header by simply testing bits' identification,
391 * because there're some flags which does not matter to audio_summary (so AudioSpecificConfig neither)
392 * so that we can take them as no change and never make new ObjectDescriptor.
393 * I know that can be done with/by bitmask also and that should be fast, but L-SMASH project prefers
394 * even foolishly straightforward way.
395 */
396 /*
397 * NOTE: About our reading algorithm for ADTS.
398 * It's rather simple if we retrieve payload of ADTS (i.e. raw AAC frame) at the same time to
399 * retrieve headers.
400 * But then we have to cache and memcpy every frame so that it requires more clocks and memory.
401 * To avoid them, I adopted this separate retrieving method.
402 */
403 mp4sys_adts_fixed_header_t header = { 0 };
404 mp4sys_adts_variable_header_t variable_header = { 0 };
405 if( mp4sys_adts_parse_headers( bs, buf, &header, &variable_header ) < 0 )
406 {
407 importer->status = IMPORTER_ERROR;
408 return 0;
409 }
410 adts_imp->variable_header = variable_header;
411 /*
412 * NOTE: About our support for change(s) of properties within an ADTS stream.
413 * We have to modify these conditions depending on the features we support.
414 * For example, if we support copyright_identification_* in any way within any feature
415 * defined by/in any specs, such as ISO/IEC 14496-1 (MPEG-4 Systems), like...
416 * "8.3 Intellectual Property Management and Protection (IPMP)", or something similar,
417 * we have to check copyright_identification_* and treat them in audio_summary.
418 * "Change(s)" may result in MP4SYS_IMPORTER_ERROR or MP4SYS_IMPORTER_CHANGE
419 * depending on the features we support, and what the spec allows.
420 * Sometimes the "change(s)" can be allowed, while sometimes they're forbidden.
421 */
422 /* currently UNsupported "change(s)". */
423 if( adts_imp->header.profile_ObjectType != header.profile_ObjectType /* currently unsupported. */
424 || adts_imp->header.ID != header.ID /* In strict, this means change of object_type_indication. */
425 || adts_imp->header.sampling_frequency_index != header.sampling_frequency_index ) /* This may change timebase. */
426 {
427 importer->status = IMPORTER_ERROR;
428 return 0;
429 }
430 /* currently supported "change(s)". */
431 if( adts_imp->header.channel_configuration != header.channel_configuration )
432 {
433 /*
434 * FIXME: About conditions of VALID "change(s)".
435 * we have to check whether any "change(s)" affect to audioProfileLevelIndication
436 * in InitialObjectDescriptor (MP4_IOD) or not.
437 * If another type or upper level is required by the change(s), that is forbidden.
438 * Because ObjectDescriptor does not have audioProfileLevelIndication,
439 * so that it seems impossible to change audioProfileLevelIndication in the middle of the stream.
440 * Note also any other properties, such as AudioObjectType, object_type_indication.
441 */
442 /*
443 * NOTE: updating summary must be done on next call,
444 * because user may retrieve summary right after this function call of this time,
445 * and that should be of current, before change, one.
446 */
447 adts_imp->header = header;
448 importer->status = IMPORTER_CHANGE;
449 return 0;
450 }
451 /* no change which matters to mp4 muxing was found */
452 importer->status = IMPORTER_OK;
453 return 0;
454 }
455
456 /* returns 0 if it seems adts. */
mp4sys_adts_probe(importer_t * importer)457 static int mp4sys_adts_probe
458 (
459 importer_t *importer
460 )
461 {
462 mp4sys_adts_importer_t *adts_imp = create_mp4sys_adts_importer( importer );
463 if( !adts_imp )
464 return LSMASH_ERR_MEMORY_ALLOC;
465 int err;
466 uint8_t buf[MP4SYS_ADTS_MAX_FRAME_LENGTH];
467 if( lsmash_bs_get_bytes_ex( importer->bs, MP4SYS_ADTS_BASIC_HEADER_LENGTH, buf ) != MP4SYS_ADTS_BASIC_HEADER_LENGTH )
468 {
469 err = LSMASH_ERR_INVALID_DATA;
470 goto fail;
471 }
472 mp4sys_adts_fixed_header_t header = { 0 };
473 mp4sys_adts_variable_header_t variable_header = { 0 };
474 if( (err = mp4sys_adts_parse_headers( importer->bs, buf, &header, &variable_header )) < 0 )
475 goto fail;
476 /* now the stream seems valid ADTS */
477 lsmash_audio_summary_t *summary = mp4sys_adts_create_summary( &header );
478 if( !summary )
479 {
480 err = LSMASH_ERR_NAMELESS;
481 goto fail;
482 }
483 /* importer status */
484 if( lsmash_list_add_entry( importer->summaries, summary ) < 0 )
485 {
486 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
487 err = LSMASH_ERR_MEMORY_ALLOC;
488 goto fail;
489 }
490 adts_imp->raw_data_block_idx = 0;
491 adts_imp->header = header;
492 adts_imp->variable_header = variable_header;
493 adts_imp->samples_in_frame = summary->samples_in_frame;
494 importer->info = adts_imp;
495 importer->status = IMPORTER_OK;
496 return 0;
497 fail:
498 remove_mp4sys_adts_importer( adts_imp );
499 return err;
500 }
501
mp4sys_adts_get_last_delta(importer_t * importer,uint32_t track_number)502 static uint32_t mp4sys_adts_get_last_delta
503 (
504 importer_t *importer,
505 uint32_t track_number
506 )
507 {
508 debug_if( !importer || !importer->info )
509 return 0;
510 mp4sys_adts_importer_t *adts_imp = (mp4sys_adts_importer_t *)importer->info;
511 if( !adts_imp || track_number != 1 || importer->status != IMPORTER_EOF )
512 return 0;
513 return adts_imp->samples_in_frame;
514 }
515
516 const importer_functions mp4sys_adts_importer =
517 {
518 { "adts" },
519 1,
520 mp4sys_adts_probe,
521 mp4sys_adts_get_accessunit,
522 mp4sys_adts_get_last_delta,
523 mp4sys_adts_cleanup
524 };
525