1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2014 L-SMASH project
6 * Authors: Takashi Hirata <silverfilain@gmail.com>
7 * Contributors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
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.
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 *****************************************************************************/
22 /* This file is available under an ISC license. */
24 #include "common/internal.h" /* must be placed first */
26 #define LSMASH_IMPORTER_INTERNAL
29 /***************************************************************************
31 ***************************************************************************/
32 #include "codecs/mp4a.h"
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
41 uint16_t syncword
; /* 12; */
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. */
52 } mp4sys_adts_fixed_header_t
;
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
;
68 static void mp4sys_adts_parse_fixed_header( uint8_t* buf
, mp4sys_adts_fixed_header_t
* header
)
70 /* FIXME: should we rewrite these code using bitstream reader? */
71 header
->syncword
= (buf
[0] << 4) | (buf
[1] >> 4);
72 header
->ID
= (buf
[1] >> 3) & 0x1;
73 header
->layer
= (buf
[1] >> 1) & 0x3;
74 header
->protection_absent
= buf
[1] & 0x1;
75 header
->profile_ObjectType
= buf
[2] >> 6;
76 header
->sampling_frequency_index
= (buf
[2] >> 2) & 0xF;
77 // header->private_bit = (buf[2] >> 1) & 0x1; /* we don't care currently. */
78 header
->channel_configuration
= ((buf
[2] << 2) | (buf
[3] >> 6)) & 0x07;
79 // header->original_copy = (buf[3] >> 5) & 0x1; /* we don't care currently. */
80 // header->home = (buf[3] >> 4) & 0x1; /* we don't care currently. */
83 static int mp4sys_adts_check_fixed_header( mp4sys_adts_fixed_header_t
* header
)
85 if( header
->syncword
!= 0xFFF ) return -1;
86 // if( header->ID != 0x0 ) return -1; /* we don't care. */
87 if( header
->layer
!= 0x0 ) return -1; /* must be 0b00 for any type of AAC */
88 // if( header->protection_absent != 0x1 ) return -1; /* we don't care. */
89 if( header
->profile_ObjectType
!= 0x1 ) return -1; /* FIXME: 0b00=Main, 0b01=LC, 0b10=SSR, 0b11=LTP. */
90 if( header
->sampling_frequency_index
> 0xB ) return -1; /* must not be > 0xB. */
91 if( header
->channel_configuration
== 0x0 ) return -1; /* FIXME: we do not support 0b000 currently. */
92 if( header
->profile_ObjectType
== 0x3 && header
->ID
!= 0x0 ) return -1; /* LTP is valid only if ID==0. */
96 static int mp4sys_adts_parse_variable_header( FILE* stream
, uint8_t* buf
, unsigned int protection_absent
, mp4sys_adts_variable_header_t
* header
)
98 /* FIXME: should we rewrite these code using bitstream reader? */
99 // header->copyright_identification_bit = (buf[3] >> 3) & 0x1; /* we don't care. */
100 // header->copyright_identification_start = (buf[3] >> 2) & 0x1; /* we don't care. */
101 header
->frame_length
= ((buf
[3] << 11) | (buf
[4] << 3) | (buf
[5] >> 5)) & 0x1FFF ;
102 // header->adts_buffer_fullness = ((buf[5] << 6) | (buf[6] >> 2)) 0x7FF ; /* we don't care. */
103 header
->number_of_raw_data_blocks_in_frame
= buf
[6] & 0x3;
105 if( header
->frame_length
<= MP4SYS_ADTS_BASIC_HEADER_LENGTH
+ 2 * (protection_absent
== 0) )
106 return -1; /* easy error check */
108 /* protection_absent and number_of_raw_data_blocks_in_frame relatives */
111 unsigned int number_of_blocks
= header
->number_of_raw_data_blocks_in_frame
;
112 if( number_of_blocks
== 0 )
114 header
->raw_data_block_size
[0] = header
->frame_length
- MP4SYS_ADTS_BASIC_HEADER_LENGTH
;
115 /* skip adts_error_check() and subtract that from block_size */
116 if( protection_absent
== 0 )
118 header
->raw_data_block_size
[0] -= 2;
119 if( fread( buf2
, 1, 2, stream
) != 2 )
125 /* now we have multiple raw_data_block()s, so evaluate adts_header_error_check() */
127 uint16_t raw_data_block_position
[MP4SYS_ADTS_MAX_RAW_DATA_BLOCKS
];
128 uint16_t first_offset
= MP4SYS_ADTS_BASIC_HEADER_LENGTH
;
129 if( protection_absent
== 0 )
131 /* process adts_header_error_check() */
132 for( int i
= 0 ; i
< number_of_blocks
; i
++ ) /* 1-based in the spec, but we use 0-based */
134 if( fread( buf2
, 1, 2, stream
) != 2 )
136 raw_data_block_position
[i
] = LSMASH_GET_BE16( buf2
);
138 /* skip crc_check in adts_header_error_check().
139 Or might be sizeof( adts_error_check() ) if we share with the case number_of_raw_data_blocks_in_frame == 0 */
140 if( fread( buf2
, 1, 2, stream
) != 2 )
142 first_offset
+= ( 2 * number_of_blocks
) + 2; /* according to above */
147 * NOTE: We never support the case where number_of_raw_data_blocks_in_frame != 0 && protection_absent != 0,
148 * because we have to parse the raw AAC bitstream itself to find boundaries of raw_data_block()s in this case.
149 * Which is to say, that braindamaged spec requires us (mp4 muxer) to decode AAC once to split frames.
150 * L-SMASH is NOT AAC DECODER, so that we've just given up for this case.
151 * This is ISO/IEC 13818-7's sin which defines ADTS format originally.
156 /* convert raw_data_block_position --> raw_data_block_size */
158 /* do conversion for first */
159 header
->raw_data_block_size
[0] = raw_data_block_position
[0] - first_offset
;
160 /* set dummy offset to tail for loop, do coversion for rest. */
161 raw_data_block_position
[number_of_blocks
] = header
->frame_length
;
162 for( int i
= 1 ; i
<= number_of_blocks
; i
++ )
163 header
->raw_data_block_size
[i
] = raw_data_block_position
[i
] - raw_data_block_position
[i
-1];
165 /* adjustment for adts_raw_data_block_error_check() */
166 if( protection_absent
== 0 && number_of_blocks
!= 0 )
167 for( int i
= 0 ; i
<= number_of_blocks
; i
++ )
168 header
->raw_data_block_size
[i
] -= 2;
173 static int mp4sys_adts_parse_headers( FILE* stream
, uint8_t* buf
, mp4sys_adts_fixed_header_t
* header
, mp4sys_adts_variable_header_t
* variable_header
)
175 mp4sys_adts_parse_fixed_header( buf
, header
);
176 if( mp4sys_adts_check_fixed_header( header
) )
178 /* get payload length & skip extra(crc) header */
179 return mp4sys_adts_parse_variable_header( stream
, buf
, header
->protection_absent
, variable_header
);
182 static lsmash_audio_summary_t
*mp4sys_adts_create_summary( mp4sys_adts_fixed_header_t
*header
)
184 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO
);
187 summary
->sample_type
= ISOM_CODEC_TYPE_MP4A_AUDIO
;
188 summary
->max_au_length
= MP4SYS_ADTS_MAX_FRAME_LENGTH
;
189 summary
->frequency
= mp4a_sampling_frequency_table
[header
->sampling_frequency_index
][1];
190 summary
->channels
= header
->channel_configuration
+ ( header
->channel_configuration
== 0x07 ); /* 0x07 means 7.1ch */
191 summary
->sample_size
= 16;
192 summary
->samples_in_frame
= 1024;
193 summary
->aot
= header
->profile_ObjectType
+ MP4A_AUDIO_OBJECT_TYPE_AAC_MAIN
;
194 summary
->sbr_mode
= MP4A_AAC_SBR_NOT_SPECIFIED
;
195 #if 0 /* FIXME: This is very unstable. Many players crash with this. */
196 if( header
->ID
!= 0 )
199 * NOTE: This ADTS seems of ISO/IEC 13818-7 (MPEG-2 AAC).
200 * It has special object_type_indications, depending on it's profile (Legacy Interface).
201 * If ADIF header is not available, it should not have decoder specific information, so AudioObjectType neither.
202 * see ISO/IEC 14496-1, DecoderSpecificInfo and 14496-3 Subpart 9: MPEG-1/2 Audio in MPEG-4.
204 summary
->object_type_indication
= header
->profile_ObjectType
+ MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_Main_Profile
;
205 summary
->aot
= MP4A_AUDIO_OBJECT_TYPE_NULL
;
207 summary
->asc_length
= 0;
208 // summary->sbr_mode = MP4A_AAC_SBR_NONE; /* MPEG-2 AAC should not be HE-AAC, but we forgive them. */
212 uint32_t data_length
;
213 uint8_t *data
= mp4a_export_AudioSpecificConfig( header
->profile_ObjectType
+ MP4A_AUDIO_OBJECT_TYPE_AAC_MAIN
,
214 summary
->frequency
, summary
->channels
, summary
->sbr_mode
,
215 NULL
, 0, &data_length
);
218 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
221 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
,
222 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
225 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
229 lsmash_mp4sys_decoder_parameters_t
*param
= (lsmash_mp4sys_decoder_parameters_t
*)specific
->data
.structured
;
230 param
->objectTypeIndication
= MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3
;
231 param
->streamType
= MP4SYS_STREAM_TYPE_AudioStream
;
232 if( lsmash_set_mp4sys_decoder_specific_info( param
, data
, data_length
) )
234 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
235 lsmash_destroy_codec_specific_data( specific
);
240 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) )
242 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
243 lsmash_destroy_codec_specific_data( specific
);
251 importer_status status
;
252 unsigned int raw_data_block_idx
;
253 mp4sys_adts_fixed_header_t header
;
254 mp4sys_adts_variable_header_t variable_header
;
255 uint32_t samples_in_frame
;
257 } mp4sys_adts_info_t
;
259 static int mp4sys_adts_get_accessunit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
*buffered_sample
)
261 debug_if( !importer
|| !importer
->info
|| !buffered_sample
->data
|| !buffered_sample
->length
)
263 if( !importer
->info
|| track_number
!= 1 )
265 mp4sys_adts_info_t
* info
= (mp4sys_adts_info_t
*)importer
->info
;
266 importer_status current_status
= info
->status
;
267 uint16_t raw_data_block_size
= info
->variable_header
.raw_data_block_size
[info
->raw_data_block_idx
];
268 if( current_status
== IMPORTER_ERROR
|| buffered_sample
->length
< raw_data_block_size
)
270 if( current_status
== IMPORTER_EOF
)
272 buffered_sample
->length
= 0;
275 if( current_status
== IMPORTER_CHANGE
)
277 lsmash_audio_summary_t
* summary
= mp4sys_adts_create_summary( &info
->header
);
280 lsmash_entry_t
* entry
= lsmash_get_entry( importer
->summaries
, track_number
);
281 if( !entry
|| !entry
->data
)
283 lsmash_cleanup_summary( entry
->data
);
284 entry
->data
= summary
;
285 info
->samples_in_frame
= summary
->samples_in_frame
;
288 /* read a raw_data_block(), typically == payload of a ADTS frame */
289 if( fread( buffered_sample
->data
, 1, raw_data_block_size
, importer
->stream
) != raw_data_block_size
)
291 info
->status
= IMPORTER_ERROR
;
294 buffered_sample
->length
= raw_data_block_size
;
295 buffered_sample
->dts
= info
->au_number
++ * info
->samples_in_frame
;
296 buffered_sample
->cts
= buffered_sample
->dts
;
297 buffered_sample
->prop
.ra_flags
= ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC
;
298 buffered_sample
->prop
.pre_roll
.distance
= 1; /* MDCT */
300 /* now we succeeded to read current frame, so "return" takes 0 always below. */
302 /* skip adts_raw_data_block_error_check() */
303 if( info
->header
.protection_absent
== 0
304 && info
->variable_header
.number_of_raw_data_blocks_in_frame
!= 0
305 && fread( buffered_sample
->data
, 1, 2, importer
->stream
) != 2 )
307 info
->status
= IMPORTER_ERROR
;
310 /* current adts_frame() has any more raw_data_block()? */
311 if( info
->raw_data_block_idx
< info
->variable_header
.number_of_raw_data_blocks_in_frame
)
313 info
->raw_data_block_idx
++;
314 info
->status
= IMPORTER_OK
;
317 info
->raw_data_block_idx
= 0;
319 /* preparation for next frame */
321 uint8_t buf
[MP4SYS_ADTS_MAX_FRAME_LENGTH
];
322 size_t ret
= fread( buf
, 1, MP4SYS_ADTS_BASIC_HEADER_LENGTH
, importer
->stream
);
325 info
->status
= IMPORTER_EOF
;
328 if( ret
!= MP4SYS_ADTS_BASIC_HEADER_LENGTH
)
330 info
->status
= IMPORTER_ERROR
;
334 * NOTE: About the spec of ADTS headers.
335 * By the spec definition, ADTS's fixed header cannot change in the middle of stream.
336 * But spec of MP4 allows that a stream(track) changes its properties in the middle of it.
339 * NOTE: About detailed check for ADTS headers.
340 * We do not ommit detailed check for fixed header by simply testing bits' identification,
341 * because there're some flags which does not matter to audio_summary (so AudioSpecificConfig neither)
342 * so that we can take them as no change and never make new ObjectDescriptor.
343 * I know that can be done with/by bitmask also and that should be fast, but L-SMASH project prefers
344 * even foolishly straightforward way.
347 * NOTE: About our reading algorithm for ADTS.
348 * It's rather simple if we retrieve payload of ADTS (i.e. raw AAC frame) at the same time to
350 * But then we have to cache and memcpy every frame so that it requires more clocks and memory.
351 * To avoid them, I adopted this separate retrieving method.
353 mp4sys_adts_fixed_header_t header
= {0};
354 mp4sys_adts_variable_header_t variable_header
= {0};
355 if( mp4sys_adts_parse_headers( importer
->stream
, buf
, &header
, &variable_header
) )
357 info
->status
= IMPORTER_ERROR
;
360 info
->variable_header
= variable_header
;
363 * NOTE: About our support for change(s) of properties within an ADTS stream.
364 * We have to modify these conditions depending on the features we support.
365 * For example, if we support copyright_identification_* in any way within any feature
366 * defined by/in any specs, such as ISO/IEC 14496-1 (MPEG-4 Systems), like...
367 * "8.3 Intellectual Property Management and Protection (IPMP)", or something similar,
368 * we have to check copyright_identification_* and treat them in audio_summary.
369 * "Change(s)" may result in MP4SYS_IMPORTER_ERROR or MP4SYS_IMPORTER_CHANGE
370 * depending on the features we support, and what the spec allows.
371 * Sometimes the "change(s)" can be allowed, while sometimes they're forbidden.
373 /* currently UNsupported "change(s)". */
374 if( info
->header
.profile_ObjectType
!= header
.profile_ObjectType
/* currently unsupported. */
375 || info
->header
.ID
!= header
.ID
/* In strict, this means change of object_type_indication. */
376 || info
->header
.sampling_frequency_index
!= header
.sampling_frequency_index
) /* This may change timebase. */
378 info
->status
= IMPORTER_ERROR
;
381 /* currently supported "change(s)". */
382 if( info
->header
.channel_configuration
!= header
.channel_configuration
)
385 * FIXME: About conditions of VALID "change(s)".
386 * we have to check whether any "change(s)" affect to audioProfileLevelIndication
387 * in InitialObjectDescriptor (MP4_IOD) or not.
388 * If another type or upper level is required by the change(s), that is forbidden.
389 * Because ObjectDescriptor does not have audioProfileLevelIndication,
390 * so that it seems impossible to change audioProfileLevelIndication in the middle of the stream.
391 * Note also any other properties, such as AudioObjectType, object_type_indication.
394 * NOTE: updating summary must be done on next call,
395 * because user may retrieve summary right after this function call of this time,
396 * and that should be of current, before change, one.
398 info
->header
= header
;
399 info
->status
= IMPORTER_CHANGE
;
402 /* no change which matters to mp4 muxing was found */
403 info
->status
= IMPORTER_OK
;
407 static void mp4sys_adts_cleanup( importer_t
*importer
)
409 debug_if( importer
&& importer
->info
)
410 lsmash_free( importer
->info
);
413 /* returns 0 if it seems adts. */
414 static int mp4sys_adts_probe( importer_t
*importer
)
416 uint8_t buf
[MP4SYS_ADTS_MAX_FRAME_LENGTH
];
417 if( fread( buf
, 1, MP4SYS_ADTS_BASIC_HEADER_LENGTH
, importer
->stream
) != MP4SYS_ADTS_BASIC_HEADER_LENGTH
)
420 mp4sys_adts_fixed_header_t header
= {0};
421 mp4sys_adts_variable_header_t variable_header
= {0};
422 if( mp4sys_adts_parse_headers( importer
->stream
, buf
, &header
, &variable_header
) )
425 /* now the stream seems valid ADTS */
427 lsmash_audio_summary_t
* summary
= mp4sys_adts_create_summary( &header
);
431 /* importer status */
432 mp4sys_adts_info_t
* info
= lsmash_malloc_zero( sizeof(mp4sys_adts_info_t
) );
435 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
438 info
->status
= IMPORTER_OK
;
439 info
->raw_data_block_idx
= 0;
440 info
->header
= header
;
441 info
->variable_header
= variable_header
;
442 info
->samples_in_frame
= summary
->samples_in_frame
;
444 if( lsmash_add_entry( importer
->summaries
, summary
) )
447 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
450 importer
->info
= info
;
455 static uint32_t mp4sys_adts_get_last_delta( importer_t
*importer
, uint32_t track_number
)
457 debug_if( !importer
|| !importer
->info
)
459 mp4sys_adts_info_t
*info
= (mp4sys_adts_info_t
*)importer
->info
;
460 if( !info
|| track_number
!= 1 || info
->status
!= IMPORTER_EOF
)
462 return info
->samples_in_frame
;
465 const importer_functions mp4sys_adts_importer
=
470 mp4sys_adts_get_accessunit
,
471 mp4sys_adts_get_last_delta
,