.gitignore: Add version script.
[L-SMASH.git] / codecs / description.c
blob05f09e8055dfde944b2bb77ea0b1c6517e612e92
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 int lsmash_convert_crop_into_clap( lsmash_crop_t crop, uint32_t width, uint32_t height, lsmash_clap_t *clap )
125 if( !clap || crop.top.d == 0 || crop.bottom.d == 0 || crop.left.d == 0 || crop.right.d == 0 )
126 return LSMASH_ERR_FUNCTION_PARAM;
127 uint64_t vertical_crop_lcm = lsmash_get_lcm( crop.top.d, crop.bottom.d );
128 uint64_t horizontal_crop_lcm = lsmash_get_lcm( crop.left.d, crop.right.d );
129 lsmash_rational_u64_t clap_height;
130 lsmash_rational_u64_t clap_width;
131 lsmash_rational_s64_t clap_horizontal_offset;
132 lsmash_rational_s64_t clap_vertical_offset;
133 clap_height.d = vertical_crop_lcm;
134 clap_width.d = horizontal_crop_lcm;
135 clap_horizontal_offset.d = 2 * vertical_crop_lcm;
136 clap_vertical_offset.d = 2 * horizontal_crop_lcm;
137 clap_height.n = height * vertical_crop_lcm
138 - (crop.top.n * (vertical_crop_lcm / crop.top.d) + crop.bottom.n * (vertical_crop_lcm / crop.bottom.d));
139 clap_width.n = width * horizontal_crop_lcm
140 - (crop.left.n * (horizontal_crop_lcm / crop.left.d) + crop.right.n * (horizontal_crop_lcm / crop.right.d));
141 clap_horizontal_offset.n = (int64_t)(crop.left.n * (horizontal_crop_lcm / crop.left.d))
142 - crop.right.n * (horizontal_crop_lcm / crop.right.d);
143 clap_vertical_offset.n = (int64_t)(crop.top.n * (vertical_crop_lcm / crop.top.d))
144 - crop.bottom.n * (vertical_crop_lcm / crop.bottom.d);
145 lsmash_reduce_fraction( &clap_height.n, &clap_height.d );
146 lsmash_reduce_fraction( &clap_width.n, &clap_width.d );
147 lsmash_reduce_fraction_su( &clap_vertical_offset.n, &clap_vertical_offset.d );
148 lsmash_reduce_fraction_su( &clap_horizontal_offset.n, &clap_horizontal_offset.d );
149 clap->height = (lsmash_rational_u32_t){ clap_height.n, clap_height.d };
150 clap->width = (lsmash_rational_u32_t){ clap_width.n, clap_width.d };
151 clap->vertical_offset = (lsmash_rational_s32_t){ clap_vertical_offset.n, clap_vertical_offset.d };
152 clap->horizontal_offset = (lsmash_rational_s32_t){ clap_horizontal_offset.n, clap_horizontal_offset.d };
153 return 0;
156 int lsmash_convert_clap_into_crop( lsmash_clap_t clap, uint32_t width, uint32_t height, lsmash_crop_t *crop )
158 if( !crop || clap.height.d == 0 || clap.vertical_offset.d == 0 || clap.width.d == 0 || clap.horizontal_offset.d == 0 )
159 return LSMASH_ERR_FUNCTION_PARAM;
160 uint64_t clap_vertical_lcm = lsmash_get_lcm( clap.height.d, clap.vertical_offset.d );
161 uint64_t clap_horizontal_lcm = lsmash_get_lcm( clap.width.d, clap.horizontal_offset.d );
162 lsmash_rational_u64_t crop_top;
163 lsmash_rational_u64_t crop_bottom;
164 lsmash_rational_u64_t crop_left;
165 lsmash_rational_u64_t crop_right;
166 crop_top.d = 2 * clap_vertical_lcm;
167 crop_bottom.d = 2 * clap_vertical_lcm;
168 crop_left.d = 2 * clap_horizontal_lcm;
169 crop_right.d = 2 * clap_horizontal_lcm;
170 crop_top.n = (height * crop_top.d - clap.height.n * (crop_top.d / clap.height.d)) / 2
171 + clap.vertical_offset.n * (crop_top.d / clap.vertical_offset.d);
172 crop_bottom.n = (height * crop_bottom.d - clap.height.n * (crop_bottom.d / clap.height.d)) / 2
173 - clap.vertical_offset.n * (crop_bottom.d / clap.vertical_offset.d);
174 crop_left.n = (width * crop_left.d - clap.width.n * (crop_left.d / clap.width.d)) / 2
175 + clap.horizontal_offset.n * (crop_left.d / clap.horizontal_offset.d);
176 crop_right.n = (width * crop_right.d - clap.width.n * (crop_right.d / clap.width.d)) / 2
177 - clap.horizontal_offset.n * (crop_right.d / clap.horizontal_offset.d);
178 lsmash_reduce_fraction( &crop_top.n, &crop_top.d );
179 lsmash_reduce_fraction( &crop_bottom.n, &crop_bottom.d );
180 lsmash_reduce_fraction( &crop_left.n, &crop_left.d );
181 lsmash_reduce_fraction( &crop_right.n, &crop_right.d );
182 crop->top = (lsmash_rational_u32_t){ crop_top.n, crop_top.d };
183 crop->bottom = (lsmash_rational_u32_t){ crop_bottom.n, crop_bottom.d };
184 crop->left = (lsmash_rational_u32_t){ crop_left.n, crop_left.d };
185 crop->right = (lsmash_rational_u32_t){ crop_right.n, crop_right.d };
186 return 0;
189 static void isom_destruct_nothing( void *data )
191 /* Do nothing. */;
194 static int isom_initialize_structured_codec_specific_data( lsmash_codec_specific_t *specific )
196 extern void mp4sys_destruct_decoder_config( void * );
197 extern void h264_destruct_specific_data( void * );
198 extern void hevc_destruct_specific_data( void * );
199 extern void vc1_destruct_specific_data( void * );
200 extern void dts_destruct_specific_data( void * );
201 switch( specific->type )
203 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
204 specific->size = sizeof(lsmash_mp4sys_decoder_parameters_t);
205 specific->destruct = mp4sys_destruct_decoder_config;
206 break;
207 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 :
208 specific->size = sizeof(lsmash_h264_specific_parameters_t);
209 specific->destruct = h264_destruct_specific_data;
210 break;
211 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC :
212 specific->size = sizeof(lsmash_hevc_specific_parameters_t);
213 specific->destruct = hevc_destruct_specific_data;
214 break;
215 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 :
216 specific->size = sizeof(lsmash_vc1_specific_parameters_t);
217 specific->destruct = vc1_destruct_specific_data;
218 break;
219 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
220 specific->size = sizeof(lsmash_ac3_specific_parameters_t);
221 specific->destruct = lsmash_free;
222 break;
223 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
224 specific->size = sizeof(lsmash_eac3_specific_parameters_t);
225 specific->destruct = lsmash_free;
226 break;
227 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
228 specific->size = sizeof(lsmash_dts_specific_parameters_t);
229 specific->destruct = dts_destruct_specific_data;
230 break;
231 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
232 specific->size = sizeof(lsmash_alac_specific_parameters_t);
233 specific->destruct = lsmash_free;
234 break;
235 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE :
236 specific->size = sizeof(lsmash_isom_sample_scale_t);
237 specific->destruct = lsmash_free;
238 break;
239 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE :
240 specific->size = sizeof(lsmash_h264_bitrate_t);
241 specific->destruct = lsmash_free;
242 break;
243 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON :
244 specific->size = sizeof(lsmash_qt_video_common_t);
245 specific->destruct = lsmash_free;
246 break;
247 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
248 specific->size = sizeof(lsmash_qt_audio_common_t);
249 specific->destruct = lsmash_free;
250 break;
251 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
252 specific->size = sizeof(lsmash_qt_audio_format_specific_flags_t);
253 specific->destruct = lsmash_free;
254 break;
255 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
256 specific->size = sizeof(lsmash_codec_global_header_t);
257 specific->destruct = global_destruct_specific_data;
258 break;
259 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO :
260 specific->size = sizeof(lsmash_qt_field_info_t);
261 specific->destruct = lsmash_free;
262 break;
263 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT :
264 specific->size = sizeof(lsmash_qt_pixel_format_t);
265 specific->destruct = lsmash_free;
266 break;
267 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS :
268 specific->size = sizeof(lsmash_qt_significant_bits_t);
269 specific->destruct = lsmash_free;
270 break;
271 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
272 specific->size = sizeof(lsmash_qt_audio_channel_layout_t);
273 specific->destruct = lsmash_free;
274 break;
275 default :
276 specific->size = 0;
277 specific->destruct = isom_destruct_nothing;
278 return 0;
280 specific->data.structured = lsmash_malloc_zero( specific->size );
281 if( !specific->data.structured )
283 specific->size = 0;
284 specific->destruct = NULL;
285 return LSMASH_ERR_MEMORY_ALLOC;
287 return 0;
290 static inline int isom_initialize_codec_specific_data( lsmash_codec_specific_t *specific,
291 lsmash_codec_specific_data_type type,
292 lsmash_codec_specific_format format )
294 specific->type = type;
295 specific->format = format;
296 if( format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
298 int err = isom_initialize_structured_codec_specific_data( specific );
299 if( err < 0 )
300 return err;
302 else
304 specific->data.unstructured = NULL;
305 specific->size = 0;
306 specific->destruct = (lsmash_codec_specific_destructor_t)lsmash_free;
308 return 0;
311 void lsmash_destroy_codec_specific_data( lsmash_codec_specific_t *specific )
313 if( !specific )
314 return;
315 if( specific->destruct )
317 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
319 if( specific->data.structured )
320 specific->destruct( specific->data.structured );
322 else
324 if( specific->data.unstructured )
325 specific->destruct( specific->data.unstructured );
328 lsmash_free( specific );
331 lsmash_codec_specific_t *lsmash_create_codec_specific_data( lsmash_codec_specific_data_type type, lsmash_codec_specific_format format )
333 lsmash_codec_specific_t *specific = lsmash_malloc( sizeof(lsmash_codec_specific_t) );
334 if( !specific )
335 return NULL;
336 if( isom_initialize_codec_specific_data( specific, type, format ) < 0 )
338 lsmash_destroy_codec_specific_data( specific );
339 return NULL;
341 return specific;
344 static int isom_duplicate_structured_specific_data( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
346 extern int mp4sys_copy_decoder_config( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
347 extern int h264_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
348 extern int hevc_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
349 extern int vc1_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
350 extern int dts_copy_codec_specific( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
351 void *src_data = src->data.structured;
352 void *dst_data = dst->data.structured;
353 switch( src->type )
355 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
356 return mp4sys_copy_decoder_config( dst, src );
357 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 :
358 return h264_copy_codec_specific( dst, src );
359 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC :
360 return hevc_copy_codec_specific( dst, src );
361 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 :
362 return vc1_copy_codec_specific( dst, src );
363 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
364 *(lsmash_ac3_specific_parameters_t *)dst_data = *(lsmash_ac3_specific_parameters_t *)src_data;
365 return 0;
366 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
367 *(lsmash_eac3_specific_parameters_t *)dst_data = *(lsmash_eac3_specific_parameters_t *)src_data;
368 return 0;
369 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
370 return dts_copy_codec_specific( dst, src );
371 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
372 *(lsmash_alac_specific_parameters_t *)dst_data = *(lsmash_alac_specific_parameters_t *)src_data;
373 return 0;
374 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE :
375 *(lsmash_isom_sample_scale_t *)dst_data = *(lsmash_isom_sample_scale_t *)src_data;
376 return 0;
377 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE :
378 *(lsmash_h264_bitrate_t *)dst_data = *(lsmash_h264_bitrate_t *)src_data;
379 return 0;
380 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON :
381 *(lsmash_qt_video_common_t *)dst_data = *(lsmash_qt_video_common_t *)src_data;
382 return 0;
383 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
384 *(lsmash_qt_audio_common_t *)dst_data = *(lsmash_qt_audio_common_t *)src_data;
385 return 0;
386 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
387 *(lsmash_qt_audio_format_specific_flags_t *)dst_data = *(lsmash_qt_audio_format_specific_flags_t *)src_data;
388 return 0;
389 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
391 lsmash_codec_global_header_t *src_global = (lsmash_codec_global_header_t *)src_data;
392 if( src_global->header_data && src_global->header_size )
394 lsmash_codec_global_header_t *dst_global = (lsmash_codec_global_header_t *)dst_data;
395 dst_global->header_data = lsmash_memdup( src_global->header_data, src_global->header_size );
396 if( !dst_global->header_data )
397 return LSMASH_ERR_MEMORY_ALLOC;
398 dst_global->header_size = src_global->header_size;
400 return 0;
402 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO :
403 *(lsmash_qt_field_info_t *)dst_data = *(lsmash_qt_field_info_t *)src_data;
404 return 0;
405 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT :
406 *(lsmash_qt_pixel_format_t *)dst_data = *(lsmash_qt_pixel_format_t *)src_data;
407 return 0;
408 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS :
409 *(lsmash_qt_significant_bits_t *)dst_data = *(lsmash_qt_significant_bits_t *)src_data;
410 return 0;
411 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL :
412 *(lsmash_qt_gamma_t *)dst_data = *(lsmash_qt_gamma_t *)src_data;
413 return 0;
414 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
415 *(lsmash_qt_audio_channel_layout_t *)dst_data = *(lsmash_qt_audio_channel_layout_t *)src_data;
416 return 0;
417 default :
418 return LSMASH_ERR_NAMELESS;
422 lsmash_codec_specific_t *isom_duplicate_codec_specific_data( lsmash_codec_specific_t *specific )
424 if( !specific )
425 return NULL;
426 lsmash_codec_specific_t *dup = lsmash_create_codec_specific_data( specific->type, specific->format );
427 if( !dup )
428 return NULL;
429 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
431 if( isom_duplicate_structured_specific_data( dup, specific ) < 0 )
433 lsmash_destroy_codec_specific_data( dup );
434 return NULL;
437 else
439 dup->data.unstructured = lsmash_memdup( specific->data.unstructured, specific->size );
440 if( !dup->data.unstructured )
442 lsmash_destroy_codec_specific_data( dup );
443 return NULL;
446 dup->size = specific->size;
447 return dup;
450 static int isom_construct_global_specific_header( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
452 if( src->size < ISOM_BASEBOX_COMMON_SIZE )
453 return LSMASH_ERR_INVALID_DATA;
454 lsmash_codec_global_header_t *global = (lsmash_codec_global_header_t *)dst->data.structured;
455 uint8_t *data = src->data.unstructured;
456 uint64_t size = LSMASH_GET_BE32( data );
457 data += ISOM_BASEBOX_COMMON_SIZE;
458 if( size == 1 )
460 size = LSMASH_GET_BE64( data );
461 data += 8;
463 if( size != src->size )
464 return LSMASH_ERR_INVALID_DATA;
465 global->header_size = size - ISOM_BASEBOX_COMMON_SIZE;
466 if( data != src->data.unstructured + ISOM_BASEBOX_COMMON_SIZE )
467 global->header_size -= 8; /* largesize */
468 if( global->header_size )
470 global->header_data = lsmash_memdup( data, global->header_size );
471 if( !global->header_data )
472 return LSMASH_ERR_MEMORY_ALLOC;
474 return 0;
477 static int isom_construct_audio_channel_layout( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
479 if( src->size < ISOM_FULLBOX_COMMON_SIZE + 12 )
480 return LSMASH_ERR_INVALID_DATA;
481 lsmash_qt_audio_channel_layout_t *layout = (lsmash_qt_audio_channel_layout_t *)dst->data.structured;
482 uint8_t *data = src->data.unstructured;
483 uint64_t size = LSMASH_GET_BE32( data );
484 data += ISOM_FULLBOX_COMMON_SIZE;
485 if( size == 1 )
487 size = LSMASH_GET_BE64( data );
488 data += 8;
490 if( size != src->size )
491 return LSMASH_ERR_INVALID_DATA;
492 layout->channelLayoutTag = LSMASH_GET_BE32( &data[0] );
493 layout->channelBitmap = LSMASH_GET_BE32( &data[4] );
494 return 0;
497 #if 0
498 static int codec_construct_qt_audio_decompression_info( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
500 if( src->size < ISOM_BASEBOX_COMMON_SIZE )
501 return LSMASH_ERR_INVALID_DATA;
502 uint8_t *data = src->data.unstructured;
503 uint64_t size;
504 uint32_t type;
505 uint32_t offset = isom_read_box_size_and_type_from_binary_string( &data, &size, &type );
506 if( size != src->size )
507 return LSMASH_ERR_INVALID_DATA;
508 uint8_t *end = src->data.unstructured + src->size;
509 isom_wave_t *wave = lsmash_malloc_zero( sizeof(isom_wave_t) );
510 if( !wave )
511 return LSMASH_ERR_MEMORY_ALLOC;
512 wave->type = QT_BOX_TYPE_WAVE;
513 for( uint8_t *pos = data; pos + ISOM_BASEBOX_COMMON_SIZE <= end; )
515 offset = isom_read_box_size_and_type_from_binary_string( &pos, &size, &type );
516 switch( type )
518 case QT_BOX_TYPE_FRMA :
520 if( pos + 4 > end )
521 return LSMASH_ERR_INVALID_DATA;
522 isom_frma_t *frma = isom_add_frma( wave );
523 if( !frma )
524 return LSMASH_ERR_NAMELESS;
525 frma->data_format = LSMASH_GET_BE32( pos );
526 pos += 4;
527 break;
529 case QT_BOX_TYPE_ENDA :
531 if( pos + 2 > end )
532 return LSMASH_ERR_INVALID_DATA;
533 isom_enda_t *enda = isom_add_enda( wave );
534 if( !enda )
535 return LSMASH_ERR_NAMELESS;
536 enda->littleEndian = LSMASH_GET_BE16( pos );
537 break;
539 case QT_BOX_TYPE_MP4A :
541 if( pos + 4 > end )
542 return LSMASH_ERR_INVALID_DATA;
543 isom_mp4a_t *mp4a = isom_add_mp4a( wave );
544 if( !mp4a )
545 return LSMASH_ERR_NAMELESS;
546 mp4a->unknown = LSMASH_GET_BE32( pos );
547 pos += 4;
548 break;
550 case QT_BOX_TYPE_TERMINATOR :
552 if( !isom_add_terminator( wave ) )
553 return LSMASH_ERR_NAMELESS;
554 break;
556 default :
558 isom_unknown_box_t *box = lsmash_malloc_zero( sizeof(isom_unknown_box_t) );
559 if( !box )
560 return LSMASH_ERR_MEMORY_ALLOC;
561 isom_init_box_common( box, wave, type, isom_remove_unknown_box );
562 box->unknown_size = size - offset;
563 box->unknown_field = lsmash_memdup( pos, box->unknown_size );
564 if( !box->unknown_field )
566 lsmash_free( box );
567 return LSMASH_ERR_MEMORY_ALLOC;
569 if( lsmash_add_entry( &wave->extensions, box ) < 0 )
571 isom_remove_unknown_box( box );
572 return LSMASH_ERR_MEMORY_ALLOC;
574 pos += box->unknown_size;
575 break;
579 return 0;
581 #endif
583 /* structured <-> unstructured conversion might be irreversible by CODEC
584 * since structured formats we defined don't always have all contents included in unstructured data. */
585 lsmash_codec_specific_t *lsmash_convert_codec_specific_format( lsmash_codec_specific_t *specific, lsmash_codec_specific_format format )
587 if( !specific || format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSPECIFIED )
588 return NULL;
589 if( format == specific->format )
590 return isom_duplicate_codec_specific_data( specific );
591 lsmash_codec_specific_t *dst = lsmash_create_codec_specific_data( specific->type, format );
592 if( !dst )
593 return NULL;
594 if( format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
595 /* structured -> unstructured */
596 switch( specific->type )
598 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
599 dst->data.unstructured = lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t *)specific->data.structured, &dst->size );
600 if( !dst->data.unstructured )
601 goto fail;
602 return dst;
603 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 :
604 dst->data.unstructured = lsmash_create_h264_specific_info( (lsmash_h264_specific_parameters_t *)specific->data.structured, &dst->size );
605 if( !dst->data.unstructured )
606 goto fail;
607 return dst;
608 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC :
609 dst->data.unstructured = lsmash_create_hevc_specific_info( (lsmash_hevc_specific_parameters_t *)specific->data.structured, &dst->size );
610 if( !dst->data.unstructured )
611 goto fail;
612 return dst;
613 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 :
614 dst->data.unstructured = lsmash_create_vc1_specific_info( (lsmash_vc1_specific_parameters_t *)specific->data.structured, &dst->size );
615 if( !dst->data.unstructured )
616 goto fail;
617 return dst;
618 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
619 dst->data.unstructured = lsmash_create_ac3_specific_info( (lsmash_ac3_specific_parameters_t *)specific->data.structured, &dst->size );
620 if( !dst->data.unstructured )
621 goto fail;
622 return dst;
623 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
624 dst->data.unstructured = lsmash_create_eac3_specific_info( (lsmash_eac3_specific_parameters_t *)specific->data.structured, &dst->size );
625 if( !dst->data.unstructured )
626 goto fail;
627 return dst;
628 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
629 dst->data.unstructured = lsmash_create_dts_specific_info( (lsmash_dts_specific_parameters_t *)specific->data.structured, &dst->size );
630 if( !dst->data.unstructured )
631 goto fail;
632 return dst;
633 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
634 dst->data.unstructured = lsmash_create_alac_specific_info( (lsmash_alac_specific_parameters_t *)specific->data.structured, &dst->size );
635 if( !dst->data.unstructured )
636 goto fail;
637 return dst;
638 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
640 lsmash_bs_t *bs = lsmash_bs_create();
641 if( !bs )
642 goto fail;
643 lsmash_codec_global_header_t *global = specific->data.structured;
644 lsmash_bs_put_be32( bs, ISOM_BASEBOX_COMMON_SIZE + global->header_size );
645 lsmash_bs_put_be32( bs, QT_BOX_TYPE_GLBL.fourcc );
646 lsmash_bs_put_bytes( bs, global->header_size, global->header_data );
647 dst->data.unstructured = lsmash_bs_export_data( bs, &dst->size );
648 lsmash_bs_cleanup( bs );
649 if( !dst->data.unstructured || dst->size != (ISOM_BASEBOX_COMMON_SIZE + global->header_size) )
650 goto fail;
651 return dst;
653 default :
654 break;
656 else if( format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
658 /* unstructured -> structured */
659 extern int mp4sys_construct_decoder_config( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
660 extern int h264_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
661 extern int hevc_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
662 extern int vc1_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
663 extern int ac3_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
664 extern int eac3_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
665 extern int dts_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
666 extern int alac_construct_specific_parameters( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
667 static const struct
669 lsmash_codec_specific_data_type data_type;
670 int (*constructor)( lsmash_codec_specific_t *, lsmash_codec_specific_t * );
671 } codec_specific_format_constructor_table[] =
673 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG, mp4sys_construct_decoder_config },
674 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264, h264_construct_specific_parameters },
675 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC, hevc_construct_specific_parameters },
676 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1, vc1_construct_specific_parameters },
677 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3, ac3_construct_specific_parameters },
678 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3, eac3_construct_specific_parameters },
679 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS, dts_construct_specific_parameters },
680 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC, alac_construct_specific_parameters },
681 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER, isom_construct_global_specific_header },
682 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT, isom_construct_audio_channel_layout },
683 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN, NULL }
685 int (*constructor)( lsmash_codec_specific_t *, lsmash_codec_specific_t * ) = NULL;
686 for( int i = 0; codec_specific_format_constructor_table[i].constructor; i++ )
687 if( specific->type == codec_specific_format_constructor_table[i].data_type )
689 constructor = codec_specific_format_constructor_table[i].constructor;
690 break;
692 if( constructor && !constructor( dst, specific ) )
693 return dst;
695 fail:
696 lsmash_destroy_codec_specific_data( dst );
697 return NULL;
700 static inline void isom_set_default_compressorname( char *compressorname, lsmash_codec_type_t sample_type )
702 static struct compressorname_table_tag
704 lsmash_codec_type_t type;
705 char name[33];
706 } compressorname_table[33] = { { LSMASH_CODEC_TYPE_INITIALIZER, { '\0' } } };
707 if( compressorname_table[0].name[0] == '\0' )
709 int i = 0;
710 #define ADD_COMPRESSORNAME_TABLE( type, name ) compressorname_table[i++] = (struct compressorname_table_tag){ type, name }
711 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC1_VIDEO, "\012AVC Coding" );
712 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC2_VIDEO, "\012AVC Coding" );
713 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC3_VIDEO, "\012AVC Coding" );
714 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC4_VIDEO, "\012AVC Coding" );
715 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVCP_VIDEO, "\016AVC Parameters" );
716 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HVC1_VIDEO, "\013HEVC Coding" );
717 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HEV1_VIDEO, "\013HEVC Coding" );
718 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_SVC1_VIDEO, "\012SVC Coding" );
719 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC1_VIDEO, "\012MVC Coding" );
720 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC2_VIDEO, "\012MVC Coding" );
721 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCH_VIDEO, "\023Apple ProRes 422 (HQ)" );
722 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCN_VIDEO, "\023Apple ProRes 422 (SD)" );
723 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCS_VIDEO, "\023Apple ProRes 422 (LT)" );
724 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCO_VIDEO, "\026Apple ProRes 422 (Proxy)" );
725 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4H_VIDEO, "\019Apple ProRes 4444" );
726 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4X_VIDEO, "\022Apple ProRes 4444 XQ" );
727 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVPP_VIDEO, "\014DVCPRO - PAL" );
728 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5N_VIDEO, "\017DVCPRO50 - NTSC" );
729 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5P_VIDEO, "\016DVCPRO50 - PAL" );
730 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH2_VIDEO, "\019DVCPRO HD 1080p25" );
731 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH3_VIDEO, "\019DVCPRO HD 1080p30" );
732 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH5_VIDEO, "\019DVCPRO HD 1080i50" );
733 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH6_VIDEO, "\019DVCPRO HD 1080i60" );
734 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHP_VIDEO, "\018DVCPRO HD 720p60" );
735 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHQ_VIDEO, "\018DVCPRO HD 720p50" );
736 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRA_VIDEO, "\017Ut Video (ULRA)" );
737 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRG_VIDEO, "\017Ut Video (ULRG)" );
738 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY0_VIDEO, "\017Ut Video (ULY0)" );
739 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY2_VIDEO, "\017Ut Video (ULY2)" );
740 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH0_VIDEO, "\017Ut Video (ULH0)" );
741 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH2_VIDEO, "\017Ut Video (ULH2)" );
742 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_UQY2_VIDEO, "\021Ut Video Pro (UQY2)" );
743 ADD_COMPRESSORNAME_TABLE( LSMASH_CODEC_TYPE_UNSPECIFIED, { '\0' } );
744 #undef ADD_COMPRESSORNAME_TABLE
746 for( int i = 0; compressorname_table[i].name[0] != '\0'; i++ )
747 if( lsmash_check_codec_type_identical( sample_type, compressorname_table[i].type ) )
749 strcpy( compressorname, compressorname_table[i].name );
750 return;
754 lsmash_codec_specific_t *isom_get_codec_specific( lsmash_codec_specific_list_t *opaque, lsmash_codec_specific_data_type type )
756 for( lsmash_entry_t *entry = opaque->list.head; entry; entry = entry->next )
758 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
759 if( !specific || specific->type != type )
760 continue;
761 return specific;
763 return NULL;
766 static int isom_check_valid_summary( lsmash_summary_t *summary )
768 if( !summary )
769 return LSMASH_ERR_NAMELESS;
770 isom_box_t temp_box;
771 temp_box.type = summary->sample_type;
772 temp_box.manager = summary->summary_type == LSMASH_SUMMARY_TYPE_AUDIO ? LSMASH_AUDIO_DESCRIPTION: 0;
773 if( isom_is_lpcm_audio( &temp_box ) )
775 if( isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS ) )
776 return 0;
777 return LSMASH_ERR_INVALID_DATA;
779 if( isom_is_uncompressed_ycbcr( summary->sample_type ) )
781 if( isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO ) )
783 if( !lsmash_check_codec_type_identical( summary->sample_type, QT_CODEC_TYPE_V216_VIDEO ) )
784 return 0;
786 else
787 return LSMASH_ERR_INVALID_DATA;
789 lsmash_codec_type_t sample_type = summary->sample_type;
790 lsmash_codec_specific_data_type required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED;
791 if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC1_VIDEO )
792 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC2_VIDEO )
793 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC3_VIDEO )
794 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC4_VIDEO ) )
795 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264;
796 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HVC1_VIDEO )
797 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HEV1_VIDEO ) )
798 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC;
799 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_VC_1_VIDEO ) )
800 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 ;
801 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULRA_VIDEO )
802 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULRG_VIDEO )
803 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULY0_VIDEO )
804 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULY2_VIDEO )
805 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULH0_VIDEO )
806 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ULH2_VIDEO )
807 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_UQY2_VIDEO ) )
808 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER;
809 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_V216_VIDEO ) )
810 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS;
811 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4V_VIDEO )
812 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4A_AUDIO )
813 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_MP4A_AUDIO ) )
814 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG;
815 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AC_3_AUDIO ) )
816 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3;
817 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_EC_3_AUDIO ) )
818 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3;
819 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSC_AUDIO )
820 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSE_AUDIO )
821 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSH_AUDIO )
822 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSL_AUDIO ) )
823 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS;
824 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_ALAC_AUDIO )
825 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ALAC_AUDIO ) )
826 required_data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC;
827 if( required_data_type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED )
828 return 0;
829 return isom_get_codec_specific( summary->opaque, required_data_type ) ? 0 : LSMASH_ERR_INVALID_DATA;
832 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 )
834 lsmash_box_type_t box_type = LSMASH_BOX_TYPE_INITIALIZER;
835 box_type.fourcc = fourcc;
836 #define GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
837 else if( (codec_type.user.fourcc == 0 \
838 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
839 && box_type.fourcc == predefined_box_type.fourcc ) \
840 box_type = predefined_box_type
841 if( 0 );
842 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC1_VIDEO, ISOM_BOX_TYPE_AVCC );
843 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC2_VIDEO, ISOM_BOX_TYPE_AVCC );
844 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC3_VIDEO, ISOM_BOX_TYPE_AVCC );
845 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC4_VIDEO, ISOM_BOX_TYPE_AVCC );
846 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVCP_VIDEO, ISOM_BOX_TYPE_AVCC );
847 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HVC1_VIDEO, ISOM_BOX_TYPE_HVCC );
848 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HEV1_VIDEO, ISOM_BOX_TYPE_HVCC );
849 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_VC_1_VIDEO, ISOM_BOX_TYPE_DVC1 );
850 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4V_VIDEO, ISOM_BOX_TYPE_ESDS );
851 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, ISOM_BOX_TYPE_BTRT );
852 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_FIEL );
853 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_CSPC );
854 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_SGBT );
855 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_GAMA );
856 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_GLBL );
857 #undef GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE
858 return box_type;
861 static int isom_setup_visual_description( isom_stsd_t *stsd, lsmash_video_summary_t *summary )
863 if( !summary
864 || !stsd
865 || !stsd->parent
866 || !stsd->parent->parent
867 || !stsd->parent->parent->parent
868 || !stsd->parent->parent->parent->parent )
869 return LSMASH_ERR_NAMELESS;
870 int err = isom_check_valid_summary( (lsmash_summary_t *)summary );
871 if( err < 0 )
872 return err;
873 isom_visual_entry_t *visual = isom_add_visual_description( stsd, summary->sample_type );
874 if( !visual )
875 return LSMASH_ERR_NAMELESS;
876 visual->data_reference_index = summary->data_ref_index;
877 visual->version = 0;
878 visual->revision_level = 0;
879 visual->vendor = 0;
880 visual->temporalQuality = 0;
881 visual->spatialQuality = 0;
882 visual->width = (uint16_t)summary->width;
883 visual->height = (uint16_t)summary->height;
884 visual->horizresolution = 0x00480000;
885 visual->vertresolution = 0x00480000;
886 visual->dataSize = 0;
887 visual->frame_count = 1;
888 visual->depth = isom_is_qt_video( visual->type ) || isom_is_nalff( visual->type )
889 ? summary->depth : 0x0018;
890 visual->color_table_ID = -1;
891 if( summary->compressorname[0] == '\0' )
892 isom_set_default_compressorname( visual->compressorname, visual->type );
893 else
895 memcpy( visual->compressorname, summary->compressorname, 32 );
896 visual->compressorname[32] = '\0';
898 err = LSMASH_ERR_NAMELESS;
899 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
901 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
902 if( !specific )
903 goto fail;
904 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
905 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
906 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
907 switch( specific->type )
909 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON :
911 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
912 continue;
913 lsmash_qt_video_common_t *data = (lsmash_qt_video_common_t *)specific->data.structured;
914 visual->revision_level = data->revision_level;
915 visual->vendor = data->vendor;
916 visual->temporalQuality = data->temporalQuality;
917 visual->spatialQuality = data->spatialQuality;
918 visual->horizresolution = data->horizontal_resolution;
919 visual->vertresolution = data->vertical_resolution;
920 visual->dataSize = data->dataSize;
921 visual->frame_count = data->frame_count;
922 visual->color_table_ID = data->color_table_ID;
923 if( data->color_table_ID == 0 )
925 lsmash_qt_color_table_t *src_ct = &data->color_table;
926 uint16_t element_count = LSMASH_MIN( src_ct->size + 1, 256 );
927 isom_qt_color_array_t *dst_array = lsmash_malloc_zero( element_count * sizeof(isom_qt_color_array_t) );
928 if( !dst_array )
930 err = LSMASH_ERR_MEMORY_ALLOC;
931 goto fail;
933 isom_qt_color_table_t *dst_ct = &visual->color_table;
934 dst_ct->array = dst_array;
935 dst_ct->seed = src_ct->seed;
936 dst_ct->flags = src_ct->flags;
937 dst_ct->size = src_ct->size;
938 for( uint16_t i = 0; i < element_count; i++ )
940 dst_array[i].value = src_ct->array[i].unused;
941 dst_array[i].r = src_ct->array[i].r;
942 dst_array[i].g = src_ct->array[i].g;
943 dst_array[i].b = src_ct->array[i].b;
946 break;
948 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE :
950 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
951 if( !cs )
952 goto fail;
953 lsmash_isom_sample_scale_t *data = (lsmash_isom_sample_scale_t *)cs->data.structured;
954 isom_stsl_t *stsl = isom_add_stsl( visual );
955 if( !stsl )
957 lsmash_destroy_codec_specific_data( cs );
958 goto fail;
960 stsl->constraint_flag = data->constraint_flag;
961 stsl->scale_method = data->scale_method;
962 stsl->display_center_x = data->display_center_x;
963 stsl->display_center_y = data->display_center_y;
964 lsmash_destroy_codec_specific_data( cs );
965 break;
967 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE :
969 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
970 if( !cs )
971 goto fail;
972 lsmash_h264_bitrate_t *data = (lsmash_h264_bitrate_t *)cs->data.structured;
973 isom_btrt_t *btrt = isom_add_btrt( visual );
974 if( !btrt )
976 lsmash_destroy_codec_specific_data( cs );
977 goto fail;
979 btrt->bufferSizeDB = data->bufferSizeDB;
980 btrt->maxBitrate = data->maxBitrate;
981 btrt->avgBitrate = data->avgBitrate;
982 lsmash_destroy_codec_specific_data( cs );
983 break;
985 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO :
987 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
988 if( !cs )
989 goto fail;
990 lsmash_qt_field_info_t *data = (lsmash_qt_field_info_t *)cs->data.structured;
991 isom_fiel_t *fiel = isom_add_fiel( visual );
992 if( !fiel )
994 lsmash_destroy_codec_specific_data( cs );
995 goto fail;
997 fiel->fields = data->fields;
998 fiel->detail = data->detail;
999 lsmash_destroy_codec_specific_data( cs );
1000 break;
1002 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT :
1004 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1005 if( !cs )
1006 goto fail;
1007 lsmash_qt_pixel_format_t *data = (lsmash_qt_pixel_format_t *)cs->data.structured;
1008 isom_cspc_t *cspc = isom_add_cspc( visual );
1009 if( !cspc )
1011 lsmash_destroy_codec_specific_data( cs );
1012 goto fail;
1014 cspc->pixel_format = data->pixel_format;
1015 lsmash_destroy_codec_specific_data( cs );
1016 break;
1018 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS :
1020 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1021 if( !cs )
1022 goto fail;
1023 lsmash_qt_significant_bits_t *data = (lsmash_qt_significant_bits_t *)cs->data.structured;
1024 isom_sgbt_t *sgbt = isom_add_sgbt( visual );
1025 if( !sgbt )
1027 lsmash_destroy_codec_specific_data( cs );
1028 goto fail;
1030 sgbt->significantBits = data->significantBits;
1031 lsmash_destroy_codec_specific_data( cs );
1032 break;
1034 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL :
1036 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1037 if( !cs )
1038 goto fail;
1039 lsmash_qt_gamma_t *data = (lsmash_qt_gamma_t *)cs->data.structured;
1040 isom_gama_t *gama = isom_add_gama( visual );
1041 if( !gama )
1043 lsmash_destroy_codec_specific_data( cs );
1044 goto fail;
1046 gama->level = data->level;
1047 lsmash_destroy_codec_specific_data( cs );
1048 break;
1050 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
1052 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1053 if( !cs )
1054 goto fail;
1055 lsmash_codec_global_header_t *data = (lsmash_codec_global_header_t *)cs->data.structured;
1056 isom_glbl_t *glbl = isom_add_glbl( visual );
1057 if( !glbl )
1059 lsmash_destroy_codec_specific_data( cs );
1060 goto fail;
1062 glbl->header_size = data->header_size;
1063 glbl->header_data = lsmash_memdup( data->header_data, data->header_size );
1064 lsmash_destroy_codec_specific_data( cs );
1065 if( !glbl->header_data )
1067 isom_remove_box_by_itself( glbl );
1068 err = LSMASH_ERR_MEMORY_ALLOC;
1069 goto fail;
1071 break;
1073 default :
1075 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
1076 if( !cs )
1077 goto fail;
1078 if( cs->size < ISOM_BASEBOX_COMMON_SIZE )
1080 lsmash_destroy_codec_specific_data( cs );
1081 err = LSMASH_ERR_INVALID_DATA;
1082 goto fail;
1084 uint8_t *data = cs->data.unstructured;
1085 lsmash_compact_box_type_t fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
1086 lsmash_box_type_t box_type = isom_guess_video_codec_specific_box_type( visual->type, fourcc );
1087 /* Append the extension. */
1088 err = isom_add_extension_binary( visual, box_type, LSMASH_BOX_PRECEDENCE_HM, cs->data.unstructured, cs->size );
1089 cs->data.unstructured = NULL; /* Avoid freeing the binary data of the extension. */
1090 lsmash_destroy_codec_specific_data( cs );
1091 if( err < 0 )
1092 goto fail;
1093 break;
1097 isom_trak_t *trak = (isom_trak_t *)visual->parent->parent->parent->parent->parent;
1098 int qt_compatible = trak->file->qt_compatible;
1099 isom_tapt_t *tapt = trak->tapt;
1100 isom_stsl_t *stsl = (isom_stsl_t *)isom_get_extension_box_format( &visual->extensions, ISOM_BOX_TYPE_STSL );
1101 int set_aperture_modes = qt_compatible /* Track Aperture Modes is only available under QuickTime file format. */
1102 && (!stsl || stsl->scale_method == 0) /* Sample scaling method might conflict with this feature. */
1103 && tapt && tapt->clef && tapt->prof && tapt->enof /* Check if required boxes exist. */
1104 && ((isom_stsd_t *)visual->parent)->list.entry_count == 1; /* Multiple sample description might conflict with this, so in that case, disable this feature. */
1105 if( !set_aperture_modes )
1106 isom_remove_box_by_itself( trak->tapt );
1107 int uncompressed_ycbcr = qt_compatible && isom_is_uncompressed_ycbcr( visual->type );
1108 /* Set up Clean Aperture. */
1109 if( set_aperture_modes || uncompressed_ycbcr
1110 || (summary->clap.width.d && summary->clap.height.d && summary->clap.horizontal_offset.d && summary->clap.vertical_offset.d) )
1112 isom_clap_t *clap = isom_add_clap( visual );
1113 if( !clap )
1114 goto fail;
1115 if( summary->clap.width.d && summary->clap.height.d && summary->clap.horizontal_offset.d && summary->clap.vertical_offset.d )
1117 clap->cleanApertureWidthN = summary->clap.width.n;
1118 clap->cleanApertureWidthD = summary->clap.width.d;
1119 clap->cleanApertureHeightN = summary->clap.height.n;
1120 clap->cleanApertureHeightD = summary->clap.height.d;
1121 clap->horizOffN = summary->clap.horizontal_offset.n;
1122 clap->horizOffD = summary->clap.horizontal_offset.d;
1123 clap->vertOffN = summary->clap.vertical_offset.n;
1124 clap->vertOffD = summary->clap.vertical_offset.d;
1126 else
1128 clap->cleanApertureWidthN = summary->width;
1129 clap->cleanApertureWidthD = 1;
1130 clap->cleanApertureHeightN = summary->height;
1131 clap->cleanApertureHeightD = 1;
1132 clap->horizOffN = 0;
1133 clap->horizOffD = 1;
1134 clap->vertOffN = 0;
1135 clap->vertOffD = 1;
1138 /* Set up Pixel Aspect Ratio. */
1139 if( set_aperture_modes || (summary->par_h && summary->par_v) )
1141 isom_pasp_t *pasp = isom_add_pasp( visual );
1142 if( !pasp )
1143 goto fail;
1144 pasp->hSpacing = LSMASH_MAX( summary->par_h, 1 );
1145 pasp->vSpacing = LSMASH_MAX( summary->par_v, 1 );
1147 /* Set up Color Parameter. */
1148 if( uncompressed_ycbcr
1149 || summary->color.primaries_index
1150 || summary->color.transfer_index
1151 || summary->color.matrix_index
1152 || (trak->file->isom_compatible && summary->color.full_range) )
1154 isom_colr_t *colr = isom_add_colr( visual );
1155 if( !colr )
1156 goto fail;
1157 /* Set 'nclc' to parameter type, we don't support 'prof'. */
1158 uint16_t primaries = summary->color.primaries_index;
1159 uint16_t transfer = summary->color.transfer_index;
1160 uint16_t matrix = summary->color.matrix_index;
1161 if( qt_compatible && !trak->file->isom_compatible )
1163 colr->manager |= LSMASH_QTFF_BASE;
1164 colr->type = QT_BOX_TYPE_COLR;
1165 colr->color_parameter_type = QT_COLOR_PARAMETER_TYPE_NCLC;
1166 colr->primaries_index = (primaries == 1 || primaries == 5 || primaries == 6)
1167 ? primaries : QT_PRIMARIES_INDEX_UNSPECIFIED;
1168 colr->transfer_function_index = (transfer == 1 || transfer == 7)
1169 ? transfer : QT_TRANSFER_INDEX_UNSPECIFIED;
1170 colr->matrix_index = (matrix == 1 || matrix == 6 || matrix == 7)
1171 ? matrix : QT_MATRIX_INDEX_UNSPECIFIED;
1173 else
1175 colr->type = ISOM_BOX_TYPE_COLR;
1176 colr->color_parameter_type = ISOM_COLOR_PARAMETER_TYPE_NCLX;
1177 colr->primaries_index = (primaries == 1 || (primaries >= 4 && primaries <= 7))
1178 ? primaries : ISOM_PRIMARIES_INDEX_UNSPECIFIED;
1179 colr->transfer_function_index = (transfer == 1 || (transfer >= 4 && transfer <= 8) || (transfer >= 11 && transfer <= 13))
1180 ? transfer : ISOM_TRANSFER_INDEX_UNSPECIFIED;
1181 colr->matrix_index = (matrix == 1 || (matrix >= 4 && matrix <= 8))
1182 ? matrix : ISOM_MATRIX_INDEX_UNSPECIFIED;
1183 colr->full_range_flag = summary->color.full_range;
1186 /* Set up Track Apeture Modes. */
1187 if( set_aperture_modes )
1189 uint32_t width = visual->width << 16;
1190 uint32_t height = visual->height << 16;
1191 isom_clap_t *clap = (isom_clap_t *)isom_get_extension_box_format( &visual->extensions, ISOM_BOX_TYPE_CLAP );
1192 isom_pasp_t *pasp = (isom_pasp_t *)isom_get_extension_box_format( &visual->extensions, ISOM_BOX_TYPE_PASP );
1193 double clap_width = ((double)clap->cleanApertureWidthN / clap->cleanApertureWidthD) * (1<<16);
1194 double clap_height = ((double)clap->cleanApertureHeightN / clap->cleanApertureHeightD) * (1<<16);
1195 double par = (double)pasp->hSpacing / pasp->vSpacing;
1196 if( par >= 1.0 )
1198 tapt->clef->width = clap_width * par;
1199 tapt->clef->height = clap_height;
1200 tapt->prof->width = width * par;
1201 tapt->prof->height = height;
1203 else
1205 tapt->clef->width = clap_width;
1206 tapt->clef->height = clap_height / par;
1207 tapt->prof->width = width;
1208 tapt->prof->height = height / par;
1210 tapt->enof->width = width;
1211 tapt->enof->height = height;
1213 return 0;
1214 fail:
1215 isom_remove_box_by_itself( visual );
1216 return err;
1219 static int isom_append_audio_es_descriptor_extension( isom_box_t *box, lsmash_audio_summary_t *summary )
1221 uint32_t esds_size = 0;
1222 uint8_t *esds_data = NULL;
1223 lsmash_codec_specific_t *specific = isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
1224 if( !specific )
1225 return LSMASH_ERR_NAMELESS;
1226 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
1228 esds_size = specific->size;
1229 esds_data = lsmash_memdup( specific->data.unstructured, specific->size );
1230 if( !esds_data )
1231 return LSMASH_ERR_MEMORY_ALLOC;
1233 else
1235 esds_data = lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t *)specific->data.structured, &esds_size );
1236 if( !esds_data )
1237 return LSMASH_ERR_NAMELESS;
1239 isom_esds_t *esds = isom_add_esds( box );
1240 if( !esds )
1242 lsmash_free( esds_data );
1243 return LSMASH_ERR_NAMELESS;
1245 lsmash_bs_t bs = { 0 };
1246 bs.buffer.data = esds_data + ISOM_FULLBOX_COMMON_SIZE;
1247 bs.buffer.alloc = esds_size - ISOM_FULLBOX_COMMON_SIZE;
1248 bs.buffer.store = bs.buffer.alloc;
1249 esds->ES = mp4sys_get_descriptor( &bs, NULL );
1250 lsmash_free( esds_data );
1251 if( !esds->ES )
1253 isom_remove_box_by_itself( esds );
1254 return LSMASH_ERR_NAMELESS;
1256 return 0;
1259 static int isom_append_channel_layout_extension( lsmash_codec_specific_t *specific, void *parent, uint32_t channels )
1261 assert( parent );
1262 if( isom_get_extension_box( &((isom_box_t *)parent)->extensions, QT_BOX_TYPE_CHAN ) )
1263 return 0; /* Audio Channel Layout Box is already present. */
1264 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1265 if( !cs )
1266 return LSMASH_ERR_NAMELESS;
1267 lsmash_qt_audio_channel_layout_t *data = (lsmash_qt_audio_channel_layout_t *)cs->data.structured;
1268 lsmash_channel_layout_tag channelLayoutTag = data->channelLayoutTag;
1269 lsmash_channel_bitmap channelBitmap = data->channelBitmap;
1270 if( channelLayoutTag == QT_CHANNEL_LAYOUT_USE_CHANNEL_DESCRIPTIONS /* We don't support the feature of Channel Descriptions. */
1271 || (channelLayoutTag == QT_CHANNEL_LAYOUT_USE_CHANNEL_BITMAP && (!channelBitmap || channelBitmap > QT_CHANNEL_BIT_FULL)) )
1273 channelLayoutTag = QT_CHANNEL_LAYOUT_UNKNOWN | channels;
1274 channelBitmap = 0;
1276 lsmash_destroy_codec_specific_data( cs );
1277 /* Don't create Audio Channel Layout Box if the channel layout is unknown. */
1278 if( (channelLayoutTag ^ QT_CHANNEL_LAYOUT_UNKNOWN) >> 16 )
1280 isom_chan_t *chan = isom_add_chan( parent );
1281 if( !chan )
1282 return LSMASH_ERR_NAMELESS;
1283 chan->channelLayoutTag = channelLayoutTag;
1284 chan->channelBitmap = channelBitmap;
1285 chan->numberChannelDescriptions = 0;
1286 chan->channelDescriptions = NULL;
1288 return 0;
1291 static int isom_set_qtff_mp4a_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1293 isom_wave_t *wave = isom_add_wave( audio );
1294 isom_frma_t *frma;
1295 if( !(frma = isom_add_frma( wave ))
1296 || !isom_add_mp4a( wave )
1297 || !isom_add_terminator( wave ) )
1299 lsmash_remove_entry_tail( &audio->extensions, wave->destruct );
1300 return LSMASH_ERR_NAMELESS;
1302 frma->data_format = audio->type.fourcc;
1303 /* Add ES Descriptor Box. */
1304 int err = isom_append_audio_es_descriptor_extension( (isom_box_t *)wave, summary );
1305 if( err < 0 )
1306 return err;
1307 /* */
1308 audio->type = QT_CODEC_TYPE_MP4A_AUDIO;
1309 audio->version = (summary->channels > 2 || summary->frequency > UINT16_MAX) ? 2 : 1;
1310 audio->channelcount = audio->version == 2 ? 3 : LSMASH_MIN( summary->channels, 2 );
1311 audio->samplesize = 16;
1312 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION;
1313 audio->packet_size = 0;
1314 if( audio->version == 1 )
1316 audio->samplerate = summary->frequency << 16;
1317 audio->samplesPerPacket = summary->samples_in_frame;
1318 audio->bytesPerPacket = 1; /* Apparently, this field is set to 1. */
1319 audio->bytesPerFrame = audio->bytesPerPacket * summary->channels;
1320 audio->bytesPerSample = 2;
1322 else /* audio->version == 2 */
1324 audio->samplerate = 0x00010000;
1325 audio->sizeOfStructOnly = 72;
1326 audio->audioSampleRate = (union {double d; uint64_t i;}){summary->frequency}.i;
1327 audio->numAudioChannels = summary->channels;
1328 audio->always7F000000 = 0x7F000000;
1329 audio->constBitsPerChannel = 0; /* compressed audio */
1330 audio->formatSpecificFlags = 0;
1331 audio->constBytesPerAudioPacket = 0; /* variable */
1332 audio->constLPCMFramesPerAudioPacket = summary->samples_in_frame;
1334 return 0;
1337 static int isom_set_isom_mp4a_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1339 if( summary->summary_type != LSMASH_SUMMARY_TYPE_AUDIO )
1340 return LSMASH_ERR_NAMELESS;
1341 /* Check objectTypeIndication. */
1342 lsmash_mp4sys_object_type_indication objectTypeIndication = lsmash_mp4sys_get_object_type_indication( (lsmash_summary_t *)summary );
1343 switch( objectTypeIndication )
1345 case MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3:
1346 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_Main_Profile:
1347 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_LC_Profile:
1348 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_SSR_Profile:
1349 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_3: /* Legacy Interface */
1350 case MP4SYS_OBJECT_TYPE_Audio_ISO_11172_3: /* Legacy Interface */
1351 break;
1352 default:
1353 return LSMASH_ERR_NAMELESS;
1355 /* Add ES Descriptor Box. */
1356 int err = isom_append_audio_es_descriptor_extension( (isom_box_t *)audio, summary );
1357 if( err < 0 )
1358 return err;
1359 /* In pure mp4 file, these "template" fields shall be default values according to the spec.
1360 But not pure - hybrid with other spec - mp4 file can take other values.
1361 Which is to say, these template values shall be ignored in terms of mp4, except some object_type_indications.
1362 see 14496-14, "Template fields used". */
1363 audio->type = ISOM_CODEC_TYPE_MP4A_AUDIO;
1364 audio->version = 0;
1365 audio->revision_level = 0;
1366 audio->vendor = 0;
1367 audio->channelcount = 2;
1368 audio->samplesize = 16;
1369 audio->compression_ID = 0;
1370 audio->packet_size = 0;
1371 /* WARNING: This field cannot retain frequency above 65535Hz.
1372 This is not "FIXME", I just honestly implemented what the spec says.
1373 BTW, who ever expects sampling frequency takes fixed-point decimal??? */
1374 audio->samplerate = summary->frequency <= UINT16_MAX ? summary->frequency << 16 : 0;
1375 return 0;
1378 static int isom_set_qtff_lpcm_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1380 lsmash_qt_audio_format_specific_flags_t *lpcm = NULL;
1381 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
1383 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
1384 if( !specific )
1385 continue;
1386 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1387 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1389 lpcm = (lsmash_qt_audio_format_specific_flags_t *)specific->data.structured;
1390 break;
1393 if( !lpcm )
1394 return LSMASH_ERR_NAMELESS;
1395 audio->manager |= LSMASH_QTFF_BASE;
1396 lsmash_codec_type_t sample_type = audio->type;
1397 /* Convert the sample type into 'lpcm' if the description doesn't match the format or version = 2 fields are needed. */
1398 if( (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_RAW_AUDIO )
1399 && (summary->sample_size != 8 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1400 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL32_AUDIO )
1401 && (summary->sample_size != 32 || !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1402 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL64_AUDIO )
1403 && (summary->sample_size != 64 || !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1404 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN24_AUDIO )
1405 && (summary->sample_size != 24 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1406 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN32_AUDIO )
1407 && (summary->sample_size != 32 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT)))
1408 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_23NI_AUDIO )
1409 && (summary->sample_size != 32 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT) || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN)))
1410 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_SOWT_AUDIO )
1411 && (summary->sample_size != 16 || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT) || (lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN)))
1412 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO )
1413 && ((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)))
1414 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NONE_AUDIO )
1415 && ((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)))
1416 || (lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NOT_SPECIFIED )
1417 && ((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)))
1418 || (summary->channels > 2 || summary->frequency > UINT16_MAX || summary->sample_size % 8) )
1420 audio->type = QT_CODEC_TYPE_LPCM_AUDIO;
1421 audio->version = 2;
1423 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_LPCM_AUDIO ) )
1424 audio->version = 2;
1425 else if( summary->sample_size > 16
1426 || (!lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_RAW_AUDIO )
1427 && !lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO )
1428 && !lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NONE_AUDIO )
1429 && !lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_NOT_SPECIFIED )) )
1430 audio->version = 1;
1431 /* Set up constBytesPerAudioPacket field.
1432 * We use constBytesPerAudioPacket as the actual size of LPCM audio frame even when version is not 2. */
1433 audio->constBytesPerAudioPacket = (summary->sample_size * summary->channels) / 8;
1434 /* Set up other fields in this description by its version. */
1435 if( audio->version == 2 )
1437 audio->channelcount = 3;
1438 audio->samplesize = 16;
1439 audio->compression_ID = -2;
1440 audio->samplerate = 0x00010000;
1441 audio->sizeOfStructOnly = 72;
1442 audio->audioSampleRate = (union {double d; uint64_t i;}){summary->frequency}.i;
1443 audio->numAudioChannels = summary->channels;
1444 audio->always7F000000 = 0x7F000000;
1445 audio->constBitsPerChannel = summary->sample_size;
1446 audio->constLPCMFramesPerAudioPacket = 1;
1447 audio->formatSpecificFlags = lpcm->format_flags;
1448 if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO ) && summary->sample_size != 8 )
1449 audio->formatSpecificFlags |= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
1450 if( lpcm->format_flags & QT_LPCM_FORMAT_FLAG_FLOAT )
1451 audio->formatSpecificFlags &= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER;
1452 if( lpcm->format_flags & QT_LPCM_FORMAT_FLAG_PACKED )
1453 audio->formatSpecificFlags &= ~QT_LPCM_FORMAT_FLAG_ALIGNED_HIGH;
1455 else if( audio->version == 1 )
1457 audio->channelcount = summary->channels;
1458 audio->samplesize = 16;
1459 /* Audio formats other than 'raw ' and 'twos' are treated as compressed audio. */
1460 if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_RAW_AUDIO )
1461 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TWOS_AUDIO ) )
1462 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED;
1463 else
1464 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION;
1465 audio->samplerate = summary->frequency << 16;
1466 audio->samplesPerPacket = 1;
1467 audio->bytesPerPacket = summary->sample_size / 8;
1468 audio->bytesPerFrame = audio->bytesPerPacket * summary->channels; /* sample_size field in stsz box is NOT used. */
1469 audio->bytesPerSample = 1 + (summary->sample_size != 8);
1470 if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL32_AUDIO )
1471 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_FL64_AUDIO )
1472 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN24_AUDIO )
1473 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_IN32_AUDIO ) )
1475 isom_wave_t *wave = isom_add_wave( audio );
1476 isom_frma_t *frma;
1477 isom_enda_t *enda;
1478 if( !(frma = isom_add_frma( wave ))
1479 || !(enda = isom_add_enda( wave ))
1480 || !isom_add_terminator( wave ) )
1482 lsmash_remove_entry_tail( &audio->extensions, wave->destruct );
1483 return LSMASH_ERR_NAMELESS;
1485 frma->data_format = sample_type.fourcc;
1486 enda->littleEndian = !(lpcm->format_flags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN);
1489 else /* audio->version == 0 */
1491 audio->channelcount = summary->channels;
1492 audio->samplesize = summary->sample_size;
1493 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED;
1494 audio->samplerate = summary->frequency << 16;
1496 return 0;
1499 static int isom_set_isom_dts_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1501 audio->version = 0;
1502 audio->revision_level = 0;
1503 audio->vendor = 0;
1504 audio->channelcount = summary->channels;
1505 audio->samplesize = 16;
1506 audio->compression_ID = 0;
1507 audio->packet_size = 0;
1508 switch( summary->frequency )
1510 case 12000 : /* Invalid? (No reference in the spec) */
1511 case 24000 :
1512 case 48000 :
1513 case 96000 :
1514 case 192000 :
1515 case 384000 : /* Invalid? (No reference in the spec) */
1516 audio->samplerate = 48000 << 16;
1517 break;
1518 case 22050 :
1519 case 44100 :
1520 case 88200 :
1521 case 176400 :
1522 case 352800 : /* Invalid? (No reference in the spec) */
1523 audio->samplerate = 44100 << 16;
1524 break;
1525 case 8000 : /* Invalid? (No reference in the spec) */
1526 case 16000 :
1527 case 32000 :
1528 case 64000 :
1529 case 128000 :
1530 audio->samplerate = 32000 << 16;
1531 break;
1532 default :
1533 audio->samplerate = 0;
1534 break;
1536 return 0;
1539 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 )
1541 lsmash_box_type_t box_type = LSMASH_BOX_TYPE_INITIALIZER;
1542 box_type.fourcc = fourcc;
1543 #define GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
1544 else if( (codec_type.user.fourcc == 0 \
1545 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
1546 && box_type.fourcc == predefined_box_type.fourcc ) \
1547 box_type = predefined_box_type
1548 if( 0 );
1549 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AC_3_AUDIO, ISOM_BOX_TYPE_DAC3 );
1550 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_EC_3_AUDIO, ISOM_BOX_TYPE_DEC3 );
1551 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSC_AUDIO, ISOM_BOX_TYPE_DDTS );
1552 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSE_AUDIO, ISOM_BOX_TYPE_DDTS );
1553 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSH_AUDIO, ISOM_BOX_TYPE_DDTS );
1554 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSL_AUDIO, ISOM_BOX_TYPE_DDTS );
1555 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_ALAC_AUDIO, ISOM_BOX_TYPE_ALAC );
1556 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4A_AUDIO, ISOM_BOX_TYPE_ESDS );
1557 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ALAC_AUDIO, QT_BOX_TYPE_ALAC );
1558 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_MP4A_AUDIO, QT_BOX_TYPE_ESDS );
1559 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_FULLMP3_AUDIO, QT_CODEC_TYPE_MP3_AUDIO );
1560 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM2_AUDIO, QT_CODEC_TYPE_ADPCM2_AUDIO );
1561 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM17_AUDIO, QT_CODEC_TYPE_ADPCM17_AUDIO );
1562 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_GSM49_AUDIO, QT_CODEC_TYPE_GSM49_AUDIO );
1563 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_CHAN );
1564 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_GLBL );
1565 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED, QT_BOX_TYPE_WAVE );
1566 #undef GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE
1567 return box_type;
1570 typedef struct
1572 uint16_t wFormatTag;
1573 uint16_t nChannels;
1574 uint32_t nSamplesPerSec;
1575 uint32_t nAvgBytesPerSec;
1576 uint16_t nBlockAlign;
1577 uint16_t wBitsPerSample;
1578 uint16_t cbSize;
1579 } wave_format_ex_t;
1581 static lsmash_bs_t *isom_create_waveform_audio_info
1583 wave_format_ex_t *wfx,
1584 lsmash_box_type_t type
1587 lsmash_bs_t *bs = lsmash_bs_create();
1588 if( !bs )
1589 return NULL;
1590 lsmash_bs_put_be32( bs, ISOM_BASEBOX_COMMON_SIZE + 18 + wfx->cbSize );
1591 lsmash_bs_put_be32( bs, type.fourcc );
1592 lsmash_bs_put_le16( bs, wfx->wFormatTag );
1593 lsmash_bs_put_le16( bs, wfx->nChannels );
1594 lsmash_bs_put_le32( bs, wfx->nSamplesPerSec );
1595 lsmash_bs_put_le32( bs, wfx->nAvgBytesPerSec );
1596 lsmash_bs_put_le16( bs, wfx->nBlockAlign );
1597 lsmash_bs_put_le16( bs, wfx->wBitsPerSample );
1598 lsmash_bs_put_le16( bs, wfx->cbSize );
1599 return bs;
1602 static int isom_setup_waveform_audio_info
1604 isom_wave_t *wave,
1605 isom_audio_entry_t *audio,
1606 lsmash_audio_summary_t *summary,
1607 uint32_t samples_per_packet,
1608 uint32_t bytes_per_frame,
1609 uint32_t sample_size
1612 wave_format_ex_t wfx;
1613 wfx.wFormatTag = 0x0000; /* WAVE_FORMAT_UNKNOWN */
1614 wfx.nChannels = summary->channels;
1615 wfx.nSamplesPerSec = summary->frequency;
1616 wfx.nAvgBytesPerSec = 0;
1617 wfx.nBlockAlign = bytes_per_frame;
1618 wfx.wBitsPerSample = sample_size;
1619 wfx.cbSize = 0;
1620 lsmash_bs_t *bs = NULL;
1621 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ADPCM2_AUDIO ) )
1623 /* ADPCMWAVEFORMAT */
1624 wfx.wFormatTag = 0x0002; /* WAVE_FORMAT_ADPCM */
1625 wfx.cbSize = 32;
1626 bs = isom_create_waveform_audio_info( &wfx, audio->type );
1627 if( !bs )
1628 return LSMASH_ERR_MEMORY_ALLOC;
1629 uint16_t wSamplesPerBlock = samples_per_packet; /* nBlockAlign * 2 / nChannels - 12 */
1630 uint16_t wNumCoef = 7; /* Microsoft ADPCM uses just 7 coefficients. */
1631 static const struct
1633 int16_t iCoef1;
1634 int16_t iCoef2;
1635 } aCoef[7] = { { 256, 0 }, { 512, -256 }, { 0,0 }, { 192,64 }, { 240,0 }, { 460, -208 }, { 392,-232 } };
1636 lsmash_bs_put_le16( bs, wSamplesPerBlock );
1637 lsmash_bs_put_le16( bs, wNumCoef );
1638 for( int i = 0; i < 7; i++ )
1640 lsmash_bs_put_le16( bs, aCoef[i].iCoef1 );
1641 lsmash_bs_put_le16( bs, aCoef[i].iCoef2 );
1644 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ADPCM17_AUDIO ) )
1646 /* IMAADPCMWAVEFORMAT */
1647 wfx.wFormatTag = 0x0011; /* WAVE_FORMAT_DVI_ADPCM / WAVE_FORMAT_IMA_ADPCM */
1648 wfx.cbSize = 2;
1649 bs = isom_create_waveform_audio_info( &wfx, audio->type );
1650 if( !bs )
1651 return LSMASH_ERR_MEMORY_ALLOC;
1652 uint16_t wSamplesPerBlock = samples_per_packet;
1653 lsmash_bs_put_le16( bs, wSamplesPerBlock );
1655 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_GSM49_AUDIO ) )
1657 /* GSM610WAVEFORMAT */
1658 wfx.wFormatTag = 0x0031; /* WAVE_FORMAT_GSM610 */
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_FULLMP3_AUDIO )
1667 || lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MP3_AUDIO ) )
1669 /* MPEGLAYER3WAVEFORMAT */
1670 wfx.wFormatTag = 0x0055; /* WAVE_FORMAT_MPEGLAYER3 */
1671 wfx.nBlockAlign = 1; /* ? */
1672 wfx.wBitsPerSample = 0; /* undefined */
1673 wfx.cbSize = 12;
1674 bs = isom_create_waveform_audio_info( &wfx, audio->type );
1675 if( !bs )
1676 return LSMASH_ERR_MEMORY_ALLOC;
1677 uint16_t wID = 1; /* MPEGLAYER3_ID_MPEG */
1678 uint32_t fdwFlags = 0; /* We don't know whether the stream is padded or not here. */
1679 uint16_t nBlockSize = 0; /* (144 * (bitrate / nSamplesPerSec) + padding) * nFramesPerBlock */
1680 uint16_t nFramesPerBlock = 1; /* the number of audio frames per block */
1681 uint16_t nCodecDelay = 0; /* Encoder delay in samples is unknown. */
1682 lsmash_bs_put_le16( bs, wID );
1683 lsmash_bs_put_le32( bs, fdwFlags );
1684 lsmash_bs_put_le16( bs, nBlockSize );
1685 lsmash_bs_put_le16( bs, nFramesPerBlock );
1686 lsmash_bs_put_le16( bs, nCodecDelay );
1688 if( !bs )
1690 assert( 0 );
1691 return LSMASH_ERR_NAMELESS;
1693 uint32_t wfx_size;
1694 uint8_t *wfx_data = lsmash_bs_export_data( bs, &wfx_size );
1695 lsmash_bs_cleanup( bs );
1696 if( !wfx_data )
1697 return LSMASH_ERR_NAMELESS;
1698 if( wfx_size != ISOM_BASEBOX_COMMON_SIZE + 18 + wfx.cbSize )
1700 lsmash_free( wfx_data );
1701 return LSMASH_ERR_NAMELESS;
1703 int err = isom_add_extension_binary( wave, audio->type, LSMASH_BOX_PRECEDENCE_HM, wfx_data, wfx_size );
1704 if( err < 0 )
1706 lsmash_free( wfx_data );
1707 return err;
1709 return 0;
1712 static int isom_set_qtff_sound_decompression_parameters
1714 isom_audio_entry_t *audio,
1715 lsmash_audio_summary_t *summary,
1716 lsmash_qt_audio_format_specific_flag *format_flags,
1717 uint32_t samples_per_packet,
1718 uint32_t bytes_per_frame,
1719 uint32_t sample_size
1722 /* A 'wave' extension itself shall be absent in the opaque CODEC specific info list.
1723 * So, create a 'wave' extension here and append it as an extension to the audio sample description. */
1724 isom_wave_t *wave = isom_add_wave( audio );
1725 if( !wave )
1726 return LSMASH_ERR_NAMELESS;
1727 if( !isom_add_frma ( wave )
1728 || !isom_add_terminator( wave ) )
1730 lsmash_remove_entry_tail( &audio->extensions, wave->destruct );
1731 return LSMASH_ERR_NAMELESS;
1733 wave->frma->data_format = audio->type.fourcc;
1734 /* Append extensions from the opaque CODEC specific info list to 'wave' extension. */
1735 int err;
1736 int waveform_audio_info_present = 0;
1737 int requires_waveform_audio_info = isom_is_waveform_audio( audio->type );
1738 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
1740 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
1741 if( !specific )
1742 return LSMASH_ERR_NAMELESS;
1743 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
1744 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1745 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
1746 switch( specific->type )
1748 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
1749 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
1750 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
1751 continue; /* These cannot be an extension for 'wave' extension. */
1752 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
1753 /* (Legacy?) ALAC might have an Audio Channel Layout Box inside 'wave' extension. */
1754 #if 1
1755 continue;
1756 #else
1757 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO ) )
1758 continue;
1759 if( (err = isom_append_channel_layout_extension( specific, wave, summary->channels )) < 0 )
1760 return err;
1761 break;
1762 #endif
1763 default :
1765 assert( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
1766 || specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS );
1767 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
1768 if( !cs )
1769 return LSMASH_ERR_NAMELESS;
1770 if( cs->size < ISOM_BASEBOX_COMMON_SIZE )
1772 lsmash_destroy_codec_specific_data( cs );
1773 continue;
1775 uint8_t *box_data = cs->data.unstructured;
1776 uint64_t box_size = cs->size;
1777 lsmash_compact_box_type_t fourcc = LSMASH_4CC( box_data[4], box_data[5], box_data[6], box_data[7] );
1778 if( audio->version == 2 && fourcc == QT_BOX_TYPE_ENDA.fourcc )
1780 /* Don't append a 'enda' extension if version == 2.
1781 * Endianness is indicated in QuickTime audio format specific flags. */
1782 if( box_size >= ISOM_BASEBOX_COMMON_SIZE + 2 )
1784 /* Override endianness indicated in format specific flags. */
1785 if( box_data[9] == 1 )
1786 *format_flags &= ~QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN;
1787 else
1788 *format_flags |= QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN;
1790 lsmash_destroy_codec_specific_data( cs );
1791 continue;
1793 lsmash_box_type_t box_type = isom_guess_audio_codec_specific_box_type( audio->type, fourcc );
1794 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_WAVE ) )
1796 /* It is insane to appened a 'wave' extension to a 'wave' extension. */
1797 lsmash_destroy_codec_specific_data( cs );
1798 continue;
1800 box_type = lsmash_form_qtff_box_type( box_type.fourcc );
1801 /* Determine 'precedence'. */
1802 uint64_t precedence;
1803 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_FRMA ) )
1804 precedence = LSMASH_BOX_PRECEDENCE_QTFF_FRMA;
1805 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ESDS ) )
1806 precedence = LSMASH_BOX_PRECEDENCE_QTFF_ESDS;
1807 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ENDA ) )
1808 precedence = LSMASH_BOX_PRECEDENCE_QTFF_ENDA;
1809 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_MP4A ) )
1810 precedence = LSMASH_BOX_PRECEDENCE_QTFF_MP4A;
1811 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_TERMINATOR ) )
1812 precedence = LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR;
1813 else
1814 precedence = LSMASH_BOX_PRECEDENCE_HM;
1815 /* Append the extension. */
1816 err = isom_add_extension_binary( wave, box_type, precedence, cs->data.unstructured, cs->size );
1817 cs->data.unstructured = NULL; /* Avoid freeing the binary data of the extension. */
1818 lsmash_destroy_codec_specific_data( cs );
1819 if( err < 0 )
1820 return err;
1821 if( isom_is_waveform_audio( box_type ) )
1822 waveform_audio_info_present = 1;
1823 break;
1827 if( requires_waveform_audio_info && !waveform_audio_info_present
1828 && (err = isom_setup_waveform_audio_info( wave, audio, summary, samples_per_packet, bytes_per_frame, sample_size )) < 0 )
1829 return err;
1830 return 0;
1833 static int isom_set_qtff_template_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1835 audio->manager |= LSMASH_QTFF_BASE;
1836 audio->type = lsmash_form_qtff_box_type( audio->type.fourcc );
1837 audio->version = (summary->channels > 2 || summary->frequency > UINT16_MAX) ? 2 : 1;
1838 /* Try to get QuickTime audio format specific flags. */
1839 lsmash_qt_audio_format_specific_flag format_flags = QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN;
1840 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
1842 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
1843 if( !specific
1844 || !specific->data.structured )
1845 continue;
1846 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1847 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1849 /* A format specific flags is found.
1850 * Force audio sample description version == 2. */
1851 format_flags = ((lsmash_qt_audio_format_specific_flags_t *)specific->data.structured)->format_flags;
1852 audio->version = 2;
1853 break;
1856 uint32_t samples_per_packet;
1857 uint32_t bytes_per_frame;
1858 uint32_t sample_size;
1859 if( !((summary->samples_in_frame == 0 || summary->bytes_per_frame == 0 || summary->sample_size == 0)
1860 && isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio, &samples_per_packet, &bytes_per_frame, &sample_size )) )
1862 samples_per_packet = summary->samples_in_frame;
1863 bytes_per_frame = summary->bytes_per_frame;
1864 sample_size = summary->sample_size;
1866 if( !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC3_AUDIO )
1867 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC6_AUDIO )
1868 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_AGSM_AUDIO )
1869 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAW_AUDIO )
1870 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ULAW_AUDIO ) )
1872 int err = isom_set_qtff_sound_decompression_parameters( audio, summary, &format_flags,
1873 samples_per_packet, bytes_per_frame, sample_size );
1874 if( err < 0 )
1875 return err;
1877 /* Set up common audio description fields. */
1878 audio->samplesize = 16;
1879 audio->packet_size = 0;
1880 if( audio->version == 2 )
1882 audio->channelcount = 3;
1883 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION;
1884 audio->samplerate = 0x00010000;
1885 audio->sizeOfStructOnly = 72;
1886 audio->audioSampleRate = (union {double d; uint64_t i;}){summary->frequency}.i;
1887 audio->numAudioChannels = summary->channels;
1888 audio->always7F000000 = 0x7F000000;
1889 audio->constBitsPerChannel = 0;
1890 audio->constBytesPerAudioPacket = bytes_per_frame;
1891 audio->constLPCMFramesPerAudioPacket = samples_per_packet;
1892 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO ) )
1894 switch( sample_size )
1896 case 16 :
1897 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA;
1898 break;
1899 case 20 :
1900 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA;
1901 break;
1902 case 24 :
1903 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA;
1904 break;
1905 case 32 :
1906 audio->formatSpecificFlags = QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA;
1907 break;
1908 default :
1909 break;
1912 else
1914 if( format_flags & QT_AUDIO_FORMAT_FLAG_FLOAT )
1915 format_flags &= ~QT_AUDIO_FORMAT_FLAG_SIGNED_INTEGER;
1916 if( format_flags & QT_AUDIO_FORMAT_FLAG_PACKED )
1917 format_flags &= ~QT_AUDIO_FORMAT_FLAG_ALIGNED_HIGH;
1918 audio->formatSpecificFlags = format_flags;
1921 else /* if( audio->version == 1 ) */
1923 audio->channelcount = LSMASH_MIN( summary->channels, 2 );
1924 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION;
1925 audio->samplerate = summary->frequency << 16;
1926 audio->samplesPerPacket = samples_per_packet;
1927 audio->bytesPerPacket = bytes_per_frame / summary->channels;
1928 audio->bytesPerFrame = bytes_per_frame; /* sample_size field in stsz box is NOT used. */
1929 audio->bytesPerSample = 1 + (sample_size != 8);
1931 return 0;
1934 static void isom_set_samplerate_division_of_media_timescale( isom_audio_entry_t *audio, int strict )
1936 if( audio->parent /* stsd */
1937 && audio->parent->parent /* stbl */
1938 && audio->parent->parent->parent /* minf */
1939 && audio->parent->parent->parent->parent /* mdia */
1940 && lsmash_check_box_type_identical( audio->parent->parent->parent->parent->type, ISOM_BOX_TYPE_MDIA )
1941 && ((isom_mdia_t *)audio->parent->parent->parent->parent)->mdhd )
1943 /* Make an effort to match the timescale with samplerate, or be an integer multiple of it. */
1944 uint32_t orig_timescale = ((isom_mdia_t *)audio->parent->parent->parent->parent)->mdhd->timescale;
1945 uint32_t timescale = orig_timescale;
1946 uint32_t i = 2;
1947 while( timescale > UINT16_MAX && timescale > 1 )
1949 if( timescale % i == 0 )
1950 timescale /= i;
1951 else
1952 i += i > 2 ? 2 : 1;
1954 if( timescale != orig_timescale && strict )
1955 lsmash_log( NULL, LSMASH_LOG_WARNING, "samplerate does not match the media timescale.\n" );
1956 if( timescale <= UINT16_MAX && timescale > 1 )
1958 audio->samplerate = timescale << 16;
1959 return;
1962 audio->samplerate = 0;
1965 static int isom_set_isom_template_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
1967 audio->version = 0; /* reserved */
1968 audio->revision_level = 0; /* reserved */
1969 audio->vendor = 0; /* reserved */
1970 audio->channelcount = 2; /* template */
1971 audio->samplesize = 16; /* template */
1972 audio->compression_ID = 0; /* pre_defined */
1973 audio->packet_size = 0; /* reserved */
1974 /* template : default output audio sampling rate at playback */
1975 if( summary->frequency <= UINT16_MAX )
1976 audio->samplerate = summary->frequency << 16;
1977 else
1978 isom_set_samplerate_division_of_media_timescale( audio, 0 );
1979 return 0;
1982 static int isom_set_isom_amr_audio_description( isom_audio_entry_t *audio, int wb )
1984 /* For AMR-NB and AMR-WB stream, these fields are not meaningful. */
1985 audio->version = 0; /* always 0 */
1986 audio->revision_level = 0; /* always 0 */
1987 audio->vendor = 0; /* always 0 */
1988 audio->channelcount = 2; /* always 2 although the actual number of channels is always 1 */
1989 audio->samplesize = 16; /* always 16 */
1990 audio->compression_ID = 0; /* always 0 */
1991 audio->packet_size = 0; /* always 0 */
1992 /* Set samplerate by trying to copy from Media Header Box of this media though the
1993 * actual samplerate is 8000 Hz for AMR-NB and 16000 Hz for AMR-WB.
1994 * 3GPP and 3GPP2 has no restriction for media timescale. Therefore, users should
1995 * set suitable media timescale by themselves within the bounds of common sense. */
1996 isom_set_samplerate_division_of_media_timescale( audio, 1 );
1997 if( audio->samplerate == 0 )
1998 /* Set hard-coded but correct samplerate in the CODEC level. */
1999 audio->samplerate = wb ? 8000 : 16000;
2000 return 0;
2003 static int isom_set_isom_alac_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
2005 return isom_set_isom_template_audio_description( audio, summary );
2008 static int isom_set_qtff_alac_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
2010 return isom_set_qtff_template_audio_description( audio, summary );
2013 static int isom_set_isom_eac3_audio_description( isom_audio_entry_t *audio, lsmash_audio_summary_t *summary )
2015 return isom_set_isom_template_audio_description( audio, summary );
2018 static int isom_setup_audio_description( isom_stsd_t *stsd, lsmash_audio_summary_t *summary )
2020 if( !stsd || !stsd->file || !summary )
2021 return LSMASH_ERR_NAMELESS;
2022 int err = isom_check_valid_summary( (lsmash_summary_t *)summary );
2023 if( err < 0 )
2024 return err;
2025 isom_audio_entry_t *audio = isom_add_audio_description( stsd, summary->sample_type );
2026 if( !audio )
2027 return LSMASH_ERR_NAMELESS;
2028 audio->data_reference_index = summary->data_ref_index;
2029 lsmash_file_t *file = stsd->file;
2030 lsmash_codec_type_t audio_type = audio->type;
2031 if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_MP4A_AUDIO )
2032 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_MP4A_AUDIO ) )
2034 if( (file->ftyp && file->ftyp->major_brand == ISOM_BRAND_TYPE_QT)
2035 || (!file->ftyp && (file->qt_compatible || (file->moov && !file->moov->iods))) )
2036 err = isom_set_qtff_mp4a_description( audio, summary );
2037 else
2038 err = isom_set_isom_mp4a_description( audio, summary );
2040 else if( isom_is_lpcm_audio( audio ) )
2041 err = isom_set_qtff_lpcm_description( audio, summary );
2042 else if( file->isom_compatible && lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_ALAC_AUDIO ) )
2043 err = isom_set_isom_alac_audio_description( audio, summary );
2044 else if( file->qt_compatible && lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_ALAC_AUDIO ) )
2045 err = isom_set_qtff_alac_audio_description( audio, summary );
2046 else if( audio->type.fourcc == ISOM_CODEC_TYPE_ALAC_AUDIO.fourcc )
2048 if( file->qt_compatible )
2049 err = isom_set_qtff_alac_audio_description( audio, summary );
2050 else
2051 err = isom_set_isom_alac_audio_description( audio, summary );
2053 else if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_DTSC_AUDIO )
2054 || lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_DTSE_AUDIO )
2055 || lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_DTSH_AUDIO )
2056 || lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_DTSL_AUDIO ) )
2057 err = isom_set_isom_dts_audio_description( audio, summary );
2058 else if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_EC_3_AUDIO ) )
2059 err = isom_set_isom_eac3_audio_description( audio, summary );
2060 else if( file->qt_compatible )
2061 err = isom_set_qtff_template_audio_description( audio, summary );
2062 else if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_SAMR_AUDIO ) )
2063 err = isom_set_isom_amr_audio_description( audio, 0 );
2064 else if( lsmash_check_codec_type_identical( audio_type, ISOM_CODEC_TYPE_SAWB_AUDIO ) )
2065 err = isom_set_isom_amr_audio_description( audio, 1 );
2066 else
2067 err = isom_set_isom_template_audio_description( audio, summary );
2068 if( err < 0 )
2069 goto fail;
2070 err = LSMASH_ERR_NAMELESS;
2071 /* Don't use audio_type since audio->type might have changed. */
2072 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
2074 lsmash_codec_specific_t *specific = (lsmash_codec_specific_t *)entry->data;
2075 if( !specific )
2076 goto fail;
2077 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
2078 && specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2079 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
2080 switch( specific->type )
2082 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON :
2084 if( specific->format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
2085 continue; /* Ignore since not fatal. */
2086 lsmash_qt_audio_common_t *data = (lsmash_qt_audio_common_t *)specific->data.structured;
2087 audio->revision_level = data->revision_level;
2088 audio->vendor = data->vendor;
2089 if( audio->version == 1
2090 && !isom_is_lpcm_audio( audio )
2091 && data->compression_ID != QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED )
2093 /* Compressed audio must not be set to QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED. */
2094 audio->compression_ID = data->compression_ID;
2095 if( audio->compression_ID == QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION )
2097 /* For variable compression, bytesPerPacket and bytesPerFrame are reserved and should be set to 0. */
2098 audio->bytesPerPacket = 0;
2099 audio->bytesPerFrame = 0;
2102 break;
2104 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT :
2106 if( !file->qt_compatible
2107 && !lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_ALAC_AUDIO )
2108 && !lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO ) )
2109 continue;
2110 if( (err = isom_append_channel_layout_extension( specific, audio, summary->channels )) < 0 )
2111 goto fail;
2112 break;
2114 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER :
2116 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2117 if( !cs )
2118 goto fail;
2119 lsmash_codec_global_header_t *data = (lsmash_codec_global_header_t *)cs->data.structured;
2120 isom_glbl_t *glbl = isom_add_glbl( audio );
2121 if( !glbl )
2123 lsmash_destroy_codec_specific_data( cs );
2124 goto fail;
2126 glbl->header_size = data->header_size;
2127 glbl->header_data = lsmash_memdup( data->header_data, data->header_size );
2128 lsmash_destroy_codec_specific_data( cs );
2129 if( !glbl->header_data )
2131 isom_remove_box_by_itself( glbl );
2132 err = LSMASH_ERR_MEMORY_ALLOC;
2133 goto fail;
2135 break;
2137 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS :
2138 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS :
2139 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG :
2140 break; /* shall be set up already */
2141 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC :
2142 if( file->qt_compatible )
2143 continue; /* shall be set up already */
2144 default :
2146 lsmash_codec_specific_t *cs = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2147 if( !cs )
2148 goto fail;
2149 if( cs->size < ISOM_BASEBOX_COMMON_SIZE )
2151 lsmash_destroy_codec_specific_data( cs );
2152 continue;
2154 uint8_t *box_data = cs->data.unstructured;
2155 lsmash_compact_box_type_t fourcc = LSMASH_4CC( box_data[4], box_data[5], box_data[6], box_data[7] );
2156 lsmash_box_type_t box_type = isom_guess_audio_codec_specific_box_type( audio->type, fourcc );
2157 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_WAVE ) )
2159 /* CODEC specific info shall be already inside 'wave' extension. */
2160 lsmash_destroy_codec_specific_data( cs );
2161 continue;
2163 /* Append the extension. */
2164 err = isom_add_extension_binary( audio, box_type, LSMASH_BOX_PRECEDENCE_HM, cs->data.unstructured, cs->size );
2165 cs->data.unstructured = NULL; /* Avoid freeing the binary data of the extension. */
2166 lsmash_destroy_codec_specific_data( cs );
2167 if( err < 0 )
2168 goto fail;
2169 break;
2173 if( audio->version == 0 )
2174 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED;
2175 else if( audio->version == 2 )
2176 audio->compression_ID = QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION;
2177 return 0;
2178 fail:
2179 isom_remove_box_by_itself( audio );
2180 return err;
2183 static int isom_setup_tx3g_description( isom_stsd_t *stsd, lsmash_summary_t *summary )
2185 isom_tx3g_entry_t *tx3g = isom_add_tx3g_description( stsd );
2186 if( !tx3g )
2187 return LSMASH_ERR_NAMELESS;
2188 /* We create a dummy font record to make valid font_ID in the sample description.
2189 * The specification (3GPP TS 26.245) does not forbid the value 0 for the identifier,
2190 * but we set 1 to it as track_ID begins from 1. */
2191 tx3g->data_reference_index = summary->data_ref_index;
2192 tx3g->font_ID = 1; /* ID of the default font record */
2193 int err = LSMASH_ERR_MEMORY_ALLOC;
2194 isom_ftab_t *ftab = isom_add_ftab( tx3g );
2195 if( !ftab )
2197 err = LSMASH_ERR_NAMELESS;
2198 goto fail;
2200 isom_font_record_t *font = lsmash_malloc( sizeof(isom_font_record_t) );
2201 if( !font )
2202 goto fail;
2203 if( lsmash_add_entry( ftab->list, font ) < 0 )
2205 lsmash_free( font );
2206 goto fail;
2208 const char font_names[] = "Serif,Sans-serif,Monospace";
2209 font->font_ID = 1;
2210 font->font_name_length = sizeof(font_names);
2211 font->font_name = lsmash_memdup( font_names, sizeof(font_names) );
2212 if( !font->font_name )
2213 goto fail;
2214 return 0;
2215 fail:
2216 isom_remove_box_by_itself( tx3g );
2217 return err;
2220 static int isom_setup_qt_text_description( isom_stsd_t *stsd, lsmash_summary_t *summary )
2222 isom_qt_text_entry_t *text = isom_add_qt_text_description( stsd );
2223 if( !text )
2224 return LSMASH_ERR_NAMELESS;
2225 text->data_reference_index = summary->data_ref_index;
2226 return 0;
2229 static int isom_setup_text_description( isom_stsd_t *stsd, lsmash_summary_t *summary )
2231 lsmash_codec_type_t sample_type = summary->sample_type;
2232 if( lsmash_check_box_type_identical( sample_type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
2233 return isom_setup_tx3g_description( stsd, summary );
2234 else if( lsmash_check_box_type_identical( sample_type, QT_CODEC_TYPE_TEXT_TEXT ) )
2235 return isom_setup_qt_text_description( stsd, summary );
2236 else
2237 return LSMASH_ERR_NAMELESS;
2240 int isom_setup_sample_description( isom_stsd_t *stsd, lsmash_media_type media_type, lsmash_summary_t *summary )
2242 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
2243 return isom_setup_visual_description( stsd, (lsmash_video_summary_t *)summary );
2244 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
2245 return isom_setup_audio_description( stsd, (lsmash_audio_summary_t *)summary );
2246 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
2247 return isom_setup_text_description( stsd, (lsmash_summary_t *)summary );
2248 else
2249 return LSMASH_ERR_NAMELESS;
2252 static lsmash_codec_specific_data_type isom_get_codec_specific_data_type( lsmash_compact_box_type_t extension_fourcc )
2254 static struct codec_specific_data_type_table_tag
2256 lsmash_compact_box_type_t extension_fourcc;
2257 lsmash_codec_specific_data_type data_type;
2258 } codec_specific_data_type_table[32] = { { 0, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN } };
2259 if( codec_specific_data_type_table[0].data_type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN )
2261 int i = 0;
2262 #define ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( extension_type, data_type ) \
2263 codec_specific_data_type_table[i++] = (struct codec_specific_data_type_table_tag){ extension_type.fourcc, data_type }
2264 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264 );
2265 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC );
2266 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1 );
2267 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 );
2268 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 );
2269 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS );
2270 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC );
2271 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
2272 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE );
2273 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE );
2274 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ALAC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC );
2275 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ESDS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
2276 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO );
2277 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT );
2278 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS );
2279 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL );
2280 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT );
2281 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER );
2282 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN );
2283 #undef ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT
2285 lsmash_codec_specific_data_type data_type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN;
2286 for( int i = 0; codec_specific_data_type_table[i].data_type != LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN; i++ )
2287 if( extension_fourcc == codec_specific_data_type_table[i].extension_fourcc )
2289 data_type = codec_specific_data_type_table[i].data_type;
2290 break;
2292 return data_type;
2295 lsmash_summary_t *isom_create_video_summary_from_description( isom_sample_entry_t *sample_entry )
2297 if( !sample_entry )
2298 return NULL;
2299 isom_visual_entry_t *visual = (isom_visual_entry_t *)sample_entry;
2300 lsmash_video_summary_t *summary = (lsmash_video_summary_t *)lsmash_create_summary( LSMASH_SUMMARY_TYPE_VIDEO );
2301 if( !summary )
2302 return NULL;
2303 summary->sample_type = visual->type;
2304 summary->data_ref_index = visual->data_reference_index;
2305 summary->width = visual->width;
2306 summary->height = visual->height;
2307 summary->depth = visual->depth;
2308 memcpy( summary->compressorname, visual->compressorname, 32 );
2309 summary->compressorname[32] = '\0';
2310 if( isom_is_qt_video( summary->sample_type ) )
2312 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON,
2313 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2314 if( !specific )
2315 goto fail;
2316 lsmash_qt_video_common_t *data = (lsmash_qt_video_common_t *)specific->data.structured;
2317 data->revision_level = visual->revision_level;
2318 data->vendor = visual->vendor;
2319 data->temporalQuality = visual->temporalQuality;
2320 data->spatialQuality = visual->spatialQuality;
2321 data->horizontal_resolution = visual->horizresolution;
2322 data->vertical_resolution = visual->vertresolution;
2323 data->dataSize = visual->dataSize;
2324 data->frame_count = visual->frame_count;
2325 data->color_table_ID = visual->color_table_ID;
2326 if( visual->color_table_ID == 0 )
2328 isom_qt_color_table_t *src_ct = &visual->color_table;
2329 if( !src_ct->array )
2331 lsmash_destroy_codec_specific_data( specific );
2332 goto fail;
2334 uint16_t element_count = LSMASH_MIN( src_ct->size + 1, 256 );
2335 lsmash_qt_color_table_t *dst_ct = &data->color_table;
2336 dst_ct->seed = src_ct->seed;
2337 dst_ct->flags = src_ct->flags;
2338 dst_ct->size = src_ct->size;
2339 for( uint16_t i = 0; i < element_count; i++ )
2341 dst_ct->array[i].unused = src_ct->array[i].value;
2342 dst_ct->array[i].r = src_ct->array[i].r;
2343 dst_ct->array[i].g = src_ct->array[i].g;
2344 dst_ct->array[i].b = src_ct->array[i].b;
2347 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2349 lsmash_destroy_codec_specific_data( specific );
2350 goto fail;
2353 for( lsmash_entry_t *entry = visual->extensions.head; entry; entry = entry->next )
2355 isom_box_t *box = (isom_box_t *)entry->data;
2356 if( !box )
2357 continue;
2358 if( !(box->manager & LSMASH_BINARY_CODED_BOX) )
2360 lsmash_codec_specific_t *specific = NULL;
2361 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_CLAP ) )
2363 isom_clap_t *clap = (isom_clap_t *)box;
2364 summary->clap.width.n = clap->cleanApertureWidthN;
2365 summary->clap.width.d = clap->cleanApertureWidthD;
2366 summary->clap.height.n = clap->cleanApertureHeightN;
2367 summary->clap.height.d = clap->cleanApertureHeightD;
2368 summary->clap.horizontal_offset.n = clap->horizOffN;
2369 summary->clap.horizontal_offset.d = clap->horizOffD;
2370 summary->clap.vertical_offset.n = clap->vertOffN;
2371 summary->clap.vertical_offset.d = clap->vertOffD;
2372 continue;
2374 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_PASP ) )
2376 isom_pasp_t *pasp = (isom_pasp_t *)box;
2377 summary->par_h = pasp->hSpacing;
2378 summary->par_v = pasp->vSpacing;
2379 continue;
2381 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_COLR )
2382 || lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_COLR ) )
2384 isom_colr_t *colr = (isom_colr_t *)box;
2385 summary->color.primaries_index = colr->primaries_index;
2386 summary->color.transfer_index = colr->transfer_function_index;
2387 summary->color.matrix_index = colr->matrix_index;
2388 summary->color.full_range = colr->full_range_flag;
2389 continue;
2391 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STSL ) )
2393 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE,
2394 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2395 if( !specific )
2396 goto fail;
2397 isom_stsl_t *stsl = (isom_stsl_t *)box;
2398 lsmash_isom_sample_scale_t *data = (lsmash_isom_sample_scale_t *)specific->data.structured;
2399 data->constraint_flag = stsl->constraint_flag;
2400 data->scale_method = stsl->scale_method;
2401 data->display_center_x = stsl->display_center_x;
2402 data->display_center_y = stsl->display_center_y;
2404 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_BTRT ) )
2406 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE,
2407 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2408 if( !specific )
2409 goto fail;
2410 isom_btrt_t *btrt = (isom_btrt_t *)box;
2411 lsmash_h264_bitrate_t *data = (lsmash_h264_bitrate_t *)specific->data.structured;
2412 data->bufferSizeDB = btrt->bufferSizeDB;
2413 data->maxBitrate = btrt->maxBitrate;
2414 data->avgBitrate = btrt->avgBitrate;
2416 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_FIEL ) )
2418 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO,
2419 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2420 if( !specific )
2421 goto fail;
2422 isom_fiel_t *fiel = (isom_fiel_t *)box;
2423 lsmash_qt_field_info_t *data = (lsmash_qt_field_info_t *)specific->data.structured;
2424 data->fields = fiel->fields;
2425 data->detail = fiel->detail;
2427 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_CSPC ) )
2429 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT,
2430 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2431 if( !specific )
2432 goto fail;
2433 isom_cspc_t *cspc = (isom_cspc_t *)box;
2434 lsmash_qt_pixel_format_t *data = (lsmash_qt_pixel_format_t *)specific->data.structured;
2435 data->pixel_format = cspc->pixel_format;
2437 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_SGBT ) )
2439 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS,
2440 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2441 if( !specific )
2442 goto fail;
2443 isom_sgbt_t *sgbt = (isom_sgbt_t *)box;
2444 lsmash_qt_significant_bits_t *data = (lsmash_qt_significant_bits_t *)specific->data.structured;
2445 data->significantBits = sgbt->significantBits;
2447 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_GLBL ) )
2449 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER,
2450 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2451 if( !specific )
2452 goto fail;
2453 isom_glbl_t *glbl = (isom_glbl_t *)box;
2454 lsmash_codec_global_header_t *data = (lsmash_codec_global_header_t *)specific->data.structured;
2455 data->header_size = glbl->header_size;
2456 data->header_data = lsmash_memdup( glbl->header_data, glbl->header_size );
2457 if( !data->header_data )
2459 lsmash_destroy_codec_specific_data( specific );
2460 goto fail;
2463 else
2464 continue;
2465 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2467 lsmash_destroy_codec_specific_data( specific );
2468 goto fail;
2471 else
2473 if( box->size < ISOM_BASEBOX_COMMON_SIZE )
2474 continue;
2475 uint8_t *data = box->binary;
2476 lsmash_compact_box_type_t fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
2477 lsmash_codec_specific_data_type type = isom_get_codec_specific_data_type( fourcc );
2478 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2479 if( !specific )
2480 goto fail;
2481 specific->size = box->size;
2482 specific->data.unstructured = lsmash_memdup( box->binary, box->size );
2483 if( !specific->data.unstructured
2484 || lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2486 lsmash_destroy_codec_specific_data( specific );
2487 goto fail;
2491 return (lsmash_summary_t *)summary;
2492 fail:
2493 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
2494 return NULL;
2497 static int isom_append_structured_mp4sys_decoder_config( lsmash_codec_specific_list_t *opaque, isom_esds_t *esds )
2499 lsmash_bs_t *bs = lsmash_bs_create();
2500 if( !bs )
2501 return LSMASH_ERR_MEMORY_ALLOC;
2502 /* Put box size, type, version and flags fields. */
2503 lsmash_bs_put_be32( bs, 0 );
2504 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_ESDS.fourcc );
2505 lsmash_bs_put_be32( bs, 0 );
2506 /* Put ES Descriptor. */
2507 mp4sys_update_descriptor_size( esds->ES );
2508 mp4sys_write_descriptor( bs, esds->ES );
2509 /* Export ES Descriptor Box as binary string. */
2510 uint32_t esds_size;
2511 uint8_t *esds_data = lsmash_bs_export_data( bs, &esds_size );
2512 lsmash_bs_cleanup( bs );
2513 if( !esds_data )
2514 return LSMASH_ERR_NAMELESS;
2515 /* Update box size. */
2516 LSMASH_SET_BE32( esds_data, esds_size );
2517 lsmash_codec_specific_data_type type = isom_get_codec_specific_data_type( ISOM_BOX_TYPE_ESDS.fourcc );
2518 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2519 if( !specific )
2521 lsmash_free( esds_data );
2522 return LSMASH_ERR_NAMELESS;
2524 specific->data.unstructured = esds_data;
2525 specific->size = esds_size;
2526 /* Convert unstructured CODEC specific data format into structured, and append it to the opaque list. */
2527 lsmash_codec_specific_t *conv = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2528 lsmash_destroy_codec_specific_data( specific );
2529 if( !conv )
2530 return LSMASH_ERR_NAMELESS;
2531 if( lsmash_add_entry( &opaque->list, conv ) < 0 )
2533 lsmash_destroy_codec_specific_data( conv );
2534 return LSMASH_ERR_MEMORY_ALLOC;
2536 return 0;
2539 lsmash_summary_t *isom_create_audio_summary_from_description( isom_sample_entry_t *sample_entry )
2541 if( !sample_entry || !sample_entry->file || !sample_entry->parent )
2542 return NULL;
2543 isom_audio_entry_t *audio = (isom_audio_entry_t *)sample_entry;
2544 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO );
2545 if( !summary )
2546 return NULL;
2547 summary->sample_type = audio->type;
2548 summary->data_ref_index = audio->data_reference_index;
2549 summary->sample_size = audio->samplesize;
2550 summary->channels = audio->channelcount;
2551 summary->frequency = audio->samplerate >> 16;
2552 if( ((isom_stsd_t *)audio->parent)->version == 0
2553 && audio->file->qt_compatible
2554 && isom_is_qt_audio( audio->type ) )
2556 if( audio->version == 0 )
2557 isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio, &summary->samples_in_frame, &summary->bytes_per_frame, &summary->sample_size );
2558 else if( audio->version == 1 )
2560 summary->channels = audio->bytesPerPacket ? audio->bytesPerFrame / audio->bytesPerPacket : audio->channelcount;
2561 summary->sample_size = audio->bytesPerPacket * 8;
2562 summary->samples_in_frame = audio->samplesPerPacket;
2563 summary->bytes_per_frame = audio->bytesPerFrame;
2565 else if( audio->version == 2 )
2567 summary->frequency = (union {uint64_t i; double d;}){audio->audioSampleRate}.d;
2568 summary->channels = audio->numAudioChannels;
2569 summary->sample_size = audio->constBitsPerChannel;
2570 summary->samples_in_frame = audio->constLPCMFramesPerAudioPacket;
2571 summary->bytes_per_frame = audio->constBytesPerAudioPacket;
2573 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON,
2574 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2575 if( !specific )
2576 goto fail;
2577 lsmash_qt_audio_common_t *common = (lsmash_qt_audio_common_t *)specific->data.structured;
2578 common->revision_level = audio->revision_level;
2579 common->vendor = audio->vendor;
2580 common->compression_ID = audio->compression_ID;
2581 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2583 lsmash_destroy_codec_specific_data( specific );
2584 goto fail;
2586 if( isom_is_lpcm_audio( audio ) )
2588 specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS,
2589 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2590 if( !specific )
2591 goto fail;
2592 lsmash_qt_audio_format_specific_flags_t *data = (lsmash_qt_audio_format_specific_flags_t *)specific->data.structured;
2593 if( audio->version == 2 )
2594 data->format_flags = audio->formatSpecificFlags;
2595 else
2597 data->format_flags = QT_LPCM_FORMAT_FLAG_BIG_ENDIAN | QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER;
2598 /* Here, don't override samplesize.
2599 * We should trust samplesize field in the description for misused CODEC indentifier. */
2600 lsmash_codec_type_t audio_type = audio->type;
2601 if( lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_TWOS_AUDIO )
2602 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_NONE_AUDIO )
2603 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_NOT_SPECIFIED ) )
2605 if( summary->sample_size <= 8 )
2606 data->format_flags &= ~(QT_LPCM_FORMAT_FLAG_BIG_ENDIAN | QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER);
2608 else
2610 if( lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_FL32_AUDIO )
2611 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_FL64_AUDIO ) )
2613 data->format_flags &= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER;
2614 data->format_flags |= QT_LPCM_FORMAT_FLAG_FLOAT;
2616 else if( lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_23NI_AUDIO )
2617 || lsmash_check_codec_type_identical( audio_type, QT_CODEC_TYPE_SOWT_AUDIO ) )
2618 data->format_flags &= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
2621 isom_wave_t *wave = (isom_wave_t *)isom_get_extension_box_format( &audio->extensions, QT_BOX_TYPE_WAVE );
2622 if( wave && wave->enda )
2624 if( wave->enda->littleEndian )
2625 data->format_flags &= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
2626 else
2627 data->format_flags |= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN;
2629 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2631 lsmash_destroy_codec_specific_data( specific );
2632 goto fail;
2635 else if( audio->version == 2
2636 && (lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_ALAC_AUDIO )
2637 || lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAC_AUDIO )) )
2638 switch( audio->formatSpecificFlags )
2640 case QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA :
2641 summary->sample_size = 16;
2642 break;
2643 case QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA :
2644 summary->sample_size = 20;
2645 break;
2646 case QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA :
2647 summary->sample_size = 24;
2648 break;
2649 case QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA :
2650 summary->sample_size = 32;
2651 break;
2652 default :
2653 break;
2656 else if( lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_SAMR_AUDIO ) )
2658 summary->channels = 1;
2659 summary->frequency = 8000;
2661 else if( lsmash_check_codec_type_identical( audio->type, ISOM_CODEC_TYPE_SAWB_AUDIO ) )
2663 summary->channels = 1;
2664 summary->frequency = 16000;
2666 uint32_t actual_sampling_rate = 0;
2667 for( lsmash_entry_t *entry = audio->extensions.head; entry; entry = entry->next )
2669 isom_box_t *box = (isom_box_t *)entry->data;
2670 if( !box )
2671 continue;
2672 if( !(box->manager & LSMASH_BINARY_CODED_BOX) )
2674 if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_CHAN ) )
2676 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT,
2677 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2678 if( !specific )
2679 goto fail;
2680 isom_chan_t *chan = (isom_chan_t *)box;
2681 lsmash_qt_audio_channel_layout_t *data = (lsmash_qt_audio_channel_layout_t *)specific->data.structured;
2682 data->channelLayoutTag = chan->channelLayoutTag;
2683 data->channelBitmap = chan->channelBitmap;
2684 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2686 lsmash_destroy_codec_specific_data( specific );
2687 goto fail;
2690 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_ESDS )
2691 || lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ESDS ) )
2693 isom_esds_t *esds = (isom_esds_t *)box;
2694 if( mp4sys_setup_summary_from_DecoderSpecificInfo( summary, esds->ES ) < 0
2695 || isom_append_structured_mp4sys_decoder_config( summary->opaque, esds ) < 0 )
2696 goto fail;
2698 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_SRAT ) )
2700 isom_srat_t *srat = (isom_srat_t *)box;
2701 actual_sampling_rate = srat->sampling_rate;
2703 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_WAVE ) )
2705 /* Don't append 'wave' extension itself to the opaque CODEC specific info list. */
2706 isom_wave_t *wave = (isom_wave_t *)box;
2707 lsmash_bs_t *bs = lsmash_bs_create();
2708 if( !bs )
2709 goto fail;
2710 for( lsmash_entry_t *wave_entry = wave->extensions.head; wave_entry; wave_entry = wave_entry->next )
2712 isom_box_t *wave_ext = (isom_box_t *)wave_entry->data;
2713 if( !wave_ext )
2714 continue;
2715 lsmash_box_type_t box_type = LSMASH_BOX_TYPE_INITIALIZER;
2716 if( !(wave_ext->manager & LSMASH_BINARY_CODED_BOX) )
2718 box_type = wave_ext->type;
2719 if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ENDA ) )
2721 isom_enda_t *enda = (isom_enda_t *)wave_ext;
2722 isom_bs_put_box_common( bs, enda );
2723 lsmash_bs_put_be16( bs, enda->littleEndian );
2725 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_MP4A ) )
2727 isom_mp4a_t *mp4a = (isom_mp4a_t *)wave_ext;
2728 isom_bs_put_box_common( bs, mp4a );
2729 lsmash_bs_put_be32( bs, mp4a->unknown );
2731 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_CHAN ) )
2733 isom_chan_t *chan = (isom_chan_t *)wave_ext;
2734 isom_bs_put_box_common( bs, chan );
2735 lsmash_bs_put_be32( bs, chan->channelLayoutTag );
2736 lsmash_bs_put_be32( bs, chan->channelBitmap );
2737 lsmash_bs_put_be32( bs, chan->numberChannelDescriptions );
2738 if( chan->channelDescriptions )
2739 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
2741 isom_channel_description_t *channelDescriptions = (isom_channel_description_t *)(&chan->channelDescriptions[i]);
2742 lsmash_bs_put_be32( bs, channelDescriptions->channelLabel );
2743 lsmash_bs_put_be32( bs, channelDescriptions->channelFlags );
2744 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[0] );
2745 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[1] );
2746 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[2] );
2749 else if( lsmash_check_box_type_identical( box_type, QT_BOX_TYPE_ESDS ) )
2751 isom_esds_t *esds = (isom_esds_t *)wave_ext;
2752 if( !esds
2753 || mp4sys_setup_summary_from_DecoderSpecificInfo( summary, esds->ES ) < 0
2754 || isom_append_structured_mp4sys_decoder_config( summary->opaque, esds ) < 0 )
2756 lsmash_bs_cleanup( bs );
2757 goto fail;
2759 continue;
2761 else
2762 /* Skip Format Box and Terminator Box since they are mandatory and fixed structure. */
2763 continue;
2765 else
2767 if( wave_ext->size < ISOM_BASEBOX_COMMON_SIZE )
2768 continue;
2769 uint8_t *data = wave_ext->binary;
2770 box_type.fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
2771 lsmash_bs_put_bytes( bs, wave_ext->size, wave_ext->binary );
2773 /* Export as binary string. */
2774 uint32_t box_size;
2775 uint8_t *box_data = lsmash_bs_export_data( bs, &box_size );
2776 lsmash_bs_empty( bs );
2777 if( !box_data )
2779 lsmash_bs_cleanup( bs );
2780 goto fail;
2782 /* Append as an unstructured CODEC specific info. */
2783 lsmash_codec_specific_data_type type;
2784 if( box_type.fourcc == QT_BOX_TYPE_CHAN.fourcc )
2785 /* Complete audio channel layout is stored as binary string.
2786 * We distinguish it from one of the outside of 'wave' extension here. */
2787 type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS;
2788 else
2790 type = isom_get_codec_specific_data_type( box_type.fourcc );
2791 if( type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN )
2792 type = LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS;
2794 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2795 if( !specific )
2797 lsmash_free( box_data );
2798 lsmash_bs_cleanup( bs );
2799 goto fail;
2801 specific->data.unstructured = box_data;
2802 specific->size = box_size;
2803 if( lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2805 lsmash_destroy_codec_specific_data( specific );
2806 lsmash_bs_cleanup( bs );
2807 goto fail;
2810 lsmash_bs_cleanup( bs );
2813 else
2815 if( box->size < ISOM_BASEBOX_COMMON_SIZE )
2816 continue;
2817 uint8_t *data = box->binary;
2818 lsmash_compact_box_type_t fourcc = LSMASH_4CC( data[4], data[5], data[6], data[7] );
2819 lsmash_codec_specific_data_type type = isom_get_codec_specific_data_type( fourcc );
2820 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( type, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2821 if( !specific )
2822 goto fail;
2823 specific->size = box->size;
2824 specific->data.unstructured = lsmash_memdup( box->binary, box->size );
2825 if( !specific->data.unstructured
2826 || lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
2828 lsmash_destroy_codec_specific_data( specific );
2829 goto fail;
2831 if( specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
2832 || specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
2833 || specific->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 )
2835 specific = lsmash_convert_codec_specific_format( specific, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
2836 if( !specific )
2837 goto fail;
2838 switch( specific->type )
2840 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS :
2842 lsmash_dts_specific_parameters_t *param = (lsmash_dts_specific_parameters_t *)specific->data.structured;
2843 summary->sample_size = param->pcmSampleDepth;
2844 summary->samples_in_frame = (summary->frequency * (512 << param->FrameDuration)) / param->DTSSamplingFrequency;
2845 break;
2847 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3 :
2849 lsmash_ac3_specific_parameters_t *param = (lsmash_ac3_specific_parameters_t *)specific->data.structured;
2850 summary->frequency = ac3_get_sample_rate( param );
2851 summary->channels = ac3_get_channel_count( param );
2852 summary->samples_in_frame = 1536;
2853 break;
2855 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3 :
2857 lsmash_eac3_specific_parameters_t *param = (lsmash_eac3_specific_parameters_t *)specific->data.structured;
2858 eac3_update_sample_rate( &summary->frequency, param, NULL );
2859 eac3_update_channel_count( &summary->channels, param );
2860 summary->samples_in_frame = 1536;
2861 break;
2863 default :
2864 break;
2866 lsmash_destroy_codec_specific_data( specific );
2870 /* Set the actual sampling rate. */
2871 if( actual_sampling_rate )
2872 summary->frequency = actual_sampling_rate;
2873 return (lsmash_summary_t *)summary;
2874 fail:
2875 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
2876 return NULL;
2879 lsmash_codec_specific_t *lsmash_get_codec_specific_data( lsmash_summary_t *summary, uint32_t extension_number )
2881 if( !summary || !summary->opaque )
2882 return NULL;
2883 uint32_t i = 0;
2884 for( lsmash_entry_t *entry = summary->opaque->list.head; entry; entry = entry->next )
2885 if( ++i == extension_number )
2886 return (lsmash_codec_specific_t *)entry->data;
2887 return NULL;
2890 uint32_t lsmash_count_codec_specific_data( lsmash_summary_t *summary )
2892 if( !summary || !summary->opaque )
2893 return 0;
2894 return summary->opaque->list.entry_count;
2897 int isom_compare_opaque_extensions( lsmash_summary_t *a, lsmash_summary_t *b )
2899 assert( a && b );
2900 uint32_t in_number_of_extensions = lsmash_count_codec_specific_data( a );
2901 uint32_t out_number_of_extensions = lsmash_count_codec_specific_data( b );
2902 if( out_number_of_extensions != in_number_of_extensions )
2903 return 1;
2904 uint32_t active_number_of_extensions = in_number_of_extensions;
2905 uint32_t identical_count = 0;
2906 for( uint32_t j = 1; j <= in_number_of_extensions; j++ )
2908 lsmash_codec_specific_t *in_cs_orig = lsmash_get_codec_specific_data( a, j );
2909 lsmash_codec_specific_t *in_cs;
2910 lsmash_codec_specific_format compare_format = LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED;
2911 if( in_cs_orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2913 if( in_cs_orig->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
2914 || in_cs_orig->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
2915 || in_cs_orig->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS )
2917 compare_format = LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED;
2918 in_cs = in_cs_orig;
2920 else
2922 in_cs = lsmash_convert_codec_specific_format( in_cs_orig, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2923 if( !in_cs )
2925 /* We don't support the format converter of this data type. */
2926 --active_number_of_extensions;
2927 continue;
2931 else
2932 in_cs = in_cs_orig;
2933 for( uint32_t k = 1; k <= out_number_of_extensions; k++ )
2935 lsmash_codec_specific_t *out_cs_orig = lsmash_get_codec_specific_data( b, k );
2936 if( out_cs_orig->type != in_cs_orig->type )
2937 continue;
2938 lsmash_codec_specific_t *out_cs;
2939 if( out_cs_orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2941 if( compare_format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
2942 out_cs = out_cs_orig;
2943 else
2945 out_cs = lsmash_convert_codec_specific_format( out_cs_orig, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
2946 if( !out_cs )
2947 continue;
2950 else
2951 out_cs = out_cs_orig;
2952 int identical;
2953 if( compare_format == LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED )
2954 identical = out_cs->size == in_cs->size && !memcmp( out_cs->data.unstructured, in_cs->data.unstructured, in_cs->size );
2955 else
2957 if( in_cs->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON )
2959 lsmash_qt_video_common_t *in_data = (lsmash_qt_video_common_t *)in_cs->data.structured;
2960 lsmash_qt_video_common_t *out_data = (lsmash_qt_video_common_t *)out_cs->data.structured;
2961 identical = in_data->revision_level == out_data->revision_level
2962 && in_data->vendor == out_data->vendor
2963 && in_data->temporalQuality == out_data->temporalQuality
2964 && in_data->spatialQuality == out_data->spatialQuality
2965 && in_data->horizontal_resolution == out_data->horizontal_resolution
2966 && in_data->vertical_resolution == out_data->vertical_resolution
2967 && in_data->dataSize == out_data->dataSize
2968 && in_data->frame_count == out_data->frame_count
2969 && in_data->color_table_ID == out_data->color_table_ID;
2971 else if( in_cs->type == LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON )
2973 lsmash_qt_audio_common_t *in_data = (lsmash_qt_audio_common_t *)in_cs->data.structured;
2974 lsmash_qt_audio_common_t *out_data = (lsmash_qt_audio_common_t *)out_cs->data.structured;
2975 identical = in_data->revision_level == out_data->revision_level
2976 && in_data->vendor == out_data->vendor
2977 && in_data->compression_ID == out_data->compression_ID;
2979 else
2981 lsmash_qt_audio_format_specific_flags_t *in_data = (lsmash_qt_audio_format_specific_flags_t *)in_cs->data.structured;
2982 lsmash_qt_audio_format_specific_flags_t *out_data = (lsmash_qt_audio_format_specific_flags_t *)out_cs->data.structured;
2983 identical = (in_data->format_flags == out_data->format_flags);
2986 if( out_cs != out_cs_orig )
2987 lsmash_destroy_codec_specific_data( out_cs );
2988 if( identical )
2990 ++identical_count;
2991 break;
2994 if( in_cs != in_cs_orig )
2995 lsmash_destroy_codec_specific_data( in_cs );
2997 return (identical_count != active_number_of_extensions);
3000 int isom_get_implicit_qt_fixed_comp_audio_sample_quants
3002 isom_audio_entry_t *audio,
3003 uint32_t *samples_per_packet,
3004 uint32_t *constant_bytes_per_frame,
3005 uint32_t *sample_size
3008 if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC3_AUDIO ) )
3010 *samples_per_packet = 6;
3011 *constant_bytes_per_frame = 2 * audio->channelcount;
3012 *sample_size = 8;
3014 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_MAC6_AUDIO ) )
3016 *samples_per_packet = 6;
3017 *constant_bytes_per_frame = audio->channelcount;
3018 *sample_size = 8;
3020 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ADPCM17_AUDIO ) )
3022 *samples_per_packet = 64;
3023 *constant_bytes_per_frame = 34 * audio->channelcount;
3024 *sample_size = 16;
3026 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_AGSM_AUDIO ) )
3028 *samples_per_packet = 160;
3029 *constant_bytes_per_frame = 33;
3030 *sample_size = 16;
3032 else if( lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ALAW_AUDIO )
3033 || lsmash_check_codec_type_identical( audio->type, QT_CODEC_TYPE_ULAW_AUDIO ) )
3035 *samples_per_packet = 1;
3036 *constant_bytes_per_frame = audio->channelcount;
3037 *sample_size = 16;
3039 else
3040 return 0;
3041 return 1;
3044 isom_bitrate_updater_t isom_get_bitrate_updater
3046 isom_sample_entry_t *sample_entry
3049 #define RETURN_BITRATE_UPDATER( func_name ) \
3051 extern int func_name( isom_stbl_t *, isom_mdhd_t *, uint32_t sample_description_index ); \
3052 return func_name; \
3054 lsmash_codec_type_t sample_type = sample_entry->type;
3055 if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC1_VIDEO )
3056 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC2_VIDEO )
3057 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC3_VIDEO )
3058 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_AVC4_VIDEO )
3059 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HVC1_VIDEO )
3060 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_HEV1_VIDEO ) )
3061 RETURN_BITRATE_UPDATER( nalu_update_bitrate )
3062 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4V_VIDEO ) )
3063 RETURN_BITRATE_UPDATER( mp4v_update_bitrate )
3064 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4A_AUDIO )
3065 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_MP4A_AUDIO ) )
3066 RETURN_BITRATE_UPDATER( mp4a_update_bitrate )
3067 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_ALAC_AUDIO )
3068 || lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_ALAC_AUDIO ) )
3069 RETURN_BITRATE_UPDATER( alac_update_bitrate )
3070 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSC_AUDIO )
3071 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSE_AUDIO )
3072 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSH_AUDIO )
3073 || lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_DTSL_AUDIO ) )
3074 RETURN_BITRATE_UPDATER( dts_update_bitrate )
3075 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_EC_3_AUDIO ) )
3076 RETURN_BITRATE_UPDATER( eac3_update_bitrate )
3077 else if( isom_is_waveform_audio( sample_type ) )
3078 RETURN_BITRATE_UPDATER( waveform_audio_update_bitrate )
3079 else
3080 return NULL;
3081 #undef RETURN_BITRATE_UPDATER