isom: Utilize meaningful error values.
[L-SMASH.git] / cli / als_imp.c
blob2a24c96332a7c3e8a8e0805681c9c4485397cae6
1 /*****************************************************************************
2 * als_imp.c
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 */
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 importer_status status;
58 lsmash_bs_t *bs;
59 als_specific_config_t alssc;
60 uint32_t samples_in_frame;
61 uint32_t au_number;
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) );
81 if( !als_imp )
82 return NULL;
83 als_imp->bs = lsmash_bs_create();
84 if( !als_imp->bs )
86 lsmash_free( als_imp );
87 return NULL;
89 return 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 );
98 if( !temp )
99 return;
100 alssc->sc_data = temp;
101 alssc->alloc = alloc;
103 memcpy( alssc->sc_data + alssc->size, lsmash_bs_get_buffer_data( bs ), size );
104 alssc->size += 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 ) )
113 return -1;
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. */
128 #if 0
129 if( alssc->samples == 0xffffffff && alssc->ra_flag == 2 )
130 return -1;
131 #endif
132 uint8_t temp8 = lsmash_bs_show_byte( bs, 20 );
133 int chan_sort = !!(temp8 & 0x1);
134 if( alssc->channels == 0 )
136 if( temp8 & 0x8 )
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. */
140 else if( chan_sort )
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 );
148 if( chan_config )
150 /* chan_config_info */
151 lsmash_bs_read( bs, 2 );
152 als_copy_from_buffer( alssc, bs, 2 );
154 if( chan_sort )
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 );
177 if( crc_enabled )
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;
188 else
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 )
197 return -1;
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 );
206 else
207 alssc->ra_unit_size = NULL;
209 /* auxiliary data */
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;
222 return 0;
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 )
228 return -1;
229 if( !importer->info || track_number != 1 )
230 return -1;
231 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_get_entry_data( importer->summaries, track_number );
232 if( !summary )
233 return -1;
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;
239 return 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;
251 return 0;
253 uint32_t au_length;
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" );
262 return -1;
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;
268 return -1;
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;
276 return 0;
279 #undef CHECK_UPDATE
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 );
284 if( !summary )
285 return NULL;
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;
297 else
299 /* Read the remainder of overall stream as an access unit. */
300 alssc->access_unit_size = lsmash_bs_get_remaining_buffer_size( bs );
301 while( !bs->eof )
303 if( lsmash_bs_read( bs, bs->buffer.max_size ) < 0 )
304 return NULL;
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 );
314 if( !data )
316 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
317 return NULL;
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 );
321 if( !specific )
323 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
324 lsmash_free( data );
325 return NULL;
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 );
334 lsmash_free( data );
335 return NULL;
337 lsmash_free( data );
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 );
342 return NULL;
344 return summary;
347 static int mp4a_als_importer_probe( importer_t *importer )
349 mp4a_als_importer_t *als_imp = create_mp4a_als_importer( importer );
350 if( !als_imp )
351 return -1;
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 )
360 goto fail;
361 lsmash_audio_summary_t *summary = als_create_summary( bs, &als_imp->alssc );
362 if( !summary )
363 goto fail;
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 );
370 goto fail;
372 importer->info = als_imp;
373 return 0;
374 fail:
375 remove_mp4a_als_importer( als_imp );
376 return -1;
379 static uint32_t mp4a_als_importer_get_last_delta( importer_t *importer, uint32_t track_number )
381 debug_if( !importer || !importer->info )
382 return 0;
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 )
385 return 0;
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