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