list: Decide the entry eliminator of list at its initialization.
[L-SMASH.git] / importer / als_imp.c
blobf2705c20a790763b7b64e514702ff7cc8fe94a41
1 /*****************************************************************************
2 * als_imp.c
3 *****************************************************************************
4 * Copyright (C) 2011-2017 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 */
25 #include <string.h>
27 #define LSMASH_IMPORTER_INTERNAL
28 #include "importer.h"
30 /***************************************************************************
31 MPEG-4 ALS importer
32 ISO/IEC 14496-3 2009 Fourth edition
33 ***************************************************************************/
34 #include "codecs/mp4a.h"
36 #define ALSSC_TWELVE_LENGTH 22
38 typedef struct
40 uint32_t size;
41 uint32_t samp_freq;
42 uint32_t samples;
43 uint32_t channels;
44 uint16_t frame_length;
45 uint8_t resolution;
46 uint8_t random_access;
47 uint8_t ra_flag;
48 uint32_t access_unit_size;
49 uint32_t number_of_ra_units;
50 uint32_t *ra_unit_size;
51 uint8_t *sc_data;
52 size_t alloc;
53 } als_specific_config_t;
55 typedef struct
57 als_specific_config_t alssc;
58 uint32_t samples_in_frame;
59 uint32_t au_number;
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 );
86 if( !temp )
87 return;
88 alssc->sc_data = temp;
89 alssc->alloc = alloc;
91 memcpy( alssc->sc_data + alssc->size, lsmash_bs_get_buffer_data( bs ), size );
92 alssc->size += 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. */
115 #if 0
116 if( alssc->samples == 0xffffffff && alssc->ra_flag == 2 )
117 return LSMASH_ERR_NAMELESS;
118 #endif
119 uint8_t temp8 = lsmash_bs_show_byte( bs, 20 );
120 int chan_sort = !!(temp8 & 0x1);
121 if( alssc->channels == 0 )
123 if( temp8 & 0x8 )
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. */
127 else if( chan_sort )
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 );
135 if( chan_config )
137 /* chan_config_info */
138 lsmash_bs_read( bs, 2 );
139 als_copy_from_buffer( alssc, bs, 2 );
141 if( chan_sort )
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 );
164 if( crc_enabled )
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;
175 else
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 );
193 else
194 alssc->ra_unit_size = NULL;
196 /* auxiliary data */
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;
209 return 0;
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_list_get_entry_data( importer->summaries, track_number );
219 if( !summary )
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 )
224 return 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 );
230 if( !sample )
231 return LSMASH_ERR_MEMORY_ALLOC;
232 *p_sample = sample;
233 memcpy( sample->data, lsmash_bs_get_buffer_data( bs ), alssc->access_unit_size );
234 sample->length = alssc->access_unit_size;
235 sample->cts = 0;
236 sample->dts = 0;
237 sample->prop.ra_flags = ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC;
238 importer->status = IMPORTER_EOF;
239 return 0;
241 uint32_t au_length;
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 );
248 if( !sample )
249 return LSMASH_ERR_MEMORY_ALLOC;
250 *p_sample = sample;
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;
263 return 0;
266 #undef CHECK_UPDATE
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 );
271 if( !summary )
272 return NULL;
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;
284 else
286 /* Read the remainder of overall stream as an access unit. */
287 alssc->access_unit_size = lsmash_bs_get_remaining_buffer_size( bs );
288 while( !bs->eof )
290 if( lsmash_bs_read( bs, bs->buffer.max_size ) < 0 )
291 goto fail;
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 );
301 if( !data )
302 goto fail;
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 );
305 if( !specific )
307 lsmash_free( data );
308 goto fail;
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 );
316 lsmash_free( data );
317 goto fail;
319 lsmash_free( data );
320 if( lsmash_list_add_entry( &summary->opaque->list, specific ) < 0 )
322 lsmash_destroy_codec_specific_data( specific );
323 goto fail;
325 return summary;
326 fail:
327 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
328 return NULL;
331 static int mp4a_als_importer_probe( importer_t *importer )
333 mp4a_als_importer_t *als_imp = create_mp4a_als_importer( importer );
334 if( !als_imp )
335 return LSMASH_ERR_MEMORY_ALLOC;
336 /* Parse ALS specific configuration. */
337 int err = als_parse_specific_config( importer->bs, als_imp );
338 if( err < 0 )
339 goto fail;
340 lsmash_audio_summary_t *summary = als_create_summary( importer->bs, &als_imp->alssc );
341 if( !summary )
343 err = LSMASH_ERR_NAMELESS;
344 goto fail;
346 /* importer status */
347 als_imp->samples_in_frame = summary->samples_in_frame;
348 if( lsmash_list_add_entry( importer->summaries, summary ) < 0 )
350 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
351 err = LSMASH_ERR_MEMORY_ALLOC;
352 goto fail;
354 importer->info = als_imp;
355 importer->status = IMPORTER_OK;
356 return 0;
357 fail:
358 remove_mp4a_als_importer( als_imp );
359 return err;
362 static uint32_t mp4a_als_importer_get_last_delta( importer_t *importer, uint32_t track_number )
364 debug_if( !importer || !importer->info )
365 return 0;
366 mp4a_als_importer_t *als_imp = (mp4a_als_importer_t *)importer->info;
367 if( !als_imp || track_number != 1 || importer->status != IMPORTER_EOF )
368 return 0;
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