dts: Support DTS:X muxing.
[L-SMASH.git] / codecs / description.c
blob0412c220fe91286296ee98cf39c2bfc10b146976
1 /*****************************************************************************
2 * description.c:
3 *****************************************************************************
4 * Copyright (C) 2012-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 */
25 #include <stdlib.h>
26 #include <string.h>
28 #include "core/box.h"
30 #include "a52.h"
31 #include "mp4a.h"
32 #include "mp4sys.h"
33 #include "description.h"
35 typedef isom_wave_t lsmash_qt_decoder_parameters_t;
37 static void global_destruct_specific_data( void *data )
39 if( !data )
40 return;
41 lsmash_codec_global_header_t *global = (lsmash_codec_global_header_t *)data;
42 lsmash_free( global->header_data );
43 lsmash_free( global );
46 static int isom_is_qt_video( lsmash_codec_type_t type )
48 return lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_2VUY_VIDEO )
49 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_APCH_VIDEO )
50 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_APCN_VIDEO )
51 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_APCS_VIDEO )
52 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_APCO_VIDEO )
53 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_AP4H_VIDEO )
54 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_AP4X_VIDEO )
55 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_CFHD_VIDEO )
56 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_CIVD_VIDEO )
57 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVC_VIDEO )
58 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVCP_VIDEO )
59 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVPP_VIDEO )
60 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DV5N_VIDEO )
61 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DV5P_VIDEO )
62 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVH2_VIDEO )
63 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVH3_VIDEO )
64 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVH5_VIDEO )
65 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVH6_VIDEO )
66 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVHP_VIDEO )
67 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVHQ_VIDEO )
68 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DV10_VIDEO )
69 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVOO_VIDEO )
70 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVOR_VIDEO )
71 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVTV_VIDEO )
72 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_DVVT_VIDEO )
73 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_FLIC_VIDEO )
74 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_GIF_VIDEO )
75 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_H261_VIDEO )
76 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_H263_VIDEO )
77 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_HD10_VIDEO )
78 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_JPEG_VIDEO )
79 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_M105_VIDEO )
80 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_MJPA_VIDEO )
81 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_MJPB_VIDEO )
82 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_PNG_VIDEO )
83 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_PNTG_VIDEO )
84 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_RAW_VIDEO )
85 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_RLE_VIDEO )
86 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_RPZA_VIDEO )
87 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_SHR0_VIDEO )
88 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_SHR1_VIDEO )
89 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_SHR2_VIDEO )
90 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_SHR3_VIDEO )
91 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_SHR4_VIDEO )
92 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_SVQ1_VIDEO )
93 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_SVQ3_VIDEO )
94 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_TGA_VIDEO )
95 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_TIFF_VIDEO )
96 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_ULRA_VIDEO )
97 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_ULRG_VIDEO )
98 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_ULY2_VIDEO )
99 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_ULY0_VIDEO )
100 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_ULH2_VIDEO )
101 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_ULH0_VIDEO )
102 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_UQY2_VIDEO )
103 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_V210_VIDEO )
104 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_V216_VIDEO )
105 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_V308_VIDEO )
106 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_V408_VIDEO )
107 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_V410_VIDEO )
108 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_YUV2_VIDEO )
109 || lsmash_check_codec_type_identical( type, QT_CODEC_TYPE_WRLE_VIDEO );
112 static int isom_is_nalff( lsmash_codec_type_t type )
114 return lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_AVC1_VIDEO )
115 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_AVC2_VIDEO )
116 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_AVC3_VIDEO )
117 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_AVC4_VIDEO )
118 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_AVCP_VIDEO )
119 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_HVC1_VIDEO )
120 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_HEV1_VIDEO );
123 static int isom_is_dts_audio( lsmash_codec_type_t type )
125 return lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_DTSC_AUDIO )
126 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_DTSE_AUDIO )
127 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_DTSH_AUDIO )
128 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_DTSL_AUDIO )
129 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_DTSX_AUDIO )
130 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_DTSEL_AUDIO )
131 || lsmash_check_codec_type_identical( type, ISOM_CODEC_TYPE_DTSDL_AUDIO );
134 int lsmash_convert_crop_into_clap( lsmash_crop_t crop, uint32_t width, uint32_t height, lsmash_clap_t *clap )
136 if( !clap || crop.top.d == 0 || crop.bottom.d == 0 || crop.left.d == 0 || crop.right.d == 0 )
137 return LSMASH_ERR_FUNCTION_PARAM;
138 uint64_t vertical_crop_lcm = lsmash_get_lcm( crop.top.d, crop.bottom.d );
139 uint64_t horizontal_crop_lcm = lsmash_get_lcm( crop.left.d, crop.right.d );
140 lsmash_rational_u64_t clap_height;
141 lsmash_rational_u64_t clap_width;
142 lsmash_rational_s64_t clap_horizontal_offset;
143 lsmash_rational_s64_t clap_vertical_offset;
144 clap_height.d = vertical_crop_lcm;
145 clap_width.d = horizontal_crop_lcm;
146 clap_horizontal_offset.d = 2 * vertical_crop_lcm;
147 clap_vertical_offset.d = 2 * horizontal_crop_lcm;
148 clap_height.n = height * vertical_crop_lcm
149 - (crop.top.n * (vertical_crop_lcm / crop.top.d) + crop.bottom.n * (vertical_crop_lcm / crop.bottom.d));
150 clap_width.n = width * horizontal_crop_lcm
151 - (crop.left.n * (horizontal_crop_lcm / crop.left.d) + crop.right.n * (horizontal_crop_lcm / crop.right.d));
152 clap_horizontal_offset.n = (int64_t)(crop.left.n * (horizontal_crop_lcm / crop.left.d))
153 - crop.right.n * (horizontal_crop_lcm / crop.right.d);
154 clap_vertical_offset.n = (int64_t)(crop.top.n * (vertical_crop_lcm / crop.top.d))
155 - crop.bottom.n * (vertical_crop_lcm / crop.bottom.d);
156 lsmash_reduce_fraction( &clap_height.n, &clap_height.d );
157 lsmash_reduce_fraction( &clap_width.n, &clap_width.d );
158 lsmash_reduce_fraction_su( &clap_vertical_offset.n, &clap_vertical_offset.d );
159 lsmash_reduce_fraction_su( &clap_horizontal_offset.n, &clap_horizontal_offset.d );
160 clap->height = (lsmash_rational_u32_t){ clap_height.n, clap_height.d };
161 clap->width = (lsmash_rational_u32_t){ clap_width.n, clap_width.d };
162 clap->vertical_offset = (lsmash_rational_s32_t){ clap_vertical_offset.n, clap_vertical_offset.d };
163 clap->horizontal_offset = (lsmash_rational_s32_t){ clap_horizontal_offset.n, clap_horizontal_offset.d };
164 return 0;
167 int lsmash_convert_clap_into_crop( lsmash_clap_t clap, uint32_t width, uint32_t height, lsmash_crop_t *crop )
169 if( !crop || clap.height.d == 0 || clap.vertical_offset.d == 0 || clap.width.d == 0 || clap.horizontal_offset.d == 0 )
170 return LSMASH_ERR_FUNCTION_PARAM;
171 uint64_t clap_vertical_lcm = lsmash_get_lcm( clap.height.d, clap.vertical_offset.d );
172 uint64_t clap_horizontal_lcm = lsmash_get_lcm( clap.width.d, clap.horizontal_offset.d );
173 lsmash_rational_u64_t crop_top;
174 lsmash_rational_u64_t crop_bottom;
175 lsmash_rational_u64_t crop_left;
176 lsmash_rational_u64_t crop_right;
177 crop_top.d = 2 * clap_vertical_lcm;
178 crop_bottom.d = 2 * clap_vertical_lcm;
179 crop_left.d = 2 * clap_horizontal_lcm;
180 crop_right.d = 2 * clap_horizontal_lcm;
181 crop_top.n = (height * crop_top.d - clap.height.n * (crop_top.d / clap.height.d)) / 2
182 + clap.vertical_offset.n * (crop_top.d / clap.vertical_offset.d);
183 crop_bottom.n = (height * crop_bottom.d - clap.height.n * (crop_bottom.d / clap.height.d)) / 2
184 - clap.vertical_offset.n * (crop_bottom.d / clap.vertical_offset.d);
185 crop_left.n = (width * crop_left.d - clap.width.n * (crop_left.d / clap.width.d)) / 2
186 + clap.horizontal_offset.n * (crop_left.d / clap.horizontal_offset.d);
187 crop_right.n = (width * crop_right.d - clap.width.n * (crop_right.d / clap.width.d)) / 2
188 - clap.horizontal_offset.n * (crop_right.d / clap.horizontal_offset.d);
189 lsmash_reduce_fraction( &crop_top.n, &crop_top.d );
190 lsmash_reduce_fraction( &crop_bottom.n, &crop_bottom.d );
191 lsmash_reduce_fraction( &crop_left.n, &crop_left.d );
192 lsmash_reduce_fraction( &crop_right.n, &crop_right.d );
193 crop->top = (lsmash_rational_u32_t){ crop_top.n, crop_top.d };
194 crop->bottom = (lsmash_rational_u32_t){ crop_bottom.n, crop_bottom.d };
195 crop->left = (lsmash_rational_u32_t){ crop_left.n, crop_left.d };
196 crop->right = (lsmash_rational_u32_t){ crop_right.n, crop_right.d };
197 return 0;
200 static void isom_destruct_nothing( void *data )
202 /* Do nothing. */;
205 static int isom_initialize_structured_codec_specific_data( lsmash_codec_specific_t *specific )
207 extern void mp4sys_destruct_decoder_config( void * );
208 extern void h264_destruct_specific_data( void * );
209 extern void hevc_destruct_specific_data( void * );
210 extern void vc1_destruct_specific_data( void * );
211 extern void dts_destruct_specific_data( void * );
212 switch( specific->type )
214 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
215 specific->size = sizeof(lsmash_mp4sys_decoder_parameters_t);
216 specific->destruct = mp4sys_destruct_decoder_config;
217 break;
218 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 :
219 specific->size = sizeof(lsmash_h264_specific_parameters_t);
220 specific->destruct = h264_destruct_specific_data;
221 break;
222 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC :
223 specific->size = sizeof(lsmash_hevc_specific_parameters_t);
224 specific->destruct = hevc_destruct_specific_data;
225 break;
226 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 :
227 specific->size = sizeof(lsmash_vc1_specific_parameters_t);
228 specific->destruct = vc1_destruct_specific_data;
229 break;
230 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
231 specific->size = sizeof(lsmash_ac3_specific_parameters_t);
232 specific->destruct = lsmash_free;
233 break;
234 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
235 specific->size = sizeof(lsmash_eac3_specific_parameters_t);
236 specific->destruct = lsmash_free;
237 break;
238 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
239 specific->size = sizeof(lsmash_dts_specific_parameters_t);
240 specific->destruct = dts_destruct_specific_data;
241 break;
242 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
243 specific->size = sizeof(lsmash_alac_specific_parameters_t);
244 specific->destruct = lsmash_free;
245 break;
246 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE :
247 specific->size = sizeof(lsmash_isom_sample_scale_t);
248 specific->destruct = lsmash_free;
249 break;
250 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE :
251 specific->size = sizeof(lsmash_h264_bitrate_t);
252 specific->destruct = lsmash_free;
253 break;
254 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON :
255 specific->size = sizeof(lsmash_qt_video_common_t);
256 specific->destruct = lsmash_free;
257 break;
258 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
259 specific->size = sizeof(lsmash_qt_audio_common_t);
260 specific->destruct = lsmash_free;
261 break;
262 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
263 specific->size = sizeof(lsmash_qt_audio_format_specific_flags_t);
264 specific->destruct = lsmash_free;
265 break;
266 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
267 specific->size = sizeof(lsmash_codec_global_header_t);
268 specific->destruct = global_destruct_specific_data;
269 break;
270 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO :
271 specific->size = sizeof(lsmash_qt_field_info_t);
272 specific->destruct = lsmash_free;
273 break;
274 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT :
275 specific->size = sizeof(lsmash_qt_pixel_format_t);
276 specific->destruct = lsmash_free;
277 break;
278 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS :
279 specific->size = sizeof(lsmash_qt_significant_bits_t);
280 specific->destruct = lsmash_free;
281 break;
282 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
283 specific->size = sizeof(lsmash_qt_audio_channel_layout_t);
284 specific->destruct = lsmash_free;
285 break;
286 default :
287 specific->size = 0;
288 specific->destruct = isom_destruct_nothing;
289 return 0;
291 specific->data.structured = lsmash_malloc_zero( specific->size );
292 if( !specific->data.structured )
294 specific->size = 0;
295 specific->destruct = NULL;
296 return LSMASH_ERR_MEMORY_ALLOC;
298 return 0;
301 static inline int isom_initialize_codec_specific_data( lsmash_codec_specific_t *specific,
302 lsmash_codec_specific_data_type type,
303 lsmash_codec_specific_format format )
305 specific->type = type;
306 specific->format = format;
307 if( format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
309 int err = isom_initialize_structured_codec_specific_data( specific );
310 if( err < 0 )
311 return err;
313 else
315 specific->data.unstructured = NULL;
316 specific->size = 0;
317 specific->destruct = (lsmash_codec_specific_destructor_t)lsmash_free;
319 return 0;
322 void lsmash_destroy_codec_specific_data( lsmash_codec_specific_t *specific )
324 if( !specific )
325 return;
326 if( specific->destruct )
328 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
330 if( specific->data.structured )
331 specific->destruct( specific->data.structured );
333 else
335 if( specific->data.unstructured )
336 specific->destruct( specific->data.unstructured );
339 lsmash_free( specific );
342 lsmash_codec_specific_t *lsmash_create_codec_specific_data( lsmash_codec_specific_data_type type, lsmash_codec_specific_format format )
344 lsmash_codec_specific_t *specific = lsmash_malloc( sizeof(lsmash_codec_specific_t) );
345 if( !specific )
346 return NULL;
347 if( isom_initialize_codec_specific_data( specific, type, format ) < 0 )
349 lsmash_destroy_codec_specific_data( specific );
350 return NULL;
352 return specific;
355 static int isom_duplicate_structured_specific_data( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
357 extern int mp4sys_copy_decoder_config( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
358 extern int h264_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
359 extern int hevc_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
360 extern int vc1_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
361 extern int dts_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
362 void *src_data = src->data.structured;
363 void *dst_data = dst->data.structured;
364 switch( src->type )
366 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
367 return mp4sys_copy_decoder_config( dst, src );
368 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 :
369 return h264_copy_codec_specific( dst, src );
370 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC :
371 return hevc_copy_codec_specific( dst, src );
372 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 :
373 return vc1_copy_codec_specific( dst, src );
374 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
375 *(lsmash_ac3_specific_parameters_t *)dst_data = *(lsmash_ac3_specific_parameters_t *)src_data;
376 return 0;
377 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
378 *(lsmash_eac3_specific_parameters_t *)dst_data = *(lsmash_eac3_specific_parameters_t *)src_data;
379 return 0;
380 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
381 return dts_copy_codec_specific( dst, src );
382 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
383 *(lsmash_alac_specific_parameters_t *)dst_data = *(lsmash_alac_specific_parameters_t *)src_data;
384 return 0;
385 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE :
386 *(lsmash_isom_sample_scale_t *)dst_data = *(lsmash_isom_sample_scale_t *)src_data;
387 return 0;
388 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE :
389 *(lsmash_h264_bitrate_t *)dst_data = *(lsmash_h264_bitrate_t *)src_data;
390 return 0;
391 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON :
392 *(lsmash_qt_video_common_t *)dst_data = *(lsmash_qt_video_common_t *)src_data;
393 return 0;
394 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
395 *(lsmash_qt_audio_common_t *)dst_data = *(lsmash_qt_audio_common_t *)src_data;
396 return 0;
397 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
398 *(lsmash_qt_audio_format_specific_flags_t *)dst_data = *(lsmash_qt_audio_format_specific_flags_t *)src_data;
399 return 0;
400 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
402 lsmash_codec_global_header_t *src_global = (lsmash_codec_global_header_t *)src_data;
403 if( src_global->header_data && src_global->header_size )
405 lsmash_codec_global_header_t *dst_global = (lsmash_codec_global_header_t *)dst_data;
406 dst_global->header_data = lsmash_memdup( src_global->header_data, src_global->header_size );
407 if( !dst_global->header_data )
408 return LSMASH_ERR_MEMORY_ALLOC;
409 dst_global->header_size = src_global->header_size;
411 return 0;
413 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO :
414 *(lsmash_qt_field_info_t *)dst_data = *(lsmash_qt_field_info_t *)src_data;
415 return 0;
416 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT :
417 *(lsmash_qt_pixel_format_t *)dst_data = *(lsmash_qt_pixel_format_t *)src_data;
418 return 0;
419 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS :
420 *(lsmash_qt_significant_bits_t *)dst_data = *(lsmash_qt_significant_bits_t *)src_data;
421 return 0;
422 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL :
423 *(lsmash_qt_gamma_t *)dst_data = *(lsmash_qt_gamma_t *)src_data;
424 return 0;
425 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
426 *(lsmash_qt_audio_channel_layout_t *)dst_data = *(lsmash_qt_audio_channel_layout_t *)src_data;
427 return 0;
428 default :
429 return LSMASH_ERR_NAMELESS;
433 lsmash_codec_specific_t *isom_duplicate_codec_specific_data( lsmash_codec_specific_t *specific )
435 if( !specific )
436 return NULL;
437 lsmash_codec_specific_t *dup = lsmash_create_codec_specific_data( specific->type, specific->format );
438 if( !dup )
439 return NULL;
440 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
442 if( isom_duplicate_structured_specific_data( dup, specific ) < 0 )
444 lsmash_destroy_codec_specific_data( dup );
445 return NULL;
448 else
450 dup->data.unstructured = lsmash_memdup( specific->data.unstructured, specific->size );
451 if( !dup->data.unstructured )
453 lsmash_destroy_codec_specific_data( dup );
454 return NULL;
457 dup->size = specific->size;
458 return dup;
461 static int isom_construct_global_specific_header( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
463 if( src->size < ISOM_BASEBOX_COMMON_SIZE )
464 return LSMASH_ERR_INVALID_DATA;
465 lsmash_codec_global_header_t *global = (lsmash_codec_global_header_t *)dst->data.structured;
466 uint8_t *data = src->data.unstructured;
467 uint64_t size = LSMASH_GET_BE32( data );
468 data += ISOM_BASEBOX_COMMON_SIZE;
469 if( size == 1 )
471 size = LSMASH_GET_BE64( data );
472 data += 8;
474 if( size != src->size )
475 return LSMASH_ERR_INVALID_DATA;
476 global->header_size = size - ISOM_BASEBOX_COMMON_SIZE;
477 if( data != src->data.unstructured + ISOM_BASEBOX_COMMON_SIZE )
478 global->header_size -= 8; /* largesize */
479 if( global->header_size )
481 global->header_data = lsmash_memdup( data, global->header_size );
482 if( !global->header_data )
483 return LSMASH_ERR_MEMORY_ALLOC;
485 return 0;
488 static int isom_construct_audio_channel_layout( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
490 if( src->size < ISOM_FULLBOX_COMMON_SIZE + 12 )
491 return LSMASH_ERR_INVALID_DATA;
492 lsmash_qt_audio_channel_layout_t *layout = (lsmash_qt_audio_channel_layout_t *)dst->data.structured;
493 uint8_t *data = src->data.unstructured;
494 uint64_t size = LSMASH_GET_BE32( data );
495 data += ISOM_FULLBOX_COMMON_SIZE;
496 if( size == 1 )
498 size = LSMASH_GET_BE64( data );
499 data += 8;
501 if( size != src->size )
502 return LSMASH_ERR_INVALID_DATA;
503 layout->channelLayoutTag = LSMASH_GET_BE32( &data[0] );
504 layout->channelBitmap = LSMASH_GET_BE32( &data[4] );
505 return 0;
508 #if 0
509 static int codec_construct_qt_audio_decompression_info( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
511 if( src->size < ISOM_BASEBOX_COMMON_SIZE )
512 return LSMASH_ERR_INVALID_DATA;
513 uint8_t *data = src->data.unstructured;
514 uint64_t size;
515 uint32_t type;
516 uint32_t offset = isom_read_box_size_and_type_from_binary_string( &data, &size, &type );
517 if( size != src->size )
518 return LSMASH_ERR_INVALID_DATA;
519 uint8_t *end = src->data.unstructured + src->size;
520 isom_wave_t *wave = lsmash_malloc_zero( sizeof(isom_wave_t) );
521 if( !wave )
522 return LSMASH_ERR_MEMORY_ALLOC;
523 wave->type = QT_BOX_TYPE_WAVE;
524 for( uint8_t *pos = data; pos + ISOM_BASEBOX_COMMON_SIZE <= end; )
526 offset = isom_read_box_size_and_type_from_binary_string( &pos, &size, &type );
527 switch( type )
529 case QT_BOX_TYPE_FRMA :
531 if( pos + 4 > end )
532 return LSMASH_ERR_INVALID_DATA;
533 isom_frma_t *frma = isom_add_frma( wave );
534 if( !frma )
535 return LSMASH_ERR_NAMELESS;
536 frma->data_format = LSMASH_GET_BE32( pos );
537 pos += 4;
538 break;
540 case QT_BOX_TYPE_ENDA :
542 if( pos + 2 > end )
543 return LSMASH_ERR_INVALID_DATA;
544 isom_enda_t *enda = isom_add_enda( wave );
545 if( !enda )
546 return LSMASH_ERR_NAMELESS;
547 enda->littleEndian = LSMASH_GET_BE16( pos );
548 break;
550 case QT_BOX_TYPE_MP4A :
552 if( pos + 4 > end )
553 return LSMASH_ERR_INVALID_DATA;
554 isom_mp4a_t *mp4a = isom_add_mp4a( wave );
555 if( !mp4a )
556 return LSMASH_ERR_NAMELESS;
557 mp4a->unknown = LSMASH_GET_BE32( pos );
558 pos += 4;
559 break;
561 case QT_BOX_TYPE_TERMINATOR :
563 if( !isom_add_terminator( wave ) )
564 return LSMASH_ERR_NAMELESS;
565 break;
567 default :
569 isom_unknown_box_t *box = lsmash_malloc_zero( sizeof(isom_unknown_box_t) );
570 if( !box )
571 return LSMASH_ERR_MEMORY_ALLOC;
572 isom_init_box_common( box, wave, type, isom_remove_unknown_box );
573 box->unknown_size = size - offset;
574 box->unknown_field = lsmash_memdup( pos, box->unknown_size );
575 if( !box->unknown_field )
577 lsmash_free( box );
578 return LSMASH_ERR_MEMORY_ALLOC;
580 if( lsmash_add_entry( &wave->extensions, box ) < 0 )
582 isom_remove_unknown_box( box );
583 return LSMASH_ERR_MEMORY_ALLOC;
585 pos += box->unknown_size;
586 break;
590 return 0;
592 #endif
594 /* structured <-> unstructured conversion might be irreversible by CODEC
595 * since structured formats we defined don't always have all contents included in unstructured data. */
596 lsmash_codec_specific_t *lsmash_convert_codec_specific_format( lsmash_codec_specific_t *specific, lsmash_codec_specific_format format )
598 if( !specific || format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSPECIFIED )
599 return NULL;
600 if( format == specific->format )
601 return isom_duplicate_codec_specific_data( specific );
602 lsmash_codec_specific_t *dst = lsmash_create_codec_specific_data( specific->type, format );
603 if( !dst )
604 return NULL;
605 if( format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
606 /* structured -> unstructured */
607 switch( specific->type )
609 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
610 dst->data.unstructured = lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t *)specific->data.structured, &dst->size );
611 if( !dst->data.unstructured )
612 goto fail;
613 return dst;
614 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 :
615 dst->data.unstructured = lsmash_create_h264_specific_info( (lsmash_h264_specific_parameters_t *)specific->data.structured, &dst->size );
616 if( !dst->data.unstructured )
617 goto fail;
618 return dst;
619 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC :
620 dst->data.unstructured = lsmash_create_hevc_specific_info( (lsmash_hevc_specific_parameters_t *)specific->data.structured, &dst->size );
621 if( !dst->data.unstructured )
622 goto fail;
623 return dst;
624 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 :
625 dst->data.unstructured = lsmash_create_vc1_specific_info( (lsmash_vc1_specific_parameters_t *)specific->data.structured, &dst->size );
626 if( !dst->data.unstructured )
627 goto fail;
628 return dst;
629 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
630 dst->data.unstructured = lsmash_create_ac3_specific_info( (lsmash_ac3_specific_parameters_t *)specific->data.structured, &dst->size );
631 if( !dst->data.unstructured )
632 goto fail;
633 return dst;
634 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
635 dst->data.unstructured = lsmash_create_eac3_specific_info( (lsmash_eac3_specific_parameters_t *)specific->data.structured, &dst->size );
636 if( !dst->data.unstructured )
637 goto fail;
638 return dst;
639 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
640 dst->data.unstructured = lsmash_create_dts_specific_info( (lsmash_dts_specific_parameters_t *)specific->data.structured, &dst->size );
641 if( !dst->data.unstructured )
642 goto fail;
643 return dst;
644 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
645 dst->data.unstructured = lsmash_create_alac_specific_info( (lsmash_alac_specific_parameters_t *)specific->data.structured, &dst->size );
646 if( !dst->data.unstructured )
647 goto fail;
648 return dst;
649 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
651 lsmash_bs_t *bs = lsmash_bs_create();
652 if( !bs )
653 goto fail;
654 lsmash_codec_global_header_t *global = specific->data.structured;
655 lsmash_bs_put_be32( bs, ISOM_BASEBOX_COMMON_SIZE + global->header_size );
656 lsmash_bs_put_be32( bs, QT_BOX_TYPE_GLBL.fourcc );
657 lsmash_bs_put_bytes( bs, global->header_size, global->header_data );
658 dst->data.unstructured = lsmash_bs_export_data( bs, &dst->size );
659 lsmash_bs_cleanup( bs );
660 if( !dst->data.unstructured || dst->size != (ISOM_BASEBOX_COMMON_SIZE + global->header_size) )
661 goto fail;
662 return dst;
664 default :
665 break;
667 else if( format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
669 /* unstructured -> structured */
670 extern int mp4sys_construct_decoder_config( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
671 extern int h264_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
672 extern int hevc_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
673 extern int vc1_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
674 extern int ac3_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
675 extern int eac3_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
676 extern int dts_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
677 extern int alac_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
678 static const struct
680 lsmash_codec_specific_data_type data_type;
681 int (*constructor)( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
682 } codec_specific_format_constructor_table[] =
684 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG, mp4sys_construct_decoder_config },
685 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264, h264_construct_specific_parameters },
686 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC, hevc_construct_specific_parameters },
687 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1, vc1_construct_specific_parameters },
688 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3, ac3_construct_specific_parameters },
689 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3, eac3_construct_specific_parameters },
690 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS, dts_construct_specific_parameters },
691 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC, alac_construct_specific_parameters },
692 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER, isom_construct_global_specific_header },
693 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT, isom_construct_audio_channel_layout },
694 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN, NULL }
696 int (*constructor)( lsmash_codec_specific_t *, lsmash_codec_specific_t * ) = NULL;
697 for( int i = 0; codec_specific_format_constructor_table[i].constructor; i++ )
698 if( specific->type == codec_specific_format_constructor_table[i].data_type )
700 constructor = codec_specific_format_constructor_table[i].constructor;
701 break;
703 if( constructor && !constructor( dst, specific ) )
704 return dst;
706 fail:
707 lsmash_destroy_codec_specific_data( dst );
708 return NULL;
711 static inline void isom_set_default_compressorname( char *compressorname, lsmash_codec_type_t sample_type )
713 static struct compressorname_table_tag
715 lsmash_codec_type_t type;
716 char name[33];
717 } compressorname_table[33] = { { LSMASH_CODEC_TYPE_INITIALIZER, { '\0' } } };
718 if( compressorname_table[0].name[0] == '\0' )
720 int i = 0;
721 #define ADD_COMPRESSORNAME_TABLE( type, name ) compressorname_table[i++] = (struct compressorname_table_tag){ type, name }
722 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC1_VIDEO, "\012AVC Coding" );
723 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC2_VIDEO, "\012AVC Coding" );
724 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC3_VIDEO, "\012AVC Coding" );
725 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC4_VIDEO, "\012AVC Coding" );
726 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVCP_VIDEO, "\016AVC Parameters" );
727 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HVC1_VIDEO, "\013HEVC Coding" );
728 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HEV1_VIDEO, "\013HEVC Coding" );
729 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_SVC1_VIDEO, "\012SVC Coding" );
730 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC1_VIDEO, "\012MVC Coding" );
731 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC2_VIDEO, "\012MVC Coding" );
732 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCH_VIDEO, "\023Apple ProRes 422 (HQ)" );
733 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCN_VIDEO, "\023Apple ProRes 422 (SD)" );
734 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCS_VIDEO, "\023Apple ProRes 422 (LT)" );
735 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCO_VIDEO, "\026Apple ProRes 422 (Proxy)" );
736 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4H_VIDEO, "\019Apple ProRes 4444" );
737 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4X_VIDEO, "\022Apple ProRes 4444 XQ" );
738 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVPP_VIDEO, "\014DVCPRO - PAL" );
739 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5N_VIDEO, "\017DVCPRO50 - NTSC" );
740 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5P_VIDEO, "\016DVCPRO50 - PAL" );
741 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH2_VIDEO, "\019DVCPRO HD 1080p25" );
742 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH3_VIDEO, "\019DVCPRO HD 1080p30" );
743 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH5_VIDEO, "\019DVCPRO HD 1080i50" );
744 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH6_VIDEO, "\019DVCPRO HD 1080i60" );
745 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHP_VIDEO, "\018DVCPRO HD 720p60" );
746 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHQ_VIDEO, "\018DVCPRO HD 720p50" );
747 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRA_VIDEO, "\017Ut Video (ULRA)" );
748 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRG_VIDEO, "\017Ut Video (ULRG)" );
749 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY0_VIDEO, "\017Ut Video (ULY0)" );
750 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY2_VIDEO, "\017Ut Video (ULY2)" );
751 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH0_VIDEO, "\017Ut Video (ULH0)" );
752 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH2_VIDEO, "\017Ut Video (ULH2)" );
753 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_UQY2_VIDEO, "\021Ut Video Pro (UQY2)" );
754 ADD_COMPRESSORNAME_TABLE( LSMASH_CODEC_TYPE_UNSPECIFIED, { '\0' } );
755 #undef ADD_COMPRESSORNAME_TABLE
757 for( int i = 0; compressorname_table[i].name[0] != '\0'; i++ )
758 if( lsmash_check_codec_type_identical( sample_type, compressorname_table[i].type ) )
760 strcpy( compressorname, compressorname_table[i].name );
761 return;
765 lsmash_codec_specific_t *isom_get_codec_specific( lsmash_codec_specific_list_t *opaque, lsmash_codec_specific_data_type type )
767 for( lsmash_entry_t *entry = opaque->list.head; entry; entry = entry->next )
769 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
770 if( !specific || specific->type != type )
771 continue;
772 return specific;
774 return NULL;
777 static int isom_check_valid_summary( lsmash_summary_t *summary )
779 if( !summary )
780 return LSMASH_ERR_NAMELESS;
781 isom_box_t temp_box;
782 temp_box.type = summary->sample_type;
783 temp_box.manager = summary->summary_type == LSMASH_SUMMARY_TYPE_AUDIO ? LSMASH_AUDIO_DESCRIPTION: 0;
784 if( isom_is_lpcm_audio( &temp_box ) )
786 if( isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS ) )
787 return 0;
788 return LSMASH_ERR_INVALID_DATA;
790 if( isom_is_uncompressed_ycbcr( summary->sample_type ) )
792 if( isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO ) )
794 if( !lsmash_check_codec_type_identical( summary->sample_type, QT_CODEC_TYPE_V216_VIDEO ) )
795 return 0;
797 else
798 return LSMASH_ERR_INVALID_DATA;
800 lsmash_codec_type_t sample_type = summary->sample_type;
801 lsmash_codec_specific_data_type required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED;
802 if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC1_VIDEO )
803 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC2_VIDEO )
804 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC3_VIDEO )
805 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC4_VIDEO ) )
806 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264;
807 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HVC1_VIDEO )
808 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HEV1_VIDEO ) )
809 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC;
810 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_VC_1_VIDEO ) )
811 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 ;
812 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULRA_VIDEO )
813 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULRG_VIDEO )
814 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULY0_VIDEO )
815 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULY2_VIDEO )
816 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULH0_VIDEO )
817 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULH2_VIDEO )
818 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_UQY2_VIDEO ) )
819 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER;
820 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_V216_VIDEO ) )
821 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS;
822 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4V_VIDEO )
823 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4A_AUDIO )
824 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_MP4A_AUDIO ) )
825 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG;
826 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AC_3_AUDIO ) )
827 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3;
828 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_EC_3_AUDIO ) )
829 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3;
830 else if( isom_is_dts_audio( sample_type ) )
831 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS;
832 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_ALAC_AUDIO )
833 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ALAC_AUDIO ) )
834 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC;
835 if( required_data_type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED )
836 return 0;
837 return isom_get_codec_specific( summary->opaque, required_data_type ) ? 0 : LSMASH_ERR_INVALID_DATA;
840 static lsmash_box_type_t isom_guess_video_codec_specific_box_type( lsmash_codec_type_t active_codec_type, lsmash_compact_box_type_t fourcc )
842 lsmash_box_type_t box_type = LSMASH_BOX_TYPE_INITIALIZER;
843 box_type.fourcc = fourcc;
844 #define GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
845 else if( (codec_type.user.fourcc == 0 \
846 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
847 && box_type.fourcc == predefined_box_type.fourcc ) \
848 box_type = predefined_box_type
849 if( 0 );
850 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC1_VIDEO, ISOM_BOX_TYPE_AVCC );
851 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC2_VIDEO, ISOM_BOX_TYPE_AVCC );
852 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC3_VIDEO, ISOM_BOX_TYPE_AVCC );
853 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC4_VIDEO, ISOM_BOX_TYPE_AVCC );
854 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVCP_VIDEO, ISOM_BOX_TYPE_AVCC );
855 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HVC1_VIDEO, ISOM_BOX_TYPE_HVCC );
856 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HEV1_VIDEO, ISOM_BOX_TYPE_HVCC );
857 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_VC_1_VIDEO, ISOM_BOX_TYPE_DVC1 );
858 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4V_VIDEO, ISOM_BOX_TYPE_ESDS );
859 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, ISOM_BOX_TYPE_BTRT );
860 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_FIEL );
861 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_CSPC );
862 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_SGBT );
863 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_GAMA );
864 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_GLBL );
865 #undef GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE
866 return box_type;
869 static int isom_setup_visual_description( isom_stsd_t *stsd, lsmash_video_summary_t *summary )
871 if( !summary
872 || !stsd
873 || !stsd->parent
874 || !stsd->parent->parent
875 || !stsd->parent->parent->parent
876 || !stsd->parent->parent->parent->parent )
877 return LSMASH_ERR_NAMELESS;
878 int err = isom_check_valid_summary( (lsmash_summary_t *)summary );
879 if( err < 0 )
880 return err;
881 isom_visual_entry_t *visual = isom_add_visual_description( stsd, summary->sample_type );
882 if( !visual )
883 return LSMASH_ERR_NAMELESS;
884 visual->data_reference_index = summary->data_ref_index;
885 visual->version = 0;
886 visual->revision_level = 0;
887 visual->vendor = 0;
888 visual->temporalQuality = 0;
889 visual->spatialQuality = 0;
890 visual->width = (uint16_t)summary->width;
891 visual->height = (uint16_t)summary->height;
892 visual->horizresolution = 0x00480000;
893 visual->vertresolution = 0x00480000;
894 visual->dataSize = 0;
895 visual->frame_count = 1;
896 visual->depth = isom_is_qt_video( visual->type ) || isom_is_nalff( visual->type )
897 ? summary->depth : 0x0018;
898 visual->color_table_ID = -1;
899 if( summary->compressorname[0] == '\0' )
900 isom_set_default_compressorname( visual->compressorname, visual->type );
901 else
903 memcpy( visual->compressorname, summary->compressorname, 32 );
904 visual->compressorname[32] = '\0';
906 err = LSMASH_ERR_NAMELESS;
907 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
909 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
910 if( !specific )
911 goto fail;
912 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
913 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
914 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
915 switch( specific->type )
917 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON :
919 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
920 continue;
921 lsmash_qt_video_common_t *data = (lsmash_qt_video_common_t *)specific->data.structured;
922 visual->revision_level = data->revision_level;
923 visual->vendor = data->vendor;
924 visual->temporalQuality = data->temporalQuality;
925 visual->spatialQuality = data->spatialQuality;
926 visual->horizresolution = data->horizontal_resolution;
927 visual->vertresolution = data->vertical_resolution;
928 visual->dataSize = data->dataSize;
929 visual->frame_count = data->frame_count;
930 visual->color_table_ID = data->color_table_ID;
931 if( data->color_table_ID == 0 )
933 lsmash_qt_color_table_t *src_ct = &data->color_table;
934 uint16_t element_count = LSMASH_MIN( src_ct->size + 1, 256 );
935 isom_qt_color_array_t *dst_array = lsmash_malloc_zero( element_count * sizeof(isom_qt_color_array_t) );
936 if( !dst_array )
938 err = LSMASH_ERR_MEMORY_ALLOC;
939 goto fail;
941 isom_qt_color_table_t *dst_ct = &visual->color_table;
942 dst_ct->array = dst_array;
943 dst_ct->seed = src_ct->seed;
944 dst_ct->flags = src_ct->flags;
945 dst_ct->size = src_ct->size;
946 for( uint16_t i = 0; i < element_count; i++ )
948 dst_array[i].value = src_ct->array[i].unused;
949 dst_array[i].r = src_ct->array[i].r;
950 dst_array[i].g = src_ct->array[i].g;
951 dst_array[i].b = src_ct->array[i].b;
954 break;
956 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE :
958 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
959 if( !cs )
960 goto fail;
961 lsmash_isom_sample_scale_t *data = (lsmash_isom_sample_scale_t *)cs->data.structured;
962 isom_stsl_t *stsl = isom_add_stsl( visual );
963 if( !stsl )
965 lsmash_destroy_codec_specific_data( cs );
966 goto fail;
968 stsl->constraint_flag = data->constraint_flag;
969 stsl->scale_method = data->scale_method;
970 stsl->display_center_x = data->display_center_x;
971 stsl->display_center_y = data->display_center_y;
972 lsmash_destroy_codec_specific_data( cs );
973 break;
975 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE :
977 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
978 if( !cs )
979 goto fail;
980 lsmash_h264_bitrate_t *data = (lsmash_h264_bitrate_t *)cs->data.structured;
981 isom_btrt_t *btrt = isom_add_btrt( visual );
982 if( !btrt )
984 lsmash_destroy_codec_specific_data( cs );
985 goto fail;
987 btrt->bufferSizeDB = data->bufferSizeDB;
988 btrt->maxBitrate = data->maxBitrate;
989 btrt->avgBitrate = data->avgBitrate;
990 lsmash_destroy_codec_specific_data( cs );
991 break;
993 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO :
995 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
996 if( !cs )
997 goto fail;
998 lsmash_qt_field_info_t *data = (lsmash_qt_field_info_t *)cs->data.structured;
999 isom_fiel_t *fiel = isom_add_fiel( visual );
1000 if( !fiel )
1002 lsmash_destroy_codec_specific_data( cs );
1003 goto fail;
1005 fiel->fields = data->fields;
1006 fiel->detail = data->detail;
1007 lsmash_destroy_codec_specific_data( cs );
1008 break;
1010 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT :
1012 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1013 if( !cs )
1014 goto fail;
1015 lsmash_qt_pixel_format_t *data = (lsmash_qt_pixel_format_t *)cs->data.structured;
1016 isom_cspc_t *cspc = isom_add_cspc( visual );
1017 if( !cspc )
1019 lsmash_destroy_codec_specific_data( cs );
1020 goto fail;
1022 cspc->pixel_format = data->pixel_format;
1023 lsmash_destroy_codec_specific_data( cs );
1024 break;
1026 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS :
1028 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1029 if( !cs )
1030 goto fail;
1031 lsmash_qt_significant_bits_t *data = (lsmash_qt_significant_bits_t *)cs->data.structured;
1032 isom_sgbt_t *sgbt = isom_add_sgbt( visual );
1033 if( !sgbt )
1035 lsmash_destroy_codec_specific_data( cs );
1036 goto fail;
1038 sgbt->significantBits = data->significantBits;
1039 lsmash_destroy_codec_specific_data( cs );
1040 break;
1042 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL :
1044 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1045 if( !cs )
1046 goto fail;
1047 lsmash_qt_gamma_t *data = (lsmash_qt_gamma_t *)cs->data.structured;
1048 isom_gama_t *gama = isom_add_gama( visual );
1049 if( !gama )
1051 lsmash_destroy_codec_specific_data( cs );
1052 goto fail;
1054 gama->level = data->level;
1055 lsmash_destroy_codec_specific_data( cs );
1056 break;
1058 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
1060 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1061 if( !cs )
1062 goto fail;
1063 lsmash_codec_global_header_t *data = (lsmash_codec_global_header_t *)cs->data.structured;
1064 isom_glbl_t *glbl = isom_add_glbl( visual );
1065 if( !glbl )
1067 lsmash_destroy_codec_specific_data( cs );
1068 goto fail;
1070 glbl->header_size = data->header_size;
1071 glbl->header_data = lsmash_memdup( data->header_data, data->header_size );
1072 lsmash_destroy_codec_specific_data( cs );
1073 if( !glbl->header_data )
1075 isom_remove_box_by_itself( glbl );
1076 err = LSMASH_ERR_MEMORY_ALLOC;
1077 goto fail;
1079 break;
1081 default :
1083 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
1084 if( !cs )
1085 goto fail;
1086 if( cs->size < ISOM_BASEBOX_COMMON_SIZE )
1088 lsmash_destroy_codec_specific_data( cs );
1089 err = LSMASH_ERR_INVALID_DATA;
1090 goto fail;
1092 uint8_t *data = cs->data.unstructured;
1093 lsmash_compact_box_type_t fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
1094 lsmash_box_type_t box_type = isom_guess_video_codec_specific_box_type( visual->type, fourcc );
1095 /* Append the extension. */
1096 err = isom_add_extension_binary( visual, box_type, LSMASH_BOX_PRECEDENCE_HM, cs->data.unstructured, cs->size );
1097 cs->data.unstructured = NULL; /* Avoid freeing the binary data of the extension. */
1098 lsmash_destroy_codec_specific_data( cs );
1099 if( err < 0 )
1100 goto fail;
1101 break;
1105 isom_trak_t *trak = (isom_trak_t *)visual->parent->parent->parent->parent->parent;
1106 int qt_compatible = trak->file->qt_compatible;
1107 isom_tapt_t *tapt = trak->tapt;
1108 isom_stsl_t *stsl = (isom_stsl_t *)isom_get_extension_box_format( &visual->extensions, ISOM_BOX_TYPE_STSL );
1109 int set_aperture_modes = qt_compatible /* Track Aperture Modes is only available under QuickTime file format. */
1110 && (!stsl || stsl->scale_method == 0) /* Sample scaling method might conflict with this feature. */
1111 && tapt && tapt->clef && tapt->prof && tapt->enof /* Check if required boxes exist. */
1112 && ((isom_stsd_t *)visual->parent)->list.entry_count == 1; /* Multiple sample description might conflict with this, so in that case, disable this feature. */
1113 if( !set_aperture_modes )
1114 isom_remove_box_by_itself( trak->tapt );
1115 int uncompressed_ycbcr = qt_compatible && isom_is_uncompressed_ycbcr( visual->type );
1116 /* Set up Clean Aperture. */
1117 if( set_aperture_modes || uncompressed_ycbcr
1118 || (summary->clap.width.d && summary->clap.height.d && summary->clap.horizontal_offset.d && summary->clap.vertical_offset.d) )
1120 isom_clap_t *clap = isom_add_clap( visual );
1121 if( !clap )
1122 goto fail;
1123 if( summary->clap.width.d && summary->clap.height.d && summary->clap.horizontal_offset.d && summary->clap.vertical_offset.d )
1125 clap->cleanApertureWidthN = summary->clap.width.n;
1126 clap->cleanApertureWidthD = summary->clap.width.d;
1127 clap->cleanApertureHeightN = summary->clap.height.n;
1128 clap->cleanApertureHeightD = summary->clap.height.d;
1129 clap->horizOffN = summary->clap.horizontal_offset.n;
1130 clap->horizOffD = summary->clap.horizontal_offset.d;
1131 clap->vertOffN = summary->clap.vertical_offset.n;
1132 clap->vertOffD = summary->clap.vertical_offset.d;
1134 else
1136 clap->cleanApertureWidthN = summary->width;
1137 clap->cleanApertureWidthD = 1;
1138 clap->cleanApertureHeightN = summary->height;
1139 clap->cleanApertureHeightD = 1;
1140 clap->horizOffN = 0;
1141 clap->horizOffD = 1;
1142 clap->vertOffN = 0;
1143 clap->vertOffD = 1;
1146 /* Set up Pixel Aspect Ratio. */
1147 if( set_aperture_modes || (summary->par_h && summary->par_v) )
1149 isom_pasp_t *pasp = isom_add_pasp( visual );
1150 if( !pasp )
1151 goto fail;
1152 pasp->hSpacing = LSMASH_MAX( summary->par_h, 1 );
1153 pasp->vSpacing = LSMASH_MAX( summary->par_v, 1 );
1155 /* Set up Color Parameter. */
1156 if( uncompressed_ycbcr
1157 || summary->color.primaries_index
1158 || summary->color.transfer_index
1159 || summary->color.matrix_index
1160 || (trak->file->isom_compatible && summary->color.full_range) )
1162 isom_colr_t *colr = isom_add_colr( visual );
1163 if( !colr )
1164 goto fail;
1165 /* Set 'nclc' to parameter type, we don't support 'prof'. */
1166 uint16_t primaries = summary->color.primaries_index;
1167 uint16_t transfer = summary->color.transfer_index;
1168 uint16_t matrix = summary->color.matrix_index;
1169 if( qt_compatible && !trak->file->isom_compatible )
1171 colr->manager |= LSMASH_QTFF_BASE;
1172 colr->type = QT_BOX_TYPE_COLR;
1173 colr->color_parameter_type = QT_COLOR_PARAMETER_TYPE_NCLC;
1174 colr->primaries_index = (primaries == 1 || primaries == 5 || primaries == 6)
1175 ? primaries : QT_PRIMARIES_INDEX_UNSPECIFIED;
1176 colr->transfer_function_index = (transfer == 1 || transfer == 7)
1177 ? transfer : QT_TRANSFER_INDEX_UNSPECIFIED;
1178 colr->matrix_index = (matrix == 1 || matrix == 6 || matrix == 7)
1179 ? matrix : QT_MATRIX_INDEX_UNSPECIFIED;
1181 else
1183 colr->type = ISOM_BOX_TYPE_COLR;
1184 colr->color_parameter_type = ISOM_COLOR_PARAMETER_TYPE_NCLX;
1185 colr->primaries_index = (primaries == 1 || (primaries >= 4 && primaries <= 7))
1186 ? primaries : ISOM_PRIMARIES_INDEX_UNSPECIFIED;
1187 colr->transfer_function_index = (transfer == 1 || (transfer >= 4 && transfer <= 8) || (transfer >= 11 && transfer <= 13))
1188 ? transfer : ISOM_TRANSFER_INDEX_UNSPECIFIED;
1189 colr->matrix_index = (matrix == 1 || (matrix >= 4 && matrix <= 8))
1190 ? matrix : ISOM_MATRIX_INDEX_UNSPECIFIED;
1191 colr->full_range_flag = summary->color.full_range;
1194 /* Set up Track Apeture Modes. */
1195 if( set_aperture_modes )
1197 uint32_t width = visual->width << 16;
1198 uint32_t height = visual->height << 16;
1199 isom_clap_t *clap = (isom_clap_t *)isom_get_extension_box_format( &visual->extensions, ISOM_BOX_TYPE_CLAP );
1200 isom_pasp_t *pasp = (isom_pasp_t *)isom_get_extension_box_format( &visual->extensions, ISOM_BOX_TYPE_PASP );
1201 double clap_width = ((double)clap->cleanApertureWidthN / clap->cleanApertureWidthD) * (1<<16);
1202 double clap_height = ((double)clap->cleanApertureHeightN / clap->cleanApertureHeightD) * (1<<16);
1203 double par = (double)pasp->hSpacing / pasp->vSpacing;
1204 if( par >= 1.0 )
1206 tapt->clef->width = clap_width * par;
1207 tapt->clef->height = clap_height;
1208 tapt->prof->width = width * par;
1209 tapt->prof->height = height;
1211 else
1213 tapt->clef->width = clap_width;
1214 tapt->clef->height = clap_height / par;
1215 tapt->prof->width = width;
1216 tapt->prof->height = height / par;
1218 tapt->enof->width = width;
1219 tapt->enof->height = height;
1221 return 0;
1222 fail:
1223 isom_remove_box_by_itself( visual );
1224 return err;
1227 static int isom_append_audio_es_descriptor_extension( isom_box_t *box, lsmash_audio_summary_t *summary )
1229 uint32_t esds_size = 0;
1230 uint8_t *esds_data = NULL;
1231 lsmash_codec_specific_t *specific = isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
1232 if( !specific )
1233 return LSMASH_ERR_NAMELESS;
1234 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
1236 esds_size = specific->size;
1237 esds_data = lsmash_memdup( specific->data.unstructured, specific->size );
1238 if( !esds_data )
1239 return LSMASH_ERR_MEMORY_ALLOC;
1241 else
1243 esds_data = lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t *)specific->data.structured, &esds_size );
1244 if( !esds_data )
1245 return LSMASH_ERR_NAMELESS;
1247 isom_esds_t *esds = isom_add_esds( box );
1248 if( !esds )
1250 lsmash_free( esds_data );
1251 return LSMASH_ERR_NAMELESS;
1253 lsmash_bs_t bs = { 0 };
1254 bs.buffer.data = esds_data + ISOM_FULLBOX_COMMON_SIZE;
1255 bs.buffer.alloc = esds_size - ISOM_FULLBOX_COMMON_SIZE;
1256 bs.buffer.store = bs.buffer.alloc;
1257 esds->ES = mp4sys_get_descriptor( &bs, NULL );
1258 lsmash_free( esds_data );
1259 if( !esds->ES )
1261 isom_remove_box_by_itself( esds );
1262 return LSMASH_ERR_NAMELESS;
1264 return 0;
1267 static int isom_append_channel_layout_extension( lsmash_codec_specific_t *specific, void *parent, uint32_t channels )
1269 assert( parent );
1270 if( isom_get_extension_box( &((isom_box_t *)parent)->extensions, QT_BOX_TYPE_CHAN ) )
1271 return 0; /* Audio Channel Layout Box is already present. */
1272 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1273 if( !cs )
1274 return LSMASH_ERR_NAMELESS;
1275 lsmash_qt_audio_channel_layout_t *data = (lsmash_qt_audio_channel_layout_t *)cs->data.structured;
1276 lsmash_channel_layout_tag channelLayoutTag = data->channelLayoutTag;
1277 lsmash_channel_bitmap channelBitmap = data->channelBitmap;
1278 if( channelLayoutTag == QT_CHANNEL_LAYOUT_USE_CHANNEL_DESCRIPTIONS /* We don't support the feature of Channel Descriptions. */
1279 || (channelLayoutTag == QT_CHANNEL_LAYOUT_USE_CHANNEL_BITMAP && (!channelBitmap || channelBitmap > QT_CHANNEL_BIT_FULL)) )
1281 channelLayoutTag = QT_CHANNEL_LAYOUT_UNKNOWN | channels;
1282 channelBitmap = 0;
1284 lsmash_destroy_codec_specific_data( cs );
1285 /* Don't create Audio Channel Layout Box if the channel layout is unknown. */
1286 if( (channelLayoutTag ^ QT_CHANNEL_LAYOUT_UNKNOWN) >> 16 )
1288 isom_chan_t *chan = isom_add_chan( parent );
1289 if( !chan )
1290 return LSMASH_ERR_NAMELESS;
1291 chan->channelLayoutTag = channelLayoutTag;
1292 chan->channelBitmap = channelBitmap;
1293 chan->numberChannelDescriptions = 0;
1294 chan->channelDescriptions = NULL;
1296 return 0;
1299 static int isom_set_qtff_mp4a_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1301 isom_wave_t *wave = isom_add_wave( audio );
1302 isom_frma_t *frma;
1303 if( !(frma = isom_add_frma( wave ))
1304 || !isom_add_mp4a( wave )
1305 || !isom_add_terminator( wave ) )
1307 lsmash_remove_entry_tail( &audio->extensions, wave->destruct );
1308 return LSMASH_ERR_NAMELESS;
1310 frma->data_format = audio->type.fourcc;
1311 /* Add ES Descriptor Box. */
1312 int err = isom_append_audio_es_descriptor_extension( (isom_box_t *)wave, summary );
1313 if( err < 0 )
1314 return err;
1315 /* */
1316 audio->type = QT_CODEC_TYPE_MP4A_AUDIO;
1317 audio->version = (summary->channels > 2 || summary->frequency > UINT16_MAX) ? 2 : 1;
1318 audio->channelcount = audio->version == 2 ? 3 : LSMASH_MIN( summary->channels, 2 );
1319 audio->samplesize = 16;
1320 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION;
1321 audio->packet_size = 0;
1322 if( audio->version == 1 )
1324 audio->samplerate = summary->frequency << 16;
1325 audio->samplesPerPacket = summary->samples_in_frame;
1326 audio->bytesPerPacket = 1; /* Apparently, this field is set to 1. */
1327 audio->bytesPerFrame = audio->bytesPerPacket * summary->channels;
1328 audio->bytesPerSample = 2;
1330 else /* audio->version == 2 */
1332 audio->samplerate = 0x00010000;
1333 audio->sizeOfStructOnly = 72;
1334 audio->audioSampleRate = (union {double d; uint64_t i;}){summary->frequency}.i;
1335 audio->numAudioChannels = summary->channels;
1336 audio->always7F000000 = 0x7F000000;
1337 audio->constBitsPerChannel = 0; /* compressed audio */
1338 audio->formatSpecificFlags = 0;
1339 audio->constBytesPerAudioPacket = 0; /* variable */
1340 audio->constLPCMFramesPerAudioPacket = summary->samples_in_frame;
1342 return 0;
1345 static int isom_set_isom_mp4a_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1347 if( summary->summary_type != LSMASH_SUMMARY_TYPE_AUDIO )
1348 return LSMASH_ERR_NAMELESS;
1349 /* Check objectTypeIndication. */
1350 lsmash_mp4sys_object_type_indication objectTypeIndication = lsmash_mp4sys_get_object_type_indication( (lsmash_summary_t *)summary );
1351 switch( objectTypeIndication )
1353 case MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3:
1354 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_Main_Profile:
1355 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_LC_Profile:
1356 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_SSR_Profile:
1357 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_3: /* Legacy Interface */
1358 case MP4SYS_OBJECT_TYPE_Audio_ISO_11172_3: /* Legacy Interface */
1359 break;
1360 default:
1361 return LSMASH_ERR_NAMELESS;
1363 /* Add ES Descriptor Box. */
1364 int err = isom_append_audio_es_descriptor_extension( (isom_box_t *)audio, summary );
1365 if( err < 0 )
1366 return err;
1367 /* In pure mp4 file, these "template" fields shall be default values according to the spec.
1368 But not pure - hybrid with other spec - mp4 file can take other values.
1369 Which is to say, these template values shall be ignored in terms of mp4, except some object_type_indications.
1370 see 14496-14, "Template fields used". */
1371 audio->type = ISOM_CODEC_TYPE_MP4A_AUDIO;
1372 audio->version = 0;
1373 audio->revision_level = 0;
1374 audio->vendor = 0;
1375 audio->channelcount = 2;
1376 audio->samplesize = 16;
1377 audio->compression_ID = 0;
1378 audio->packet_size = 0;
1379 /* WARNING: This field cannot retain frequency above 65535Hz.
1380 This is not "FIXME", I just honestly implemented what the spec says.
1381 BTW, who ever expects sampling frequency takes fixed-point decimal??? */
1382 audio->samplerate = summary->frequency <= UINT16_MAX ? summary->frequency << 16 : 0;
1383 return 0;
1386 static int isom_set_qtff_lpcm_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1388 lsmash_qt_audio_format_specific_flags_t *lpcm = NULL;
1389 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
1391 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
1392 if( !specific )
1393 continue;
1394 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1395 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1397 lpcm = (lsmash_qt_audio_format_specific_flags_t *)specific->data.structured;
1398 break;
1401 if( !lpcm )
1402 return LSMASH_ERR_NAMELESS;
1403 audio->manager |= LSMASH_QTFF_BASE;
1404 lsmash_codec_type_t sample_type = audio->type;
1405 /* Convert the sample type into 'lpcm' if the description doesn't match the format or version = 2 fields are needed. */
1406 if( (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_RAW_AUDIO )
1407 && (summary->sample_size != 8 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1408 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL32_AUDIO )
1409 && (summary->sample_size != 32 || !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1410 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL64_AUDIO )
1411 && (summary->sample_size != 64 || !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1412 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN24_AUDIO )
1413 && (summary->sample_size != 24 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1414 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN32_AUDIO )
1415 && (summary->sample_size != 32 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1416 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_23NI_AUDIO )
1417 && (summary->sample_size != 32 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT) || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN)))
1418 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_SOWT_AUDIO )
1419 && (summary->sample_size != 16 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT) || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN)))
1420 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO )
1421 && ((summary->sample_size != 16 && summary->sample_size != 8) || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT) || !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN)))
1422 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NONE_AUDIO )
1423 && ((summary->sample_size != 16 && summary->sample_size != 8) || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT) || !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN)))
1424 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NOT_SPECIFIED )
1425 && ((summary->sample_size != 16 && summary->sample_size != 8) || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT) || !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN)))
1426 || (summary->channels > 2 || summary->frequency > UINT16_MAX || summary->sample_size % 8) )
1428 audio->type = QT_CODEC_TYPE_LPCM_AUDIO;
1429 audio->version = 2;
1431 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_LPCM_AUDIO ) )
1432 audio->version = 2;
1433 else if( summary->sample_size > 16
1434 || (!lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_RAW_AUDIO )
1435 && !lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO )
1436 && !lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NONE_AUDIO )
1437 && !lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NOT_SPECIFIED )) )
1438 audio->version = 1;
1439 /* Set up constBytesPerAudioPacket field.
1440 * We use constBytesPerAudioPacket as the actual size of LPCM audio frame even when version is not 2. */
1441 audio->constBytesPerAudioPacket = (summary->sample_size * summary->channels) / 8;
1442 /* Set up other fields in this description by its version. */
1443 if( audio->version == 2 )
1445 audio->channelcount = 3;
1446 audio->samplesize = 16;
1447 audio->compression_ID = -2;
1448 audio->samplerate = 0x00010000;
1449 audio->sizeOfStructOnly = 72;
1450 audio->audioSampleRate = (union {double d; uint64_t i;}){summary->frequency}.i;
1451 audio->numAudioChannels = summary->channels;
1452 audio->always7F000000 = 0x7F000000;
1453 audio->constBitsPerChannel = summary->sample_size;
1454 audio->constLPCMFramesPerAudioPacket = 1;
1455 audio->formatSpecificFlags = lpcm->format_flags;
1456 if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO ) && summary->sample_size != 8 )
1457 audio->formatSpecificFlags |= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
1458 if( lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT )
1459 audio->formatSpecificFlags &= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER;
1460 if( lpcm->format_flags & QT_LPCM_FORMAT_FLAG_PACKED )
1461 audio->formatSpecificFlags &= ~QT_LPCM_FORMAT_FLAG_ALIGNED_HIGH;
1463 else if( audio->version == 1 )
1465 audio->channelcount = summary->channels;
1466 audio->samplesize = 16;
1467 /* Audio formats other than 'raw ' and 'twos' are treated as compressed audio. */
1468 if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_RAW_AUDIO )
1469 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO ) )
1470 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED;
1471 else
1472 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION;
1473 audio->samplerate = summary->frequency << 16;
1474 audio->samplesPerPacket = 1;
1475 audio->bytesPerPacket = summary->sample_size / 8;
1476 audio->bytesPerFrame = audio->bytesPerPacket * summary->channels; /* sample_size field in stsz box is NOT used. */
1477 audio->bytesPerSample = 1 + (summary->sample_size != 8);
1478 if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL32_AUDIO )
1479 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL64_AUDIO )
1480 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN24_AUDIO )
1481 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN32_AUDIO ) )
1483 isom_wave_t *wave = isom_add_wave( audio );
1484 isom_frma_t *frma;
1485 isom_enda_t *enda;
1486 if( !(frma = isom_add_frma( wave ))
1487 || !(enda = isom_add_enda( wave ))
1488 || !isom_add_terminator( wave ) )
1490 lsmash_remove_entry_tail( &audio->extensions, wave->destruct );
1491 return LSMASH_ERR_NAMELESS;
1493 frma->data_format = sample_type.fourcc;
1494 enda->littleEndian = !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN);
1497 else /* audio->version == 0 */
1499 audio->channelcount = summary->channels;
1500 audio->samplesize = summary->sample_size;
1501 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED;
1502 audio->samplerate = summary->frequency << 16;
1504 return 0;
1507 static int isom_set_isom_dts_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1509 audio->version = 0;
1510 audio->revision_level = 0;
1511 audio->vendor = 0;
1512 audio->channelcount = summary->channels;
1513 audio->samplesize = 16;
1514 audio->compression_ID = 0;
1515 audio->packet_size = 0;
1516 switch( summary->frequency )
1518 case 12000 : /* Invalid? (No reference in the spec) */
1519 case 24000 :
1520 case 48000 :
1521 case 96000 :
1522 case 192000 :
1523 case 384000 : /* Invalid? (No reference in the spec) */
1524 audio->samplerate = 48000 << 16;
1525 break;
1526 case 22050 :
1527 case 44100 :
1528 case 88200 :
1529 case 176400 :
1530 case 352800 : /* Invalid? (No reference in the spec) */
1531 audio->samplerate = 44100 << 16;
1532 break;
1533 case 8000 : /* Invalid? (No reference in the spec) */
1534 case 16000 :
1535 case 32000 :
1536 case 64000 :
1537 case 128000 :
1538 audio->samplerate = 32000 << 16;
1539 break;
1540 default :
1541 audio->samplerate = 0;
1542 break;
1544 return 0;
1547 static lsmash_box_type_t isom_guess_audio_codec_specific_box_type( lsmash_codec_type_t active_codec_type, lsmash_compact_box_type_t fourcc )
1549 lsmash_box_type_t box_type = LSMASH_BOX_TYPE_INITIALIZER;
1550 box_type.fourcc = fourcc;
1551 #define GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
1552 else if( (codec_type.user.fourcc == 0 \
1553 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
1554 && box_type.fourcc == predefined_box_type.fourcc ) \
1555 box_type = predefined_box_type
1556 if( 0 );
1557 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AC_3_AUDIO, ISOM_BOX_TYPE_DAC3 );
1558 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_EC_3_AUDIO, ISOM_BOX_TYPE_DEC3 );
1559 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSC_AUDIO, ISOM_BOX_TYPE_DDTS );
1560 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSE_AUDIO, ISOM_BOX_TYPE_DDTS );
1561 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSH_AUDIO, ISOM_BOX_TYPE_DDTS );
1562 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSL_AUDIO, ISOM_BOX_TYPE_DDTS );
1563 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSX_AUDIO, ISOM_BOX_TYPE_DDTS );
1564 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSEL_AUDIO, ISOM_BOX_TYPE_DDTS );
1565 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSDL_AUDIO, ISOM_BOX_TYPE_DDTS );
1566 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_ALAC_AUDIO, ISOM_BOX_TYPE_ALAC );
1567 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4A_AUDIO, ISOM_BOX_TYPE_ESDS );
1568 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ALAC_AUDIO, QT_BOX_TYPE_ALAC );
1569 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_MP4A_AUDIO, QT_BOX_TYPE_ESDS );
1570 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_FULLMP3_AUDIO, QT_CODEC_TYPE_MP3_AUDIO );
1571 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM2_AUDIO, QT_CODEC_TYPE_ADPCM2_AUDIO );
1572 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM17_AUDIO, QT_CODEC_TYPE_ADPCM17_AUDIO );
1573 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_GSM49_AUDIO, QT_CODEC_TYPE_GSM49_AUDIO );
1574 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_CHAN );
1575 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_GLBL );
1576 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_WAVE );
1577 #undef GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE
1578 return box_type;
1581 typedef struct
1583 uint16_t wFormatTag;
1584 uint16_t nChannels;
1585 uint32_t nSamplesPerSec;
1586 uint32_t nAvgBytesPerSec;
1587 uint16_t nBlockAlign;
1588 uint16_t wBitsPerSample;
1589 uint16_t cbSize;
1590 } wave_format_ex_t;
1592 static lsmash_bs_t *isom_create_waveform_audio_info
1594 wave_format_ex_t *wfx,
1595 lsmash_box_type_t type
1598 lsmash_bs_t *bs = lsmash_bs_create();
1599 if( !bs )
1600 return NULL;
1601 lsmash_bs_put_be32( bs, ISOM_BASEBOX_COMMON_SIZE + 18 + wfx->cbSize );
1602 lsmash_bs_put_be32( bs, type.fourcc );
1603 lsmash_bs_put_le16( bs, wfx->wFormatTag );
1604 lsmash_bs_put_le16( bs, wfx->nChannels );
1605 lsmash_bs_put_le32( bs, wfx->nSamplesPerSec );
1606 lsmash_bs_put_le32( bs, wfx->nAvgBytesPerSec );
1607 lsmash_bs_put_le16( bs, wfx->nBlockAlign );
1608 lsmash_bs_put_le16( bs, wfx->wBitsPerSample );
1609 lsmash_bs_put_le16( bs, wfx->cbSize );
1610 return bs;
1613 static int isom_setup_waveform_audio_info
1615 isom_wave_t *wave,
1616 isom_audio_entry_t *audio,
1617 lsmash_audio_summary_t *summary,
1618 uint32_t samples_per_packet,
1619 uint32_t bytes_per_frame,
1620 uint32_t sample_size
1623 wave_format_ex_t wfx;
1624 wfx.wFormatTag = 0x0000; /* WAVE_FORMAT_UNKNOWN */
1625 wfx.nChannels = summary->channels;
1626 wfx.nSamplesPerSec = summary->frequency;
1627 wfx.nAvgBytesPerSec = 0;
1628 wfx.nBlockAlign = bytes_per_frame;
1629 wfx.wBitsPerSample = sample_size;
1630 wfx.cbSize = 0;
1631 lsmash_bs_t *bs = NULL;
1632 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ADPCM2_AUDIO ) )
1634 /* ADPCMWAVEFORMAT */
1635 wfx.wFormatTag = 0x0002; /* WAVE_FORMAT_ADPCM */
1636 wfx.cbSize = 32;
1637 bs = isom_create_waveform_audio_info( &wfx, audio->type );
1638 if( !bs )
1639 return LSMASH_ERR_MEMORY_ALLOC;
1640 uint16_t wSamplesPerBlock = samples_per_packet; /* nBlockAlign * 2 / nChannels - 12 */
1641 uint16_t wNumCoef = 7; /* Microsoft ADPCM uses just 7 coefficients. */
1642 static const struct
1644 int16_t iCoef1;
1645 int16_t iCoef2;
1646 } aCoef[7] = { { 256, 0 }, { 512, -256 }, { 0,0 }, { 192,64 }, { 240,0 }, { 460, -208 }, { 392,-232 } };
1647 lsmash_bs_put_le16( bs, wSamplesPerBlock );
1648 lsmash_bs_put_le16( bs, wNumCoef );
1649 for( int i = 0; i < 7; i++ )
1651 lsmash_bs_put_le16( bs, aCoef[i].iCoef1 );
1652 lsmash_bs_put_le16( bs, aCoef[i].iCoef2 );
1655 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ADPCM17_AUDIO ) )
1657 /* IMAADPCMWAVEFORMAT */
1658 wfx.wFormatTag = 0x0011; /* WAVE_FORMAT_DVI_ADPCM / WAVE_FORMAT_IMA_ADPCM */
1659 wfx.cbSize = 2;
1660 bs = isom_create_waveform_audio_info( &wfx, audio->type );
1661 if( !bs )
1662 return LSMASH_ERR_MEMORY_ALLOC;
1663 uint16_t wSamplesPerBlock = samples_per_packet;
1664 lsmash_bs_put_le16( bs, wSamplesPerBlock );
1666 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_GSM49_AUDIO ) )
1668 /* GSM610WAVEFORMAT */
1669 wfx.wFormatTag = 0x0031; /* WAVE_FORMAT_GSM610 */
1670 wfx.cbSize = 2;
1671 bs = isom_create_waveform_audio_info( &wfx, audio->type );
1672 if( !bs )
1673 return LSMASH_ERR_MEMORY_ALLOC;
1674 uint16_t wSamplesPerBlock = samples_per_packet;
1675 lsmash_bs_put_le16( bs, wSamplesPerBlock );
1677 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_FULLMP3_AUDIO )
1678 || lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MP3_AUDIO ) )
1680 /* MPEGLAYER3WAVEFORMAT */
1681 wfx.wFormatTag = 0x0055; /* WAVE_FORMAT_MPEGLAYER3 */
1682 wfx.nBlockAlign = 1; /* ? */
1683 wfx.wBitsPerSample = 0; /* undefined */
1684 wfx.cbSize = 12;
1685 bs = isom_create_waveform_audio_info( &wfx, audio->type );
1686 if( !bs )
1687 return LSMASH_ERR_MEMORY_ALLOC;
1688 uint16_t wID = 1; /* MPEGLAYER3_ID_MPEG */
1689 uint32_t fdwFlags = 0; /* We don't know whether the stream is padded or not here. */
1690 uint16_t nBlockSize = 0; /* (144 * (bitrate / nSamplesPerSec) + padding) * nFramesPerBlock */
1691 uint16_t nFramesPerBlock = 1; /* the number of audio frames per block */
1692 uint16_t nCodecDelay = 0; /* Encoder delay in samples is unknown. */
1693 lsmash_bs_put_le16( bs, wID );
1694 lsmash_bs_put_le32( bs, fdwFlags );
1695 lsmash_bs_put_le16( bs, nBlockSize );
1696 lsmash_bs_put_le16( bs, nFramesPerBlock );
1697 lsmash_bs_put_le16( bs, nCodecDelay );
1699 if( !bs )
1701 assert( 0 );
1702 return LSMASH_ERR_NAMELESS;
1704 uint32_t wfx_size;
1705 uint8_t *wfx_data = lsmash_bs_export_data( bs, &wfx_size );
1706 lsmash_bs_cleanup( bs );
1707 if( !wfx_data )
1708 return LSMASH_ERR_NAMELESS;
1709 if( wfx_size != ISOM_BASEBOX_COMMON_SIZE + 18 + wfx.cbSize )
1711 lsmash_free( wfx_data );
1712 return LSMASH_ERR_NAMELESS;
1714 int err = isom_add_extension_binary( wave, audio->type, LSMASH_BOX_PRECEDENCE_HM, wfx_data, wfx_size );
1715 if( err < 0 )
1717 lsmash_free( wfx_data );
1718 return err;
1720 return 0;
1723 static int isom_set_qtff_sound_decompression_parameters
1725 isom_audio_entry_t *audio,
1726 lsmash_audio_summary_t *summary,
1727 lsmash_qt_audio_format_specific_flag *format_flags,
1728 uint32_t samples_per_packet,
1729 uint32_t bytes_per_frame,
1730 uint32_t sample_size
1733 /* A 'wave' extension itself shall be absent in the opaque CODEC specific info list.
1734 * So, create a 'wave' extension here and append it as an extension to the audio sample description. */
1735 isom_wave_t *wave = isom_add_wave( audio );
1736 if( !wave )
1737 return LSMASH_ERR_NAMELESS;
1738 if( !isom_add_frma ( wave )
1739 || !isom_add_terminator( wave ) )
1741 lsmash_remove_entry_tail( &audio->extensions, wave->destruct );
1742 return LSMASH_ERR_NAMELESS;
1744 wave->frma->data_format = audio->type.fourcc;
1745 /* Append extensions from the opaque CODEC specific info list to 'wave' extension. */
1746 int err;
1747 int waveform_audio_info_present = 0;
1748 int requires_waveform_audio_info = isom_is_waveform_audio( audio->type );
1749 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
1751 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
1752 if( !specific )
1753 return LSMASH_ERR_NAMELESS;
1754 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
1755 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1756 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
1757 switch( specific->type )
1759 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
1760 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
1761 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
1762 continue; /* These cannot be an extension for 'wave' extension. */
1763 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
1764 /* (Legacy?) ALAC might have an Audio Channel Layout Box inside 'wave' extension. */
1765 #if 1
1766 continue;
1767 #else
1768 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO ) )
1769 continue;
1770 if( (err = isom_append_channel_layout_extension( specific, wave, summary->channels )) < 0 )
1771 return err;
1772 break;
1773 #endif
1774 default :
1776 assert( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
1777 || specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS );
1778 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
1779 if( !cs )
1780 return LSMASH_ERR_NAMELESS;
1781 if( cs->size < ISOM_BASEBOX_COMMON_SIZE )
1783 lsmash_destroy_codec_specific_data( cs );
1784 continue;
1786 uint8_t *box_data = cs->data.unstructured;
1787 uint64_t box_size = cs->size;
1788 lsmash_compact_box_type_t fourcc = LSMASH_4CC( box_data[4], box_data[5], box_data[6], box_data[7] );
1789 if( audio->version == 2 && fourcc == QT_BOX_TYPE_ENDA.fourcc )
1791 /* Don't append a 'enda' extension if version == 2.
1792 * Endianness is indicated in QuickTime audio format specific flags. */
1793 if( box_size >= ISOM_BASEBOX_COMMON_SIZE + 2 )
1795 /* Override endianness indicated in format specific flags. */
1796 if( box_data[9] == 1 )
1797 *format_flags &= ~QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN;
1798 else
1799 *format_flags |= QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN;
1801 lsmash_destroy_codec_specific_data( cs );
1802 continue;
1804 lsmash_box_type_t box_type = isom_guess_audio_codec_specific_box_type( audio->type, fourcc );
1805 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_WAVE ) )
1807 /* It is insane to appened a 'wave' extension to a 'wave' extension. */
1808 lsmash_destroy_codec_specific_data( cs );
1809 continue;
1811 box_type = lsmash_form_qtff_box_type( box_type.fourcc );
1812 /* Determine 'precedence'. */
1813 uint64_t precedence;
1814 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_FRMA ) )
1815 precedence = LSMASH_BOX_PRECEDENCE_QTFF_FRMA;
1816 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ESDS ) )
1817 precedence = LSMASH_BOX_PRECEDENCE_QTFF_ESDS;
1818 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ENDA ) )
1819 precedence = LSMASH_BOX_PRECEDENCE_QTFF_ENDA;
1820 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_MP4A ) )
1821 precedence = LSMASH_BOX_PRECEDENCE_QTFF_MP4A;
1822 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_TERMINATOR ) )
1823 precedence = LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR;
1824 else
1825 precedence = LSMASH_BOX_PRECEDENCE_HM;
1826 /* Append the extension. */
1827 err = isom_add_extension_binary( wave, box_type, precedence, cs->data.unstructured, cs->size );
1828 cs->data.unstructured = NULL; /* Avoid freeing the binary data of the extension. */
1829 lsmash_destroy_codec_specific_data( cs );
1830 if( err < 0 )
1831 return err;
1832 if( isom_is_waveform_audio( box_type ) )
1833 waveform_audio_info_present = 1;
1834 break;
1838 if( requires_waveform_audio_info && !waveform_audio_info_present
1839 && (err = isom_setup_waveform_audio_info( wave, audio, summary, samples_per_packet, bytes_per_frame, sample_size )) < 0 )
1840 return err;
1841 return 0;
1844 static int isom_set_qtff_template_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1846 audio->manager |= LSMASH_QTFF_BASE;
1847 audio->type = lsmash_form_qtff_box_type( audio->type.fourcc );
1848 audio->version = (summary->channels > 2 || summary->frequency > UINT16_MAX) ? 2 : 1;
1849 /* Try to get QuickTime audio format specific flags. */
1850 lsmash_qt_audio_format_specific_flag format_flags = QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN;
1851 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
1853 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
1854 if( !specific
1855 || !specific->data.structured )
1856 continue;
1857 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1858 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1860 /* A format specific flags is found.
1861 * Force audio sample description version == 2. */
1862 format_flags = ((lsmash_qt_audio_format_specific_flags_t *)specific->data.structured)->format_flags;
1863 audio->version = 2;
1864 break;
1867 uint32_t samples_per_packet;
1868 uint32_t bytes_per_frame;
1869 uint32_t sample_size;
1870 if( !((summary->samples_in_frame == 0 || summary->bytes_per_frame == 0 || summary->sample_size == 0)
1871 && isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio, &samples_per_packet, &bytes_per_frame, &sample_size )) )
1873 samples_per_packet = summary->samples_in_frame;
1874 bytes_per_frame = summary->bytes_per_frame;
1875 sample_size = summary->sample_size;
1877 if( !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC3_AUDIO )
1878 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC6_AUDIO )
1879 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_AGSM_AUDIO )
1880 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAW_AUDIO )
1881 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ULAW_AUDIO ) )
1883 int err = isom_set_qtff_sound_decompression_parameters( audio, summary, &format_flags,
1884 samples_per_packet, bytes_per_frame, sample_size );
1885 if( err < 0 )
1886 return err;
1888 /* Set up common audio description fields. */
1889 audio->samplesize = 16;
1890 audio->packet_size = 0;
1891 if( audio->version == 2 )
1893 audio->channelcount = 3;
1894 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION;
1895 audio->samplerate = 0x00010000;
1896 audio->sizeOfStructOnly = 72;
1897 audio->audioSampleRate = (union {double d; uint64_t i;}){summary->frequency}.i;
1898 audio->numAudioChannels = summary->channels;
1899 audio->always7F000000 = 0x7F000000;
1900 audio->constBitsPerChannel = 0;
1901 audio->constBytesPerAudioPacket = bytes_per_frame;
1902 audio->constLPCMFramesPerAudioPacket = samples_per_packet;
1903 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO ) )
1905 switch( sample_size )
1907 case 16 :
1908 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA;
1909 break;
1910 case 20 :
1911 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA;
1912 break;
1913 case 24 :
1914 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA;
1915 break;
1916 case 32 :
1917 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA;
1918 break;
1919 default :
1920 break;
1923 else
1925 if( format_flags & QT_AUDIO_FORMAT_FLAG_FLOAT )
1926 format_flags &= ~QT_AUDIO_FORMAT_FLAG_SIGNED_INTEGER;
1927 if( format_flags & QT_AUDIO_FORMAT_FLAG_PACKED )
1928 format_flags &= ~QT_AUDIO_FORMAT_FLAG_ALIGNED_HIGH;
1929 audio->formatSpecificFlags = format_flags;
1932 else /* if( audio->version == 1 ) */
1934 audio->channelcount = LSMASH_MIN( summary->channels, 2 );
1935 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION;
1936 audio->samplerate = summary->frequency << 16;
1937 audio->samplesPerPacket = samples_per_packet;
1938 audio->bytesPerPacket = bytes_per_frame / summary->channels;
1939 audio->bytesPerFrame = bytes_per_frame; /* sample_size field in stsz box is NOT used. */
1940 audio->bytesPerSample = 1 + (sample_size != 8);
1942 return 0;
1945 static void isom_set_samplerate_division_of_media_timescale( isom_audio_entry_t *audio, int strict )
1947 if( audio->parent /* stsd */
1948 && audio->parent->parent /* stbl */
1949 && audio->parent->parent->parent /* minf */
1950 && audio->parent->parent->parent->parent /* mdia */
1951 && lsmash_check_box_type_identical( audio->parent->parent->parent->parent->type, ISOM_BOX_TYPE_MDIA )
1952 && ((isom_mdia_t *)audio->parent->parent->parent->parent)->mdhd )
1954 /* Make an effort to match the timescale with samplerate, or be an integer multiple of it. */
1955 uint32_t orig_timescale = ((isom_mdia_t *)audio->parent->parent->parent->parent)->mdhd->timescale;
1956 uint32_t timescale = orig_timescale;
1957 uint32_t i = 2;
1958 while( timescale > UINT16_MAX && timescale > 1 )
1960 if( timescale % i == 0 )
1961 timescale /= i;
1962 else
1963 i += i > 2 ? 2 : 1;
1965 if( timescale != orig_timescale && strict )
1966 lsmash_log( NULL, LSMASH_LOG_WARNING, "samplerate does not match the media timescale.\n" );
1967 if( timescale <= UINT16_MAX && timescale > 1 )
1969 audio->samplerate = timescale << 16;
1970 return;
1973 audio->samplerate = 0;
1976 static int isom_set_isom_template_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1978 audio->version = 0; /* reserved */
1979 audio->revision_level = 0; /* reserved */
1980 audio->vendor = 0; /* reserved */
1981 audio->channelcount = 2; /* template */
1982 audio->samplesize = 16; /* template */
1983 audio->compression_ID = 0; /* pre_defined */
1984 audio->packet_size = 0; /* reserved */
1985 /* template : default output audio sampling rate at playback */
1986 if( summary->frequency <= UINT16_MAX )
1987 audio->samplerate = summary->frequency << 16;
1988 else
1989 isom_set_samplerate_division_of_media_timescale( audio, 0 );
1990 return 0;
1993 static int isom_set_isom_amr_audio_description( isom_audio_entry_t *audio, int wb )
1995 /* For AMR-NB and AMR-WB stream, these fields are not meaningful. */
1996 audio->version = 0; /* always 0 */
1997 audio->revision_level = 0; /* always 0 */
1998 audio->vendor = 0; /* always 0 */
1999 audio->channelcount = 2; /* always 2 although the actual number of channels is always 1 */
2000 audio->samplesize = 16; /* always 16 */
2001 audio->compression_ID = 0; /* always 0 */
2002 audio->packet_size = 0; /* always 0 */
2003 /* Set samplerate by trying to copy from Media Header Box of this media though the
2004 * actual samplerate is 8000 Hz for AMR-NB and 16000 Hz for AMR-WB.
2005 * 3GPP and 3GPP2 has no restriction for media timescale. Therefore, users should
2006 * set suitable media timescale by themselves within the bounds of common sense. */
2007 isom_set_samplerate_division_of_media_timescale( audio, 1 );
2008 if( audio->samplerate == 0 )
2009 /* Set hard-coded but correct samplerate in the CODEC level. */
2010 audio->samplerate = wb ? 8000 : 16000;
2011 return 0;
2014 static int isom_set_isom_alac_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
2016 return isom_set_isom_template_audio_description( audio, summary );
2019 static int isom_set_qtff_alac_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
2021 return isom_set_qtff_template_audio_description( audio, summary );
2024 static int isom_set_isom_eac3_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
2026 return isom_set_isom_template_audio_description( audio, summary );
2029 static int isom_setup_audio_description( isom_stsd_t *stsd, lsmash_audio_summary_t *summary )
2031 if( !stsd || !stsd->file || !summary )
2032 return LSMASH_ERR_NAMELESS;
2033 int err = isom_check_valid_summary( (lsmash_summary_t *)summary );
2034 if( err < 0 )
2035 return err;
2036 isom_audio_entry_t *audio = isom_add_audio_description( stsd, summary->sample_type );
2037 if( !audio )
2038 return LSMASH_ERR_NAMELESS;
2039 audio->data_reference_index = summary->data_ref_index;
2040 lsmash_file_t *file = stsd->file;
2041 lsmash_codec_type_t audio_type = audio->type;
2042 if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_MP4A_AUDIO )
2043 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_MP4A_AUDIO ) )
2045 if( (file->ftyp && file->ftyp->major_brand == ISOM_BRAND_TYPE_QT)
2046 || (!file->ftyp && (file->qt_compatible || (file->moov && !file->moov->iods))) )
2047 err = isom_set_qtff_mp4a_description( audio, summary );
2048 else
2049 err = isom_set_isom_mp4a_description( audio, summary );
2051 else if( isom_is_lpcm_audio( audio ) )
2052 err = isom_set_qtff_lpcm_description( audio, summary );
2053 else if( file->isom_compatible && lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_ALAC_AUDIO ) )
2054 err = isom_set_isom_alac_audio_description( audio, summary );
2055 else if( file->qt_compatible && lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_ALAC_AUDIO ) )
2056 err = isom_set_qtff_alac_audio_description( audio, summary );
2057 else if( audio->type.fourcc == ISOM_CODEC_TYPE_ALAC_AUDIO.fourcc )
2059 if( file->qt_compatible )
2060 err = isom_set_qtff_alac_audio_description( audio, summary );
2061 else
2062 err = isom_set_isom_alac_audio_description( audio, summary );
2064 else if( isom_is_dts_audio( audio_type ) )
2065 err = isom_set_isom_dts_audio_description( audio, summary );
2066 else if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_EC_3_AUDIO ) )
2067 err = isom_set_isom_eac3_audio_description( audio, summary );
2068 else if( file->qt_compatible )
2069 err = isom_set_qtff_template_audio_description( audio, summary );
2070 else if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_SAMR_AUDIO ) )
2071 err = isom_set_isom_amr_audio_description( audio, 0 );
2072 else if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_SAWB_AUDIO ) )
2073 err = isom_set_isom_amr_audio_description( audio, 1 );
2074 else
2075 err = isom_set_isom_template_audio_description( audio, summary );
2076 if( err < 0 )
2077 goto fail;
2078 err = LSMASH_ERR_NAMELESS;
2079 /* Don't use audio_type since audio->type might have changed. */
2080 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
2082 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
2083 if( !specific )
2084 goto fail;
2085 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
2086 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2087 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
2088 switch( specific->type )
2090 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
2092 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
2093 continue; /* Ignore since not fatal. */
2094 lsmash_qt_audio_common_t *data = (lsmash_qt_audio_common_t *)specific->data.structured;
2095 audio->revision_level = data->revision_level;
2096 audio->vendor = data->vendor;
2097 if( audio->version == 1
2098 && !isom_is_lpcm_audio( audio )
2099 && data->compression_ID != QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED )
2101 /* Compressed audio must not be set to QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED. */
2102 audio->compression_ID = data->compression_ID;
2103 if( audio->compression_ID == QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION )
2105 /* For variable compression, bytesPerPacket and bytesPerFrame are reserved and should be set to 0. */
2106 audio->bytesPerPacket = 0;
2107 audio->bytesPerFrame = 0;
2110 break;
2112 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
2114 if( !file->qt_compatible
2115 && !lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_ALAC_AUDIO )
2116 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO ) )
2117 continue;
2118 if( (err = isom_append_channel_layout_extension( specific, audio, summary->channels )) < 0 )
2119 goto fail;
2120 break;
2122 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
2124 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2125 if( !cs )
2126 goto fail;
2127 lsmash_codec_global_header_t *data = (lsmash_codec_global_header_t *)cs->data.structured;
2128 isom_glbl_t *glbl = isom_add_glbl( audio );
2129 if( !glbl )
2131 lsmash_destroy_codec_specific_data( cs );
2132 goto fail;
2134 glbl->header_size = data->header_size;
2135 glbl->header_data = lsmash_memdup( data->header_data, data->header_size );
2136 lsmash_destroy_codec_specific_data( cs );
2137 if( !glbl->header_data )
2139 isom_remove_box_by_itself( glbl );
2140 err = LSMASH_ERR_MEMORY_ALLOC;
2141 goto fail;
2143 break;
2145 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
2146 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS :
2147 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
2148 break; /* shall be set up already */
2149 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
2150 if( file->qt_compatible )
2151 continue; /* shall be set up already */
2152 default :
2154 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2155 if( !cs )
2156 goto fail;
2157 if( cs->size < ISOM_BASEBOX_COMMON_SIZE )
2159 lsmash_destroy_codec_specific_data( cs );
2160 continue;
2162 uint8_t *box_data = cs->data.unstructured;
2163 lsmash_compact_box_type_t fourcc = LSMASH_4CC( box_data[4], box_data[5], box_data[6], box_data[7] );
2164 lsmash_box_type_t box_type = isom_guess_audio_codec_specific_box_type( audio->type, fourcc );
2165 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_WAVE ) )
2167 /* CODEC specific info shall be already inside 'wave' extension. */
2168 lsmash_destroy_codec_specific_data( cs );
2169 continue;
2171 /* Append the extension. */
2172 err = isom_add_extension_binary( audio, box_type, LSMASH_BOX_PRECEDENCE_HM, cs->data.unstructured, cs->size );
2173 cs->data.unstructured = NULL; /* Avoid freeing the binary data of the extension. */
2174 lsmash_destroy_codec_specific_data( cs );
2175 if( err < 0 )
2176 goto fail;
2177 break;
2181 if( audio->version == 0 )
2182 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED;
2183 else if( audio->version == 2 )
2184 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION;
2185 return 0;
2186 fail:
2187 isom_remove_box_by_itself( audio );
2188 return err;
2191 static int isom_setup_tx3g_description( isom_stsd_t *stsd, lsmash_summary_t *summary )
2193 isom_tx3g_entry_t *tx3g = isom_add_tx3g_description( stsd );
2194 if( !tx3g )
2195 return LSMASH_ERR_NAMELESS;
2196 /* We create a dummy font record to make valid font_ID in the sample description.
2197 * The specification (3GPP TS 26.245) does not forbid the value 0 for the identifier,
2198 * but we set 1 to it as track_ID begins from 1. */
2199 tx3g->data_reference_index = summary->data_ref_index;
2200 tx3g->font_ID = 1; /* ID of the default font record */
2201 int err = LSMASH_ERR_MEMORY_ALLOC;
2202 isom_ftab_t *ftab = isom_add_ftab( tx3g );
2203 if( !ftab )
2205 err = LSMASH_ERR_NAMELESS;
2206 goto fail;
2208 isom_font_record_t *font = lsmash_malloc( sizeof(isom_font_record_t) );
2209 if( !font )
2210 goto fail;
2211 if( lsmash_add_entry( ftab->list, font ) < 0 )
2213 lsmash_free( font );
2214 goto fail;
2216 const char font_names[] = "Serif,Sans-serif,Monospace";
2217 font->font_ID = 1;
2218 font->font_name_length = sizeof(font_names);
2219 font->font_name = lsmash_memdup( font_names, sizeof(font_names) );
2220 if( !font->font_name )
2221 goto fail;
2222 return 0;
2223 fail:
2224 isom_remove_box_by_itself( tx3g );
2225 return err;
2228 static int isom_setup_qt_text_description( isom_stsd_t *stsd, lsmash_summary_t *summary )
2230 isom_qt_text_entry_t *text = isom_add_qt_text_description( stsd );
2231 if( !text )
2232 return LSMASH_ERR_NAMELESS;
2233 text->data_reference_index = summary->data_ref_index;
2234 return 0;
2237 static int isom_setup_text_description( isom_stsd_t *stsd, lsmash_summary_t *summary )
2239 lsmash_codec_type_t sample_type = summary->sample_type;
2240 if( lsmash_check_box_type_identical( sample_type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
2241 return isom_setup_tx3g_description( stsd, summary );
2242 else if( lsmash_check_box_type_identical( sample_type, QT_CODEC_TYPE_TEXT_TEXT ) )
2243 return isom_setup_qt_text_description( stsd, summary );
2244 else
2245 return LSMASH_ERR_NAMELESS;
2248 int isom_setup_sample_description( isom_stsd_t *stsd, lsmash_media_type media_type, lsmash_summary_t *summary )
2250 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
2251 return isom_setup_visual_description( stsd, (lsmash_video_summary_t *)summary );
2252 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
2253 return isom_setup_audio_description( stsd, (lsmash_audio_summary_t *)summary );
2254 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
2255 return isom_setup_text_description( stsd, (lsmash_summary_t *)summary );
2256 else
2257 return LSMASH_ERR_NAMELESS;
2260 static lsmash_codec_specific_data_type isom_get_codec_specific_data_type( lsmash_compact_box_type_t extension_fourcc )
2262 static struct codec_specific_data_type_table_tag
2264 lsmash_compact_box_type_t extension_fourcc;
2265 lsmash_codec_specific_data_type data_type;
2266 } codec_specific_data_type_table[32] = { { 0, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN } };
2267 if( codec_specific_data_type_table[0].data_type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN )
2269 int i = 0;
2270 #define ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( extension_type, data_type ) \
2271 codec_specific_data_type_table[i++] = (struct codec_specific_data_type_table_tag){ extension_type.fourcc, data_type }
2272 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 );
2273 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC );
2274 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 );
2275 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 );
2276 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 );
2277 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS );
2278 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC );
2279 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
2280 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE );
2281 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE );
2282 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ALAC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC );
2283 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ESDS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
2284 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO );
2285 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT );
2286 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS );
2287 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL );
2288 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT );
2289 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER );
2290 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN );
2291 #undef ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT
2293 lsmash_codec_specific_data_type data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN;
2294 for( int i = 0; codec_specific_data_type_table[i].data_type != LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN; i++ )
2295 if( extension_fourcc == codec_specific_data_type_table[i].extension_fourcc )
2297 data_type = codec_specific_data_type_table[i].data_type;
2298 break;
2300 return data_type;
2303 lsmash_summary_t *isom_create_video_summary_from_description( isom_sample_entry_t *sample_entry )
2305 if( !sample_entry )
2306 return NULL;
2307 isom_visual_entry_t *visual = (isom_visual_entry_t *)sample_entry;
2308 lsmash_video_summary_t *summary = (lsmash_video_summary_t *)lsmash_create_summary( LSMASH_SUMMARY_TYPE_VIDEO );
2309 if( !summary )
2310 return NULL;
2311 summary->sample_type = visual->type;
2312 summary->data_ref_index = visual->data_reference_index;
2313 summary->width = visual->width;
2314 summary->height = visual->height;
2315 summary->depth = visual->depth;
2316 memcpy( summary->compressorname, visual->compressorname, 32 );
2317 summary->compressorname[32] = '\0';
2318 if( isom_is_qt_video( summary->sample_type ) )
2320 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON,
2321 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2322 if( !specific )
2323 goto fail;
2324 lsmash_qt_video_common_t *data = (lsmash_qt_video_common_t *)specific->data.structured;
2325 data->revision_level = visual->revision_level;
2326 data->vendor = visual->vendor;
2327 data->temporalQuality = visual->temporalQuality;
2328 data->spatialQuality = visual->spatialQuality;
2329 data->horizontal_resolution = visual->horizresolution;
2330 data->vertical_resolution = visual->vertresolution;
2331 data->dataSize = visual->dataSize;
2332 data->frame_count = visual->frame_count;
2333 data->color_table_ID = visual->color_table_ID;
2334 if( visual->color_table_ID == 0 )
2336 isom_qt_color_table_t *src_ct = &visual->color_table;
2337 if( !src_ct->array )
2339 lsmash_destroy_codec_specific_data( specific );
2340 goto fail;
2342 uint16_t element_count = LSMASH_MIN( src_ct->size + 1, 256 );
2343 lsmash_qt_color_table_t *dst_ct = &data->color_table;
2344 dst_ct->seed = src_ct->seed;
2345 dst_ct->flags = src_ct->flags;
2346 dst_ct->size = src_ct->size;
2347 for( uint16_t i = 0; i < element_count; i++ )
2349 dst_ct->array[i].unused = src_ct->array[i].value;
2350 dst_ct->array[i].r = src_ct->array[i].r;
2351 dst_ct->array[i].g = src_ct->array[i].g;
2352 dst_ct->array[i].b = src_ct->array[i].b;
2355 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2357 lsmash_destroy_codec_specific_data( specific );
2358 goto fail;
2361 for( lsmash_entry_t *entry = visual->extensions.head; entry; entry = entry->next )
2363 isom_box_t *box = (isom_box_t *)entry->data;
2364 if( !box )
2365 continue;
2366 if( !(box->manager & LSMASH_BINARY_CODED_BOX) )
2368 lsmash_codec_specific_t *specific = NULL;
2369 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_CLAP ) )
2371 isom_clap_t *clap = (isom_clap_t *)box;
2372 summary->clap.width.n = clap->cleanApertureWidthN;
2373 summary->clap.width.d = clap->cleanApertureWidthD;
2374 summary->clap.height.n = clap->cleanApertureHeightN;
2375 summary->clap.height.d = clap->cleanApertureHeightD;
2376 summary->clap.horizontal_offset.n = clap->horizOffN;
2377 summary->clap.horizontal_offset.d = clap->horizOffD;
2378 summary->clap.vertical_offset.n = clap->vertOffN;
2379 summary->clap.vertical_offset.d = clap->vertOffD;
2380 continue;
2382 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_PASP ) )
2384 isom_pasp_t *pasp = (isom_pasp_t *)box;
2385 summary->par_h = pasp->hSpacing;
2386 summary->par_v = pasp->vSpacing;
2387 continue;
2389 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_COLR )
2390 || lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_COLR ) )
2392 isom_colr_t *colr = (isom_colr_t *)box;
2393 summary->color.primaries_index = colr->primaries_index;
2394 summary->color.transfer_index = colr->transfer_function_index;
2395 summary->color.matrix_index = colr->matrix_index;
2396 summary->color.full_range = colr->full_range_flag;
2397 continue;
2399 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STSL ) )
2401 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE,
2402 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2403 if( !specific )
2404 goto fail;
2405 isom_stsl_t *stsl = (isom_stsl_t *)box;
2406 lsmash_isom_sample_scale_t *data = (lsmash_isom_sample_scale_t *)specific->data.structured;
2407 data->constraint_flag = stsl->constraint_flag;
2408 data->scale_method = stsl->scale_method;
2409 data->display_center_x = stsl->display_center_x;
2410 data->display_center_y = stsl->display_center_y;
2412 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_BTRT ) )
2414 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE,
2415 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2416 if( !specific )
2417 goto fail;
2418 isom_btrt_t *btrt = (isom_btrt_t *)box;
2419 lsmash_h264_bitrate_t *data = (lsmash_h264_bitrate_t *)specific->data.structured;
2420 data->bufferSizeDB = btrt->bufferSizeDB;
2421 data->maxBitrate = btrt->maxBitrate;
2422 data->avgBitrate = btrt->avgBitrate;
2424 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_FIEL ) )
2426 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO,
2427 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2428 if( !specific )
2429 goto fail;
2430 isom_fiel_t *fiel = (isom_fiel_t *)box;
2431 lsmash_qt_field_info_t *data = (lsmash_qt_field_info_t *)specific->data.structured;
2432 data->fields = fiel->fields;
2433 data->detail = fiel->detail;
2435 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_CSPC ) )
2437 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT,
2438 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2439 if( !specific )
2440 goto fail;
2441 isom_cspc_t *cspc = (isom_cspc_t *)box;
2442 lsmash_qt_pixel_format_t *data = (lsmash_qt_pixel_format_t *)specific->data.structured;
2443 data->pixel_format = cspc->pixel_format;
2445 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_SGBT ) )
2447 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS,
2448 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2449 if( !specific )
2450 goto fail;
2451 isom_sgbt_t *sgbt = (isom_sgbt_t *)box;
2452 lsmash_qt_significant_bits_t *data = (lsmash_qt_significant_bits_t *)specific->data.structured;
2453 data->significantBits = sgbt->significantBits;
2455 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_GLBL ) )
2457 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER,
2458 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2459 if( !specific )
2460 goto fail;
2461 isom_glbl_t *glbl = (isom_glbl_t *)box;
2462 lsmash_codec_global_header_t *data = (lsmash_codec_global_header_t *)specific->data.structured;
2463 data->header_size = glbl->header_size;
2464 data->header_data = lsmash_memdup( glbl->header_data, glbl->header_size );
2465 if( !data->header_data )
2467 lsmash_destroy_codec_specific_data( specific );
2468 goto fail;
2471 else
2472 continue;
2473 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2475 lsmash_destroy_codec_specific_data( specific );
2476 goto fail;
2479 else
2481 if( box->size < ISOM_BASEBOX_COMMON_SIZE )
2482 continue;
2483 uint8_t *data = box->binary;
2484 lsmash_compact_box_type_t fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
2485 lsmash_codec_specific_data_type type = isom_get_codec_specific_data_type( fourcc );
2486 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2487 if( !specific )
2488 goto fail;
2489 specific->size = box->size;
2490 specific->data.unstructured = lsmash_memdup( box->binary, box->size );
2491 if( !specific->data.unstructured
2492 || lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2494 lsmash_destroy_codec_specific_data( specific );
2495 goto fail;
2499 return (lsmash_summary_t *)summary;
2500 fail:
2501 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
2502 return NULL;
2505 static int isom_append_structured_mp4sys_decoder_config( lsmash_codec_specific_list_t *opaque, isom_esds_t *esds )
2507 lsmash_bs_t *bs = lsmash_bs_create();
2508 if( !bs )
2509 return LSMASH_ERR_MEMORY_ALLOC;
2510 /* Put box size, type, version and flags fields. */
2511 lsmash_bs_put_be32( bs, 0 );
2512 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_ESDS.fourcc );
2513 lsmash_bs_put_be32( bs, 0 );
2514 /* Put ES Descriptor. */
2515 mp4sys_update_descriptor_size( esds->ES );
2516 mp4sys_write_descriptor( bs, esds->ES );
2517 /* Export ES Descriptor Box as binary string. */
2518 uint32_t esds_size;
2519 uint8_t *esds_data = lsmash_bs_export_data( bs, &esds_size );
2520 lsmash_bs_cleanup( bs );
2521 if( !esds_data )
2522 return LSMASH_ERR_NAMELESS;
2523 /* Update box size. */
2524 LSMASH_SET_BE32( esds_data, esds_size );
2525 lsmash_codec_specific_data_type type = isom_get_codec_specific_data_type( ISOM_BOX_TYPE_ESDS.fourcc );
2526 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2527 if( !specific )
2529 lsmash_free( esds_data );
2530 return LSMASH_ERR_NAMELESS;
2532 specific->data.unstructured = esds_data;
2533 specific->size = esds_size;
2534 /* Convert unstructured CODEC specific data format into structured, and append it to the opaque list. */
2535 lsmash_codec_specific_t *conv = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2536 lsmash_destroy_codec_specific_data( specific );
2537 if( !conv )
2538 return LSMASH_ERR_NAMELESS;
2539 if( lsmash_add_entry( &opaque->list, conv ) < 0 )
2541 lsmash_destroy_codec_specific_data( conv );
2542 return LSMASH_ERR_MEMORY_ALLOC;
2544 return 0;
2547 lsmash_summary_t *isom_create_audio_summary_from_description( isom_sample_entry_t *sample_entry )
2549 if( !sample_entry || !sample_entry->file || !sample_entry->parent )
2550 return NULL;
2551 isom_audio_entry_t *audio = (isom_audio_entry_t *)sample_entry;
2552 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO );
2553 if( !summary )
2554 return NULL;
2555 summary->sample_type = audio->type;
2556 summary->data_ref_index = audio->data_reference_index;
2557 summary->sample_size = audio->samplesize;
2558 summary->channels = audio->channelcount;
2559 summary->frequency = audio->samplerate >> 16;
2560 if( ((isom_stsd_t *)audio->parent)->version == 0
2561 && audio->file->qt_compatible
2562 && isom_is_qt_audio( audio->type ) )
2564 if( audio->version == 0 )
2565 isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio, &summary->samples_in_frame, &summary->bytes_per_frame, &summary->sample_size );
2566 else if( audio->version == 1 )
2568 summary->channels = audio->bytesPerPacket ? audio->bytesPerFrame / audio->bytesPerPacket : audio->channelcount;
2569 summary->sample_size = audio->bytesPerPacket * 8;
2570 summary->samples_in_frame = audio->samplesPerPacket;
2571 summary->bytes_per_frame = audio->bytesPerFrame;
2573 else if( audio->version == 2 )
2575 summary->frequency = (union {uint64_t i; double d;}){audio->audioSampleRate}.d;
2576 summary->channels = audio->numAudioChannels;
2577 summary->sample_size = audio->constBitsPerChannel;
2578 summary->samples_in_frame = audio->constLPCMFramesPerAudioPacket;
2579 summary->bytes_per_frame = audio->constBytesPerAudioPacket;
2581 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON,
2582 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2583 if( !specific )
2584 goto fail;
2585 lsmash_qt_audio_common_t *common = (lsmash_qt_audio_common_t *)specific->data.structured;
2586 common->revision_level = audio->revision_level;
2587 common->vendor = audio->vendor;
2588 common->compression_ID = audio->compression_ID;
2589 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2591 lsmash_destroy_codec_specific_data( specific );
2592 goto fail;
2594 if( isom_is_lpcm_audio( audio ) )
2596 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS,
2597 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2598 if( !specific )
2599 goto fail;
2600 lsmash_qt_audio_format_specific_flags_t *data = (lsmash_qt_audio_format_specific_flags_t *)specific->data.structured;
2601 if( audio->version == 2 )
2602 data->format_flags = audio->formatSpecificFlags;
2603 else
2605 data->format_flags = QT_LPCM_FORMAT_FLAG_BIG_ENDIAN | QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER;
2606 /* Here, don't override samplesize.
2607 * We should trust samplesize field in the description for misused CODEC indentifier. */
2608 lsmash_codec_type_t audio_type = audio->type;
2609 if( lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_TWOS_AUDIO )
2610 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_NONE_AUDIO )
2611 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_NOT_SPECIFIED ) )
2613 if( summary->sample_size <= 8 )
2614 data->format_flags &= ~(QT_LPCM_FORMAT_FLAG_BIG_ENDIAN | QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER);
2616 else
2618 if( lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_FL32_AUDIO )
2619 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_FL64_AUDIO ) )
2621 data->format_flags &= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER;
2622 data->format_flags |= QT_LPCM_FORMAT_FLAG_FLOAT;
2624 else if( lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_23NI_AUDIO )
2625 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_SOWT_AUDIO ) )
2626 data->format_flags &= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
2629 isom_wave_t *wave = (isom_wave_t *)isom_get_extension_box_format( &audio->extensions, QT_BOX_TYPE_WAVE );
2630 if( wave && wave->enda )
2632 if( wave->enda->littleEndian )
2633 data->format_flags &= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
2634 else
2635 data->format_flags |= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
2637 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2639 lsmash_destroy_codec_specific_data( specific );
2640 goto fail;
2643 else if( audio->version == 2
2644 && (lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_ALAC_AUDIO )
2645 || lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO )) )
2646 switch( audio->formatSpecificFlags )
2648 case QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA :
2649 summary->sample_size = 16;
2650 break;
2651 case QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA :
2652 summary->sample_size = 20;
2653 break;
2654 case QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA :
2655 summary->sample_size = 24;
2656 break;
2657 case QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA :
2658 summary->sample_size = 32;
2659 break;
2660 default :
2661 break;
2664 else if( lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_SAMR_AUDIO ) )
2666 summary->channels = 1;
2667 summary->frequency = 8000;
2669 else if( lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_SAWB_AUDIO ) )
2671 summary->channels = 1;
2672 summary->frequency = 16000;
2674 uint32_t actual_sampling_rate = 0;
2675 for( lsmash_entry_t *entry = audio->extensions.head; entry; entry = entry->next )
2677 isom_box_t *box = (isom_box_t *)entry->data;
2678 if( !box )
2679 continue;
2680 if( !(box->manager & LSMASH_BINARY_CODED_BOX) )
2682 if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_CHAN ) )
2684 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT,
2685 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2686 if( !specific )
2687 goto fail;
2688 isom_chan_t *chan = (isom_chan_t *)box;
2689 lsmash_qt_audio_channel_layout_t *data = (lsmash_qt_audio_channel_layout_t *)specific->data.structured;
2690 data->channelLayoutTag = chan->channelLayoutTag;
2691 data->channelBitmap = chan->channelBitmap;
2692 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2694 lsmash_destroy_codec_specific_data( specific );
2695 goto fail;
2698 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_ESDS )
2699 || lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ESDS ) )
2701 isom_esds_t *esds = (isom_esds_t *)box;
2702 if( mp4sys_setup_summary_from_DecoderSpecificInfo( summary, esds->ES ) < 0
2703 || isom_append_structured_mp4sys_decoder_config( summary->opaque, esds ) < 0 )
2704 goto fail;
2706 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_SRAT ) )
2708 isom_srat_t *srat = (isom_srat_t *)box;
2709 actual_sampling_rate = srat->sampling_rate;
2711 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_WAVE ) )
2713 /* Don't append 'wave' extension itself to the opaque CODEC specific info list. */
2714 isom_wave_t *wave = (isom_wave_t *)box;
2715 lsmash_bs_t *bs = lsmash_bs_create();
2716 if( !bs )
2717 goto fail;
2718 for( lsmash_entry_t *wave_entry = wave->extensions.head; wave_entry; wave_entry = wave_entry->next )
2720 isom_box_t *wave_ext = (isom_box_t *)wave_entry->data;
2721 if( !wave_ext )
2722 continue;
2723 lsmash_box_type_t box_type = LSMASH_BOX_TYPE_INITIALIZER;
2724 if( !(wave_ext->manager & LSMASH_BINARY_CODED_BOX) )
2726 box_type = wave_ext->type;
2727 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ENDA ) )
2729 isom_enda_t *enda = (isom_enda_t *)wave_ext;
2730 isom_bs_put_box_common( bs, enda );
2731 lsmash_bs_put_be16( bs, enda->littleEndian );
2733 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_MP4A ) )
2735 isom_mp4a_t *mp4a = (isom_mp4a_t *)wave_ext;
2736 isom_bs_put_box_common( bs, mp4a );
2737 lsmash_bs_put_be32( bs, mp4a->unknown );
2739 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_CHAN ) )
2741 isom_chan_t *chan = (isom_chan_t *)wave_ext;
2742 isom_bs_put_box_common( bs, chan );
2743 lsmash_bs_put_be32( bs, chan->channelLayoutTag );
2744 lsmash_bs_put_be32( bs, chan->channelBitmap );
2745 lsmash_bs_put_be32( bs, chan->numberChannelDescriptions );
2746 if( chan->channelDescriptions )
2747 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
2749 isom_channel_description_t *channelDescriptions = (isom_channel_description_t *)(&chan->channelDescriptions[i]);
2750 lsmash_bs_put_be32( bs, channelDescriptions->channelLabel );
2751 lsmash_bs_put_be32( bs, channelDescriptions->channelFlags );
2752 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[0] );
2753 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[1] );
2754 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[2] );
2757 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ESDS ) )
2759 isom_esds_t *esds = (isom_esds_t *)wave_ext;
2760 if( !esds
2761 || mp4sys_setup_summary_from_DecoderSpecificInfo( summary, esds->ES ) < 0
2762 || isom_append_structured_mp4sys_decoder_config( summary->opaque, esds ) < 0 )
2764 lsmash_bs_cleanup( bs );
2765 goto fail;
2767 continue;
2769 else
2770 /* Skip Format Box and Terminator Box since they are mandatory and fixed structure. */
2771 continue;
2773 else
2775 if( wave_ext->size < ISOM_BASEBOX_COMMON_SIZE )
2776 continue;
2777 uint8_t *data = wave_ext->binary;
2778 box_type.fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
2779 lsmash_bs_put_bytes( bs, wave_ext->size, wave_ext->binary );
2781 /* Export as binary string. */
2782 uint32_t box_size;
2783 uint8_t *box_data = lsmash_bs_export_data( bs, &box_size );
2784 lsmash_bs_empty( bs );
2785 if( !box_data )
2787 lsmash_bs_cleanup( bs );
2788 goto fail;
2790 /* Append as an unstructured CODEC specific info. */
2791 lsmash_codec_specific_data_type type;
2792 if( box_type.fourcc == QT_BOX_TYPE_CHAN.fourcc )
2793 /* Complete audio channel layout is stored as binary string.
2794 * We distinguish it from one of the outside of 'wave' extension here. */
2795 type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS;
2796 else
2798 type = isom_get_codec_specific_data_type( box_type.fourcc );
2799 if( type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN )
2800 type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS;
2802 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2803 if( !specific )
2805 lsmash_free( box_data );
2806 lsmash_bs_cleanup( bs );
2807 goto fail;
2809 specific->data.unstructured = box_data;
2810 specific->size = box_size;
2811 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2813 lsmash_destroy_codec_specific_data( specific );
2814 lsmash_bs_cleanup( bs );
2815 goto fail;
2818 lsmash_bs_cleanup( bs );
2821 else
2823 if( box->size < ISOM_BASEBOX_COMMON_SIZE )
2824 continue;
2825 uint8_t *data = box->binary;
2826 lsmash_compact_box_type_t fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
2827 lsmash_codec_specific_data_type type = isom_get_codec_specific_data_type( fourcc );
2828 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2829 if( !specific )
2830 goto fail;
2831 specific->size = box->size;
2832 specific->data.unstructured = lsmash_memdup( box->binary, box->size );
2833 if( !specific->data.unstructured
2834 || lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2836 lsmash_destroy_codec_specific_data( specific );
2837 goto fail;
2839 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
2840 || specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
2841 || specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 )
2843 specific = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2844 if( !specific )
2845 goto fail;
2846 switch( specific->type )
2848 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
2850 lsmash_dts_specific_parameters_t *param = (lsmash_dts_specific_parameters_t *)specific->data.structured;
2851 summary->sample_size = param->pcmSampleDepth;
2852 summary->samples_in_frame = (summary->frequency * (512 << param->FrameDuration)) / param->DTSSamplingFrequency;
2853 break;
2855 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
2857 lsmash_ac3_specific_parameters_t *param = (lsmash_ac3_specific_parameters_t *)specific->data.structured;
2858 summary->frequency = ac3_get_sample_rate( param );
2859 summary->channels = ac3_get_channel_count( param );
2860 summary->samples_in_frame = 1536;
2861 break;
2863 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
2865 lsmash_eac3_specific_parameters_t *param = (lsmash_eac3_specific_parameters_t *)specific->data.structured;
2866 eac3_update_sample_rate( &summary->frequency, param, NULL );
2867 eac3_update_channel_count( &summary->channels, param );
2868 summary->samples_in_frame = 1536;
2869 break;
2871 default :
2872 break;
2874 lsmash_destroy_codec_specific_data( specific );
2878 /* Set the actual sampling rate. */
2879 if( actual_sampling_rate )
2880 summary->frequency = actual_sampling_rate;
2881 return (lsmash_summary_t *)summary;
2882 fail:
2883 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
2884 return NULL;
2887 lsmash_codec_specific_t *lsmash_get_codec_specific_data( lsmash_summary_t *summary, uint32_t extension_number )
2889 if( !summary || !summary->opaque )
2890 return NULL;
2891 uint32_t i = 0;
2892 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
2893 if( ++i == extension_number )
2894 return (lsmash_codec_specific_t *)entry->data;
2895 return NULL;
2898 uint32_t lsmash_count_codec_specific_data( lsmash_summary_t *summary )
2900 if( !summary || !summary->opaque )
2901 return 0;
2902 return summary->opaque->list.entry_count;
2905 int isom_compare_opaque_extensions( lsmash_summary_t *a, lsmash_summary_t *b )
2907 assert( a && b );
2908 uint32_t in_number_of_extensions = lsmash_count_codec_specific_data( a );
2909 uint32_t out_number_of_extensions = lsmash_count_codec_specific_data( b );
2910 if( out_number_of_extensions != in_number_of_extensions )
2911 return 1;
2912 uint32_t active_number_of_extensions = in_number_of_extensions;
2913 uint32_t identical_count = 0;
2914 for( uint32_t j = 1; j <= in_number_of_extensions; j++ )
2916 lsmash_codec_specific_t *in_cs_orig = lsmash_get_codec_specific_data( a, j );
2917 lsmash_codec_specific_t *in_cs;
2918 lsmash_codec_specific_format compare_format = LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED;
2919 if( in_cs_orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2921 if( in_cs_orig->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
2922 || in_cs_orig->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
2923 || in_cs_orig->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS )
2925 compare_format = LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED;
2926 in_cs = in_cs_orig;
2928 else
2930 in_cs = lsmash_convert_codec_specific_format( in_cs_orig, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2931 if( !in_cs )
2933 /* We don't support the format converter of this data type. */
2934 --active_number_of_extensions;
2935 continue;
2939 else
2940 in_cs = in_cs_orig;
2941 for( uint32_t k = 1; k <= out_number_of_extensions; k++ )
2943 lsmash_codec_specific_t *out_cs_orig = lsmash_get_codec_specific_data( b, k );
2944 if( out_cs_orig->type != in_cs_orig->type )
2945 continue;
2946 lsmash_codec_specific_t *out_cs;
2947 if( out_cs_orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2949 if( compare_format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2950 out_cs = out_cs_orig;
2951 else
2953 out_cs = lsmash_convert_codec_specific_format( out_cs_orig, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2954 if( !out_cs )
2955 continue;
2958 else
2959 out_cs = out_cs_orig;
2960 int identical;
2961 if( compare_format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
2962 identical = out_cs->size == in_cs->size && !memcmp( out_cs->data.unstructured, in_cs->data.unstructured, in_cs->size );
2963 else
2965 if( in_cs->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON )
2967 lsmash_qt_video_common_t *in_data = (lsmash_qt_video_common_t *)in_cs->data.structured;
2968 lsmash_qt_video_common_t *out_data = (lsmash_qt_video_common_t *)out_cs->data.structured;
2969 identical = in_data->revision_level == out_data->revision_level
2970 && in_data->vendor == out_data->vendor
2971 && in_data->temporalQuality == out_data->temporalQuality
2972 && in_data->spatialQuality == out_data->spatialQuality
2973 && in_data->horizontal_resolution == out_data->horizontal_resolution
2974 && in_data->vertical_resolution == out_data->vertical_resolution
2975 && in_data->dataSize == out_data->dataSize
2976 && in_data->frame_count == out_data->frame_count
2977 && in_data->color_table_ID == out_data->color_table_ID;
2979 else if( in_cs->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON )
2981 lsmash_qt_audio_common_t *in_data = (lsmash_qt_audio_common_t *)in_cs->data.structured;
2982 lsmash_qt_audio_common_t *out_data = (lsmash_qt_audio_common_t *)out_cs->data.structured;
2983 identical = in_data->revision_level == out_data->revision_level
2984 && in_data->vendor == out_data->vendor
2985 && in_data->compression_ID == out_data->compression_ID;
2987 else
2989 lsmash_qt_audio_format_specific_flags_t *in_data = (lsmash_qt_audio_format_specific_flags_t *)in_cs->data.structured;
2990 lsmash_qt_audio_format_specific_flags_t *out_data = (lsmash_qt_audio_format_specific_flags_t *)out_cs->data.structured;
2991 identical = (in_data->format_flags == out_data->format_flags);
2994 if( out_cs != out_cs_orig )
2995 lsmash_destroy_codec_specific_data( out_cs );
2996 if( identical )
2998 ++identical_count;
2999 break;
3002 if( in_cs != in_cs_orig )
3003 lsmash_destroy_codec_specific_data( in_cs );
3005 return (identical_count != active_number_of_extensions);
3008 int isom_get_implicit_qt_fixed_comp_audio_sample_quants
3010 isom_audio_entry_t *audio,
3011 uint32_t *samples_per_packet,
3012 uint32_t *constant_bytes_per_frame,
3013 uint32_t *sample_size
3016 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC3_AUDIO ) )
3018 *samples_per_packet = 6;
3019 *constant_bytes_per_frame = 2 * audio->channelcount;
3020 *sample_size = 8;
3022 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC6_AUDIO ) )
3024 *samples_per_packet = 6;
3025 *constant_bytes_per_frame = audio->channelcount;
3026 *sample_size = 8;
3028 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ADPCM17_AUDIO ) )
3030 *samples_per_packet = 64;
3031 *constant_bytes_per_frame = 34 * audio->channelcount;
3032 *sample_size = 16;
3034 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_AGSM_AUDIO ) )
3036 *samples_per_packet = 160;
3037 *constant_bytes_per_frame = 33;
3038 *sample_size = 16;
3040 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAW_AUDIO )
3041 || lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ULAW_AUDIO ) )
3043 *samples_per_packet = 1;
3044 *constant_bytes_per_frame = audio->channelcount;
3045 *sample_size = 16;
3047 else
3048 return 0;
3049 return 1;
3052 isom_bitrate_updater_t isom_get_bitrate_updater
3054 isom_sample_entry_t *sample_entry
3057 #define RETURN_BITRATE_UPDATER( func_name ) \
3059 extern int func_name( isom_stbl_t *, isom_mdhd_t *, uint32_t sample_description_index ); \
3060 return func_name; \
3062 lsmash_codec_type_t sample_type = sample_entry->type;
3063 if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC1_VIDEO )
3064 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC2_VIDEO )
3065 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC3_VIDEO )
3066 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC4_VIDEO )
3067 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HVC1_VIDEO )
3068 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HEV1_VIDEO ) )
3069 RETURN_BITRATE_UPDATER( nalu_update_bitrate )
3070 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4V_VIDEO ) )
3071 RETURN_BITRATE_UPDATER( mp4v_update_bitrate )
3072 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4A_AUDIO )
3073 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_MP4A_AUDIO ) )
3074 RETURN_BITRATE_UPDATER( mp4a_update_bitrate )
3075 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_ALAC_AUDIO )
3076 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ALAC_AUDIO ) )
3077 RETURN_BITRATE_UPDATER( alac_update_bitrate )
3078 else if( isom_is_dts_audio( sample_type ) )
3079 RETURN_BITRATE_UPDATER( dts_update_bitrate )
3080 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_EC_3_AUDIO ) )
3081 RETURN_BITRATE_UPDATER( eac3_update_bitrate )
3082 else if( isom_is_waveform_audio( sample_type ) )
3083 RETURN_BITRATE_UPDATER( waveform_audio_update_bitrate )
3084 else
3085 return NULL;
3086 #undef RETURN_BITRATE_UPDATER