1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2011-2014 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
27 #define LSMASH_IMPORTER_INTERNAL
30 /***************************************************************************
32 ISO/IEC 14496-3 2009 Fourth edition
33 ***************************************************************************/
34 #include "codecs/mp4a.h"
36 #define ALSSC_TWELVE_LENGTH 22
44 uint16_t frame_length
;
46 uint8_t random_access
;
48 uint32_t access_unit_size
;
49 uint32_t number_of_ra_units
;
50 uint32_t *ra_unit_size
;
53 } als_specific_config_t
;
57 importer_status status
;
59 als_specific_config_t alssc
;
60 uint32_t samples_in_frame
;
62 } mp4a_als_importer_t
;
64 static void remove_mp4a_als_importer( mp4a_als_importer_t
*als_imp
)
66 lsmash_bs_cleanup( als_imp
->bs
);
67 lsmash_free( als_imp
->alssc
.ra_unit_size
);
68 lsmash_free( als_imp
->alssc
.sc_data
);
69 lsmash_free( als_imp
);
72 static void mp4a_als_importer_cleanup( importer_t
*importer
)
74 debug_if( importer
&& importer
->info
)
75 remove_mp4a_als_importer( importer
->info
);
78 static mp4a_als_importer_t
*create_mp4a_als_importer( importer_t
*importer
)
80 mp4a_als_importer_t
*als_imp
= lsmash_malloc_zero( sizeof(mp4a_als_importer_t
) );
83 als_imp
->bs
= lsmash_bs_create();
86 lsmash_free( als_imp
);
92 static void als_copy_from_buffer( als_specific_config_t
*alssc
, lsmash_bs_t
*bs
, uint64_t size
)
94 if( alssc
->alloc
< size
)
96 size_t alloc
= alssc
->alloc
? (alssc
->alloc
<< 1) : (1 << 10);
97 uint8_t *temp
= lsmash_realloc( alssc
->sc_data
, alloc
);
100 alssc
->sc_data
= temp
;
101 alssc
->alloc
= alloc
;
103 memcpy( alssc
->sc_data
+ alssc
->size
, lsmash_bs_get_buffer_data( bs
), size
);
105 lsmash_bs_read_seek( bs
, size
, SEEK_CUR
);
108 static int als_parse_specific_config( mp4a_als_importer_t
*als_imp
)
110 lsmash_bs_t
*bs
= als_imp
->bs
;
111 /* Check ALS identifier( = 0x414C5300). */
112 if( 0x414C5300 != lsmash_bs_show_be32( bs
, 0 ) )
114 als_specific_config_t
*alssc
= &als_imp
->alssc
;
115 alssc
->samp_freq
= lsmash_bs_show_be32( bs
, 4 );
116 alssc
->samples
= lsmash_bs_show_be32( bs
, 8 );
117 if( alssc
->samples
== 0xffffffff )
118 return -1; /* We don't support this case. */
119 alssc
->channels
= lsmash_bs_show_be16( bs
, 12 );
120 alssc
->resolution
= (lsmash_bs_show_byte( bs
, 14 ) & 0x1c) >> 2;
121 if( alssc
->resolution
> 3 )
122 return -1; /* reserved */
123 alssc
->frame_length
= lsmash_bs_show_be16( bs
, 15 );
124 alssc
->random_access
= lsmash_bs_show_byte( bs
, 17 );
125 alssc
->ra_flag
= (lsmash_bs_show_byte( bs
, 18 ) & 0xc0) >> 6;
126 if( alssc
->ra_flag
== 0 )
127 return -1; /* We don't support this case. */
129 if( alssc
->samples
== 0xffffffff && alssc
->ra_flag
== 2 )
132 uint8_t temp8
= lsmash_bs_show_byte( bs
, 20 );
133 int chan_sort
= !!(temp8
& 0x1);
134 if( alssc
->channels
== 0 )
137 return -1; /* If channels = 0 (mono), joint_stereo = 0. */
138 else if( temp8
& 0x4 )
139 return -1; /* If channels = 0 (mono), mc_coding = 0. */
141 return -1; /* If channels = 0 (mono), chan_sort = 0. */
143 int chan_config
= !!(temp8
& 0x2);
144 temp8
= lsmash_bs_show_byte( bs
, 21 );
145 int crc_enabled
= !!(temp8
& 0x80);
146 int aux_data_enabled
= !!(temp8
& 0x1);
147 als_copy_from_buffer( alssc
, bs
, ALSSC_TWELVE_LENGTH
);
150 /* chan_config_info */
151 lsmash_bs_read( bs
, 2 );
152 als_copy_from_buffer( alssc
, bs
, 2 );
156 uint32_t ChBits
= lsmash_ceil_log2( alssc
->channels
+ 1 );
157 uint32_t chan_pos_length
= (alssc
->channels
+ 1) * ChBits
;
158 chan_pos_length
= ((uint64_t)chan_pos_length
+ 7) / 8; /* byte_align */
159 lsmash_bs_read( bs
, chan_pos_length
);
160 als_copy_from_buffer( alssc
, bs
, chan_pos_length
);
162 /* orig_header, orig_trailer and crc. */
164 uint32_t header_size
= lsmash_bs_show_be32( bs
, 0 );
165 uint32_t trailer_size
= lsmash_bs_show_be32( bs
, 4 );
166 als_copy_from_buffer( alssc
, bs
, 8 );
167 if( header_size
!= 0xffffffff )
169 lsmash_bs_read( bs
, header_size
);
170 als_copy_from_buffer( alssc
, bs
, header_size
);
172 if( trailer_size
!= 0xffffffff )
174 lsmash_bs_read( bs
, trailer_size
);
175 als_copy_from_buffer( alssc
, bs
, trailer_size
);
179 lsmash_bs_read( bs
, 4 );
180 als_copy_from_buffer( alssc
, bs
, 4 );
183 /* Random access units */
185 uint32_t number_of_frames
= ((alssc
->samples
+ alssc
->frame_length
) / (alssc
->frame_length
+ 1));
186 if( alssc
->random_access
!= 0 )
187 alssc
->number_of_ra_units
= ((uint64_t)number_of_frames
+ alssc
->random_access
- 1) / alssc
->random_access
;
189 alssc
->number_of_ra_units
= 0;
190 if( alssc
->ra_flag
== 2 && alssc
->random_access
!= 0 )
192 /* We don't copy all ra_unit_size into alssc->sc_data. */
193 int64_t read_size
= (int64_t)alssc
->number_of_ra_units
* 4;
194 int64_t end_offset
= lsmash_bs_get_stream_pos( bs
) + read_size
;
195 alssc
->ra_unit_size
= lsmash_malloc( read_size
);
196 if( !alssc
->ra_unit_size
)
198 uint32_t max_ra_unit_size
= 0;
199 for( uint32_t i
= 0; i
< alssc
->number_of_ra_units
; i
++ )
201 alssc
->ra_unit_size
[i
] = lsmash_bs_get_be32( bs
);
202 max_ra_unit_size
= LSMASH_MAX( max_ra_unit_size
, alssc
->ra_unit_size
[i
] );
204 lsmash_bs_read_seek( bs
, end_offset
, SEEK_SET
);
207 alssc
->ra_unit_size
= NULL
;
210 if( aux_data_enabled
)
212 uint32_t aux_size
= lsmash_bs_show_be32( bs
, 0 );
213 als_copy_from_buffer( alssc
, bs
, 4 );
214 if( aux_size
&& aux_size
!= 0xffffffff )
216 lsmash_bs_read( bs
, aux_size
);
217 als_copy_from_buffer( alssc
, bs
, aux_size
);
220 /* Set 0 to ra_flag. We will remove ra_unit_size in each access unit. */
221 alssc
->sc_data
[18] &= 0x3f;
225 static int mp4a_als_importer_get_accessunit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
*buffered_sample
)
227 debug_if( !importer
|| !importer
->info
|| !buffered_sample
->data
|| !buffered_sample
->length
)
229 if( !importer
->info
|| track_number
!= 1 )
231 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_get_entry_data( importer
->summaries
, track_number
);
234 mp4a_als_importer_t
*als_imp
= (mp4a_als_importer_t
*)importer
->info
;
235 importer_status current_status
= als_imp
->status
;
236 if( current_status
== IMPORTER_EOF
)
238 buffered_sample
->length
= 0;
241 lsmash_bs_t
*bs
= als_imp
->bs
;
242 als_specific_config_t
*alssc
= &als_imp
->alssc
;
243 if( alssc
->number_of_ra_units
== 0 )
245 memcpy( buffered_sample
->data
, lsmash_bs_get_buffer_data( bs
), alssc
->access_unit_size
);
246 buffered_sample
->length
= alssc
->access_unit_size
;
247 buffered_sample
->cts
= 0;
248 buffered_sample
->dts
= 0;
249 buffered_sample
->prop
.ra_flags
= ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC
;
250 als_imp
->status
= IMPORTER_EOF
;
254 if( alssc
->ra_flag
== 2 )
255 au_length
= alssc
->ra_unit_size
[ als_imp
->au_number
];
256 else /* if( alssc->ra_flag == 1 ) */
257 /* We don't export ra_unit_size into a sample. */
258 au_length
= lsmash_bs_get_be32( bs
);
259 if( buffered_sample
->length
< au_length
)
261 lsmash_log( importer
, LSMASH_LOG_WARNING
, "the buffer has not enough size.\n" );
264 if( lsmash_bs_get_bytes_ex( bs
, au_length
, buffered_sample
->data
) != au_length
)
266 lsmash_log( importer
, LSMASH_LOG_WARNING
, "failed to read an access unit.\n" );
267 als_imp
->status
= IMPORTER_ERROR
;
270 buffered_sample
->length
= au_length
;
271 buffered_sample
->dts
= als_imp
->au_number
++ * als_imp
->samples_in_frame
;
272 buffered_sample
->cts
= buffered_sample
->dts
;
273 buffered_sample
->prop
.ra_flags
= ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC
;
274 if( als_imp
->au_number
== alssc
->number_of_ra_units
)
275 als_imp
->status
= IMPORTER_EOF
;
281 static lsmash_audio_summary_t
*als_create_summary( lsmash_bs_t
*bs
, als_specific_config_t
*alssc
)
283 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO
);
286 summary
->sample_type
= ISOM_CODEC_TYPE_MP4A_AUDIO
;
287 summary
->aot
= MP4A_AUDIO_OBJECT_TYPE_ALS
;
288 summary
->frequency
= alssc
->samp_freq
;
289 summary
->channels
= alssc
->channels
+ 1;
290 summary
->sample_size
= (alssc
->resolution
+ 1) * 8;
291 summary
->sbr_mode
= MP4A_AAC_SBR_NOT_SPECIFIED
; /* no effect */
292 if( alssc
->random_access
!= 0 )
294 summary
->samples_in_frame
= (alssc
->frame_length
+ 1) * alssc
->random_access
;
295 summary
->max_au_length
= summary
->channels
* (summary
->sample_size
/ 8) * summary
->samples_in_frame
;
299 /* Read the remainder of overall stream as an access unit. */
300 alssc
->access_unit_size
= lsmash_bs_get_remaining_buffer_size( bs
);
303 if( lsmash_bs_read( bs
, bs
->buffer
.max_size
) < 0 )
305 alssc
->access_unit_size
= lsmash_bs_get_remaining_buffer_size( bs
);
307 summary
->max_au_length
= alssc
->access_unit_size
;
308 summary
->samples_in_frame
= 0; /* hack for mp4sys_als_importer_get_last_delta() */
310 uint32_t data_length
;
311 uint8_t *data
= mp4a_export_AudioSpecificConfig( MP4A_AUDIO_OBJECT_TYPE_ALS
,
312 summary
->frequency
, summary
->channels
, summary
->sbr_mode
,
313 alssc
->sc_data
, alssc
->size
, &data_length
);
316 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
319 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
,
320 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
323 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
327 lsmash_mp4sys_decoder_parameters_t
*param
= (lsmash_mp4sys_decoder_parameters_t
*)specific
->data
.structured
;
328 param
->objectTypeIndication
= MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3
;
329 param
->streamType
= MP4SYS_STREAM_TYPE_AudioStream
;
330 if( lsmash_set_mp4sys_decoder_specific_info( param
, data
, data_length
) < 0 )
332 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
333 lsmash_destroy_codec_specific_data( specific
);
338 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
340 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
341 lsmash_destroy_codec_specific_data( specific
);
347 static int mp4a_als_importer_probe( importer_t
*importer
)
349 mp4a_als_importer_t
*als_imp
= create_mp4a_als_importer( importer
);
352 lsmash_bs_t
*bs
= als_imp
->bs
;
353 bs
->stream
= importer
->stream
;
354 bs
->read
= lsmash_fread_wrapper
;
355 bs
->seek
= lsmash_fseek_wrapper
;
356 bs
->unseekable
= importer
->is_stdin
;
357 bs
->buffer
.max_size
= BS_MAX_DEFAULT_READ_SIZE
;
358 /* Parse ALS specific configuration. */
359 if( als_parse_specific_config( als_imp
) < 0 )
361 lsmash_audio_summary_t
*summary
= als_create_summary( bs
, &als_imp
->alssc
);
364 /* importer status */
365 als_imp
->status
= IMPORTER_OK
;
366 als_imp
->samples_in_frame
= summary
->samples_in_frame
;
367 if( lsmash_add_entry( importer
->summaries
, summary
) < 0 )
369 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
372 importer
->info
= als_imp
;
375 remove_mp4a_als_importer( als_imp
);
379 static uint32_t mp4a_als_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
381 debug_if( !importer
|| !importer
->info
)
383 mp4a_als_importer_t
*als_imp
= (mp4a_als_importer_t
*)importer
->info
;
384 if( !als_imp
|| track_number
!= 1 || als_imp
->status
!= IMPORTER_EOF
)
386 als_specific_config_t
*alssc
= &als_imp
->alssc
;
387 /* If alssc->number_of_ra_units == 0, then the last sample duration is just alssc->samples
388 * since als_create_summary sets 0 to summary->samples_in_frame i.e. als_imp->samples_in_frame. */
389 return alssc
->samples
- (alssc
->number_of_ra_units
- 1) * als_imp
->samples_in_frame
;
392 const importer_functions mp4a_als_importer
=
394 { "MPEG-4 ALS", offsetof( importer_t
, log_level
) },
396 mp4a_als_importer_probe
,
397 mp4a_als_importer_get_accessunit
,
398 mp4a_als_importer_get_last_delta
,
399 mp4a_als_importer_cleanup