1 /*****************************************************************************
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 */
33 #include "description.h"
35 typedef isom_wave_t lsmash_qt_decoder_parameters_t
;
37 static void global_destruct_specific_data( void *data
)
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
};
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
};
189 static void isom_destruct_nothing( void *data
)
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
;
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
;
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
;
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
;
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
;
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
;
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
;
231 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
:
232 specific
->size
= sizeof(lsmash_alac_specific_parameters_t
);
233 specific
->destruct
= lsmash_free
;
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
;
239 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
:
240 specific
->size
= sizeof(lsmash_h264_bitrate_t
);
241 specific
->destruct
= lsmash_free
;
243 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
:
244 specific
->size
= sizeof(lsmash_qt_video_common_t
);
245 specific
->destruct
= lsmash_free
;
247 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
:
248 specific
->size
= sizeof(lsmash_qt_audio_common_t
);
249 specific
->destruct
= lsmash_free
;
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
;
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
;
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
;
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
;
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
;
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
;
277 specific
->destruct
= isom_destruct_nothing
;
280 specific
->data
.structured
= lsmash_malloc_zero( specific
->size
);
281 if( !specific
->data
.structured
)
284 specific
->destruct
= NULL
;
285 return LSMASH_ERR_MEMORY_ALLOC
;
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
);
304 specific
->data
.unstructured
= NULL
;
306 specific
->destruct
= (lsmash_codec_specific_destructor_t
)lsmash_free
;
311 void lsmash_destroy_codec_specific_data( lsmash_codec_specific_t
*specific
)
315 if( specific
->destruct
)
317 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
319 if( specific
->data
.structured
)
320 specific
->destruct( specific
->data
.structured
);
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
) );
336 if( isom_initialize_codec_specific_data( specific
, type
, format
) < 0 )
338 lsmash_destroy_codec_specific_data( 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
;
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
;
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
;
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
;
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
;
377 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
:
378 *(lsmash_h264_bitrate_t
*)dst_data
= *(lsmash_h264_bitrate_t
*)src_data
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
411 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL
:
412 *(lsmash_qt_gamma_t
*)dst_data
= *(lsmash_qt_gamma_t
*)src_data
;
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
;
418 return LSMASH_ERR_NAMELESS
;
422 lsmash_codec_specific_t
*isom_duplicate_codec_specific_data( lsmash_codec_specific_t
*specific
)
426 lsmash_codec_specific_t
*dup
= lsmash_create_codec_specific_data( specific
->type
, specific
->format
);
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
);
439 dup
->data
.unstructured
= lsmash_memdup( specific
->data
.unstructured
, specific
->size
);
440 if( !dup
->data
.unstructured
)
442 lsmash_destroy_codec_specific_data( dup
);
446 dup
->size
= specific
->size
;
450 static size_t isom_description_read_box_common( uint8_t **p_data
, uint64_t *size
, lsmash_box_type_t
*type
)
452 uint8_t *orig
= *p_data
;
453 uint8_t *data
= *p_data
;
454 *size
= LSMASH_GET_BE32( &data
[0] );
455 type
->fourcc
= LSMASH_GET_BE32( &data
[4] );
456 data
+= ISOM_BASEBOX_COMMON_SIZE
;
459 *size
= LSMASH_GET_BE64( data
);
463 if( type
->fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
465 type
->user
.fourcc
= LSMASH_GET_BE32( &data
[0] );
466 memcpy( type
->user
.id
, &data
[4], 12 );
471 uint8_t *isom_get_child_box_position( uint8_t *parent_data
, uint32_t parent_size
, lsmash_box_type_t child_type
, uint32_t *child_size
)
473 if( !parent_data
|| !child_size
|| parent_size
< ISOM_BASEBOX_COMMON_SIZE
)
475 uint8_t *data
= parent_data
;
477 lsmash_box_type_t type
;
478 uint32_t offset
= isom_description_read_box_common( &data
, &size
, &type
);
479 if( size
!= parent_size
)
481 uint8_t *end
= parent_data
+ parent_size
;
482 for( uint8_t *pos
= data
; pos
+ ISOM_BASEBOX_COMMON_SIZE
<= end
; )
484 offset
= isom_description_read_box_common( &pos
, &size
, &type
);
485 if( lsmash_check_box_type_identical( type
, child_type
) )
490 pos
+= size
- offset
; /* Move to the next box. */
495 static int isom_construct_global_specific_header( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
497 if( src
->size
< ISOM_BASEBOX_COMMON_SIZE
)
498 return LSMASH_ERR_INVALID_DATA
;
499 lsmash_codec_global_header_t
*global
= (lsmash_codec_global_header_t
*)dst
->data
.structured
;
500 uint8_t *data
= src
->data
.unstructured
;
501 uint64_t size
= LSMASH_GET_BE32( data
);
502 data
+= ISOM_BASEBOX_COMMON_SIZE
;
505 size
= LSMASH_GET_BE64( data
);
508 if( size
!= src
->size
)
509 return LSMASH_ERR_INVALID_DATA
;
510 global
->header_size
= size
- ISOM_BASEBOX_COMMON_SIZE
;
511 if( data
!= src
->data
.unstructured
+ ISOM_BASEBOX_COMMON_SIZE
)
512 global
->header_size
-= 8; /* largesize */
513 if( global
->header_size
)
515 global
->header_data
= lsmash_memdup( data
, global
->header_size
);
516 if( !global
->header_data
)
517 return LSMASH_ERR_MEMORY_ALLOC
;
522 static int isom_construct_audio_channel_layout( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
524 if( src
->size
< ISOM_FULLBOX_COMMON_SIZE
+ 12 )
525 return LSMASH_ERR_INVALID_DATA
;
526 lsmash_qt_audio_channel_layout_t
*layout
= (lsmash_qt_audio_channel_layout_t
*)dst
->data
.structured
;
527 uint8_t *data
= src
->data
.unstructured
;
528 uint64_t size
= LSMASH_GET_BE32( data
);
529 data
+= ISOM_FULLBOX_COMMON_SIZE
;
532 size
= LSMASH_GET_BE64( data
);
535 if( size
!= src
->size
)
536 return LSMASH_ERR_INVALID_DATA
;
537 layout
->channelLayoutTag
= LSMASH_GET_BE32( &data
[0] );
538 layout
->channelBitmap
= LSMASH_GET_BE32( &data
[4] );
543 static int codec_construct_qt_audio_decompression_info( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
545 if( src
->size
< ISOM_BASEBOX_COMMON_SIZE
)
546 return LSMASH_ERR_INVALID_DATA
;
547 uint8_t *data
= src
->data
.unstructured
;
550 uint32_t offset
= isom_description_read_box_common( &data
, &size
, &type
);
551 if( size
!= src
->size
)
552 return LSMASH_ERR_INVALID_DATA
;
553 uint8_t *end
= src
->data
.unstructured
+ src
->size
;
554 isom_wave_t
*wave
= lsmash_malloc_zero( sizeof(isom_wave_t
) );
556 return LSMASH_ERR_MEMORY_ALLOC
;
557 wave
->type
= QT_BOX_TYPE_WAVE
;
558 for( uint8_t *pos
= data
; pos
+ ISOM_BASEBOX_COMMON_SIZE
<= end
; )
560 offset
= isom_description_read_box_common( &pos
, &size
, &type
);
563 case QT_BOX_TYPE_FRMA
:
566 return LSMASH_ERR_INVALID_DATA
;
567 isom_frma_t
*frma
= isom_add_frma( wave
);
569 return LSMASH_ERR_NAMELESS
;
570 frma
->data_format
= LSMASH_GET_BE32( pos
);
574 case QT_BOX_TYPE_ENDA
:
577 return LSMASH_ERR_INVALID_DATA
;
578 isom_enda_t
*enda
= isom_add_enda( wave
);
580 return LSMASH_ERR_NAMELESS
;
581 enda
->littleEndian
= LSMASH_GET_BE16( pos
);
584 case QT_BOX_TYPE_MP4A
:
587 return LSMASH_ERR_INVALID_DATA
;
588 isom_mp4a_t
*mp4a
= isom_add_mp4a( wave
);
590 return LSMASH_ERR_NAMELESS
;
591 mp4a
->unknown
= LSMASH_GET_BE32( pos
);
595 case QT_BOX_TYPE_TERMINATOR
:
597 if( !isom_add_terminator( wave
) )
598 return LSMASH_ERR_NAMELESS
;
603 isom_unknown_box_t
*box
= lsmash_malloc_zero( sizeof(isom_unknown_box_t
) );
605 return LSMASH_ERR_MEMORY_ALLOC
;
606 isom_init_box_common( box
, wave
, type
, isom_remove_unknown_box
);
607 box
->unknown_size
= size
- offset
;
608 box
->unknown_field
= lsmash_memdup( pos
, box
->unknown_size
);
609 if( !box
->unknown_field
)
612 return LSMASH_ERR_MEMORY_ALLOC
;
614 if( lsmash_add_entry( &wave
->extensions
, box
) < 0 )
616 isom_remove_unknown_box( box
);
617 return LSMASH_ERR_MEMORY_ALLOC
;
619 pos
+= box
->unknown_size
;
628 /* structured <-> unstructured conversion might be irreversible by CODEC
629 * since structured formats we defined don't always have all contents included in unstructured data. */
630 lsmash_codec_specific_t
*lsmash_convert_codec_specific_format( lsmash_codec_specific_t
*specific
, lsmash_codec_specific_format format
)
632 if( !specific
|| format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSPECIFIED
)
634 if( format
== specific
->format
)
635 return isom_duplicate_codec_specific_data( specific
);
636 lsmash_codec_specific_t
*dst
= lsmash_create_codec_specific_data( specific
->type
, format
);
639 if( format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
640 /* structured -> unstructured */
641 switch( specific
->type
)
643 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
:
644 dst
->data
.unstructured
= lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t
*)specific
->data
.structured
, &dst
->size
);
645 if( !dst
->data
.unstructured
)
648 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
:
649 dst
->data
.unstructured
= lsmash_create_h264_specific_info( (lsmash_h264_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
650 if( !dst
->data
.unstructured
)
653 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
:
654 dst
->data
.unstructured
= lsmash_create_hevc_specific_info( (lsmash_hevc_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
655 if( !dst
->data
.unstructured
)
658 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
:
659 dst
->data
.unstructured
= lsmash_create_vc1_specific_info( (lsmash_vc1_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
660 if( !dst
->data
.unstructured
)
663 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
:
664 dst
->data
.unstructured
= lsmash_create_ac3_specific_info( (lsmash_ac3_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
665 if( !dst
->data
.unstructured
)
668 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
:
669 dst
->data
.unstructured
= lsmash_create_eac3_specific_info( (lsmash_eac3_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
670 if( !dst
->data
.unstructured
)
673 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
:
674 dst
->data
.unstructured
= lsmash_create_dts_specific_info( (lsmash_dts_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
675 if( !dst
->data
.unstructured
)
678 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
:
679 dst
->data
.unstructured
= lsmash_create_alac_specific_info( (lsmash_alac_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
680 if( !dst
->data
.unstructured
)
683 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
685 lsmash_bs_t
*bs
= lsmash_bs_create();
688 lsmash_codec_global_header_t
*global
= specific
->data
.structured
;
689 lsmash_bs_put_be32( bs
, ISOM_BASEBOX_COMMON_SIZE
+ global
->header_size
);
690 lsmash_bs_put_be32( bs
, QT_BOX_TYPE_GLBL
.fourcc
);
691 lsmash_bs_put_bytes( bs
, global
->header_size
, global
->header_data
);
692 dst
->data
.unstructured
= lsmash_bs_export_data( bs
, &dst
->size
);
693 lsmash_bs_cleanup( bs
);
694 if( !dst
->data
.unstructured
|| dst
->size
!= (ISOM_BASEBOX_COMMON_SIZE
+ global
->header_size
) )
701 else if( format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
703 /* unstructured -> structured */
704 extern int mp4sys_construct_decoder_config( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
705 extern int h264_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
706 extern int hevc_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
707 extern int vc1_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
708 extern int ac3_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
709 extern int eac3_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
710 extern int dts_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
711 extern int alac_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
714 lsmash_codec_specific_data_type data_type
;
715 int (*constructor
)( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
716 } codec_specific_format_constructor_table
[] =
718 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
, mp4sys_construct_decoder_config
},
719 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
, h264_construct_specific_parameters
},
720 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
, hevc_construct_specific_parameters
},
721 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
, vc1_construct_specific_parameters
},
722 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
, ac3_construct_specific_parameters
},
723 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
, eac3_construct_specific_parameters
},
724 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
, dts_construct_specific_parameters
},
725 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
, alac_construct_specific_parameters
},
726 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
, isom_construct_global_specific_header
},
727 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
, isom_construct_audio_channel_layout
},
728 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
, NULL
}
730 int (*constructor
)( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* ) = NULL
;
731 for( int i
= 0; codec_specific_format_constructor_table
[i
].constructor
; i
++ )
732 if( specific
->type
== codec_specific_format_constructor_table
[i
].data_type
)
734 constructor
= codec_specific_format_constructor_table
[i
].constructor
;
737 if( constructor
&& !constructor( dst
, specific
) )
741 lsmash_destroy_codec_specific_data( dst
);
745 static inline void isom_set_default_compressorname( char *compressorname
, lsmash_codec_type_t sample_type
)
747 static struct compressorname_table_tag
749 lsmash_codec_type_t type
;
751 } compressorname_table
[33] = { { LSMASH_CODEC_TYPE_INITIALIZER
, { '\0' } } };
752 if( compressorname_table
[0].name
[0] == '\0' )
755 #define ADD_COMPRESSORNAME_TABLE( type, name ) compressorname_table[i++] = (struct compressorname_table_tag){ type, name }
756 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC1_VIDEO
, "\012AVC Coding" );
757 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC2_VIDEO
, "\012AVC Coding" );
758 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC3_VIDEO
, "\012AVC Coding" );
759 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC4_VIDEO
, "\012AVC Coding" );
760 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVCP_VIDEO
, "\016AVC Parameters" );
761 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HVC1_VIDEO
, "\013HEVC Coding" );
762 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HEV1_VIDEO
, "\013HEVC Coding" );
763 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_SVC1_VIDEO
, "\012SVC Coding" );
764 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC1_VIDEO
, "\012MVC Coding" );
765 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC2_VIDEO
, "\012MVC Coding" );
766 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCH_VIDEO
, "\023Apple ProRes 422 (HQ)" );
767 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCN_VIDEO
, "\023Apple ProRes 422 (SD)" );
768 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCS_VIDEO
, "\023Apple ProRes 422 (LT)" );
769 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCO_VIDEO
, "\026Apple ProRes 422 (Proxy)" );
770 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4H_VIDEO
, "\019Apple ProRes 4444" );
771 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4X_VIDEO
, "\022Apple ProRes 4444 XQ" );
772 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVPP_VIDEO
, "\014DVCPRO - PAL" );
773 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5N_VIDEO
, "\017DVCPRO50 - NTSC" );
774 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5P_VIDEO
, "\016DVCPRO50 - PAL" );
775 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH2_VIDEO
, "\019DVCPRO HD 1080p25" );
776 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH3_VIDEO
, "\019DVCPRO HD 1080p30" );
777 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH5_VIDEO
, "\019DVCPRO HD 1080i50" );
778 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH6_VIDEO
, "\019DVCPRO HD 1080i60" );
779 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHP_VIDEO
, "\018DVCPRO HD 720p60" );
780 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHQ_VIDEO
, "\018DVCPRO HD 720p50" );
781 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRA_VIDEO
, "\017Ut Video (ULRA)" );
782 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRG_VIDEO
, "\017Ut Video (ULRG)" );
783 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY0_VIDEO
, "\017Ut Video (ULY0)" );
784 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY2_VIDEO
, "\017Ut Video (ULY2)" );
785 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH0_VIDEO
, "\017Ut Video (ULH0)" );
786 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH2_VIDEO
, "\017Ut Video (ULH2)" );
787 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_UQY2_VIDEO
, "\021Ut Video Pro (UQY2)" );
788 ADD_COMPRESSORNAME_TABLE( LSMASH_CODEC_TYPE_UNSPECIFIED
, { '\0' } );
789 #undef ADD_COMPRESSORNAME_TABLE
791 for( int i
= 0; compressorname_table
[i
].name
[0] != '\0'; i
++ )
792 if( lsmash_check_codec_type_identical( sample_type
, compressorname_table
[i
].type
) )
794 strcpy( compressorname
, compressorname_table
[i
].name
);
799 lsmash_codec_specific_t
*isom_get_codec_specific( lsmash_codec_specific_list_t
*opaque
, lsmash_codec_specific_data_type type
)
801 for( lsmash_entry_t
*entry
= opaque
->list
.head
; entry
; entry
= entry
->next
)
803 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
804 if( !specific
|| specific
->type
!= type
)
811 static int isom_check_valid_summary( lsmash_summary_t
*summary
)
814 return LSMASH_ERR_NAMELESS
;
816 temp_box
.type
= summary
->sample_type
;
817 temp_box
.manager
= summary
->summary_type
== LSMASH_SUMMARY_TYPE_AUDIO
? LSMASH_AUDIO_DESCRIPTION
: 0;
818 if( isom_is_lpcm_audio( &temp_box
) )
820 if( isom_get_codec_specific( summary
->opaque
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
) )
822 return LSMASH_ERR_INVALID_DATA
;
824 if( isom_is_uncompressed_ycbcr( summary
->sample_type
) )
826 if( isom_get_codec_specific( summary
->opaque
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
) )
828 if( !lsmash_check_codec_type_identical( summary
->sample_type
, QT_CODEC_TYPE_V216_VIDEO
) )
832 return LSMASH_ERR_INVALID_DATA
;
834 lsmash_codec_type_t sample_type
= summary
->sample_type
;
835 lsmash_codec_specific_data_type required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED
;
836 if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC1_VIDEO
)
837 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC2_VIDEO
)
838 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC3_VIDEO
)
839 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC4_VIDEO
) )
840 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
;
841 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_HVC1_VIDEO
)
842 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_HEV1_VIDEO
) )
843 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
;
844 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_VC_1_VIDEO
) )
845 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
;
846 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULRA_VIDEO
)
847 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULRG_VIDEO
)
848 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULY0_VIDEO
)
849 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULY2_VIDEO
)
850 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULH0_VIDEO
)
851 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULH2_VIDEO
)
852 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_UQY2_VIDEO
) )
853 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
;
854 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_V216_VIDEO
) )
855 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
;
856 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4V_VIDEO
)
857 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4A_AUDIO
)
858 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_MP4A_AUDIO
) )
859 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
;
860 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AC_3_AUDIO
) )
861 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
;
862 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_EC_3_AUDIO
) )
863 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
;
864 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_DTSC_AUDIO
)
865 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_DTSE_AUDIO
)
866 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_DTSH_AUDIO
)
867 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_DTSL_AUDIO
) )
868 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
;
869 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_ALAC_AUDIO
)
870 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
871 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
;
872 if( required_data_type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED
)
874 return isom_get_codec_specific( summary
->opaque
, required_data_type
) ? 0 : LSMASH_ERR_INVALID_DATA
;
877 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
)
879 lsmash_box_type_t box_type
= LSMASH_BOX_TYPE_INITIALIZER
;
880 box_type
.fourcc
= fourcc
;
881 #define GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
882 else if( (codec_type.user.fourcc == 0 \
883 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
884 && box_type.fourcc == predefined_box_type.fourcc ) \
885 box_type = predefined_box_type
887 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC1_VIDEO
, ISOM_BOX_TYPE_AVCC
);
888 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC2_VIDEO
, ISOM_BOX_TYPE_AVCC
);
889 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC3_VIDEO
, ISOM_BOX_TYPE_AVCC
);
890 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC4_VIDEO
, ISOM_BOX_TYPE_AVCC
);
891 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVCP_VIDEO
, ISOM_BOX_TYPE_AVCC
);
892 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HVC1_VIDEO
, ISOM_BOX_TYPE_HVCC
);
893 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HEV1_VIDEO
, ISOM_BOX_TYPE_HVCC
);
894 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_VC_1_VIDEO
, ISOM_BOX_TYPE_DVC1
);
895 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4V_VIDEO
, ISOM_BOX_TYPE_ESDS
);
896 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, ISOM_BOX_TYPE_BTRT
);
897 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_FIEL
);
898 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_CSPC
);
899 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_SGBT
);
900 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_GAMA
);
901 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_GLBL
);
902 #undef GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE
906 int isom_setup_visual_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
, lsmash_video_summary_t
*summary
)
911 || !stsd
->parent
->parent
912 || !stsd
->parent
->parent
->parent
913 || !stsd
->parent
->parent
->parent
->parent
)
914 return LSMASH_ERR_NAMELESS
;
915 int err
= isom_check_valid_summary( (lsmash_summary_t
*)summary
);
918 isom_visual_entry_t
*visual
= isom_add_visual_description( stsd
, sample_type
);
920 return LSMASH_ERR_NAMELESS
;
921 visual
->data_reference_index
= summary
->data_ref_index
;
923 visual
->revision_level
= 0;
925 visual
->temporalQuality
= 0;
926 visual
->spatialQuality
= 0;
927 visual
->width
= (uint16_t)summary
->width
;
928 visual
->height
= (uint16_t)summary
->height
;
929 visual
->horizresolution
= 0x00480000;
930 visual
->vertresolution
= 0x00480000;
931 visual
->dataSize
= 0;
932 visual
->frame_count
= 1;
933 visual
->depth
= isom_is_qt_video( summary
->sample_type
) || isom_is_nalff( summary
->sample_type
)
934 ? summary
->depth
: 0x0018;
935 visual
->color_table_ID
= -1;
936 if( summary
->compressorname
[0] == '\0' )
937 isom_set_default_compressorname( visual
->compressorname
, sample_type
);
940 memcpy( visual
->compressorname
, summary
->compressorname
, 32 );
941 visual
->compressorname
[32] = '\0';
943 err
= LSMASH_ERR_NAMELESS
;
944 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
946 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
949 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
950 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
951 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
952 switch( specific
->type
)
954 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
:
956 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
958 lsmash_qt_video_common_t
*data
= (lsmash_qt_video_common_t
*)specific
->data
.structured
;
959 visual
->revision_level
= data
->revision_level
;
960 visual
->vendor
= data
->vendor
;
961 visual
->temporalQuality
= data
->temporalQuality
;
962 visual
->spatialQuality
= data
->spatialQuality
;
963 visual
->horizresolution
= data
->horizontal_resolution
;
964 visual
->vertresolution
= data
->vertical_resolution
;
965 visual
->dataSize
= data
->dataSize
;
966 visual
->frame_count
= data
->frame_count
;
967 visual
->color_table_ID
= data
->color_table_ID
;
968 if( data
->color_table_ID
== 0 )
970 lsmash_qt_color_table_t
*src_ct
= &data
->color_table
;
971 uint16_t element_count
= LSMASH_MIN( src_ct
->size
+ 1, 256 );
972 isom_qt_color_array_t
*dst_array
= lsmash_malloc_zero( element_count
* sizeof(isom_qt_color_array_t
) );
975 err
= LSMASH_ERR_MEMORY_ALLOC
;
978 isom_qt_color_table_t
*dst_ct
= &visual
->color_table
;
979 dst_ct
->array
= dst_array
;
980 dst_ct
->seed
= src_ct
->seed
;
981 dst_ct
->flags
= src_ct
->flags
;
982 dst_ct
->size
= src_ct
->size
;
983 for( uint16_t i
= 0; i
< element_count
; i
++ )
985 dst_array
[i
].value
= src_ct
->array
[i
].unused
;
986 dst_array
[i
].r
= src_ct
->array
[i
].r
;
987 dst_array
[i
].g
= src_ct
->array
[i
].g
;
988 dst_array
[i
].b
= src_ct
->array
[i
].b
;
993 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
:
995 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
998 lsmash_isom_sample_scale_t
*data
= (lsmash_isom_sample_scale_t
*)cs
->data
.structured
;
999 isom_stsl_t
*stsl
= isom_add_stsl( visual
);
1002 lsmash_destroy_codec_specific_data( cs
);
1005 stsl
->constraint_flag
= data
->constraint_flag
;
1006 stsl
->scale_method
= data
->scale_method
;
1007 stsl
->display_center_x
= data
->display_center_x
;
1008 stsl
->display_center_y
= data
->display_center_y
;
1009 lsmash_destroy_codec_specific_data( cs
);
1012 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
:
1014 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1017 lsmash_h264_bitrate_t
*data
= (lsmash_h264_bitrate_t
*)cs
->data
.structured
;
1018 isom_btrt_t
*btrt
= isom_add_btrt( visual
);
1021 lsmash_destroy_codec_specific_data( cs
);
1024 btrt
->bufferSizeDB
= data
->bufferSizeDB
;
1025 btrt
->maxBitrate
= data
->maxBitrate
;
1026 btrt
->avgBitrate
= data
->avgBitrate
;
1027 lsmash_destroy_codec_specific_data( cs
);
1030 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
:
1032 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1035 lsmash_qt_field_info_t
*data
= (lsmash_qt_field_info_t
*)cs
->data
.structured
;
1036 isom_fiel_t
*fiel
= isom_add_fiel( visual
);
1039 lsmash_destroy_codec_specific_data( cs
);
1042 fiel
->fields
= data
->fields
;
1043 fiel
->detail
= data
->detail
;
1044 lsmash_destroy_codec_specific_data( cs
);
1047 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
:
1049 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1052 lsmash_qt_pixel_format_t
*data
= (lsmash_qt_pixel_format_t
*)cs
->data
.structured
;
1053 isom_cspc_t
*cspc
= isom_add_cspc( visual
);
1056 lsmash_destroy_codec_specific_data( cs
);
1059 cspc
->pixel_format
= data
->pixel_format
;
1060 lsmash_destroy_codec_specific_data( cs
);
1063 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
:
1065 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1068 lsmash_qt_significant_bits_t
*data
= (lsmash_qt_significant_bits_t
*)cs
->data
.structured
;
1069 isom_sgbt_t
*sgbt
= isom_add_sgbt( visual
);
1072 lsmash_destroy_codec_specific_data( cs
);
1075 sgbt
->significantBits
= data
->significantBits
;
1076 lsmash_destroy_codec_specific_data( cs
);
1079 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL
:
1081 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1084 lsmash_qt_gamma_t
*data
= (lsmash_qt_gamma_t
*)cs
->data
.structured
;
1085 isom_gama_t
*gama
= isom_add_gama( visual
);
1088 lsmash_destroy_codec_specific_data( cs
);
1091 gama
->level
= data
->level
;
1092 lsmash_destroy_codec_specific_data( cs
);
1095 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
1097 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1100 lsmash_codec_global_header_t
*data
= (lsmash_codec_global_header_t
*)cs
->data
.structured
;
1101 isom_glbl_t
*glbl
= isom_add_glbl( visual
);
1104 lsmash_destroy_codec_specific_data( cs
);
1107 glbl
->header_size
= data
->header_size
;
1108 glbl
->header_data
= lsmash_memdup( data
->header_data
, data
->header_size
);
1109 lsmash_destroy_codec_specific_data( cs
);
1110 if( !glbl
->header_data
)
1112 isom_remove_box_by_itself( glbl
);
1113 err
= LSMASH_ERR_MEMORY_ALLOC
;
1120 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
1123 if( cs
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1125 lsmash_destroy_codec_specific_data( cs
);
1126 err
= LSMASH_ERR_INVALID_DATA
;
1129 uint8_t *data
= cs
->data
.unstructured
;
1130 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
1131 lsmash_box_type_t box_type
= isom_guess_video_codec_specific_box_type( visual
->type
, fourcc
);
1132 /* Append the extension. */
1133 err
= isom_add_extension_binary( visual
, box_type
, LSMASH_BOX_PRECEDENCE_HM
, cs
->data
.unstructured
, cs
->size
);
1134 cs
->data
.unstructured
= NULL
; /* Avoid freeing the binary data of the extension. */
1135 lsmash_destroy_codec_specific_data( cs
);
1142 isom_trak_t
*trak
= (isom_trak_t
*)visual
->parent
->parent
->parent
->parent
->parent
;
1143 int qt_compatible
= trak
->file
->qt_compatible
;
1144 isom_tapt_t
*tapt
= trak
->tapt
;
1145 isom_stsl_t
*stsl
= (isom_stsl_t
*)isom_get_extension_box_format( &visual
->extensions
, ISOM_BOX_TYPE_STSL
);
1146 int set_aperture_modes
= qt_compatible
/* Track Aperture Modes is only available under QuickTime file format. */
1147 && (!stsl
|| stsl
->scale_method
== 0) /* Sample scaling method might conflict with this feature. */
1148 && tapt
&& tapt
->clef
&& tapt
->prof
&& tapt
->enof
/* Check if required boxes exist. */
1149 && ((isom_stsd_t
*)visual
->parent
)->list
.entry_count
== 1; /* Multiple sample description might conflict with this, so in that case, disable this feature. */
1150 if( !set_aperture_modes
)
1151 isom_remove_box_by_itself( trak
->tapt
);
1152 int uncompressed_ycbcr
= qt_compatible
&& isom_is_uncompressed_ycbcr( visual
->type
);
1153 /* Set up Clean Aperture. */
1154 if( set_aperture_modes
|| uncompressed_ycbcr
1155 || (summary
->clap
.width
.d
&& summary
->clap
.height
.d
&& summary
->clap
.horizontal_offset
.d
&& summary
->clap
.vertical_offset
.d
) )
1157 isom_clap_t
*clap
= isom_add_clap( visual
);
1160 if( summary
->clap
.width
.d
&& summary
->clap
.height
.d
&& summary
->clap
.horizontal_offset
.d
&& summary
->clap
.vertical_offset
.d
)
1162 clap
->cleanApertureWidthN
= summary
->clap
.width
.n
;
1163 clap
->cleanApertureWidthD
= summary
->clap
.width
.d
;
1164 clap
->cleanApertureHeightN
= summary
->clap
.height
.n
;
1165 clap
->cleanApertureHeightD
= summary
->clap
.height
.d
;
1166 clap
->horizOffN
= summary
->clap
.horizontal_offset
.n
;
1167 clap
->horizOffD
= summary
->clap
.horizontal_offset
.d
;
1168 clap
->vertOffN
= summary
->clap
.vertical_offset
.n
;
1169 clap
->vertOffD
= summary
->clap
.vertical_offset
.d
;
1173 clap
->cleanApertureWidthN
= summary
->width
;
1174 clap
->cleanApertureWidthD
= 1;
1175 clap
->cleanApertureHeightN
= summary
->height
;
1176 clap
->cleanApertureHeightD
= 1;
1177 clap
->horizOffN
= 0;
1178 clap
->horizOffD
= 1;
1183 /* Set up Pixel Aspect Ratio. */
1184 if( set_aperture_modes
|| (summary
->par_h
&& summary
->par_v
) )
1186 isom_pasp_t
*pasp
= isom_add_pasp( visual
);
1189 pasp
->hSpacing
= LSMASH_MAX( summary
->par_h
, 1 );
1190 pasp
->vSpacing
= LSMASH_MAX( summary
->par_v
, 1 );
1192 /* Set up Color Parameter. */
1193 if( uncompressed_ycbcr
1194 || summary
->color
.primaries_index
1195 || summary
->color
.transfer_index
1196 || summary
->color
.matrix_index
1197 || (trak
->file
->isom_compatible
&& summary
->color
.full_range
) )
1199 isom_colr_t
*colr
= isom_add_colr( visual
);
1202 /* Set 'nclc' to parameter type, we don't support 'prof'. */
1203 uint16_t primaries
= summary
->color
.primaries_index
;
1204 uint16_t transfer
= summary
->color
.transfer_index
;
1205 uint16_t matrix
= summary
->color
.matrix_index
;
1206 if( qt_compatible
&& !trak
->file
->isom_compatible
)
1208 colr
->manager
|= LSMASH_QTFF_BASE
;
1209 colr
->type
= QT_BOX_TYPE_COLR
;
1210 colr
->color_parameter_type
= QT_COLOR_PARAMETER_TYPE_NCLC
;
1211 colr
->primaries_index
= (primaries
== 1 || primaries
== 5 || primaries
== 6)
1212 ? primaries
: QT_PRIMARIES_INDEX_UNSPECIFIED
;
1213 colr
->transfer_function_index
= (transfer
== 1 || transfer
== 7)
1214 ? transfer
: QT_TRANSFER_INDEX_UNSPECIFIED
;
1215 colr
->matrix_index
= (matrix
== 1 || matrix
== 6 || matrix
== 7)
1216 ? matrix
: QT_MATRIX_INDEX_UNSPECIFIED
;
1220 colr
->type
= ISOM_BOX_TYPE_COLR
;
1221 colr
->color_parameter_type
= ISOM_COLOR_PARAMETER_TYPE_NCLX
;
1222 colr
->primaries_index
= (primaries
== 1 || (primaries
>= 4 && primaries
<= 7))
1223 ? primaries
: ISOM_PRIMARIES_INDEX_UNSPECIFIED
;
1224 colr
->transfer_function_index
= (transfer
== 1 || (transfer
>= 4 && transfer
<= 8) || (transfer
>= 11 && transfer
<= 13))
1225 ? transfer
: ISOM_TRANSFER_INDEX_UNSPECIFIED
;
1226 colr
->matrix_index
= (matrix
== 1 || (matrix
>= 4 && matrix
<= 8))
1227 ? matrix
: ISOM_MATRIX_INDEX_UNSPECIFIED
;
1228 colr
->full_range_flag
= summary
->color
.full_range
;
1231 /* Set up Track Apeture Modes. */
1232 if( set_aperture_modes
)
1234 uint32_t width
= visual
->width
<< 16;
1235 uint32_t height
= visual
->height
<< 16;
1236 isom_clap_t
*clap
= (isom_clap_t
*)isom_get_extension_box_format( &visual
->extensions
, ISOM_BOX_TYPE_CLAP
);
1237 isom_pasp_t
*pasp
= (isom_pasp_t
*)isom_get_extension_box_format( &visual
->extensions
, ISOM_BOX_TYPE_PASP
);
1238 double clap_width
= ((double)clap
->cleanApertureWidthN
/ clap
->cleanApertureWidthD
) * (1<<16);
1239 double clap_height
= ((double)clap
->cleanApertureHeightN
/ clap
->cleanApertureHeightD
) * (1<<16);
1240 double par
= (double)pasp
->hSpacing
/ pasp
->vSpacing
;
1243 tapt
->clef
->width
= clap_width
* par
;
1244 tapt
->clef
->height
= clap_height
;
1245 tapt
->prof
->width
= width
* par
;
1246 tapt
->prof
->height
= height
;
1250 tapt
->clef
->width
= clap_width
;
1251 tapt
->clef
->height
= clap_height
/ par
;
1252 tapt
->prof
->width
= width
;
1253 tapt
->prof
->height
= height
/ par
;
1255 tapt
->enof
->width
= width
;
1256 tapt
->enof
->height
= height
;
1260 isom_remove_box_by_itself( visual
);
1264 static int isom_append_audio_es_descriptor_extension( isom_box_t
*box
, lsmash_audio_summary_t
*summary
)
1266 uint32_t esds_size
= 0;
1267 uint8_t *esds_data
= NULL
;
1268 lsmash_codec_specific_t
*specific
= isom_get_codec_specific( summary
->opaque
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
);
1270 return LSMASH_ERR_NAMELESS
;
1271 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
1273 esds_size
= specific
->size
;
1274 esds_data
= lsmash_memdup( specific
->data
.unstructured
, specific
->size
);
1276 return LSMASH_ERR_MEMORY_ALLOC
;
1280 esds_data
= lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t
*)specific
->data
.structured
, &esds_size
);
1282 return LSMASH_ERR_NAMELESS
;
1284 isom_esds_t
*esds
= isom_add_esds( box
);
1287 lsmash_free( esds_data
);
1288 return LSMASH_ERR_NAMELESS
;
1290 lsmash_bs_t bs
= { 0 };
1291 bs
.buffer
.data
= esds_data
+ ISOM_FULLBOX_COMMON_SIZE
;
1292 bs
.buffer
.alloc
= esds_size
- ISOM_FULLBOX_COMMON_SIZE
;
1293 bs
.buffer
.store
= bs
.buffer
.alloc
;
1294 esds
->ES
= mp4sys_get_descriptor( &bs
, NULL
);
1295 lsmash_free( esds_data
);
1298 isom_remove_box_by_itself( esds
);
1299 return LSMASH_ERR_NAMELESS
;
1304 static int isom_append_channel_layout_extension( lsmash_codec_specific_t
*specific
, void *parent
, uint32_t channels
)
1307 if( isom_get_extension_box( &((isom_box_t
*)parent
)->extensions
, QT_BOX_TYPE_CHAN
) )
1308 return 0; /* Audio Channel Layout Box is already present. */
1309 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1311 return LSMASH_ERR_NAMELESS
;
1312 lsmash_qt_audio_channel_layout_t
*data
= (lsmash_qt_audio_channel_layout_t
*)cs
->data
.structured
;
1313 lsmash_channel_layout_tag channelLayoutTag
= data
->channelLayoutTag
;
1314 lsmash_channel_bitmap channelBitmap
= data
->channelBitmap
;
1315 if( channelLayoutTag
== QT_CHANNEL_LAYOUT_USE_CHANNEL_DESCRIPTIONS
/* We don't support the feature of Channel Descriptions. */
1316 || (channelLayoutTag
== QT_CHANNEL_LAYOUT_USE_CHANNEL_BITMAP
&& (!channelBitmap
|| channelBitmap
> QT_CHANNEL_BIT_FULL
)) )
1318 channelLayoutTag
= QT_CHANNEL_LAYOUT_UNKNOWN
| channels
;
1321 lsmash_destroy_codec_specific_data( cs
);
1322 /* Don't create Audio Channel Layout Box if the channel layout is unknown. */
1323 if( (channelLayoutTag
^ QT_CHANNEL_LAYOUT_UNKNOWN
) >> 16 )
1325 isom_chan_t
*chan
= isom_add_chan( parent
);
1327 return LSMASH_ERR_NAMELESS
;
1328 chan
->channelLayoutTag
= channelLayoutTag
;
1329 chan
->channelBitmap
= channelBitmap
;
1330 chan
->numberChannelDescriptions
= 0;
1331 chan
->channelDescriptions
= NULL
;
1336 static int isom_set_qtff_mp4a_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1338 isom_wave_t
*wave
= isom_add_wave( audio
);
1340 if( !(frma
= isom_add_frma( wave
))
1341 || !isom_add_mp4a( wave
)
1342 || !isom_add_terminator( wave
) )
1344 lsmash_remove_entry_tail( &audio
->extensions
, wave
->destruct
);
1345 return LSMASH_ERR_NAMELESS
;
1347 frma
->data_format
= audio
->type
.fourcc
;
1348 /* Add ES Descriptor Box. */
1349 int err
= isom_append_audio_es_descriptor_extension( (isom_box_t
*)wave
, summary
);
1353 audio
->type
= QT_CODEC_TYPE_MP4A_AUDIO
;
1354 audio
->version
= (summary
->channels
> 2 || summary
->frequency
> UINT16_MAX
) ? 2 : 1;
1355 audio
->channelcount
= audio
->version
== 2 ? 3 : LSMASH_MIN( summary
->channels
, 2 );
1356 audio
->samplesize
= 16;
1357 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
;
1358 audio
->packet_size
= 0;
1359 if( audio
->version
== 1 )
1361 audio
->samplerate
= summary
->frequency
<< 16;
1362 audio
->samplesPerPacket
= summary
->samples_in_frame
;
1363 audio
->bytesPerPacket
= 1; /* Apparently, this field is set to 1. */
1364 audio
->bytesPerFrame
= audio
->bytesPerPacket
* summary
->channels
;
1365 audio
->bytesPerSample
= 2;
1367 else /* audio->version == 2 */
1369 audio
->samplerate
= 0x00010000;
1370 audio
->sizeOfStructOnly
= 72;
1371 audio
->audioSampleRate
= (union {double d
; uint64_t i
;}){summary
->frequency
}.i
;
1372 audio
->numAudioChannels
= summary
->channels
;
1373 audio
->always7F000000
= 0x7F000000;
1374 audio
->constBitsPerChannel
= 0; /* compressed audio */
1375 audio
->formatSpecificFlags
= 0;
1376 audio
->constBytesPerAudioPacket
= 0; /* variable */
1377 audio
->constLPCMFramesPerAudioPacket
= summary
->samples_in_frame
;
1382 static int isom_set_isom_mp4a_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1384 if( summary
->summary_type
!= LSMASH_SUMMARY_TYPE_AUDIO
)
1385 return LSMASH_ERR_NAMELESS
;
1386 /* Check objectTypeIndication. */
1387 lsmash_mp4sys_object_type_indication objectTypeIndication
= lsmash_mp4sys_get_object_type_indication( (lsmash_summary_t
*)summary
);
1388 switch( objectTypeIndication
)
1390 case MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3
:
1391 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_Main_Profile
:
1392 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_LC_Profile
:
1393 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_SSR_Profile
:
1394 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_3
: /* Legacy Interface */
1395 case MP4SYS_OBJECT_TYPE_Audio_ISO_11172_3
: /* Legacy Interface */
1398 return LSMASH_ERR_NAMELESS
;
1400 /* Add ES Descriptor Box. */
1401 int err
= isom_append_audio_es_descriptor_extension( (isom_box_t
*)audio
, summary
);
1404 /* In pure mp4 file, these "template" fields shall be default values according to the spec.
1405 But not pure - hybrid with other spec - mp4 file can take other values.
1406 Which is to say, these template values shall be ignored in terms of mp4, except some object_type_indications.
1407 see 14496-14, "Template fields used". */
1408 audio
->type
= ISOM_CODEC_TYPE_MP4A_AUDIO
;
1410 audio
->revision_level
= 0;
1412 audio
->channelcount
= 2;
1413 audio
->samplesize
= 16;
1414 audio
->compression_ID
= 0;
1415 audio
->packet_size
= 0;
1416 /* WARNING: This field cannot retain frequency above 65535Hz.
1417 This is not "FIXME", I just honestly implemented what the spec says.
1418 BTW, who ever expects sampling frequency takes fixed-point decimal??? */
1419 audio
->samplerate
= summary
->frequency
<= UINT16_MAX
? summary
->frequency
<< 16 : 0;
1423 static int isom_set_qtff_lpcm_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1425 lsmash_qt_audio_format_specific_flags_t
*lpcm
= NULL
;
1426 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
1428 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
1431 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1432 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
1434 lpcm
= (lsmash_qt_audio_format_specific_flags_t
*)specific
->data
.structured
;
1439 return LSMASH_ERR_NAMELESS
;
1440 audio
->manager
|= LSMASH_QTFF_BASE
;
1441 lsmash_codec_type_t sample_type
= audio
->type
;
1442 /* Convert the sample type into 'lpcm' if the description doesn't match the format or version = 2 fields are needed. */
1443 if( (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_RAW_AUDIO
)
1444 && (summary
->sample_size
!= 8 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1445 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL32_AUDIO
)
1446 && (summary
->sample_size
!= 32 || !(lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1447 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL64_AUDIO
)
1448 && (summary
->sample_size
!= 64 || !(lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1449 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN24_AUDIO
)
1450 && (summary
->sample_size
!= 24 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1451 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN32_AUDIO
)
1452 && (summary
->sample_size
!= 32 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1453 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_23NI_AUDIO
)
1454 && (summary
->sample_size
!= 32 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
) || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
)))
1455 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_SOWT_AUDIO
)
1456 && (summary
->sample_size
!= 16 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
) || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
)))
1457 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
)
1458 && ((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
)))
1459 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NONE_AUDIO
)
1460 && ((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
)))
1461 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NOT_SPECIFIED
)
1462 && ((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
)))
1463 || (summary
->channels
> 2 || summary
->frequency
> UINT16_MAX
|| summary
->sample_size
% 8) )
1465 audio
->type
= QT_CODEC_TYPE_LPCM_AUDIO
;
1468 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_LPCM_AUDIO
) )
1470 else if( summary
->sample_size
> 16
1471 || (!lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_RAW_AUDIO
)
1472 && !lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
)
1473 && !lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NONE_AUDIO
)
1474 && !lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NOT_SPECIFIED
)) )
1476 /* Set up constBytesPerAudioPacket field.
1477 * We use constBytesPerAudioPacket as the actual size of LPCM audio frame even when version is not 2. */
1478 audio
->constBytesPerAudioPacket
= (summary
->sample_size
* summary
->channels
) / 8;
1479 /* Set up other fields in this description by its version. */
1480 if( audio
->version
== 2 )
1482 audio
->channelcount
= 3;
1483 audio
->samplesize
= 16;
1484 audio
->compression_ID
= -2;
1485 audio
->samplerate
= 0x00010000;
1486 audio
->sizeOfStructOnly
= 72;
1487 audio
->audioSampleRate
= (union {double d
; uint64_t i
;}){summary
->frequency
}.i
;
1488 audio
->numAudioChannels
= summary
->channels
;
1489 audio
->always7F000000
= 0x7F000000;
1490 audio
->constBitsPerChannel
= summary
->sample_size
;
1491 audio
->constLPCMFramesPerAudioPacket
= 1;
1492 audio
->formatSpecificFlags
= lpcm
->format_flags
;
1493 if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
) && summary
->sample_size
!= 8 )
1494 audio
->formatSpecificFlags
|= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
1495 if( lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)
1496 audio
->formatSpecificFlags
&= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
;
1497 if( lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_PACKED
)
1498 audio
->formatSpecificFlags
&= ~QT_LPCM_FORMAT_FLAG_ALIGNED_HIGH
;
1500 else if( audio
->version
== 1 )
1502 audio
->channelcount
= summary
->channels
;
1503 audio
->samplesize
= 16;
1504 /* Audio formats other than 'raw ' and 'twos' are treated as compressed audio. */
1505 if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_RAW_AUDIO
)
1506 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
) )
1507 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
;
1509 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION
;
1510 audio
->samplerate
= summary
->frequency
<< 16;
1511 audio
->samplesPerPacket
= 1;
1512 audio
->bytesPerPacket
= summary
->sample_size
/ 8;
1513 audio
->bytesPerFrame
= audio
->bytesPerPacket
* summary
->channels
; /* sample_size field in stsz box is NOT used. */
1514 audio
->bytesPerSample
= 1 + (summary
->sample_size
!= 8);
1515 if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL32_AUDIO
)
1516 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL64_AUDIO
)
1517 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN24_AUDIO
)
1518 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN32_AUDIO
) )
1520 isom_wave_t
*wave
= isom_add_wave( audio
);
1523 if( !(frma
= isom_add_frma( wave
))
1524 || !(enda
= isom_add_enda( wave
))
1525 || !isom_add_terminator( wave
) )
1527 lsmash_remove_entry_tail( &audio
->extensions
, wave
->destruct
);
1528 return LSMASH_ERR_NAMELESS
;
1530 frma
->data_format
= sample_type
.fourcc
;
1531 enda
->littleEndian
= !(lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
);
1534 else /* audio->version == 0 */
1536 audio
->channelcount
= summary
->channels
;
1537 audio
->samplesize
= summary
->sample_size
;
1538 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
;
1539 audio
->samplerate
= summary
->frequency
<< 16;
1544 static int isom_set_isom_dts_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1547 audio
->revision_level
= 0;
1549 audio
->channelcount
= summary
->channels
;
1550 audio
->samplesize
= 16;
1551 audio
->compression_ID
= 0;
1552 audio
->packet_size
= 0;
1553 switch( summary
->frequency
)
1555 case 12000 : /* Invalid? (No reference in the spec) */
1560 case 384000 : /* Invalid? (No reference in the spec) */
1561 audio
->samplerate
= 48000 << 16;
1567 case 352800 : /* Invalid? (No reference in the spec) */
1568 audio
->samplerate
= 44100 << 16;
1570 case 8000 : /* Invalid? (No reference in the spec) */
1575 audio
->samplerate
= 32000 << 16;
1578 audio
->samplerate
= 0;
1584 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
)
1586 lsmash_box_type_t box_type
= LSMASH_BOX_TYPE_INITIALIZER
;
1587 box_type
.fourcc
= fourcc
;
1588 #define GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
1589 else if( (codec_type.user.fourcc == 0 \
1590 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
1591 && box_type.fourcc == predefined_box_type.fourcc ) \
1592 box_type = predefined_box_type
1594 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AC_3_AUDIO
, ISOM_BOX_TYPE_DAC3
);
1595 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_EC_3_AUDIO
, ISOM_BOX_TYPE_DEC3
);
1596 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSC_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1597 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSE_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1598 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSH_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1599 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSL_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1600 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_ALAC_AUDIO
, ISOM_BOX_TYPE_ALAC
);
1601 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4A_AUDIO
, ISOM_BOX_TYPE_ESDS
);
1602 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ALAC_AUDIO
, QT_BOX_TYPE_ALAC
);
1603 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_MP4A_AUDIO
, QT_BOX_TYPE_ESDS
);
1604 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_FULLMP3_AUDIO
, QT_CODEC_TYPE_MP3_AUDIO
);
1605 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM2_AUDIO
, QT_CODEC_TYPE_ADPCM2_AUDIO
);
1606 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM17_AUDIO
, QT_CODEC_TYPE_ADPCM17_AUDIO
);
1607 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_GSM49_AUDIO
, QT_CODEC_TYPE_GSM49_AUDIO
);
1608 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_CHAN
);
1609 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_GLBL
);
1610 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_WAVE
);
1611 #undef GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE
1617 uint16_t wFormatTag
;
1619 uint32_t nSamplesPerSec
;
1620 uint32_t nAvgBytesPerSec
;
1621 uint16_t nBlockAlign
;
1622 uint16_t wBitsPerSample
;
1626 static lsmash_bs_t
*isom_create_waveform_audio_info
1628 wave_format_ex_t
*wfx
,
1629 lsmash_box_type_t type
1632 lsmash_bs_t
*bs
= lsmash_bs_create();
1635 lsmash_bs_put_be32( bs
, ISOM_BASEBOX_COMMON_SIZE
+ 18 + wfx
->cbSize
);
1636 lsmash_bs_put_be32( bs
, type
.fourcc
);
1637 lsmash_bs_put_le16( bs
, wfx
->wFormatTag
);
1638 lsmash_bs_put_le16( bs
, wfx
->nChannels
);
1639 lsmash_bs_put_le32( bs
, wfx
->nSamplesPerSec
);
1640 lsmash_bs_put_le32( bs
, wfx
->nAvgBytesPerSec
);
1641 lsmash_bs_put_le16( bs
, wfx
->nBlockAlign
);
1642 lsmash_bs_put_le16( bs
, wfx
->wBitsPerSample
);
1643 lsmash_bs_put_le16( bs
, wfx
->cbSize
);
1647 static int isom_setup_waveform_audio_info
1650 isom_audio_entry_t
*audio
,
1651 lsmash_audio_summary_t
*summary
,
1652 uint32_t samples_per_packet
,
1653 uint32_t bytes_per_frame
,
1654 uint32_t sample_size
1657 wave_format_ex_t wfx
;
1658 wfx
.wFormatTag
= 0x0000; /* WAVE_FORMAT_UNKNOWN */
1659 wfx
.nChannels
= summary
->channels
;
1660 wfx
.nSamplesPerSec
= summary
->frequency
;
1661 wfx
.nAvgBytesPerSec
= 0;
1662 wfx
.nBlockAlign
= bytes_per_frame
;
1663 wfx
.wBitsPerSample
= sample_size
;
1665 lsmash_bs_t
*bs
= NULL
;
1666 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ADPCM2_AUDIO
) )
1668 /* ADPCMWAVEFORMAT */
1669 wfx
.wFormatTag
= 0x0002; /* WAVE_FORMAT_ADPCM */
1671 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1673 return LSMASH_ERR_MEMORY_ALLOC
;
1674 uint16_t wSamplesPerBlock
= samples_per_packet
; /* nBlockAlign * 2 / nChannels - 12 */
1675 uint16_t wNumCoef
= 7; /* Microsoft ADPCM uses just 7 coefficients. */
1680 } aCoef
[7] = { { 256, 0 }, { 512, -256 }, { 0,0 }, { 192,64 }, { 240,0 }, { 460, -208 }, { 392,-232 } };
1681 lsmash_bs_put_le16( bs
, wSamplesPerBlock
);
1682 lsmash_bs_put_le16( bs
, wNumCoef
);
1683 for( int i
= 0; i
< 7; i
++ )
1685 lsmash_bs_put_le16( bs
, aCoef
[i
].iCoef1
);
1686 lsmash_bs_put_le16( bs
, aCoef
[i
].iCoef2
);
1689 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ADPCM17_AUDIO
) )
1691 /* IMAADPCMWAVEFORMAT */
1692 wfx
.wFormatTag
= 0x0011; /* WAVE_FORMAT_DVI_ADPCM / WAVE_FORMAT_IMA_ADPCM */
1694 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1696 return LSMASH_ERR_MEMORY_ALLOC
;
1697 uint16_t wSamplesPerBlock
= samples_per_packet
;
1698 lsmash_bs_put_le16( bs
, wSamplesPerBlock
);
1700 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_GSM49_AUDIO
) )
1702 /* GSM610WAVEFORMAT */
1703 wfx
.wFormatTag
= 0x0031; /* WAVE_FORMAT_GSM610 */
1705 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1707 return LSMASH_ERR_MEMORY_ALLOC
;
1708 uint16_t wSamplesPerBlock
= samples_per_packet
;
1709 lsmash_bs_put_le16( bs
, wSamplesPerBlock
);
1711 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
1712 || lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MP3_AUDIO
) )
1714 /* MPEGLAYER3WAVEFORMAT */
1715 wfx
.wFormatTag
= 0x0055; /* WAVE_FORMAT_MPEGLAYER3 */
1716 wfx
.nBlockAlign
= 1; /* ? */
1717 wfx
.wBitsPerSample
= 0; /* undefined */
1719 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1721 return LSMASH_ERR_MEMORY_ALLOC
;
1722 uint16_t wID
= 1; /* MPEGLAYER3_ID_MPEG */
1723 uint32_t fdwFlags
= 0; /* We don't know whether the stream is padded or not here. */
1724 uint16_t nBlockSize
= 0; /* (144 * (bitrate / nSamplesPerSec) + padding) * nFramesPerBlock */
1725 uint16_t nFramesPerBlock
= 1; /* the number of audio frames per block */
1726 uint16_t nCodecDelay
= 0; /* Encoder delay in samples is unknown. */
1727 lsmash_bs_put_le16( bs
, wID
);
1728 lsmash_bs_put_le32( bs
, fdwFlags
);
1729 lsmash_bs_put_le16( bs
, nBlockSize
);
1730 lsmash_bs_put_le16( bs
, nFramesPerBlock
);
1731 lsmash_bs_put_le16( bs
, nCodecDelay
);
1736 return LSMASH_ERR_NAMELESS
;
1739 uint8_t *wfx_data
= lsmash_bs_export_data( bs
, &wfx_size
);
1740 lsmash_bs_cleanup( bs
);
1742 return LSMASH_ERR_NAMELESS
;
1743 if( wfx_size
!= ISOM_BASEBOX_COMMON_SIZE
+ 18 + wfx
.cbSize
)
1745 lsmash_free( wfx_data
);
1746 return LSMASH_ERR_NAMELESS
;
1748 int err
= isom_add_extension_binary( wave
, audio
->type
, LSMASH_BOX_PRECEDENCE_HM
, wfx_data
, wfx_size
);
1751 lsmash_free( wfx_data
);
1757 static int isom_set_qtff_sound_decompression_parameters
1759 isom_audio_entry_t
*audio
,
1760 lsmash_audio_summary_t
*summary
,
1761 lsmash_qt_audio_format_specific_flag
*format_flags
,
1762 uint32_t samples_per_packet
,
1763 uint32_t bytes_per_frame
,
1764 uint32_t sample_size
1767 /* A 'wave' extension itself shall be absent in the opaque CODEC specific info list.
1768 * So, create a 'wave' extension here and append it as an extension to the audio sample description. */
1769 isom_wave_t
*wave
= isom_add_wave( audio
);
1770 if( !isom_add_frma ( wave
)
1771 || !isom_add_terminator( wave
) )
1773 lsmash_remove_entry_tail( &audio
->extensions
, wave
->destruct
);
1774 return LSMASH_ERR_NAMELESS
;
1776 wave
->frma
->data_format
= audio
->type
.fourcc
;
1777 /* Append extensions from the opaque CODEC specific info list to 'wave' extension. */
1779 int waveform_audio_info_present
= 0;
1780 int requires_waveform_audio_info
= isom_is_waveform_audio( audio
->type
);
1781 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
1783 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
1785 return LSMASH_ERR_NAMELESS
;
1786 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
1787 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
1788 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
1789 switch( specific
->type
)
1791 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
:
1792 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
1793 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
:
1794 continue; /* These cannot be an extension for 'wave' extension. */
1795 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
:
1796 /* (Legacy?) ALAC might have an Audio Channel Layout Box inside 'wave' extension. */
1800 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
1802 if( (err
= isom_append_channel_layout_extension( specific
, wave
, summary
->channels
)) < 0 )
1808 assert( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
1809 || specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
);
1810 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
1812 return LSMASH_ERR_NAMELESS
;
1813 if( cs
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1815 lsmash_destroy_codec_specific_data( cs
);
1818 uint8_t *box_data
= cs
->data
.unstructured
;
1819 uint64_t box_size
= cs
->size
;
1820 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( box_data
[4], box_data
[5], box_data
[6], box_data
[7] );
1821 if( audio
->version
== 2 && fourcc
== QT_BOX_TYPE_ENDA
.fourcc
)
1823 /* Don't append a 'enda' extension if version == 2.
1824 * Endianness is indicated in QuickTime audio format specific flags. */
1825 if( box_size
>= ISOM_BASEBOX_COMMON_SIZE
+ 2 )
1827 /* Override endianness indicated in format specific flags. */
1828 if( box_data
[9] == 1 )
1829 *format_flags
&= ~QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN
;
1831 *format_flags
|= QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN
;
1833 lsmash_destroy_codec_specific_data( cs
);
1836 lsmash_box_type_t box_type
= isom_guess_audio_codec_specific_box_type( audio
->type
, fourcc
);
1837 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_WAVE
) )
1839 /* It is insane to appened a 'wave' extension to a 'wave' extension. */
1840 lsmash_destroy_codec_specific_data( cs
);
1843 box_type
= lsmash_form_qtff_box_type( box_type
.fourcc
);
1844 /* Determine 'precedence'. */
1845 uint64_t precedence
;
1846 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_FRMA
) )
1847 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_FRMA
;
1848 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ESDS
) )
1849 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_ESDS
;
1850 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ENDA
) )
1851 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_ENDA
;
1852 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_MP4A
) )
1853 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_MP4A
;
1854 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_TERMINATOR
) )
1855 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR
;
1857 precedence
= LSMASH_BOX_PRECEDENCE_HM
;
1858 /* Append the extension. */
1859 err
= isom_add_extension_binary( wave
, box_type
, precedence
, cs
->data
.unstructured
, cs
->size
);
1860 cs
->data
.unstructured
= NULL
; /* Avoid freeing the binary data of the extension. */
1861 lsmash_destroy_codec_specific_data( cs
);
1864 if( isom_is_waveform_audio( box_type
) )
1865 waveform_audio_info_present
= 1;
1870 if( requires_waveform_audio_info
&& !waveform_audio_info_present
1871 && (err
= isom_setup_waveform_audio_info( wave
, audio
, summary
, samples_per_packet
, bytes_per_frame
, sample_size
)) < 0 )
1876 static int isom_set_qtff_template_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1878 audio
->manager
|= LSMASH_QTFF_BASE
;
1879 audio
->type
= lsmash_form_qtff_box_type( audio
->type
.fourcc
);
1880 audio
->version
= (summary
->channels
> 2 || summary
->frequency
> UINT16_MAX
) ? 2 : 1;
1881 /* Try to get QuickTime audio format specific flags. */
1882 lsmash_qt_audio_format_specific_flag format_flags
= QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN
;
1883 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
1885 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
1887 || !specific
->data
.structured
)
1889 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1890 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
1892 /* A format specific flags is found.
1893 * Force audio sample description version == 2. */
1894 format_flags
= ((lsmash_qt_audio_format_specific_flags_t
*)specific
->data
.structured
)->format_flags
;
1899 uint32_t samples_per_packet
;
1900 uint32_t bytes_per_frame
;
1901 uint32_t sample_size
;
1902 if( !((summary
->samples_in_frame
== 0 || summary
->bytes_per_frame
== 0 || summary
->sample_size
== 0)
1903 && isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio
, &samples_per_packet
, &bytes_per_frame
, &sample_size
)) )
1905 samples_per_packet
= summary
->samples_in_frame
;
1906 bytes_per_frame
= summary
->bytes_per_frame
;
1907 sample_size
= summary
->sample_size
;
1909 if( !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC3_AUDIO
)
1910 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC6_AUDIO
)
1911 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_AGSM_AUDIO
)
1912 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAW_AUDIO
)
1913 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ULAW_AUDIO
) )
1915 int err
= isom_set_qtff_sound_decompression_parameters( audio
, summary
, &format_flags
,
1916 samples_per_packet
, bytes_per_frame
, sample_size
);
1920 /* Set up common audio description fields. */
1921 audio
->samplesize
= 16;
1922 audio
->packet_size
= 0;
1923 if( audio
->version
== 2 )
1925 audio
->channelcount
= 3;
1926 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
;
1927 audio
->samplerate
= 0x00010000;
1928 audio
->sizeOfStructOnly
= 72;
1929 audio
->audioSampleRate
= (union {double d
; uint64_t i
;}){summary
->frequency
}.i
;
1930 audio
->numAudioChannels
= summary
->channels
;
1931 audio
->always7F000000
= 0x7F000000;
1932 audio
->constBitsPerChannel
= 0;
1933 audio
->constBytesPerAudioPacket
= bytes_per_frame
;
1934 audio
->constLPCMFramesPerAudioPacket
= samples_per_packet
;
1935 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
1937 switch( sample_size
)
1940 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA
;
1943 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA
;
1946 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA
;
1949 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA
;
1957 if( format_flags
& QT_AUDIO_FORMAT_FLAG_FLOAT
)
1958 format_flags
&= ~QT_AUDIO_FORMAT_FLAG_SIGNED_INTEGER
;
1959 if( format_flags
& QT_AUDIO_FORMAT_FLAG_PACKED
)
1960 format_flags
&= ~QT_AUDIO_FORMAT_FLAG_ALIGNED_HIGH
;
1961 audio
->formatSpecificFlags
= format_flags
;
1964 else /* if( audio->version == 1 ) */
1966 audio
->channelcount
= LSMASH_MIN( summary
->channels
, 2 );
1967 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION
;
1968 audio
->samplerate
= summary
->frequency
<< 16;
1969 audio
->samplesPerPacket
= samples_per_packet
;
1970 audio
->bytesPerPacket
= bytes_per_frame
/ summary
->channels
;
1971 audio
->bytesPerFrame
= bytes_per_frame
; /* sample_size field in stsz box is NOT used. */
1972 audio
->bytesPerSample
= 1 + (sample_size
!= 8);
1977 static void isom_set_samplerate_division_of_media_timescale( isom_audio_entry_t
*audio
, int strict
)
1979 if( audio
->parent
/* stsd */
1980 && audio
->parent
->parent
/* stbl */
1981 && audio
->parent
->parent
->parent
/* minf */
1982 && audio
->parent
->parent
->parent
->parent
/* mdia */
1983 && lsmash_check_box_type_identical( audio
->parent
->parent
->parent
->parent
->type
, ISOM_BOX_TYPE_MDIA
)
1984 && ((isom_mdia_t
*)audio
->parent
->parent
->parent
->parent
)->mdhd
)
1986 /* Make an effort to match the timescale with samplerate, or be an integer multiple of it. */
1987 uint32_t orig_timescale
= ((isom_mdia_t
*)audio
->parent
->parent
->parent
->parent
)->mdhd
->timescale
;
1988 uint32_t timescale
= orig_timescale
;
1990 while( timescale
> UINT16_MAX
&& timescale
> 1 )
1992 if( timescale
% i
== 0 )
1997 if( timescale
!= orig_timescale
&& strict
)
1998 lsmash_log( NULL
, LSMASH_LOG_WARNING
, "samplerate does not match the media timescale.\n" );
1999 if( timescale
<= UINT16_MAX
&& timescale
> 1 )
2001 audio
->samplerate
= timescale
<< 16;
2005 audio
->samplerate
= 0;
2008 static int isom_set_isom_template_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
2010 audio
->version
= 0; /* reserved */
2011 audio
->revision_level
= 0; /* reserved */
2012 audio
->vendor
= 0; /* reserved */
2013 audio
->channelcount
= 2; /* template */
2014 audio
->samplesize
= 16; /* template */
2015 audio
->compression_ID
= 0; /* pre_defined */
2016 audio
->packet_size
= 0; /* reserved */
2017 /* template : default output audio sampling rate at playback */
2018 if( summary
->frequency
<= UINT16_MAX
)
2019 audio
->samplerate
= summary
->frequency
<< 16;
2021 isom_set_samplerate_division_of_media_timescale( audio
, 0 );
2025 static int isom_set_isom_amr_audio_description( isom_audio_entry_t
*audio
, int wb
)
2027 /* For AMR-NB and AMR-WB stream, these fields are not meaningful. */
2028 audio
->version
= 0; /* always 0 */
2029 audio
->revision_level
= 0; /* always 0 */
2030 audio
->vendor
= 0; /* always 0 */
2031 audio
->channelcount
= 2; /* always 2 although the actual number of channels is always 1 */
2032 audio
->samplesize
= 16; /* always 16 */
2033 audio
->compression_ID
= 0; /* always 0 */
2034 audio
->packet_size
= 0; /* always 0 */
2035 /* Set samplerate by trying to copy from Media Header Box of this media though the
2036 * actual samplerate is 8000 Hz for AMR-NB and 16000 Hz for AMR-WB.
2037 * 3GPP and 3GPP2 has no restriction for media timescale. Therefore, users should
2038 * set suitable media timescale by themselves within the bounds of common sense. */
2039 isom_set_samplerate_division_of_media_timescale( audio
, 1 );
2040 if( audio
->samplerate
== 0 )
2041 /* Set hard-coded but correct samplerate in the CODEC level. */
2042 audio
->samplerate
= wb
? 8000 : 16000;
2046 int isom_setup_audio_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
, lsmash_audio_summary_t
*summary
)
2048 if( !stsd
|| !stsd
->file
|| !summary
)
2049 return LSMASH_ERR_NAMELESS
;
2050 int err
= isom_check_valid_summary( (lsmash_summary_t
*)summary
);
2053 isom_audio_entry_t
*audio
= isom_add_audio_description( stsd
, sample_type
);
2055 return LSMASH_ERR_NAMELESS
;
2056 audio
->data_reference_index
= summary
->data_ref_index
;
2057 lsmash_file_t
*file
= stsd
->file
;
2058 lsmash_codec_type_t audio_type
= audio
->type
;
2059 if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_MP4A_AUDIO
)
2060 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_MP4A_AUDIO
) )
2062 if( (file
->ftyp
&& file
->ftyp
->major_brand
== ISOM_BRAND_TYPE_QT
)
2063 || (!file
->ftyp
&& (file
->qt_compatible
|| (file
->moov
&& !file
->moov
->iods
))) )
2064 err
= isom_set_qtff_mp4a_description( audio
, summary
);
2066 err
= isom_set_isom_mp4a_description( audio
, summary
);
2068 else if( isom_is_lpcm_audio( audio
) )
2069 err
= isom_set_qtff_lpcm_description( audio
, summary
);
2070 else if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_DTSC_AUDIO
)
2071 || lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_DTSE_AUDIO
)
2072 || lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_DTSH_AUDIO
)
2073 || lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_DTSL_AUDIO
) )
2074 err
= isom_set_isom_dts_description( audio
, summary
);
2075 else if( file
->qt_compatible
)
2076 err
= isom_set_qtff_template_audio_description( audio
, summary
);
2077 else if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_SAMR_AUDIO
) )
2078 err
= isom_set_isom_amr_audio_description( audio
, 0 );
2079 else if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_SAWB_AUDIO
) )
2080 err
= isom_set_isom_amr_audio_description( audio
, 1 );
2082 err
= isom_set_isom_template_audio_description( audio
, summary
);
2085 err
= LSMASH_ERR_NAMELESS
;
2086 /* Don't use audio_type since audio->type might have changed. */
2087 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
2089 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
2092 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
2093 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
2094 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
2095 switch( specific
->type
)
2097 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
:
2099 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
2100 continue; /* Ignore since not fatal. */
2101 lsmash_qt_audio_common_t
*data
= (lsmash_qt_audio_common_t
*)specific
->data
.structured
;
2102 audio
->revision_level
= data
->revision_level
;
2103 audio
->vendor
= data
->vendor
;
2104 if( audio
->version
== 1
2105 && !isom_is_lpcm_audio( audio
)
2106 && data
->compression_ID
!= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
)
2108 /* Compressed audio must not be set to QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED. */
2109 audio
->compression_ID
= data
->compression_ID
;
2110 if( audio
->compression_ID
== QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
)
2112 /* For variable compression, bytesPerPacket and bytesPerFrame are reserved and should be set to 0. */
2113 audio
->bytesPerPacket
= 0;
2114 audio
->bytesPerFrame
= 0;
2119 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
:
2121 if( !file
->qt_compatible
2122 && !lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_ALAC_AUDIO
)
2123 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
2125 if( (err
= isom_append_channel_layout_extension( specific
, audio
, summary
->channels
)) < 0 )
2129 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
2131 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2134 lsmash_codec_global_header_t
*data
= (lsmash_codec_global_header_t
*)cs
->data
.structured
;
2135 isom_glbl_t
*glbl
= isom_add_glbl( audio
);
2138 lsmash_destroy_codec_specific_data( cs
);
2141 glbl
->header_size
= data
->header_size
;
2142 glbl
->header_data
= lsmash_memdup( data
->header_data
, data
->header_size
);
2143 lsmash_destroy_codec_specific_data( cs
);
2144 if( !glbl
->header_data
)
2146 isom_remove_box_by_itself( glbl
);
2147 err
= LSMASH_ERR_MEMORY_ALLOC
;
2152 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
:
2153 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
:
2154 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
:
2155 break; /* shall be set up already */
2156 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
:
2157 if( file
->qt_compatible
)
2158 continue; /* shall be set up already */
2161 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2164 if( cs
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2166 lsmash_destroy_codec_specific_data( cs
);
2169 uint8_t *box_data
= cs
->data
.unstructured
;
2170 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( box_data
[4], box_data
[5], box_data
[6], box_data
[7] );
2171 lsmash_box_type_t box_type
= isom_guess_audio_codec_specific_box_type( audio
->type
, fourcc
);
2172 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_WAVE
) )
2174 /* CODEC specific info shall be already inside 'wave' extension. */
2175 lsmash_destroy_codec_specific_data( cs
);
2178 /* Append the extension. */
2179 err
= isom_add_extension_binary( audio
, box_type
, LSMASH_BOX_PRECEDENCE_HM
, cs
->data
.unstructured
, cs
->size
);
2180 cs
->data
.unstructured
= NULL
; /* Avoid freeing the binary data of the extension. */
2181 lsmash_destroy_codec_specific_data( cs
);
2188 if( audio
->version
== 0 )
2189 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
;
2190 else if( audio
->version
== 2 )
2191 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
;
2194 isom_remove_box_by_itself( audio
);
2198 int isom_setup_tx3g_description( isom_stsd_t
*stsd
, lsmash_summary_t
*summary
)
2200 isom_tx3g_entry_t
*tx3g
= isom_add_tx3g_description( stsd
);
2202 return LSMASH_ERR_NAMELESS
;
2203 /* We create a dummy font record to make valid font_ID in the sample description.
2204 * The specification (3GPP TS 26.245) does not forbid the value 0 for the identifier,
2205 * but we set 1 to it as track_ID begins from 1. */
2206 tx3g
->data_reference_index
= summary
->data_ref_index
;
2207 tx3g
->font_ID
= 1; /* ID of the default font record */
2208 int err
= LSMASH_ERR_MEMORY_ALLOC
;
2209 isom_ftab_t
*ftab
= isom_add_ftab( tx3g
);
2212 err
= LSMASH_ERR_NAMELESS
;
2215 isom_font_record_t
*font
= lsmash_malloc( sizeof(isom_font_record_t
) );
2218 if( lsmash_add_entry( ftab
->list
, font
) < 0 )
2220 lsmash_free( font
);
2223 const char font_names
[] = "Serif,Sans-serif,Monospace";
2225 font
->font_name_length
= sizeof(font_names
);
2226 font
->font_name
= lsmash_memdup( font_names
, sizeof(font_names
) );
2227 if( !font
->font_name
)
2231 isom_remove_box_by_itself( tx3g
);
2235 static lsmash_codec_specific_data_type
isom_get_codec_specific_data_type( lsmash_compact_box_type_t extension_fourcc
)
2237 static struct codec_specific_data_type_table_tag
2239 lsmash_compact_box_type_t extension_fourcc
;
2240 lsmash_codec_specific_data_type data_type
;
2241 } codec_specific_data_type_table
[32] = { { 0, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
} };
2242 if( codec_specific_data_type_table
[0].data_type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
)
2245 #define ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( extension_type, data_type ) \
2246 codec_specific_data_type_table[i++] = (struct codec_specific_data_type_table_tag){ extension_type.fourcc, data_type }
2247 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
);
2248 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
);
2249 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
);
2250 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
);
2251 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
);
2252 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
);
2253 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
);
2254 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
);
2255 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
);
2256 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
);
2257 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ALAC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC );
2258 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ESDS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
2259 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
);
2260 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
);
2261 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
);
2262 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL
);
2263 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
);
2264 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
);
2265 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
);
2266 #undef ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT
2268 lsmash_codec_specific_data_type data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
;
2269 for( int i
= 0; codec_specific_data_type_table
[i
].data_type
!= LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
; i
++ )
2270 if( extension_fourcc
== codec_specific_data_type_table
[i
].extension_fourcc
)
2272 data_type
= codec_specific_data_type_table
[i
].data_type
;
2278 lsmash_summary_t
*isom_create_video_summary_from_description( isom_sample_entry_t
*sample_entry
)
2282 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)sample_entry
;
2283 lsmash_video_summary_t
*summary
= (lsmash_video_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_VIDEO
);
2286 summary
->sample_type
= visual
->type
;
2287 summary
->data_ref_index
= visual
->data_reference_index
;
2288 summary
->width
= visual
->width
;
2289 summary
->height
= visual
->height
;
2290 summary
->depth
= visual
->depth
;
2291 memcpy( summary
->compressorname
, visual
->compressorname
, 32 );
2292 summary
->compressorname
[32] = '\0';
2293 if( isom_is_qt_video( summary
->sample_type
) )
2295 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
,
2296 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2299 lsmash_qt_video_common_t
*data
= (lsmash_qt_video_common_t
*)specific
->data
.structured
;
2300 data
->revision_level
= visual
->revision_level
;
2301 data
->vendor
= visual
->vendor
;
2302 data
->temporalQuality
= visual
->temporalQuality
;
2303 data
->spatialQuality
= visual
->spatialQuality
;
2304 data
->horizontal_resolution
= visual
->horizresolution
;
2305 data
->vertical_resolution
= visual
->vertresolution
;
2306 data
->dataSize
= visual
->dataSize
;
2307 data
->frame_count
= visual
->frame_count
;
2308 data
->color_table_ID
= visual
->color_table_ID
;
2309 if( visual
->color_table_ID
== 0 )
2311 isom_qt_color_table_t
*src_ct
= &visual
->color_table
;
2312 if( !src_ct
->array
)
2314 lsmash_destroy_codec_specific_data( specific
);
2317 uint16_t element_count
= LSMASH_MIN( src_ct
->size
+ 1, 256 );
2318 lsmash_qt_color_table_t
*dst_ct
= &data
->color_table
;
2319 dst_ct
->seed
= src_ct
->seed
;
2320 dst_ct
->flags
= src_ct
->flags
;
2321 dst_ct
->size
= src_ct
->size
;
2322 for( uint16_t i
= 0; i
< element_count
; i
++ )
2324 dst_ct
->array
[i
].unused
= src_ct
->array
[i
].value
;
2325 dst_ct
->array
[i
].r
= src_ct
->array
[i
].r
;
2326 dst_ct
->array
[i
].g
= src_ct
->array
[i
].g
;
2327 dst_ct
->array
[i
].b
= src_ct
->array
[i
].b
;
2330 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2332 lsmash_destroy_codec_specific_data( specific
);
2336 for( lsmash_entry_t
*entry
= visual
->extensions
.head
; entry
; entry
= entry
->next
)
2338 isom_box_t
*box
= (isom_box_t
*)entry
->data
;
2341 if( !(box
->manager
& LSMASH_BINARY_CODED_BOX
) )
2343 lsmash_codec_specific_t
*specific
= NULL
;
2344 if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_CLAP
) )
2346 isom_clap_t
*clap
= (isom_clap_t
*)box
;
2347 summary
->clap
.width
.n
= clap
->cleanApertureWidthN
;
2348 summary
->clap
.width
.d
= clap
->cleanApertureWidthD
;
2349 summary
->clap
.height
.n
= clap
->cleanApertureHeightN
;
2350 summary
->clap
.height
.d
= clap
->cleanApertureHeightD
;
2351 summary
->clap
.horizontal_offset
.n
= clap
->horizOffN
;
2352 summary
->clap
.horizontal_offset
.d
= clap
->horizOffD
;
2353 summary
->clap
.vertical_offset
.n
= clap
->vertOffN
;
2354 summary
->clap
.vertical_offset
.d
= clap
->vertOffD
;
2357 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_PASP
) )
2359 isom_pasp_t
*pasp
= (isom_pasp_t
*)box
;
2360 summary
->par_h
= pasp
->hSpacing
;
2361 summary
->par_v
= pasp
->vSpacing
;
2364 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_COLR
)
2365 || lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_COLR
) )
2367 isom_colr_t
*colr
= (isom_colr_t
*)box
;
2368 summary
->color
.primaries_index
= colr
->primaries_index
;
2369 summary
->color
.transfer_index
= colr
->transfer_function_index
;
2370 summary
->color
.matrix_index
= colr
->matrix_index
;
2371 summary
->color
.full_range
= colr
->full_range_flag
;
2374 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_STSL
) )
2376 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
,
2377 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2380 isom_stsl_t
*stsl
= (isom_stsl_t
*)box
;
2381 lsmash_isom_sample_scale_t
*data
= (lsmash_isom_sample_scale_t
*)specific
->data
.structured
;
2382 data
->constraint_flag
= stsl
->constraint_flag
;
2383 data
->scale_method
= stsl
->scale_method
;
2384 data
->display_center_x
= stsl
->display_center_x
;
2385 data
->display_center_y
= stsl
->display_center_y
;
2387 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_BTRT
) )
2389 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
,
2390 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2393 isom_btrt_t
*btrt
= (isom_btrt_t
*)box
;
2394 lsmash_h264_bitrate_t
*data
= (lsmash_h264_bitrate_t
*)specific
->data
.structured
;
2395 data
->bufferSizeDB
= btrt
->bufferSizeDB
;
2396 data
->maxBitrate
= btrt
->maxBitrate
;
2397 data
->avgBitrate
= btrt
->avgBitrate
;
2399 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_FIEL
) )
2401 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
,
2402 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2405 isom_fiel_t
*fiel
= (isom_fiel_t
*)box
;
2406 lsmash_qt_field_info_t
*data
= (lsmash_qt_field_info_t
*)specific
->data
.structured
;
2407 data
->fields
= fiel
->fields
;
2408 data
->detail
= fiel
->detail
;
2410 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CSPC
) )
2412 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
,
2413 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2416 isom_cspc_t
*cspc
= (isom_cspc_t
*)box
;
2417 lsmash_qt_pixel_format_t
*data
= (lsmash_qt_pixel_format_t
*)specific
->data
.structured
;
2418 data
->pixel_format
= cspc
->pixel_format
;
2420 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_SGBT
) )
2422 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
,
2423 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2426 isom_sgbt_t
*sgbt
= (isom_sgbt_t
*)box
;
2427 lsmash_qt_significant_bits_t
*data
= (lsmash_qt_significant_bits_t
*)specific
->data
.structured
;
2428 data
->significantBits
= sgbt
->significantBits
;
2430 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_GLBL
) )
2432 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
,
2433 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2436 isom_glbl_t
*glbl
= (isom_glbl_t
*)box
;
2437 lsmash_codec_global_header_t
*data
= (lsmash_codec_global_header_t
*)specific
->data
.structured
;
2438 data
->header_size
= glbl
->header_size
;
2439 data
->header_data
= lsmash_memdup( glbl
->header_data
, glbl
->header_size
);
2440 if( !data
->header_data
)
2442 lsmash_destroy_codec_specific_data( specific
);
2448 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2450 lsmash_destroy_codec_specific_data( specific
);
2456 if( box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2458 uint8_t *data
= box
->binary
;
2459 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
2460 lsmash_codec_specific_data_type type
= isom_get_codec_specific_data_type( fourcc
);
2461 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2464 specific
->size
= box
->size
;
2465 specific
->data
.unstructured
= lsmash_memdup( box
->binary
, box
->size
);
2466 if( !specific
->data
.unstructured
2467 || lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2469 lsmash_destroy_codec_specific_data( specific
);
2474 return (lsmash_summary_t
*)summary
;
2476 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
2480 static int isom_append_structured_mp4sys_decoder_config( lsmash_codec_specific_list_t
*opaque
, isom_esds_t
*esds
)
2482 lsmash_bs_t
*bs
= lsmash_bs_create();
2484 return LSMASH_ERR_MEMORY_ALLOC
;
2485 /* Put box size, type, version and flags fields. */
2486 lsmash_bs_put_be32( bs
, 0 );
2487 lsmash_bs_put_be32( bs
, ISOM_BOX_TYPE_ESDS
.fourcc
);
2488 lsmash_bs_put_be32( bs
, 0 );
2489 /* Put ES Descriptor. */
2490 mp4sys_update_descriptor_size( esds
->ES
);
2491 mp4sys_write_descriptor( bs
, esds
->ES
);
2492 /* Export ES Descriptor Box as binary string. */
2494 uint8_t *esds_data
= lsmash_bs_export_data( bs
, &esds_size
);
2495 lsmash_bs_cleanup( bs
);
2497 return LSMASH_ERR_NAMELESS
;
2498 /* Update box size. */
2499 LSMASH_SET_BE32( esds_data
, esds_size
);
2500 lsmash_codec_specific_data_type type
= isom_get_codec_specific_data_type( ISOM_BOX_TYPE_ESDS
.fourcc
);
2501 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2504 lsmash_free( esds_data
);
2505 return LSMASH_ERR_NAMELESS
;
2507 specific
->data
.unstructured
= esds_data
;
2508 specific
->size
= esds_size
;
2509 /* Convert unstructured CODEC specific data format into structured, and append it to the opaque list. */
2510 lsmash_codec_specific_t
*conv
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2511 lsmash_destroy_codec_specific_data( specific
);
2513 return LSMASH_ERR_NAMELESS
;
2514 if( lsmash_add_entry( &opaque
->list
, conv
) < 0 )
2516 lsmash_destroy_codec_specific_data( conv
);
2517 return LSMASH_ERR_MEMORY_ALLOC
;
2522 lsmash_summary_t
*isom_create_audio_summary_from_description( isom_sample_entry_t
*sample_entry
)
2524 if( !sample_entry
|| !sample_entry
->file
|| !sample_entry
->parent
)
2526 isom_audio_entry_t
*audio
= (isom_audio_entry_t
*)sample_entry
;
2527 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO
);
2530 summary
->sample_type
= audio
->type
;
2531 summary
->data_ref_index
= audio
->data_reference_index
;
2532 summary
->sample_size
= audio
->samplesize
;
2533 summary
->channels
= audio
->channelcount
;
2534 summary
->frequency
= audio
->samplerate
>> 16;
2535 if( ((isom_stsd_t
*)audio
->parent
)->version
== 0
2536 && audio
->file
->qt_compatible
2537 && isom_is_qt_audio( audio
->type
) )
2539 if( audio
->version
== 0 )
2540 isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio
, &summary
->samples_in_frame
, &summary
->bytes_per_frame
, &summary
->sample_size
);
2541 else if( audio
->version
== 1 )
2543 summary
->channels
= audio
->bytesPerPacket
? audio
->bytesPerFrame
/ audio
->bytesPerPacket
: audio
->channelcount
;
2544 summary
->sample_size
= audio
->bytesPerPacket
* 8;
2545 summary
->samples_in_frame
= audio
->samplesPerPacket
;
2546 summary
->bytes_per_frame
= audio
->bytesPerFrame
;
2548 else if( audio
->version
== 2 )
2550 summary
->frequency
= (union {uint64_t i
; double d
;}){audio
->audioSampleRate
}.d
;
2551 summary
->channels
= audio
->numAudioChannels
;
2552 summary
->sample_size
= audio
->constBitsPerChannel
;
2553 summary
->samples_in_frame
= audio
->constLPCMFramesPerAudioPacket
;
2554 summary
->bytes_per_frame
= audio
->constBytesPerAudioPacket
;
2556 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
,
2557 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2560 lsmash_qt_audio_common_t
*common
= (lsmash_qt_audio_common_t
*)specific
->data
.structured
;
2561 common
->revision_level
= audio
->revision_level
;
2562 common
->vendor
= audio
->vendor
;
2563 common
->compression_ID
= audio
->compression_ID
;
2564 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2566 lsmash_destroy_codec_specific_data( specific
);
2569 if( isom_is_lpcm_audio( audio
) )
2571 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
,
2572 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2575 lsmash_qt_audio_format_specific_flags_t
*data
= (lsmash_qt_audio_format_specific_flags_t
*)specific
->data
.structured
;
2576 if( audio
->version
== 2 )
2577 data
->format_flags
= audio
->formatSpecificFlags
;
2580 data
->format_flags
= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
| QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
;
2581 /* Here, don't override samplesize.
2582 * We should trust samplesize field in the description for misused CODEC indentifier. */
2583 lsmash_codec_type_t audio_type
= audio
->type
;
2584 if( lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_TWOS_AUDIO
)
2585 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_NONE_AUDIO
)
2586 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_NOT_SPECIFIED
) )
2588 if( summary
->sample_size
<= 8 )
2589 data
->format_flags
&= ~(QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
| QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
);
2593 if( lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_FL32_AUDIO
)
2594 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_FL64_AUDIO
) )
2596 data
->format_flags
&= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
;
2597 data
->format_flags
|= QT_LPCM_FORMAT_FLAG_FLOAT
;
2599 else if( lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_23NI_AUDIO
)
2600 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_SOWT_AUDIO
) )
2601 data
->format_flags
&= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
2604 isom_wave_t
*wave
= (isom_wave_t
*)isom_get_extension_box_format( &audio
->extensions
, QT_BOX_TYPE_WAVE
);
2605 if( wave
&& wave
->enda
)
2607 if( wave
->enda
->littleEndian
)
2608 data
->format_flags
&= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
2610 data
->format_flags
|= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
2612 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2614 lsmash_destroy_codec_specific_data( specific
);
2618 else if( audio
->version
== 2
2619 && (lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_ALAC_AUDIO
)
2620 || lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
)) )
2621 switch( audio
->formatSpecificFlags
)
2623 case QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA
:
2624 summary
->sample_size
= 16;
2626 case QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA
:
2627 summary
->sample_size
= 20;
2629 case QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA
:
2630 summary
->sample_size
= 24;
2632 case QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA
:
2633 summary
->sample_size
= 32;
2639 else if( lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_SAMR_AUDIO
) )
2641 summary
->channels
= 1;
2642 summary
->frequency
= 8000;
2644 else if( lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_SAWB_AUDIO
) )
2646 summary
->channels
= 1;
2647 summary
->frequency
= 16000;
2649 uint32_t actual_sampling_rate
= 0;
2650 for( lsmash_entry_t
*entry
= audio
->extensions
.head
; entry
; entry
= entry
->next
)
2652 isom_box_t
*box
= (isom_box_t
*)entry
->data
;
2655 if( !(box
->manager
& LSMASH_BINARY_CODED_BOX
) )
2657 if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CHAN
) )
2659 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
,
2660 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2663 isom_chan_t
*chan
= (isom_chan_t
*)box
;
2664 lsmash_qt_audio_channel_layout_t
*data
= (lsmash_qt_audio_channel_layout_t
*)specific
->data
.structured
;
2665 data
->channelLayoutTag
= chan
->channelLayoutTag
;
2666 data
->channelBitmap
= chan
->channelBitmap
;
2667 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2669 lsmash_destroy_codec_specific_data( specific
);
2673 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_ESDS
)
2674 || lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ESDS
) )
2676 isom_esds_t
*esds
= (isom_esds_t
*)box
;
2677 if( mp4sys_setup_summary_from_DecoderSpecificInfo( summary
, esds
->ES
) < 0
2678 || isom_append_structured_mp4sys_decoder_config( summary
->opaque
, esds
) < 0 )
2681 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_SRAT
) )
2683 isom_srat_t
*srat
= (isom_srat_t
*)box
;
2684 actual_sampling_rate
= srat
->sampling_rate
;
2686 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_WAVE
) )
2688 /* Don't append 'wave' extension itself to the opaque CODEC specific info list. */
2689 isom_wave_t
*wave
= (isom_wave_t
*)box
;
2690 lsmash_bs_t
*bs
= lsmash_bs_create();
2693 for( lsmash_entry_t
*wave_entry
= wave
->extensions
.head
; wave_entry
; wave_entry
= wave_entry
->next
)
2695 isom_box_t
*wave_ext
= (isom_box_t
*)wave_entry
->data
;
2698 lsmash_box_type_t box_type
= LSMASH_BOX_TYPE_INITIALIZER
;
2699 if( !(wave_ext
->manager
& LSMASH_BINARY_CODED_BOX
) )
2701 box_type
= wave_ext
->type
;
2702 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ENDA
) )
2704 isom_enda_t
*enda
= (isom_enda_t
*)wave_ext
;
2705 isom_bs_put_box_common( bs
, enda
);
2706 lsmash_bs_put_be16( bs
, enda
->littleEndian
);
2708 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_MP4A
) )
2710 isom_mp4a_t
*mp4a
= (isom_mp4a_t
*)wave_ext
;
2711 isom_bs_put_box_common( bs
, mp4a
);
2712 lsmash_bs_put_be32( bs
, mp4a
->unknown
);
2714 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_CHAN
) )
2716 isom_chan_t
*chan
= (isom_chan_t
*)wave_ext
;
2717 isom_bs_put_box_common( bs
, chan
);
2718 lsmash_bs_put_be32( bs
, chan
->channelLayoutTag
);
2719 lsmash_bs_put_be32( bs
, chan
->channelBitmap
);
2720 lsmash_bs_put_be32( bs
, chan
->numberChannelDescriptions
);
2721 if( chan
->channelDescriptions
)
2722 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
2724 isom_channel_description_t
*channelDescriptions
= (isom_channel_description_t
*)(&chan
->channelDescriptions
[i
]);
2725 lsmash_bs_put_be32( bs
, channelDescriptions
->channelLabel
);
2726 lsmash_bs_put_be32( bs
, channelDescriptions
->channelFlags
);
2727 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[0] );
2728 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[1] );
2729 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[2] );
2732 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ESDS
) )
2734 isom_esds_t
*esds
= (isom_esds_t
*)wave_ext
;
2736 || mp4sys_setup_summary_from_DecoderSpecificInfo( summary
, esds
->ES
) < 0
2737 || isom_append_structured_mp4sys_decoder_config( summary
->opaque
, esds
) < 0 )
2739 lsmash_bs_cleanup( bs
);
2745 /* Skip Format Box and Terminator Box since they are mandatory and fixed structure. */
2750 if( wave_ext
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2752 uint8_t *data
= wave_ext
->binary
;
2753 box_type
.fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
2754 lsmash_bs_put_bytes( bs
, wave_ext
->size
, wave_ext
->binary
);
2756 /* Export as binary string. */
2758 uint8_t *box_data
= lsmash_bs_export_data( bs
, &box_size
);
2759 lsmash_bs_empty( bs
);
2762 lsmash_bs_cleanup( bs
);
2765 /* Append as an unstructured CODEC specific info. */
2766 lsmash_codec_specific_data_type type
;
2767 if( box_type
.fourcc
== QT_BOX_TYPE_CHAN
.fourcc
)
2768 /* Complete audio channel layout is stored as binary string.
2769 * We distinguish it from one of the outside of 'wave' extension here. */
2770 type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
;
2773 type
= isom_get_codec_specific_data_type( box_type
.fourcc
);
2774 if( type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
)
2775 type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
;
2777 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2780 lsmash_free( box_data
);
2781 lsmash_bs_cleanup( bs
);
2784 specific
->data
.unstructured
= box_data
;
2785 specific
->size
= box_size
;
2786 if( lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2788 lsmash_destroy_codec_specific_data( specific
);
2789 lsmash_bs_cleanup( bs
);
2793 lsmash_bs_cleanup( bs
);
2798 if( box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2800 uint8_t *data
= box
->binary
;
2801 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
2802 lsmash_codec_specific_data_type type
= isom_get_codec_specific_data_type( fourcc
);
2803 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2806 specific
->size
= box
->size
;
2807 specific
->data
.unstructured
= lsmash_memdup( box
->binary
, box
->size
);
2808 if( !specific
->data
.unstructured
2809 || lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2811 lsmash_destroy_codec_specific_data( specific
);
2814 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
2815 || specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
2816 || specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
)
2818 specific
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2821 switch( specific
->type
)
2823 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
:
2825 lsmash_dts_specific_parameters_t
*param
= (lsmash_dts_specific_parameters_t
*)specific
->data
.structured
;
2826 summary
->sample_size
= param
->pcmSampleDepth
;
2827 summary
->samples_in_frame
= (summary
->frequency
* (512 << param
->FrameDuration
)) / param
->DTSSamplingFrequency
;
2830 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
:
2832 lsmash_ac3_specific_parameters_t
*param
= (lsmash_ac3_specific_parameters_t
*)specific
->data
.structured
;
2833 summary
->frequency
= ac3_get_sample_rate( param
);
2834 summary
->channels
= ac3_get_channel_count( param
);
2835 summary
->samples_in_frame
= 1536;
2838 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
:
2840 lsmash_eac3_specific_parameters_t
*param
= (lsmash_eac3_specific_parameters_t
*)specific
->data
.structured
;
2841 eac3_update_sample_rate( &summary
->frequency
, param
, NULL
);
2842 eac3_update_channel_count( &summary
->channels
, param
);
2843 summary
->samples_in_frame
= 1536;
2849 lsmash_destroy_codec_specific_data( specific
);
2853 /* Set the actual sampling rate. */
2854 if( actual_sampling_rate
)
2855 summary
->frequency
= actual_sampling_rate
;
2856 return (lsmash_summary_t
*)summary
;
2858 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
2862 lsmash_codec_specific_t
*lsmash_get_codec_specific_data( lsmash_summary_t
*summary
, uint32_t extension_number
)
2864 if( !summary
|| !summary
->opaque
)
2867 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
2868 if( ++i
== extension_number
)
2869 return (lsmash_codec_specific_t
*)entry
->data
;
2873 uint32_t lsmash_count_codec_specific_data( lsmash_summary_t
*summary
)
2875 if( !summary
|| !summary
->opaque
)
2877 return summary
->opaque
->list
.entry_count
;
2880 int isom_compare_opaque_extensions( lsmash_summary_t
*a
, lsmash_summary_t
*b
)
2883 uint32_t in_number_of_extensions
= lsmash_count_codec_specific_data( a
);
2884 uint32_t out_number_of_extensions
= lsmash_count_codec_specific_data( b
);
2885 if( out_number_of_extensions
!= in_number_of_extensions
)
2887 uint32_t active_number_of_extensions
= in_number_of_extensions
;
2888 uint32_t identical_count
= 0;
2889 for( uint32_t j
= 1; j
<= in_number_of_extensions
; j
++ )
2891 lsmash_codec_specific_t
*in_cs_orig
= lsmash_get_codec_specific_data( a
, j
);
2892 lsmash_codec_specific_t
*in_cs
;
2893 lsmash_codec_specific_format compare_format
= LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
;
2894 if( in_cs_orig
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
2896 if( in_cs_orig
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
2897 || in_cs_orig
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
2898 || in_cs_orig
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
)
2900 compare_format
= LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
;
2905 in_cs
= lsmash_convert_codec_specific_format( in_cs_orig
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2908 /* We don't support the format converter of this data type. */
2909 --active_number_of_extensions
;
2916 for( uint32_t k
= 1; k
<= out_number_of_extensions
; k
++ )
2918 lsmash_codec_specific_t
*out_cs_orig
= lsmash_get_codec_specific_data( b
, k
);
2919 if( out_cs_orig
->type
!= in_cs_orig
->type
)
2921 lsmash_codec_specific_t
*out_cs
;
2922 if( out_cs_orig
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
2924 if( compare_format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
2925 out_cs
= out_cs_orig
;
2928 out_cs
= lsmash_convert_codec_specific_format( out_cs_orig
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2934 out_cs
= out_cs_orig
;
2936 if( compare_format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
2937 identical
= out_cs
->size
== in_cs
->size
&& !memcmp( out_cs
->data
.unstructured
, in_cs
->data
.unstructured
, in_cs
->size
);
2940 if( in_cs
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
)
2942 lsmash_qt_video_common_t
*in_data
= (lsmash_qt_video_common_t
*)in_cs
->data
.structured
;
2943 lsmash_qt_video_common_t
*out_data
= (lsmash_qt_video_common_t
*)out_cs
->data
.structured
;
2944 identical
= in_data
->revision_level
== out_data
->revision_level
2945 && in_data
->vendor
== out_data
->vendor
2946 && in_data
->temporalQuality
== out_data
->temporalQuality
2947 && in_data
->spatialQuality
== out_data
->spatialQuality
2948 && in_data
->horizontal_resolution
== out_data
->horizontal_resolution
2949 && in_data
->vertical_resolution
== out_data
->vertical_resolution
2950 && in_data
->dataSize
== out_data
->dataSize
2951 && in_data
->frame_count
== out_data
->frame_count
2952 && in_data
->color_table_ID
== out_data
->color_table_ID
;
2954 else if( in_cs
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
)
2956 lsmash_qt_audio_common_t
*in_data
= (lsmash_qt_audio_common_t
*)in_cs
->data
.structured
;
2957 lsmash_qt_audio_common_t
*out_data
= (lsmash_qt_audio_common_t
*)out_cs
->data
.structured
;
2958 identical
= in_data
->revision_level
== out_data
->revision_level
2959 && in_data
->vendor
== out_data
->vendor
2960 && in_data
->compression_ID
== out_data
->compression_ID
;
2964 lsmash_qt_audio_format_specific_flags_t
*in_data
= (lsmash_qt_audio_format_specific_flags_t
*)in_cs
->data
.structured
;
2965 lsmash_qt_audio_format_specific_flags_t
*out_data
= (lsmash_qt_audio_format_specific_flags_t
*)out_cs
->data
.structured
;
2966 identical
= (in_data
->format_flags
== out_data
->format_flags
);
2969 if( out_cs
!= out_cs_orig
)
2970 lsmash_destroy_codec_specific_data( out_cs
);
2977 if( in_cs
!= in_cs_orig
)
2978 lsmash_destroy_codec_specific_data( in_cs
);
2980 return (identical_count
!= active_number_of_extensions
);
2983 int isom_get_implicit_qt_fixed_comp_audio_sample_quants
2985 isom_audio_entry_t
*audio
,
2986 uint32_t *samples_per_packet
,
2987 uint32_t *constant_bytes_per_frame
,
2988 uint32_t *sample_size
2991 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC3_AUDIO
) )
2993 *samples_per_packet
= 6;
2994 *constant_bytes_per_frame
= 2 * audio
->channelcount
;
2997 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC6_AUDIO
) )
2999 *samples_per_packet
= 6;
3000 *constant_bytes_per_frame
= audio
->channelcount
;
3003 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ADPCM17_AUDIO
) )
3005 *samples_per_packet
= 64;
3006 *constant_bytes_per_frame
= 34 * audio
->channelcount
;
3009 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_AGSM_AUDIO
) )
3011 *samples_per_packet
= 160;
3012 *constant_bytes_per_frame
= 33;
3015 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAW_AUDIO
)
3016 || lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ULAW_AUDIO
) )
3018 *samples_per_packet
= 1;
3019 *constant_bytes_per_frame
= audio
->channelcount
;