1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2011-2015 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 als_specific_config_t alssc
;
58 uint32_t samples_in_frame
;
60 } mp4a_als_importer_t
;
62 static void remove_mp4a_als_importer( mp4a_als_importer_t
*als_imp
)
64 lsmash_free( als_imp
->alssc
.ra_unit_size
);
65 lsmash_free( als_imp
->alssc
.sc_data
);
66 lsmash_free( als_imp
);
69 static void mp4a_als_importer_cleanup( importer_t
*importer
)
71 debug_if( importer
&& importer
->info
)
72 remove_mp4a_als_importer( importer
->info
);
75 static mp4a_als_importer_t
*create_mp4a_als_importer( importer_t
*importer
)
77 return (mp4a_als_importer_t
*)lsmash_malloc_zero( sizeof(mp4a_als_importer_t
) );
80 static void als_copy_from_buffer( als_specific_config_t
*alssc
, lsmash_bs_t
*bs
, uint64_t size
)
82 if( alssc
->alloc
< size
)
84 size_t alloc
= alssc
->alloc
? (alssc
->alloc
<< 1) : (1 << 10);
85 uint8_t *temp
= lsmash_realloc( alssc
->sc_data
, alloc
);
88 alssc
->sc_data
= temp
;
91 memcpy( alssc
->sc_data
+ alssc
->size
, lsmash_bs_get_buffer_data( bs
), size
);
93 lsmash_bs_read_seek( bs
, size
, SEEK_CUR
);
96 static int als_parse_specific_config( lsmash_bs_t
*bs
, mp4a_als_importer_t
*als_imp
)
98 /* Check ALS identifier( = 0x414C5300). */
99 if( 0x414C5300 != lsmash_bs_show_be32( bs
, 0 ) )
100 return LSMASH_ERR_INVALID_DATA
;
101 als_specific_config_t
*alssc
= &als_imp
->alssc
;
102 alssc
->samp_freq
= lsmash_bs_show_be32( bs
, 4 );
103 alssc
->samples
= lsmash_bs_show_be32( bs
, 8 );
104 if( alssc
->samples
== 0xffffffff )
105 return LSMASH_ERR_PATCH_WELCOME
; /* We don't support this case. */
106 alssc
->channels
= lsmash_bs_show_be16( bs
, 12 );
107 alssc
->resolution
= (lsmash_bs_show_byte( bs
, 14 ) & 0x1c) >> 2;
108 if( alssc
->resolution
> 3 )
109 return LSMASH_ERR_NAMELESS
; /* reserved */
110 alssc
->frame_length
= lsmash_bs_show_be16( bs
, 15 );
111 alssc
->random_access
= lsmash_bs_show_byte( bs
, 17 );
112 alssc
->ra_flag
= (lsmash_bs_show_byte( bs
, 18 ) & 0xc0) >> 6;
113 if( alssc
->ra_flag
== 0 )
114 return LSMASH_ERR_PATCH_WELCOME
; /* We don't support this case. */
116 if( alssc
->samples
== 0xffffffff && alssc
->ra_flag
== 2 )
117 return LSMASH_ERR_NAMELESS
;
119 uint8_t temp8
= lsmash_bs_show_byte( bs
, 20 );
120 int chan_sort
= !!(temp8
& 0x1);
121 if( alssc
->channels
== 0 )
124 return LSMASH_ERR_INVALID_DATA
; /* If channels = 0 (mono), joint_stereo = 0. */
125 else if( temp8
& 0x4 )
126 return LSMASH_ERR_INVALID_DATA
; /* If channels = 0 (mono), mc_coding = 0. */
128 return LSMASH_ERR_INVALID_DATA
; /* If channels = 0 (mono), chan_sort = 0. */
130 int chan_config
= !!(temp8
& 0x2);
131 temp8
= lsmash_bs_show_byte( bs
, 21 );
132 int crc_enabled
= !!(temp8
& 0x80);
133 int aux_data_enabled
= !!(temp8
& 0x1);
134 als_copy_from_buffer( alssc
, bs
, ALSSC_TWELVE_LENGTH
);
137 /* chan_config_info */
138 lsmash_bs_read( bs
, 2 );
139 als_copy_from_buffer( alssc
, bs
, 2 );
143 uint32_t ChBits
= lsmash_ceil_log2( alssc
->channels
+ 1 );
144 uint32_t chan_pos_length
= (alssc
->channels
+ 1) * ChBits
;
145 chan_pos_length
= ((uint64_t)chan_pos_length
+ 7) / 8; /* byte_align */
146 lsmash_bs_read( bs
, chan_pos_length
);
147 als_copy_from_buffer( alssc
, bs
, chan_pos_length
);
149 /* orig_header, orig_trailer and crc. */
151 uint32_t header_size
= lsmash_bs_show_be32( bs
, 0 );
152 uint32_t trailer_size
= lsmash_bs_show_be32( bs
, 4 );
153 als_copy_from_buffer( alssc
, bs
, 8 );
154 if( header_size
!= 0xffffffff )
156 lsmash_bs_read( bs
, header_size
);
157 als_copy_from_buffer( alssc
, bs
, header_size
);
159 if( trailer_size
!= 0xffffffff )
161 lsmash_bs_read( bs
, trailer_size
);
162 als_copy_from_buffer( alssc
, bs
, trailer_size
);
166 lsmash_bs_read( bs
, 4 );
167 als_copy_from_buffer( alssc
, bs
, 4 );
170 /* Random access units */
172 uint32_t number_of_frames
= ((alssc
->samples
+ alssc
->frame_length
) / (alssc
->frame_length
+ 1));
173 if( alssc
->random_access
!= 0 )
174 alssc
->number_of_ra_units
= ((uint64_t)number_of_frames
+ alssc
->random_access
- 1) / alssc
->random_access
;
176 alssc
->number_of_ra_units
= 0;
177 if( alssc
->ra_flag
== 2 && alssc
->random_access
!= 0 )
179 /* We don't copy all ra_unit_size into alssc->sc_data. */
180 int64_t read_size
= (int64_t)alssc
->number_of_ra_units
* 4;
181 int64_t end_offset
= lsmash_bs_get_stream_pos( bs
) + read_size
;
182 alssc
->ra_unit_size
= lsmash_malloc( read_size
);
183 if( !alssc
->ra_unit_size
)
184 return LSMASH_ERR_MEMORY_ALLOC
;
185 uint32_t max_ra_unit_size
= 0;
186 for( uint32_t i
= 0; i
< alssc
->number_of_ra_units
; i
++ )
188 alssc
->ra_unit_size
[i
] = lsmash_bs_get_be32( bs
);
189 max_ra_unit_size
= LSMASH_MAX( max_ra_unit_size
, alssc
->ra_unit_size
[i
] );
191 lsmash_bs_read_seek( bs
, end_offset
, SEEK_SET
);
194 alssc
->ra_unit_size
= NULL
;
197 if( aux_data_enabled
)
199 uint32_t aux_size
= lsmash_bs_show_be32( bs
, 0 );
200 als_copy_from_buffer( alssc
, bs
, 4 );
201 if( aux_size
&& aux_size
!= 0xffffffff )
203 lsmash_bs_read( bs
, aux_size
);
204 als_copy_from_buffer( alssc
, bs
, aux_size
);
207 /* Set 0 to ra_flag. We will remove ra_unit_size in each access unit. */
208 alssc
->sc_data
[18] &= 0x3f;
212 static int mp4a_als_importer_get_accessunit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
**p_sample
)
214 if( !importer
->info
)
215 return LSMASH_ERR_NAMELESS
;
216 if( track_number
!= 1 )
217 return LSMASH_ERR_FUNCTION_PARAM
;
218 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_get_entry_data( importer
->summaries
, track_number
);
220 return LSMASH_ERR_NAMELESS
;
221 mp4a_als_importer_t
*als_imp
= (mp4a_als_importer_t
*)importer
->info
;
222 importer_status current_status
= importer
->status
;
223 if( current_status
== IMPORTER_EOF
)
225 lsmash_bs_t
*bs
= importer
->bs
;
226 als_specific_config_t
*alssc
= &als_imp
->alssc
;
227 if( alssc
->number_of_ra_units
== 0 )
229 lsmash_sample_t
*sample
= lsmash_create_sample( alssc
->access_unit_size
);
231 return LSMASH_ERR_MEMORY_ALLOC
;
233 memcpy( sample
->data
, lsmash_bs_get_buffer_data( bs
), alssc
->access_unit_size
);
234 sample
->length
= alssc
->access_unit_size
;
237 sample
->prop
.ra_flags
= ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC
;
238 importer
->status
= IMPORTER_EOF
;
242 if( alssc
->ra_flag
== 2 )
243 au_length
= alssc
->ra_unit_size
[ als_imp
->au_number
];
244 else /* if( alssc->ra_flag == 1 ) */
245 /* We don't export ra_unit_size into a sample. */
246 au_length
= lsmash_bs_get_be32( bs
);
247 lsmash_sample_t
*sample
= lsmash_create_sample( au_length
);
249 return LSMASH_ERR_MEMORY_ALLOC
;
251 if( lsmash_bs_get_bytes_ex( bs
, au_length
, sample
->data
) != au_length
)
253 lsmash_log( importer
, LSMASH_LOG_WARNING
, "failed to read an access unit.\n" );
254 importer
->status
= IMPORTER_ERROR
;
255 return LSMASH_ERR_INVALID_DATA
;
257 sample
->length
= au_length
;
258 sample
->dts
= als_imp
->au_number
++ * als_imp
->samples_in_frame
;
259 sample
->cts
= sample
->dts
;
260 sample
->prop
.ra_flags
= ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC
;
261 if( als_imp
->au_number
== alssc
->number_of_ra_units
)
262 importer
->status
= IMPORTER_EOF
;
268 static lsmash_audio_summary_t
*als_create_summary( lsmash_bs_t
*bs
, als_specific_config_t
*alssc
)
270 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO
);
273 summary
->sample_type
= ISOM_CODEC_TYPE_MP4A_AUDIO
;
274 summary
->aot
= MP4A_AUDIO_OBJECT_TYPE_ALS
;
275 summary
->frequency
= alssc
->samp_freq
;
276 summary
->channels
= alssc
->channels
+ 1;
277 summary
->sample_size
= (alssc
->resolution
+ 1) * 8;
278 summary
->sbr_mode
= MP4A_AAC_SBR_NOT_SPECIFIED
; /* no effect */
279 if( alssc
->random_access
!= 0 )
281 summary
->samples_in_frame
= (alssc
->frame_length
+ 1) * alssc
->random_access
;
282 summary
->max_au_length
= summary
->channels
* (summary
->sample_size
/ 8) * summary
->samples_in_frame
;
286 /* Read the remainder of overall stream as an access unit. */
287 alssc
->access_unit_size
= lsmash_bs_get_remaining_buffer_size( bs
);
290 if( lsmash_bs_read( bs
, bs
->buffer
.max_size
) < 0 )
292 alssc
->access_unit_size
= lsmash_bs_get_remaining_buffer_size( bs
);
294 summary
->max_au_length
= alssc
->access_unit_size
;
295 summary
->samples_in_frame
= 0; /* hack for mp4sys_als_importer_get_last_delta() */
297 uint32_t data_length
;
298 uint8_t *data
= mp4a_export_AudioSpecificConfig( MP4A_AUDIO_OBJECT_TYPE_ALS
,
299 summary
->frequency
, summary
->channels
, summary
->sbr_mode
,
300 alssc
->sc_data
, alssc
->size
, &data_length
);
303 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
,
304 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
310 lsmash_mp4sys_decoder_parameters_t
*param
= (lsmash_mp4sys_decoder_parameters_t
*)specific
->data
.structured
;
311 param
->objectTypeIndication
= MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3
;
312 param
->streamType
= MP4SYS_STREAM_TYPE_AudioStream
;
313 if( lsmash_set_mp4sys_decoder_specific_info( param
, data
, data_length
) < 0 )
315 lsmash_destroy_codec_specific_data( specific
);
320 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
322 lsmash_destroy_codec_specific_data( specific
);
327 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
331 static int mp4a_als_importer_probe( importer_t
*importer
)
333 mp4a_als_importer_t
*als_imp
= create_mp4a_als_importer( importer
);
335 return LSMASH_ERR_MEMORY_ALLOC
;
336 /* Parse ALS specific configuration. */
337 int err
= als_parse_specific_config( importer
->bs
, als_imp
);
340 lsmash_audio_summary_t
*summary
= als_create_summary( importer
->bs
, &als_imp
->alssc
);
343 err
= LSMASH_ERR_NAMELESS
;
346 /* importer status */
347 als_imp
->samples_in_frame
= summary
->samples_in_frame
;
348 if( lsmash_add_entry( importer
->summaries
, summary
) < 0 )
350 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
351 err
= LSMASH_ERR_MEMORY_ALLOC
;
354 importer
->info
= als_imp
;
355 importer
->status
= IMPORTER_OK
;
358 remove_mp4a_als_importer( als_imp
);
362 static uint32_t mp4a_als_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
364 debug_if( !importer
|| !importer
->info
)
366 mp4a_als_importer_t
*als_imp
= (mp4a_als_importer_t
*)importer
->info
;
367 if( !als_imp
|| track_number
!= 1 || importer
->status
!= IMPORTER_EOF
)
369 als_specific_config_t
*alssc
= &als_imp
->alssc
;
370 /* If alssc->number_of_ra_units == 0, then the last sample duration is just alssc->samples
371 * since als_create_summary sets 0 to summary->samples_in_frame i.e. als_imp->samples_in_frame. */
372 return alssc
->samples
- (alssc
->number_of_ra_units
- 1) * als_imp
->samples_in_frame
;
375 const importer_functions mp4a_als_importer
=
377 { "MPEG-4 ALS", offsetof( importer_t
, log_level
) },
379 mp4a_als_importer_probe
,
380 mp4a_als_importer_get_accessunit
,
381 mp4a_als_importer_get_last_delta
,
382 mp4a_als_importer_cleanup