1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2012-2017 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
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 static int isom_is_dts_audio( lsmash_codec_type_t type
)
125 return lsmash_check_codec_type_identical( type
, ISOM_CODEC_TYPE_DTSC_AUDIO
)
126 || lsmash_check_codec_type_identical( type
, ISOM_CODEC_TYPE_DTSE_AUDIO
)
127 || lsmash_check_codec_type_identical( type
, ISOM_CODEC_TYPE_DTSH_AUDIO
)
128 || lsmash_check_codec_type_identical( type
, ISOM_CODEC_TYPE_DTSL_AUDIO
)
129 || lsmash_check_codec_type_identical( type
, ISOM_CODEC_TYPE_DTSX_AUDIO
)
130 || lsmash_check_codec_type_identical( type
, ISOM_CODEC_TYPE_DTSEL_AUDIO
)
131 || lsmash_check_codec_type_identical( type
, ISOM_CODEC_TYPE_DTSDL_AUDIO
);
134 int lsmash_convert_crop_into_clap( lsmash_crop_t crop
, uint32_t width
, uint32_t height
, lsmash_clap_t
*clap
)
136 if( !clap
|| crop
.top
.d
== 0 || crop
.bottom
.d
== 0 || crop
.left
.d
== 0 || crop
.right
.d
== 0 )
137 return LSMASH_ERR_FUNCTION_PARAM
;
138 uint64_t vertical_crop_lcm
= lsmash_get_lcm( crop
.top
.d
, crop
.bottom
.d
);
139 uint64_t horizontal_crop_lcm
= lsmash_get_lcm( crop
.left
.d
, crop
.right
.d
);
140 lsmash_rational_u64_t clap_height
;
141 lsmash_rational_u64_t clap_width
;
142 lsmash_rational_s64_t clap_horizontal_offset
;
143 lsmash_rational_s64_t clap_vertical_offset
;
144 clap_height
.d
= vertical_crop_lcm
;
145 clap_width
.d
= horizontal_crop_lcm
;
146 clap_horizontal_offset
.d
= 2 * vertical_crop_lcm
;
147 clap_vertical_offset
.d
= 2 * horizontal_crop_lcm
;
148 clap_height
.n
= height
* vertical_crop_lcm
149 - (crop
.top
.n
* (vertical_crop_lcm
/ crop
.top
.d
) + crop
.bottom
.n
* (vertical_crop_lcm
/ crop
.bottom
.d
));
150 clap_width
.n
= width
* horizontal_crop_lcm
151 - (crop
.left
.n
* (horizontal_crop_lcm
/ crop
.left
.d
) + crop
.right
.n
* (horizontal_crop_lcm
/ crop
.right
.d
));
152 clap_horizontal_offset
.n
= (int64_t)(crop
.left
.n
* (horizontal_crop_lcm
/ crop
.left
.d
))
153 - crop
.right
.n
* (horizontal_crop_lcm
/ crop
.right
.d
);
154 clap_vertical_offset
.n
= (int64_t)(crop
.top
.n
* (vertical_crop_lcm
/ crop
.top
.d
))
155 - crop
.bottom
.n
* (vertical_crop_lcm
/ crop
.bottom
.d
);
156 lsmash_reduce_fraction( &clap_height
.n
, &clap_height
.d
);
157 lsmash_reduce_fraction( &clap_width
.n
, &clap_width
.d
);
158 lsmash_reduce_fraction_su( &clap_vertical_offset
.n
, &clap_vertical_offset
.d
);
159 lsmash_reduce_fraction_su( &clap_horizontal_offset
.n
, &clap_horizontal_offset
.d
);
160 clap
->height
= (lsmash_rational_u32_t
){ clap_height
.n
, clap_height
.d
};
161 clap
->width
= (lsmash_rational_u32_t
){ clap_width
.n
, clap_width
.d
};
162 clap
->vertical_offset
= (lsmash_rational_s32_t
){ clap_vertical_offset
.n
, clap_vertical_offset
.d
};
163 clap
->horizontal_offset
= (lsmash_rational_s32_t
){ clap_horizontal_offset
.n
, clap_horizontal_offset
.d
};
167 int lsmash_convert_clap_into_crop( lsmash_clap_t clap
, uint32_t width
, uint32_t height
, lsmash_crop_t
*crop
)
169 if( !crop
|| clap
.height
.d
== 0 || clap
.vertical_offset
.d
== 0 || clap
.width
.d
== 0 || clap
.horizontal_offset
.d
== 0 )
170 return LSMASH_ERR_FUNCTION_PARAM
;
171 uint64_t clap_vertical_lcm
= lsmash_get_lcm( clap
.height
.d
, clap
.vertical_offset
.d
);
172 uint64_t clap_horizontal_lcm
= lsmash_get_lcm( clap
.width
.d
, clap
.horizontal_offset
.d
);
173 lsmash_rational_u64_t crop_top
;
174 lsmash_rational_u64_t crop_bottom
;
175 lsmash_rational_u64_t crop_left
;
176 lsmash_rational_u64_t crop_right
;
177 crop_top
.d
= 2 * clap_vertical_lcm
;
178 crop_bottom
.d
= 2 * clap_vertical_lcm
;
179 crop_left
.d
= 2 * clap_horizontal_lcm
;
180 crop_right
.d
= 2 * clap_horizontal_lcm
;
181 crop_top
.n
= (height
* crop_top
.d
- clap
.height
.n
* (crop_top
.d
/ clap
.height
.d
)) / 2
182 + clap
.vertical_offset
.n
* (crop_top
.d
/ clap
.vertical_offset
.d
);
183 crop_bottom
.n
= (height
* crop_bottom
.d
- clap
.height
.n
* (crop_bottom
.d
/ clap
.height
.d
)) / 2
184 - clap
.vertical_offset
.n
* (crop_bottom
.d
/ clap
.vertical_offset
.d
);
185 crop_left
.n
= (width
* crop_left
.d
- clap
.width
.n
* (crop_left
.d
/ clap
.width
.d
)) / 2
186 + clap
.horizontal_offset
.n
* (crop_left
.d
/ clap
.horizontal_offset
.d
);
187 crop_right
.n
= (width
* crop_right
.d
- clap
.width
.n
* (crop_right
.d
/ clap
.width
.d
)) / 2
188 - clap
.horizontal_offset
.n
* (crop_right
.d
/ clap
.horizontal_offset
.d
);
189 lsmash_reduce_fraction( &crop_top
.n
, &crop_top
.d
);
190 lsmash_reduce_fraction( &crop_bottom
.n
, &crop_bottom
.d
);
191 lsmash_reduce_fraction( &crop_left
.n
, &crop_left
.d
);
192 lsmash_reduce_fraction( &crop_right
.n
, &crop_right
.d
);
193 crop
->top
= (lsmash_rational_u32_t
){ crop_top
.n
, crop_top
.d
};
194 crop
->bottom
= (lsmash_rational_u32_t
){ crop_bottom
.n
, crop_bottom
.d
};
195 crop
->left
= (lsmash_rational_u32_t
){ crop_left
.n
, crop_left
.d
};
196 crop
->right
= (lsmash_rational_u32_t
){ crop_right
.n
, crop_right
.d
};
200 static void isom_destruct_nothing( void *data
)
205 static int isom_initialize_structured_codec_specific_data( lsmash_codec_specific_t
*specific
)
207 extern void mp4sys_destruct_decoder_config( void * );
208 extern void h264_destruct_specific_data( void * );
209 extern void hevc_destruct_specific_data( void * );
210 extern void vc1_destruct_specific_data( void * );
211 extern void dts_destruct_specific_data( void * );
212 switch( specific
->type
)
214 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
:
215 specific
->size
= sizeof(lsmash_mp4sys_decoder_parameters_t
);
216 specific
->destruct
= mp4sys_destruct_decoder_config
;
218 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
:
219 specific
->size
= sizeof(lsmash_h264_specific_parameters_t
);
220 specific
->destruct
= h264_destruct_specific_data
;
222 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
:
223 specific
->size
= sizeof(lsmash_hevc_specific_parameters_t
);
224 specific
->destruct
= hevc_destruct_specific_data
;
226 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
:
227 specific
->size
= sizeof(lsmash_vc1_specific_parameters_t
);
228 specific
->destruct
= vc1_destruct_specific_data
;
230 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
:
231 specific
->size
= sizeof(lsmash_ac3_specific_parameters_t
);
232 specific
->destruct
= lsmash_free
;
234 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
:
235 specific
->size
= sizeof(lsmash_eac3_specific_parameters_t
);
236 specific
->destruct
= lsmash_free
;
238 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
:
239 specific
->size
= sizeof(lsmash_dts_specific_parameters_t
);
240 specific
->destruct
= dts_destruct_specific_data
;
242 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
:
243 specific
->size
= sizeof(lsmash_alac_specific_parameters_t
);
244 specific
->destruct
= lsmash_free
;
246 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
:
247 specific
->size
= sizeof(lsmash_isom_sample_scale_t
);
248 specific
->destruct
= lsmash_free
;
250 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
:
251 specific
->size
= sizeof(lsmash_h264_bitrate_t
);
252 specific
->destruct
= lsmash_free
;
254 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
:
255 specific
->size
= sizeof(lsmash_qt_video_common_t
);
256 specific
->destruct
= lsmash_free
;
258 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
:
259 specific
->size
= sizeof(lsmash_qt_audio_common_t
);
260 specific
->destruct
= lsmash_free
;
262 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
:
263 specific
->size
= sizeof(lsmash_qt_audio_format_specific_flags_t
);
264 specific
->destruct
= lsmash_free
;
266 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
267 specific
->size
= sizeof(lsmash_codec_global_header_t
);
268 specific
->destruct
= global_destruct_specific_data
;
270 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
:
271 specific
->size
= sizeof(lsmash_qt_field_info_t
);
272 specific
->destruct
= lsmash_free
;
274 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
:
275 specific
->size
= sizeof(lsmash_qt_pixel_format_t
);
276 specific
->destruct
= lsmash_free
;
278 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
:
279 specific
->size
= sizeof(lsmash_qt_significant_bits_t
);
280 specific
->destruct
= lsmash_free
;
282 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
:
283 specific
->size
= sizeof(lsmash_qt_audio_channel_layout_t
);
284 specific
->destruct
= lsmash_free
;
286 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_RTP_HINT_COMMON
:
287 specific
->size
= sizeof(lsmash_isom_rtp_reception_hint_t
);
288 specific
->destruct
= lsmash_free
;
292 specific
->destruct
= isom_destruct_nothing
;
295 specific
->data
.structured
= lsmash_malloc_zero( specific
->size
);
296 if( !specific
->data
.structured
)
299 specific
->destruct
= NULL
;
300 return LSMASH_ERR_MEMORY_ALLOC
;
305 static inline int isom_initialize_codec_specific_data( lsmash_codec_specific_t
*specific
,
306 lsmash_codec_specific_data_type type
,
307 lsmash_codec_specific_format format
)
309 specific
->type
= type
;
310 specific
->format
= format
;
311 if( format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
313 int err
= isom_initialize_structured_codec_specific_data( specific
);
319 specific
->data
.unstructured
= NULL
;
321 specific
->destruct
= (lsmash_codec_specific_destructor_t
)lsmash_free
;
326 void lsmash_destroy_codec_specific_data( lsmash_codec_specific_t
*specific
)
330 if( specific
->destruct
)
332 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
334 if( specific
->data
.structured
)
335 specific
->destruct( specific
->data
.structured
);
339 if( specific
->data
.unstructured
)
340 specific
->destruct( specific
->data
.unstructured
);
343 lsmash_free( specific
);
346 lsmash_codec_specific_t
*lsmash_create_codec_specific_data( lsmash_codec_specific_data_type type
, lsmash_codec_specific_format format
)
348 lsmash_codec_specific_t
*specific
= lsmash_malloc( sizeof(lsmash_codec_specific_t
) );
351 if( isom_initialize_codec_specific_data( specific
, type
, format
) < 0 )
353 lsmash_destroy_codec_specific_data( specific
);
359 static int isom_duplicate_structured_specific_data( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
361 extern int mp4sys_copy_decoder_config( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
362 extern int h264_copy_codec_specific( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
363 extern int hevc_copy_codec_specific( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
364 extern int vc1_copy_codec_specific( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
365 extern int dts_copy_codec_specific( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
366 void *src_data
= src
->data
.structured
;
367 void *dst_data
= dst
->data
.structured
;
370 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
:
371 return mp4sys_copy_decoder_config( dst
, src
);
372 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
:
373 return h264_copy_codec_specific( dst
, src
);
374 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
:
375 return hevc_copy_codec_specific( dst
, src
);
376 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
:
377 return vc1_copy_codec_specific( dst
, src
);
378 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
:
379 *(lsmash_ac3_specific_parameters_t
*)dst_data
= *(lsmash_ac3_specific_parameters_t
*)src_data
;
381 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
:
382 *(lsmash_eac3_specific_parameters_t
*)dst_data
= *(lsmash_eac3_specific_parameters_t
*)src_data
;
384 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
:
385 return dts_copy_codec_specific( dst
, src
);
386 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
:
387 *(lsmash_alac_specific_parameters_t
*)dst_data
= *(lsmash_alac_specific_parameters_t
*)src_data
;
389 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
:
390 *(lsmash_isom_sample_scale_t
*)dst_data
= *(lsmash_isom_sample_scale_t
*)src_data
;
392 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
:
393 *(lsmash_h264_bitrate_t
*)dst_data
= *(lsmash_h264_bitrate_t
*)src_data
;
395 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
:
396 *(lsmash_qt_video_common_t
*)dst_data
= *(lsmash_qt_video_common_t
*)src_data
;
398 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
:
399 *(lsmash_qt_audio_common_t
*)dst_data
= *(lsmash_qt_audio_common_t
*)src_data
;
401 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
:
402 *(lsmash_qt_audio_format_specific_flags_t
*)dst_data
= *(lsmash_qt_audio_format_specific_flags_t
*)src_data
;
404 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
406 lsmash_codec_global_header_t
*src_global
= (lsmash_codec_global_header_t
*)src_data
;
407 if( src_global
->header_data
&& src_global
->header_size
)
409 lsmash_codec_global_header_t
*dst_global
= (lsmash_codec_global_header_t
*)dst_data
;
410 dst_global
->header_data
= lsmash_memdup( src_global
->header_data
, src_global
->header_size
);
411 if( !dst_global
->header_data
)
412 return LSMASH_ERR_MEMORY_ALLOC
;
413 dst_global
->header_size
= src_global
->header_size
;
417 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
:
418 *(lsmash_qt_field_info_t
*)dst_data
= *(lsmash_qt_field_info_t
*)src_data
;
420 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
:
421 *(lsmash_qt_pixel_format_t
*)dst_data
= *(lsmash_qt_pixel_format_t
*)src_data
;
423 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
:
424 *(lsmash_qt_significant_bits_t
*)dst_data
= *(lsmash_qt_significant_bits_t
*)src_data
;
426 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL
:
427 *(lsmash_qt_gamma_t
*)dst_data
= *(lsmash_qt_gamma_t
*)src_data
;
429 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_CONTENT_LIGHT_LEVEL_INFO
:
430 *(lsmash_qt_content_light_level_info_t
*)dst_data
= *(lsmash_qt_content_light_level_info_t
*)src_data
;
432 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_MASTERING_DISPLAY_COLOR_VOLUME
:
433 *(lsmash_qt_mastering_display_color_volume_t
*)dst_data
= *(lsmash_qt_mastering_display_color_volume_t
*)src_data
;
435 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
:
436 *(lsmash_qt_audio_channel_layout_t
*)dst_data
= *(lsmash_qt_audio_channel_layout_t
*)src_data
;
438 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_RTP_HINT_COMMON
:
439 *(lsmash_isom_rtp_reception_hint_t
*)dst_data
= *(lsmash_isom_rtp_reception_hint_t
*)src_data
;
442 return LSMASH_ERR_NAMELESS
;
446 lsmash_codec_specific_t
*isom_duplicate_codec_specific_data( lsmash_codec_specific_t
*specific
)
450 lsmash_codec_specific_t
*dup
= lsmash_create_codec_specific_data( specific
->type
, specific
->format
);
453 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
455 if( isom_duplicate_structured_specific_data( dup
, specific
) < 0 )
457 lsmash_destroy_codec_specific_data( dup
);
463 dup
->data
.unstructured
= lsmash_memdup( specific
->data
.unstructured
, specific
->size
);
464 if( !dup
->data
.unstructured
)
466 lsmash_destroy_codec_specific_data( dup
);
470 dup
->size
= specific
->size
;
474 static int isom_construct_global_specific_header( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
476 if( src
->size
< ISOM_BASEBOX_COMMON_SIZE
)
477 return LSMASH_ERR_INVALID_DATA
;
478 lsmash_codec_global_header_t
*global
= (lsmash_codec_global_header_t
*)dst
->data
.structured
;
479 uint8_t *data
= src
->data
.unstructured
;
480 uint64_t size
= LSMASH_GET_BE32( data
);
481 data
+= ISOM_BASEBOX_COMMON_SIZE
;
484 size
= LSMASH_GET_BE64( data
);
487 if( size
!= src
->size
)
488 return LSMASH_ERR_INVALID_DATA
;
489 global
->header_size
= size
- ISOM_BASEBOX_COMMON_SIZE
;
490 if( data
!= src
->data
.unstructured
+ ISOM_BASEBOX_COMMON_SIZE
)
491 global
->header_size
-= 8; /* largesize */
492 if( global
->header_size
)
494 global
->header_data
= lsmash_memdup( data
, global
->header_size
);
495 if( !global
->header_data
)
496 return LSMASH_ERR_MEMORY_ALLOC
;
501 static int isom_construct_audio_channel_layout( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
503 if( src
->size
< ISOM_FULLBOX_COMMON_SIZE
+ 12 )
504 return LSMASH_ERR_INVALID_DATA
;
505 lsmash_qt_audio_channel_layout_t
*layout
= (lsmash_qt_audio_channel_layout_t
*)dst
->data
.structured
;
506 uint8_t *data
= src
->data
.unstructured
;
507 uint64_t size
= LSMASH_GET_BE32( data
);
508 data
+= ISOM_FULLBOX_COMMON_SIZE
;
511 size
= LSMASH_GET_BE64( data
);
514 if( size
!= src
->size
)
515 return LSMASH_ERR_INVALID_DATA
;
516 layout
->channelLayoutTag
= LSMASH_GET_BE32( &data
[0] );
517 layout
->channelBitmap
= LSMASH_GET_BE32( &data
[4] );
522 static int codec_construct_qt_audio_decompression_info( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
524 if( src
->size
< ISOM_BASEBOX_COMMON_SIZE
)
525 return LSMASH_ERR_INVALID_DATA
;
526 uint8_t *data
= src
->data
.unstructured
;
529 uint32_t offset
= isom_read_box_size_and_type_from_binary_string( &data
, &size
, &type
);
530 if( size
!= src
->size
)
531 return LSMASH_ERR_INVALID_DATA
;
532 uint8_t *end
= src
->data
.unstructured
+ src
->size
;
533 isom_wave_t
*wave
= isom_add_wave( isom_non_existing_audio_entry() );
534 if( LSMASH_IS_NON_EXISTING_BOX( wave
) )
535 return LSMASH_ERR_MEMORY_ALLOC
;
536 wave
->type
= QT_BOX_TYPE_WAVE
;
537 for( uint8_t *pos
= data
; pos
+ ISOM_BASEBOX_COMMON_SIZE
<= end
; )
539 offset
= isom_read_box_size_and_type_from_binary_string( &pos
, &size
, &type
);
542 case QT_BOX_TYPE_FRMA
:
545 return LSMASH_ERR_INVALID_DATA
;
546 isom_frma_t
*frma
= isom_add_frma( wave
);
547 if( LSMASH_IS_NON_EXISTING_BOX( frma
) )
548 return LSMASH_ERR_NAMELESS
;
549 frma
->data_format
= LSMASH_GET_BE32( pos
);
553 case QT_BOX_TYPE_ENDA
:
556 return LSMASH_ERR_INVALID_DATA
;
557 isom_enda_t
*enda
= isom_add_enda( wave
);
558 if( LSMASH_IS_NON_EXISTING_BOX( enda
) )
559 return LSMASH_ERR_NAMELESS
;
560 enda
->littleEndian
= LSMASH_GET_BE16( pos
);
563 case QT_BOX_TYPE_MP4A
:
566 return LSMASH_ERR_INVALID_DATA
;
567 isom_mp4a_t
*mp4a
= isom_add_mp4a( wave
);
568 if( LSMASH_IS_NON_EXISTING_BOX( mp4a
) )
569 return LSMASH_ERR_NAMELESS
;
570 mp4a
->unknown
= LSMASH_GET_BE32( pos
);
574 case QT_BOX_TYPE_TERMINATOR
:
576 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_terminator( wave
) ) )
577 return LSMASH_ERR_NAMELESS
;
582 isom_unknown_box_t
*box
= lsmash_malloc_zero( sizeof(isom_unknown_box_t
) );
583 if( LSMASH_IS_NON_EXISTING_BOX( box
) )
584 return LSMASH_ERR_MEMORY_ALLOC
;
585 isom_init_box_common( box
, wave
, type
, isom_remove_unknown_box
);
586 box
->unknown_size
= size
- offset
;
587 box
->unknown_field
= lsmash_memdup( pos
, box
->unknown_size
);
588 if( !box
->unknown_field
)
590 isom_remove_box_by_itself( box
);
591 return LSMASH_ERR_MEMORY_ALLOC
;
593 if( lsmash_list_add_entry( &wave
->extensions
, box
) < 0 )
595 isom_remove_unknown_box( box
);
596 return LSMASH_ERR_MEMORY_ALLOC
;
598 pos
+= box
->unknown_size
;
607 /* structured <-> unstructured conversion might be irreversible by CODEC
608 * since structured formats we defined don't always have all contents included in unstructured data. */
609 lsmash_codec_specific_t
*lsmash_convert_codec_specific_format( lsmash_codec_specific_t
*specific
, lsmash_codec_specific_format format
)
611 if( !specific
|| format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSPECIFIED
)
613 if( format
== specific
->format
)
614 return isom_duplicate_codec_specific_data( specific
);
615 lsmash_codec_specific_t
*dst
= lsmash_create_codec_specific_data( specific
->type
, format
);
618 if( format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
619 /* structured -> unstructured */
620 switch( specific
->type
)
622 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
:
623 dst
->data
.unstructured
= lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t
*)specific
->data
.structured
, &dst
->size
);
624 if( !dst
->data
.unstructured
)
627 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
:
628 dst
->data
.unstructured
= lsmash_create_h264_specific_info( (lsmash_h264_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
629 if( !dst
->data
.unstructured
)
632 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
:
633 dst
->data
.unstructured
= lsmash_create_hevc_specific_info( (lsmash_hevc_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
634 if( !dst
->data
.unstructured
)
637 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
:
638 dst
->data
.unstructured
= lsmash_create_vc1_specific_info( (lsmash_vc1_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
639 if( !dst
->data
.unstructured
)
642 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
:
643 dst
->data
.unstructured
= lsmash_create_ac3_specific_info( (lsmash_ac3_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
644 if( !dst
->data
.unstructured
)
647 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
:
648 dst
->data
.unstructured
= lsmash_create_eac3_specific_info( (lsmash_eac3_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
649 if( !dst
->data
.unstructured
)
652 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
:
653 dst
->data
.unstructured
= lsmash_create_dts_specific_info( (lsmash_dts_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
654 if( !dst
->data
.unstructured
)
657 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
:
658 dst
->data
.unstructured
= lsmash_create_alac_specific_info( (lsmash_alac_specific_parameters_t
*)specific
->data
.structured
, &dst
->size
);
659 if( !dst
->data
.unstructured
)
662 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
664 lsmash_bs_t
*bs
= lsmash_bs_create();
667 lsmash_codec_global_header_t
*global
= specific
->data
.structured
;
668 lsmash_bs_put_be32( bs
, ISOM_BASEBOX_COMMON_SIZE
+ global
->header_size
);
669 lsmash_bs_put_be32( bs
, QT_BOX_TYPE_GLBL
.fourcc
);
670 lsmash_bs_put_bytes( bs
, global
->header_size
, global
->header_data
);
671 dst
->data
.unstructured
= lsmash_bs_export_data( bs
, &dst
->size
);
672 lsmash_bs_cleanup( bs
);
673 if( !dst
->data
.unstructured
|| dst
->size
!= (ISOM_BASEBOX_COMMON_SIZE
+ global
->header_size
) )
680 else if( format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
682 /* unstructured -> structured */
683 extern int mp4sys_construct_decoder_config( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
684 extern int h264_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
685 extern int hevc_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
686 extern int vc1_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
687 extern int ac3_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
688 extern int eac3_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
689 extern int dts_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
690 extern int alac_construct_specific_parameters( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
693 lsmash_codec_specific_data_type data_type
;
694 int (*constructor
)( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* );
695 } codec_specific_format_constructor_table
[] =
697 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
, mp4sys_construct_decoder_config
},
698 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
, h264_construct_specific_parameters
},
699 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
, hevc_construct_specific_parameters
},
700 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
, vc1_construct_specific_parameters
},
701 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
, ac3_construct_specific_parameters
},
702 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
, eac3_construct_specific_parameters
},
703 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
, dts_construct_specific_parameters
},
704 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
, alac_construct_specific_parameters
},
705 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
, isom_construct_global_specific_header
},
706 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
, isom_construct_audio_channel_layout
},
707 { LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
, NULL
}
709 int (*constructor
)( lsmash_codec_specific_t
*, lsmash_codec_specific_t
* ) = NULL
;
710 for( int i
= 0; codec_specific_format_constructor_table
[i
].constructor
; i
++ )
711 if( specific
->type
== codec_specific_format_constructor_table
[i
].data_type
)
713 constructor
= codec_specific_format_constructor_table
[i
].constructor
;
716 if( constructor
&& !constructor( dst
, specific
) )
720 lsmash_destroy_codec_specific_data( dst
);
724 static inline void isom_set_default_compressorname( char *compressorname
, lsmash_codec_type_t sample_type
)
726 static struct compressorname_table_tag
728 lsmash_codec_type_t type
;
730 } compressorname_table
[33] = { { LSMASH_CODEC_TYPE_INITIALIZER
, { '\0' } } };
731 if( compressorname_table
[0].name
[0] == '\0' )
734 #define ADD_COMPRESSORNAME_TABLE( type, name ) compressorname_table[i++] = (struct compressorname_table_tag){ type, name }
735 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC1_VIDEO
, "\012AVC Coding" );
736 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC2_VIDEO
, "\012AVC Coding" );
737 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC3_VIDEO
, "\012AVC Coding" );
738 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVC4_VIDEO
, "\012AVC Coding" );
739 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_AVCP_VIDEO
, "\016AVC Parameters" );
740 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HVC1_VIDEO
, "\013HEVC Coding" );
741 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_HEV1_VIDEO
, "\013HEVC Coding" );
742 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_SVC1_VIDEO
, "\012SVC Coding" );
743 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC1_VIDEO
, "\012MVC Coding" );
744 ADD_COMPRESSORNAME_TABLE( ISOM_CODEC_TYPE_MVC2_VIDEO
, "\012MVC Coding" );
745 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCH_VIDEO
, "\023Apple ProRes 422 (HQ)" );
746 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCN_VIDEO
, "\023Apple ProRes 422 (SD)" );
747 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCS_VIDEO
, "\023Apple ProRes 422 (LT)" );
748 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_APCO_VIDEO
, "\026Apple ProRes 422 (Proxy)" );
749 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4H_VIDEO
, "\019Apple ProRes 4444" );
750 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_AP4X_VIDEO
, "\022Apple ProRes 4444 XQ" );
751 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVPP_VIDEO
, "\014DVCPRO - PAL" );
752 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5N_VIDEO
, "\017DVCPRO50 - NTSC" );
753 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DV5P_VIDEO
, "\016DVCPRO50 - PAL" );
754 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH2_VIDEO
, "\019DVCPRO HD 1080p25" );
755 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH3_VIDEO
, "\019DVCPRO HD 1080p30" );
756 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH5_VIDEO
, "\019DVCPRO HD 1080i50" );
757 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVH6_VIDEO
, "\019DVCPRO HD 1080i60" );
758 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHP_VIDEO
, "\018DVCPRO HD 720p60" );
759 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_DVHQ_VIDEO
, "\018DVCPRO HD 720p50" );
760 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRA_VIDEO
, "\017Ut Video (ULRA)" );
761 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULRG_VIDEO
, "\017Ut Video (ULRG)" );
762 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY0_VIDEO
, "\017Ut Video (ULY0)" );
763 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULY2_VIDEO
, "\017Ut Video (ULY2)" );
764 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH0_VIDEO
, "\017Ut Video (ULH0)" );
765 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_ULH2_VIDEO
, "\017Ut Video (ULH2)" );
766 ADD_COMPRESSORNAME_TABLE( QT_CODEC_TYPE_UQY2_VIDEO
, "\021Ut Video Pro (UQY2)" );
767 ADD_COMPRESSORNAME_TABLE( LSMASH_CODEC_TYPE_UNSPECIFIED
, { '\0' } );
768 #undef ADD_COMPRESSORNAME_TABLE
770 for( int i
= 0; compressorname_table
[i
].name
[0] != '\0'; i
++ )
771 if( lsmash_check_codec_type_identical( sample_type
, compressorname_table
[i
].type
) )
773 strcpy( compressorname
, compressorname_table
[i
].name
);
778 lsmash_codec_specific_t
*isom_get_codec_specific( lsmash_codec_specific_list_t
*opaque
, lsmash_codec_specific_data_type type
)
780 for( lsmash_entry_t
*entry
= opaque
->list
.head
; entry
; entry
= entry
->next
)
782 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
783 if( !specific
|| specific
->type
!= type
)
790 static int isom_check_valid_summary( lsmash_summary_t
*summary
)
793 return LSMASH_ERR_NAMELESS
;
795 temp_box
.type
= summary
->sample_type
;
796 temp_box
.manager
= summary
->summary_type
== LSMASH_SUMMARY_TYPE_AUDIO
? LSMASH_AUDIO_DESCRIPTION
: 0;
797 if( isom_is_lpcm_audio( &temp_box
) )
799 if( isom_get_codec_specific( summary
->opaque
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
) )
801 return LSMASH_ERR_INVALID_DATA
;
803 if( isom_is_uncompressed_ycbcr( summary
->sample_type
) )
805 if( isom_get_codec_specific( summary
->opaque
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
) )
807 if( !lsmash_check_codec_type_identical( summary
->sample_type
, QT_CODEC_TYPE_V216_VIDEO
) )
811 return LSMASH_ERR_INVALID_DATA
;
813 lsmash_codec_type_t sample_type
= summary
->sample_type
;
814 lsmash_codec_specific_data_type required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED
;
815 if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC1_VIDEO
)
816 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC2_VIDEO
)
817 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC3_VIDEO
)
818 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC4_VIDEO
) )
819 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
;
820 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_HVC1_VIDEO
)
821 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_HEV1_VIDEO
) )
822 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
;
823 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_VC_1_VIDEO
) )
824 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
;
825 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULRA_VIDEO
)
826 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULRG_VIDEO
)
827 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULY0_VIDEO
)
828 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULY2_VIDEO
)
829 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULH0_VIDEO
)
830 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ULH2_VIDEO
)
831 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_UQY2_VIDEO
) )
832 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
;
833 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_V216_VIDEO
) )
834 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
;
835 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4V_VIDEO
)
836 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4A_AUDIO
)
837 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_MP4A_AUDIO
) )
838 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
;
839 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AC_3_AUDIO
) )
840 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
;
841 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_EC_3_AUDIO
) )
842 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
;
843 else if( isom_is_dts_audio( sample_type
) )
844 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
;
845 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_ALAC_AUDIO
)
846 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
847 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
;
848 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_RRTP_HINT
) )
849 required_data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_RTP_HINT_COMMON
;
850 if( required_data_type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNSPECIFIED
)
852 return isom_get_codec_specific( summary
->opaque
, required_data_type
) ? 0 : LSMASH_ERR_INVALID_DATA
;
855 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
)
857 lsmash_box_type_t box_type
= LSMASH_BOX_TYPE_INITIALIZER
;
858 box_type
.fourcc
= fourcc
;
859 #define GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
860 else if( (codec_type.user.fourcc == 0 \
861 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
862 && box_type.fourcc == predefined_box_type.fourcc ) \
863 box_type = predefined_box_type
865 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC1_VIDEO
, ISOM_BOX_TYPE_AVCC
);
866 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC2_VIDEO
, ISOM_BOX_TYPE_AVCC
);
867 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC3_VIDEO
, ISOM_BOX_TYPE_AVCC
);
868 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVC4_VIDEO
, ISOM_BOX_TYPE_AVCC
);
869 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AVCP_VIDEO
, ISOM_BOX_TYPE_AVCC
);
870 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HVC1_VIDEO
, ISOM_BOX_TYPE_HVCC
);
871 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_HEV1_VIDEO
, ISOM_BOX_TYPE_HVCC
);
872 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_VC_1_VIDEO
, ISOM_BOX_TYPE_DVC1
);
873 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4V_VIDEO
, ISOM_BOX_TYPE_ESDS
);
874 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, ISOM_BOX_TYPE_BTRT
);
875 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_FIEL
);
876 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_CSPC
);
877 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_SGBT
);
878 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_GAMA
);
879 GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_GLBL
);
880 #undef GUESS_VIDEO_CODEC_SPECIFIC_BOX_TYPE
884 static int isom_setup_visual_description( isom_stsd_t
*stsd
, lsmash_video_summary_t
*summary
)
886 if( !summary
|| LSMASH_IS_NON_EXISTING_BOX( stsd
->parent
->parent
->parent
->parent
) )
887 return LSMASH_ERR_NAMELESS
;
888 int err
= isom_check_valid_summary( (lsmash_summary_t
*)summary
);
891 isom_visual_entry_t
*visual
= isom_add_visual_description( stsd
, summary
->sample_type
);
892 if( LSMASH_IS_NON_EXISTING_BOX( visual
) )
893 return LSMASH_ERR_NAMELESS
;
894 visual
->data_reference_index
= summary
->data_ref_index
;
896 visual
->revision_level
= 0;
898 visual
->temporalQuality
= 0;
899 visual
->spatialQuality
= 0;
900 visual
->width
= (uint16_t)summary
->width
;
901 visual
->height
= (uint16_t)summary
->height
;
902 visual
->horizresolution
= 0x00480000;
903 visual
->vertresolution
= 0x00480000;
904 visual
->dataSize
= 0;
905 visual
->frame_count
= 1;
906 visual
->depth
= isom_is_qt_video( visual
->type
) || isom_is_nalff( visual
->type
)
907 ? summary
->depth
: 0x0018;
908 visual
->color_table_ID
= -1;
909 if( summary
->compressorname
[0] == '\0' )
910 isom_set_default_compressorname( visual
->compressorname
, visual
->type
);
913 memcpy( visual
->compressorname
, summary
->compressorname
, 32 );
914 visual
->compressorname
[32] = '\0';
916 err
= LSMASH_ERR_NAMELESS
;
917 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
919 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
922 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
923 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
924 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
925 switch( specific
->type
)
927 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
:
929 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
931 lsmash_qt_video_common_t
*data
= (lsmash_qt_video_common_t
*)specific
->data
.structured
;
932 visual
->revision_level
= data
->revision_level
;
933 visual
->vendor
= data
->vendor
;
934 visual
->temporalQuality
= data
->temporalQuality
;
935 visual
->spatialQuality
= data
->spatialQuality
;
936 visual
->horizresolution
= data
->horizontal_resolution
;
937 visual
->vertresolution
= data
->vertical_resolution
;
938 visual
->dataSize
= data
->dataSize
;
939 visual
->frame_count
= data
->frame_count
;
940 visual
->color_table_ID
= data
->color_table_ID
;
941 if( data
->color_table_ID
== 0 )
943 lsmash_qt_color_table_t
*src_ct
= &data
->color_table
;
944 uint16_t element_count
= LSMASH_MIN( src_ct
->size
+ 1, 256 );
945 isom_qt_color_array_t
*dst_array
= lsmash_malloc_zero( element_count
* sizeof(isom_qt_color_array_t
) );
948 err
= LSMASH_ERR_MEMORY_ALLOC
;
951 isom_qt_color_table_t
*dst_ct
= &visual
->color_table
;
952 dst_ct
->array
= dst_array
;
953 dst_ct
->seed
= src_ct
->seed
;
954 dst_ct
->flags
= src_ct
->flags
;
955 dst_ct
->size
= src_ct
->size
;
956 for( uint16_t i
= 0; i
< element_count
; i
++ )
958 dst_array
[i
].value
= src_ct
->array
[i
].unused
;
959 dst_array
[i
].r
= src_ct
->array
[i
].r
;
960 dst_array
[i
].g
= src_ct
->array
[i
].g
;
961 dst_array
[i
].b
= src_ct
->array
[i
].b
;
966 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
:
968 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
971 lsmash_isom_sample_scale_t
*data
= (lsmash_isom_sample_scale_t
*)cs
->data
.structured
;
972 isom_stsl_t
*stsl
= isom_add_stsl( visual
);
973 if( LSMASH_IS_NON_EXISTING_BOX( stsl
) )
975 lsmash_destroy_codec_specific_data( cs
);
978 stsl
->constraint_flag
= data
->constraint_flag
;
979 stsl
->scale_method
= data
->scale_method
;
980 stsl
->display_center_x
= data
->display_center_x
;
981 stsl
->display_center_y
= data
->display_center_y
;
982 lsmash_destroy_codec_specific_data( cs
);
985 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
:
987 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
990 lsmash_h264_bitrate_t
*data
= (lsmash_h264_bitrate_t
*)cs
->data
.structured
;
991 isom_btrt_t
*btrt
= isom_add_btrt( visual
);
992 if( LSMASH_IS_NON_EXISTING_BOX( btrt
) )
994 lsmash_destroy_codec_specific_data( cs
);
997 btrt
->bufferSizeDB
= data
->bufferSizeDB
;
998 btrt
->maxBitrate
= data
->maxBitrate
;
999 btrt
->avgBitrate
= data
->avgBitrate
;
1000 lsmash_destroy_codec_specific_data( cs
);
1003 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
:
1005 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1008 lsmash_qt_field_info_t
*data
= (lsmash_qt_field_info_t
*)cs
->data
.structured
;
1009 isom_fiel_t
*fiel
= isom_add_fiel( visual
);
1010 if( LSMASH_IS_NON_EXISTING_BOX( fiel
) )
1012 lsmash_destroy_codec_specific_data( cs
);
1015 fiel
->fields
= data
->fields
;
1016 fiel
->detail
= data
->detail
;
1017 lsmash_destroy_codec_specific_data( cs
);
1020 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
:
1022 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1025 lsmash_qt_pixel_format_t
*data
= (lsmash_qt_pixel_format_t
*)cs
->data
.structured
;
1026 isom_cspc_t
*cspc
= isom_add_cspc( visual
);
1027 if( LSMASH_IS_NON_EXISTING_BOX( cspc
) )
1029 lsmash_destroy_codec_specific_data( cs
);
1032 cspc
->pixel_format
= data
->pixel_format
;
1033 lsmash_destroy_codec_specific_data( cs
);
1036 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
:
1038 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1041 lsmash_qt_significant_bits_t
*data
= (lsmash_qt_significant_bits_t
*)cs
->data
.structured
;
1042 isom_sgbt_t
*sgbt
= isom_add_sgbt( visual
);
1043 if( LSMASH_IS_NON_EXISTING_BOX( sgbt
) )
1045 lsmash_destroy_codec_specific_data( cs
);
1048 sgbt
->significantBits
= data
->significantBits
;
1049 lsmash_destroy_codec_specific_data( cs
);
1052 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL
:
1054 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1057 lsmash_qt_gamma_t
*data
= (lsmash_qt_gamma_t
*)cs
->data
.structured
;
1058 isom_gama_t
*gama
= isom_add_gama( visual
);
1059 if( LSMASH_IS_NON_EXISTING_BOX( gama
) )
1061 lsmash_destroy_codec_specific_data( cs
);
1064 gama
->level
= data
->level
;
1065 lsmash_destroy_codec_specific_data( cs
);
1068 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_CONTENT_LIGHT_LEVEL_INFO
:
1070 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1073 lsmash_qt_content_light_level_info_t
*data
= (lsmash_qt_content_light_level_info_t
*)cs
->data
.structured
;
1074 isom_clli_t
*clli
= isom_add_clli( visual
);
1075 if( LSMASH_IS_NON_EXISTING_BOX( clli
) )
1077 lsmash_destroy_codec_specific_data( cs
);
1080 clli
->max_content_light_level
= data
->max_content_light_level
;
1081 clli
->max_pic_average_light_level
= data
->max_pic_average_light_level
;
1082 lsmash_destroy_codec_specific_data( cs
);
1085 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_MASTERING_DISPLAY_COLOR_VOLUME
:
1087 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1090 lsmash_qt_mastering_display_color_volume_t
*data
= (lsmash_qt_mastering_display_color_volume_t
*)cs
->data
.structured
;
1091 isom_mdcv_t
*mdcv
= isom_add_mdcv( visual
);
1092 if( LSMASH_IS_NON_EXISTING_BOX( mdcv
) )
1094 lsmash_destroy_codec_specific_data( cs
);
1097 mdcv
->display_primaries_g_x
= data
->display_primaries_g_x
;
1098 mdcv
->display_primaries_g_y
= data
->display_primaries_g_y
;
1099 mdcv
->display_primaries_b_x
= data
->display_primaries_b_x
;
1100 mdcv
->display_primaries_b_y
= data
->display_primaries_b_y
;
1101 mdcv
->display_primaries_r_x
= data
->display_primaries_r_x
;
1102 mdcv
->display_primaries_r_y
= data
->display_primaries_r_y
;
1103 mdcv
->white_point_x
= data
->white_point_x
;
1104 mdcv
->white_point_y
= data
->white_point_y
;
1105 mdcv
->max_display_mastering_luminance
= data
->max_display_mastering_luminance
;
1106 mdcv
->min_display_mastering_luminance
= data
->min_display_mastering_luminance
;
1107 lsmash_destroy_codec_specific_data( cs
);
1110 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
1112 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1115 lsmash_codec_global_header_t
*data
= (lsmash_codec_global_header_t
*)cs
->data
.structured
;
1116 isom_glbl_t
*glbl
= isom_add_glbl( visual
);
1117 if( LSMASH_IS_NON_EXISTING_BOX( glbl
) )
1119 lsmash_destroy_codec_specific_data( cs
);
1122 glbl
->header_size
= data
->header_size
;
1123 glbl
->header_data
= lsmash_memdup( data
->header_data
, data
->header_size
);
1124 lsmash_destroy_codec_specific_data( cs
);
1125 if( !glbl
->header_data
)
1127 isom_remove_box_by_itself( glbl
);
1128 err
= LSMASH_ERR_MEMORY_ALLOC
;
1135 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
1138 if( cs
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1140 lsmash_destroy_codec_specific_data( cs
);
1141 err
= LSMASH_ERR_INVALID_DATA
;
1144 uint8_t *data
= cs
->data
.unstructured
;
1145 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
1146 lsmash_box_type_t box_type
= isom_guess_video_codec_specific_box_type( visual
->type
, fourcc
);
1147 /* Append the extension. */
1148 err
= isom_add_extension_binary( visual
, box_type
, LSMASH_BOX_PRECEDENCE_HM
, cs
->data
.unstructured
, cs
->size
);
1149 cs
->data
.unstructured
= NULL
; /* Avoid freeing the binary data of the extension. */
1150 lsmash_destroy_codec_specific_data( cs
);
1157 isom_trak_t
*trak
= (isom_trak_t
*)visual
->parent
->parent
->parent
->parent
->parent
;
1158 int qt_compatible
= trak
->file
->qt_compatible
;
1159 isom_tapt_t
*tapt
= trak
->tapt
;
1160 isom_stsl_t
*stsl
= (isom_stsl_t
*)isom_get_extension_box_format( &visual
->extensions
, ISOM_BOX_TYPE_STSL
);
1161 int set_aperture_modes
= qt_compatible
/* Track Aperture Modes is only available under QuickTime file format. */
1162 && (LSMASH_IS_NON_EXISTING_BOX( stsl
) || stsl
->scale_method
== 0) /* Sample scaling method might conflict with this feature. */
1163 && LSMASH_IS_EXISTING_BOX( tapt
->clef
)
1164 && LSMASH_IS_EXISTING_BOX( tapt
->prof
)
1165 && LSMASH_IS_EXISTING_BOX( tapt
->enof
) /* Check if required boxes exist. */
1166 && ((isom_stsd_t
*)visual
->parent
)->list
.entry_count
== 1; /* Multiple sample description might conflict with this, so in that case, disable this feature. */
1167 if( !set_aperture_modes
)
1168 isom_remove_box_by_itself( trak
->tapt
);
1169 int uncompressed_ycbcr
= qt_compatible
&& isom_is_uncompressed_ycbcr( visual
->type
);
1170 /* Set up Clean Aperture. */
1171 if( set_aperture_modes
|| uncompressed_ycbcr
1172 || (summary
->clap
.width
.d
&& summary
->clap
.height
.d
&& summary
->clap
.horizontal_offset
.d
&& summary
->clap
.vertical_offset
.d
) )
1174 isom_clap_t
*clap
= isom_add_clap( visual
);
1175 if( LSMASH_IS_NON_EXISTING_BOX( clap
) )
1177 if( summary
->clap
.width
.d
&& summary
->clap
.height
.d
&& summary
->clap
.horizontal_offset
.d
&& summary
->clap
.vertical_offset
.d
)
1179 clap
->cleanApertureWidthN
= summary
->clap
.width
.n
;
1180 clap
->cleanApertureWidthD
= summary
->clap
.width
.d
;
1181 clap
->cleanApertureHeightN
= summary
->clap
.height
.n
;
1182 clap
->cleanApertureHeightD
= summary
->clap
.height
.d
;
1183 clap
->horizOffN
= summary
->clap
.horizontal_offset
.n
;
1184 clap
->horizOffD
= summary
->clap
.horizontal_offset
.d
;
1185 clap
->vertOffN
= summary
->clap
.vertical_offset
.n
;
1186 clap
->vertOffD
= summary
->clap
.vertical_offset
.d
;
1190 clap
->cleanApertureWidthN
= summary
->width
;
1191 clap
->cleanApertureWidthD
= 1;
1192 clap
->cleanApertureHeightN
= summary
->height
;
1193 clap
->cleanApertureHeightD
= 1;
1194 clap
->horizOffN
= 0;
1195 clap
->horizOffD
= 1;
1200 /* Set up Pixel Aspect Ratio. */
1201 if( set_aperture_modes
|| (summary
->par_h
&& summary
->par_v
) )
1203 isom_pasp_t
*pasp
= isom_add_pasp( visual
);
1204 if( LSMASH_IS_NON_EXISTING_BOX( pasp
) )
1206 pasp
->hSpacing
= LSMASH_MAX( summary
->par_h
, 1 );
1207 pasp
->vSpacing
= LSMASH_MAX( summary
->par_v
, 1 );
1209 /* Set up Color Parameter. */
1210 if( uncompressed_ycbcr
1211 || summary
->color
.primaries_index
1212 || summary
->color
.transfer_index
1213 || summary
->color
.matrix_index
1214 || (trak
->file
->isom_compatible
&& summary
->color
.full_range
) )
1216 isom_colr_t
*colr
= isom_add_colr( visual
);
1217 if( LSMASH_IS_NON_EXISTING_BOX( colr
) )
1219 /* Set 'nclc' to parameter type, we don't support 'prof'. */
1220 uint16_t primaries
= summary
->color
.primaries_index
;
1221 uint16_t transfer
= summary
->color
.transfer_index
;
1222 uint16_t matrix
= summary
->color
.matrix_index
;
1223 if( qt_compatible
&& !trak
->file
->isom_compatible
)
1225 colr
->manager
|= LSMASH_QTFF_BASE
;
1226 colr
->type
= QT_BOX_TYPE_COLR
;
1227 colr
->color_parameter_type
= QT_COLOR_PARAMETER_TYPE_NCLC
;
1228 colr
->primaries_index
= (primaries
== 1 || primaries
== 5 || primaries
== 6)
1229 ? primaries
: QT_PRIMARIES_INDEX_UNSPECIFIED
;
1230 colr
->transfer_function_index
= (transfer
== 1 || transfer
== 7)
1231 ? transfer
: QT_TRANSFER_INDEX_UNSPECIFIED
;
1232 colr
->matrix_index
= (matrix
== 1 || matrix
== 6 || matrix
== 7)
1233 ? matrix
: QT_MATRIX_INDEX_UNSPECIFIED
;
1237 colr
->type
= ISOM_BOX_TYPE_COLR
;
1238 colr
->color_parameter_type
= ISOM_COLOR_PARAMETER_TYPE_NCLX
;
1239 colr
->primaries_index
= (primaries
== 1 || (primaries
>= 4 && primaries
<= 7))
1240 ? primaries
: ISOM_PRIMARIES_INDEX_UNSPECIFIED
;
1241 colr
->transfer_function_index
= (transfer
== 1 || (transfer
>= 4 && transfer
<= 8) || (transfer
>= 11 && transfer
<= 13))
1242 ? transfer
: ISOM_TRANSFER_INDEX_UNSPECIFIED
;
1243 colr
->matrix_index
= (matrix
== 1 || (matrix
>= 4 && matrix
<= 8))
1244 ? matrix
: ISOM_MATRIX_INDEX_UNSPECIFIED
;
1245 colr
->full_range_flag
= summary
->color
.full_range
;
1248 /* Set up Track Apeture Modes. */
1249 if( set_aperture_modes
)
1251 uint32_t width
= visual
->width
<< 16;
1252 uint32_t height
= visual
->height
<< 16;
1253 isom_clap_t
*clap
= (isom_clap_t
*)isom_get_extension_box_format( &visual
->extensions
, ISOM_BOX_TYPE_CLAP
);
1254 isom_pasp_t
*pasp
= (isom_pasp_t
*)isom_get_extension_box_format( &visual
->extensions
, ISOM_BOX_TYPE_PASP
);
1255 double clap_width
= ((double)clap
->cleanApertureWidthN
/ clap
->cleanApertureWidthD
) * (1<<16);
1256 double clap_height
= ((double)clap
->cleanApertureHeightN
/ clap
->cleanApertureHeightD
) * (1<<16);
1257 double par
= (double)pasp
->hSpacing
/ pasp
->vSpacing
;
1260 tapt
->clef
->width
= clap_width
* par
;
1261 tapt
->clef
->height
= clap_height
;
1262 tapt
->prof
->width
= width
* par
;
1263 tapt
->prof
->height
= height
;
1267 tapt
->clef
->width
= clap_width
;
1268 tapt
->clef
->height
= clap_height
/ par
;
1269 tapt
->prof
->width
= width
;
1270 tapt
->prof
->height
= height
/ par
;
1272 tapt
->enof
->width
= width
;
1273 tapt
->enof
->height
= height
;
1277 isom_remove_box_by_itself( visual
);
1281 static int isom_append_audio_es_descriptor_extension( isom_box_t
*box
, lsmash_audio_summary_t
*summary
)
1283 uint32_t esds_size
= 0;
1284 uint8_t *esds_data
= NULL
;
1285 lsmash_codec_specific_t
*specific
= isom_get_codec_specific( summary
->opaque
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
);
1287 return LSMASH_ERR_NAMELESS
;
1288 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
1290 esds_size
= specific
->size
;
1291 esds_data
= lsmash_memdup( specific
->data
.unstructured
, specific
->size
);
1293 return LSMASH_ERR_MEMORY_ALLOC
;
1297 esds_data
= lsmash_create_mp4sys_decoder_config( (lsmash_mp4sys_decoder_parameters_t
*)specific
->data
.structured
, &esds_size
);
1299 return LSMASH_ERR_NAMELESS
;
1301 isom_esds_t
*esds
= isom_add_esds( box
);
1302 if( LSMASH_IS_NON_EXISTING_BOX( esds
) )
1304 lsmash_free( esds_data
);
1305 return LSMASH_ERR_NAMELESS
;
1307 lsmash_bs_t bs
= { 0 };
1308 bs
.buffer
.data
= esds_data
+ ISOM_FULLBOX_COMMON_SIZE
;
1309 bs
.buffer
.alloc
= esds_size
- ISOM_FULLBOX_COMMON_SIZE
;
1310 bs
.buffer
.store
= bs
.buffer
.alloc
;
1311 esds
->ES
= mp4sys_get_descriptor( &bs
, NULL
);
1312 lsmash_free( esds_data
);
1315 isom_remove_box_by_itself( esds
);
1316 return LSMASH_ERR_NAMELESS
;
1321 static int isom_append_channel_layout_extension( lsmash_codec_specific_t
*specific
, void *parent
, uint32_t channels
)
1323 assert( LSMASH_IS_EXISTING_BOX( (isom_box_t
*)parent
) );
1324 if( isom_get_extension_box( &((isom_box_t
*)parent
)->extensions
, QT_BOX_TYPE_CHAN
) )
1325 return 0; /* Audio Channel Layout Box is already present. */
1326 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
1328 return LSMASH_ERR_NAMELESS
;
1329 lsmash_qt_audio_channel_layout_t
*data
= (lsmash_qt_audio_channel_layout_t
*)cs
->data
.structured
;
1330 lsmash_channel_layout_tag channelLayoutTag
= data
->channelLayoutTag
;
1331 lsmash_channel_bitmap channelBitmap
= data
->channelBitmap
;
1332 if( channelLayoutTag
== QT_CHANNEL_LAYOUT_USE_CHANNEL_DESCRIPTIONS
/* We don't support the feature of Channel Descriptions. */
1333 || (channelLayoutTag
== QT_CHANNEL_LAYOUT_USE_CHANNEL_BITMAP
&& (!channelBitmap
|| channelBitmap
> QT_CHANNEL_BIT_FULL
)) )
1335 channelLayoutTag
= QT_CHANNEL_LAYOUT_UNKNOWN
| channels
;
1338 lsmash_destroy_codec_specific_data( cs
);
1339 /* Don't create Audio Channel Layout Box if the channel layout is unknown. */
1340 if( (channelLayoutTag
^ QT_CHANNEL_LAYOUT_UNKNOWN
) >> 16 )
1342 isom_chan_t
*chan
= isom_add_chan( parent
);
1343 if( LSMASH_IS_NON_EXISTING_BOX( chan
) )
1344 return LSMASH_ERR_NAMELESS
;
1345 chan
->channelLayoutTag
= channelLayoutTag
;
1346 chan
->channelBitmap
= channelBitmap
;
1347 chan
->numberChannelDescriptions
= 0;
1348 chan
->channelDescriptions
= NULL
;
1353 static int isom_set_qtff_mp4a_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1358 isom_terminator_t
*terminator
;
1359 if( (wave
= isom_add_wave( audio
), LSMASH_IS_NON_EXISTING_BOX( wave
))
1360 || (frma
= isom_add_frma( wave
), LSMASH_IS_NON_EXISTING_BOX( frma
))
1361 || (mp4a
= isom_add_mp4a( wave
), LSMASH_IS_NON_EXISTING_BOX( mp4a
))
1362 || (terminator
= isom_add_terminator( wave
), LSMASH_IS_NON_EXISTING_BOX( terminator
)) )
1364 lsmash_list_remove_entry_tail( &audio
->extensions
);
1365 return LSMASH_ERR_NAMELESS
;
1367 frma
->data_format
= audio
->type
.fourcc
;
1368 /* Add ES Descriptor Box. */
1369 int err
= isom_append_audio_es_descriptor_extension( (isom_box_t
*)wave
, summary
);
1373 audio
->type
= QT_CODEC_TYPE_MP4A_AUDIO
;
1374 audio
->version
= (summary
->channels
> 2 || summary
->frequency
> UINT16_MAX
) ? 2 : 1;
1375 audio
->channelcount
= audio
->version
== 2 ? 3 : LSMASH_MIN( summary
->channels
, 2 );
1376 audio
->samplesize
= 16;
1377 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
;
1378 audio
->packet_size
= 0;
1379 if( audio
->version
== 1 )
1381 audio
->samplerate
= summary
->frequency
<< 16;
1382 audio
->samplesPerPacket
= summary
->samples_in_frame
;
1383 audio
->bytesPerPacket
= 1; /* Apparently, this field is set to 1. */
1384 audio
->bytesPerFrame
= audio
->bytesPerPacket
* summary
->channels
;
1385 audio
->bytesPerSample
= 2;
1387 else /* audio->version == 2 */
1389 audio
->samplerate
= 0x00010000;
1390 audio
->sizeOfStructOnly
= 72;
1391 audio
->audioSampleRate
= (union {double d
; uint64_t i
;}){summary
->frequency
}.i
;
1392 audio
->numAudioChannels
= summary
->channels
;
1393 audio
->always7F000000
= 0x7F000000;
1394 audio
->constBitsPerChannel
= 0; /* compressed audio */
1395 audio
->formatSpecificFlags
= 0;
1396 audio
->constBytesPerAudioPacket
= 0; /* variable */
1397 audio
->constLPCMFramesPerAudioPacket
= summary
->samples_in_frame
;
1402 static int isom_set_isom_mp4a_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1404 if( summary
->summary_type
!= LSMASH_SUMMARY_TYPE_AUDIO
)
1405 return LSMASH_ERR_NAMELESS
;
1406 /* Check objectTypeIndication. */
1407 lsmash_mp4sys_object_type_indication objectTypeIndication
= lsmash_mp4sys_get_object_type_indication( (lsmash_summary_t
*)summary
);
1408 switch( objectTypeIndication
)
1410 case MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3
:
1411 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_Main_Profile
:
1412 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_LC_Profile
:
1413 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_7_SSR_Profile
:
1414 case MP4SYS_OBJECT_TYPE_Audio_ISO_13818_3
: /* Legacy Interface */
1415 case MP4SYS_OBJECT_TYPE_Audio_ISO_11172_3
: /* Legacy Interface */
1418 return LSMASH_ERR_NAMELESS
;
1420 /* Add ES Descriptor Box. */
1421 int err
= isom_append_audio_es_descriptor_extension( (isom_box_t
*)audio
, summary
);
1424 /* In pure mp4 file, these "template" fields shall be default values according to the spec.
1425 But not pure - hybrid with other spec - mp4 file can take other values.
1426 Which is to say, these template values shall be ignored in terms of mp4, except some object_type_indications.
1427 see 14496-14, "Template fields used". */
1428 audio
->type
= ISOM_CODEC_TYPE_MP4A_AUDIO
;
1430 audio
->revision_level
= 0;
1432 audio
->channelcount
= 2;
1433 audio
->samplesize
= 16;
1434 audio
->compression_ID
= 0;
1435 audio
->packet_size
= 0;
1436 /* WARNING: This field cannot retain frequency above 65535Hz.
1437 This is not "FIXME", I just honestly implemented what the spec says.
1438 BTW, who ever expects sampling frequency takes fixed-point decimal??? */
1439 audio
->samplerate
= summary
->frequency
<= UINT16_MAX
? summary
->frequency
<< 16 : 0;
1443 static int isom_set_qtff_lpcm_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1445 lsmash_qt_audio_format_specific_flags_t
*lpcm
= NULL
;
1446 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
1448 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
1451 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1452 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
1454 lpcm
= (lsmash_qt_audio_format_specific_flags_t
*)specific
->data
.structured
;
1459 return LSMASH_ERR_NAMELESS
;
1460 audio
->manager
|= LSMASH_QTFF_BASE
;
1461 lsmash_codec_type_t sample_type
= audio
->type
;
1462 /* Convert the sample type into 'lpcm' if the description doesn't match the format or version = 2 fields are needed. */
1463 if( (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_RAW_AUDIO
)
1464 && (summary
->sample_size
!= 8 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1465 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL32_AUDIO
)
1466 && (summary
->sample_size
!= 32 || !(lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1467 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL64_AUDIO
)
1468 && (summary
->sample_size
!= 64 || !(lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1469 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN24_AUDIO
)
1470 && (summary
->sample_size
!= 24 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1471 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN32_AUDIO
)
1472 && (summary
->sample_size
!= 32 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)))
1473 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_23NI_AUDIO
)
1474 && (summary
->sample_size
!= 32 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
) || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
)))
1475 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_SOWT_AUDIO
)
1476 && (summary
->sample_size
!= 16 || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
) || (lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
)))
1477 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
)
1478 && ((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
)))
1479 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NONE_AUDIO
)
1480 && ((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
)))
1481 || (lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NOT_SPECIFIED
)
1482 && ((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
)))
1483 || (summary
->channels
> 2 || summary
->frequency
> UINT16_MAX
|| summary
->sample_size
% 8) )
1485 audio
->type
= QT_CODEC_TYPE_LPCM_AUDIO
;
1488 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_LPCM_AUDIO
) )
1490 else if( summary
->sample_size
> 16
1491 || (!lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_RAW_AUDIO
)
1492 && !lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
)
1493 && !lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NONE_AUDIO
)
1494 && !lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_NOT_SPECIFIED
)) )
1496 /* Set up constBytesPerAudioPacket field.
1497 * We use constBytesPerAudioPacket as the actual size of LPCM audio frame even when version is not 2. */
1498 audio
->constBytesPerAudioPacket
= (summary
->sample_size
* summary
->channels
) / 8;
1499 /* Set up other fields in this description by its version. */
1500 if( audio
->version
== 2 )
1502 audio
->channelcount
= 3;
1503 audio
->samplesize
= 16;
1504 audio
->compression_ID
= -2;
1505 audio
->samplerate
= 0x00010000;
1506 audio
->sizeOfStructOnly
= 72;
1507 audio
->audioSampleRate
= (union {double d
; uint64_t i
;}){summary
->frequency
}.i
;
1508 audio
->numAudioChannels
= summary
->channels
;
1509 audio
->always7F000000
= 0x7F000000;
1510 audio
->constBitsPerChannel
= summary
->sample_size
;
1511 audio
->constLPCMFramesPerAudioPacket
= 1;
1512 audio
->formatSpecificFlags
= lpcm
->format_flags
;
1513 if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
) && summary
->sample_size
!= 8 )
1514 audio
->formatSpecificFlags
|= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
1515 if( lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_FLOAT
)
1516 audio
->formatSpecificFlags
&= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
;
1517 if( lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_PACKED
)
1518 audio
->formatSpecificFlags
&= ~QT_LPCM_FORMAT_FLAG_ALIGNED_HIGH
;
1520 else if( audio
->version
== 1 )
1522 audio
->channelcount
= summary
->channels
;
1523 audio
->samplesize
= 16;
1524 /* Audio formats other than 'raw ' and 'twos' are treated as compressed audio. */
1525 if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_RAW_AUDIO
)
1526 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TWOS_AUDIO
) )
1527 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
;
1529 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION
;
1530 audio
->samplerate
= summary
->frequency
<< 16;
1531 audio
->samplesPerPacket
= 1;
1532 audio
->bytesPerPacket
= summary
->sample_size
/ 8;
1533 audio
->bytesPerFrame
= audio
->bytesPerPacket
* summary
->channels
; /* sample_size field in stsz box is NOT used. */
1534 audio
->bytesPerSample
= 1 + (summary
->sample_size
!= 8);
1535 if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL32_AUDIO
)
1536 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_FL64_AUDIO
)
1537 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN24_AUDIO
)
1538 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_IN32_AUDIO
) )
1543 isom_terminator_t
*terminator
;
1544 if( (wave
= isom_add_wave( audio
), LSMASH_IS_NON_EXISTING_BOX( wave
))
1545 || (frma
= isom_add_frma( wave
), LSMASH_IS_NON_EXISTING_BOX( frma
))
1546 || (enda
= isom_add_enda( wave
), LSMASH_IS_NON_EXISTING_BOX( enda
))
1547 || (terminator
= isom_add_terminator( wave
), LSMASH_IS_NON_EXISTING_BOX( terminator
)) )
1549 lsmash_list_remove_entry_tail( &audio
->extensions
);
1550 return LSMASH_ERR_NAMELESS
;
1552 frma
->data_format
= sample_type
.fourcc
;
1553 enda
->littleEndian
= !(lpcm
->format_flags
& QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
);
1556 else /* audio->version == 0 */
1558 audio
->channelcount
= summary
->channels
;
1559 audio
->samplesize
= summary
->sample_size
;
1560 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
;
1561 audio
->samplerate
= summary
->frequency
<< 16;
1566 static int isom_set_isom_dts_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1569 audio
->revision_level
= 0;
1571 audio
->channelcount
= summary
->channels
;
1572 audio
->samplesize
= 16;
1573 audio
->compression_ID
= 0;
1574 audio
->packet_size
= 0;
1575 switch( summary
->frequency
)
1577 case 12000 : /* Invalid? (No reference in the spec) */
1582 case 384000 : /* Invalid? (No reference in the spec) */
1583 audio
->samplerate
= 48000 << 16;
1589 case 352800 : /* Invalid? (No reference in the spec) */
1590 audio
->samplerate
= 44100 << 16;
1592 case 8000 : /* Invalid? (No reference in the spec) */
1597 audio
->samplerate
= 32000 << 16;
1600 audio
->samplerate
= 0;
1606 static int isom_set_hint_summary( isom_hint_entry_t
*hint
, lsmash_hint_summary_t
*summary
)
1608 hint
->hinttrackversion
= summary
->version
;
1609 hint
->highestcompatibleversion
= summary
->highestcompatibleversion
;
1610 hint
->maxpacketsize
= summary
->maxpacketsize
;
1614 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
)
1616 lsmash_box_type_t box_type
= LSMASH_BOX_TYPE_INITIALIZER
;
1617 box_type
.fourcc
= fourcc
;
1618 #define GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( codec_type, predefined_box_type ) \
1619 else if( (codec_type.user.fourcc == 0 \
1620 || lsmash_check_codec_type_identical( active_codec_type, codec_type )) \
1621 && box_type.fourcc == predefined_box_type.fourcc ) \
1622 box_type = predefined_box_type
1624 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_AC_3_AUDIO
, ISOM_BOX_TYPE_DAC3
);
1625 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_EC_3_AUDIO
, ISOM_BOX_TYPE_DEC3
);
1626 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSC_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1627 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSE_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1628 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSH_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1629 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSL_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1630 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSX_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1631 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSEL_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1632 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_DTSDL_AUDIO
, ISOM_BOX_TYPE_DDTS
);
1633 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_ALAC_AUDIO
, ISOM_BOX_TYPE_ALAC
);
1634 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( ISOM_CODEC_TYPE_MP4A_AUDIO
, ISOM_BOX_TYPE_ESDS
);
1635 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ALAC_AUDIO
, QT_BOX_TYPE_ALAC
);
1636 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_MP4A_AUDIO
, QT_BOX_TYPE_ESDS
);
1637 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_FULLMP3_AUDIO
, QT_CODEC_TYPE_MP3_AUDIO
);
1638 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM2_AUDIO
, QT_CODEC_TYPE_ADPCM2_AUDIO
);
1639 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_ADPCM17_AUDIO
, QT_CODEC_TYPE_ADPCM17_AUDIO
);
1640 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( QT_CODEC_TYPE_GSM49_AUDIO
, QT_CODEC_TYPE_GSM49_AUDIO
);
1641 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_CHAN
);
1642 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_GLBL
);
1643 GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE( LSMASH_CODEC_TYPE_UNSPECIFIED
, QT_BOX_TYPE_WAVE
);
1644 #undef GUESS_AUDIO_CODEC_SPECIFIC_BOX_TYPE
1650 uint16_t wFormatTag
;
1652 uint32_t nSamplesPerSec
;
1653 uint32_t nAvgBytesPerSec
;
1654 uint16_t nBlockAlign
;
1655 uint16_t wBitsPerSample
;
1659 static lsmash_bs_t
*isom_create_waveform_audio_info
1661 wave_format_ex_t
*wfx
,
1662 lsmash_box_type_t type
1665 lsmash_bs_t
*bs
= lsmash_bs_create();
1668 lsmash_bs_put_be32( bs
, ISOM_BASEBOX_COMMON_SIZE
+ 18 + wfx
->cbSize
);
1669 lsmash_bs_put_be32( bs
, type
.fourcc
);
1670 lsmash_bs_put_le16( bs
, wfx
->wFormatTag
);
1671 lsmash_bs_put_le16( bs
, wfx
->nChannels
);
1672 lsmash_bs_put_le32( bs
, wfx
->nSamplesPerSec
);
1673 lsmash_bs_put_le32( bs
, wfx
->nAvgBytesPerSec
);
1674 lsmash_bs_put_le16( bs
, wfx
->nBlockAlign
);
1675 lsmash_bs_put_le16( bs
, wfx
->wBitsPerSample
);
1676 lsmash_bs_put_le16( bs
, wfx
->cbSize
);
1680 static int isom_setup_waveform_audio_info
1683 isom_audio_entry_t
*audio
,
1684 lsmash_audio_summary_t
*summary
,
1685 uint32_t samples_per_packet
,
1686 uint32_t bytes_per_frame
,
1687 uint32_t sample_size
1690 wave_format_ex_t wfx
;
1691 wfx
.wFormatTag
= 0x0000; /* WAVE_FORMAT_UNKNOWN */
1692 wfx
.nChannels
= summary
->channels
;
1693 wfx
.nSamplesPerSec
= summary
->frequency
;
1694 wfx
.nAvgBytesPerSec
= 0;
1695 wfx
.nBlockAlign
= bytes_per_frame
;
1696 wfx
.wBitsPerSample
= sample_size
;
1698 lsmash_bs_t
*bs
= NULL
;
1699 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ADPCM2_AUDIO
) )
1701 /* ADPCMWAVEFORMAT */
1702 wfx
.wFormatTag
= 0x0002; /* WAVE_FORMAT_ADPCM */
1704 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1706 return LSMASH_ERR_MEMORY_ALLOC
;
1707 uint16_t wSamplesPerBlock
= samples_per_packet
; /* nBlockAlign * 2 / nChannels - 12 */
1708 uint16_t wNumCoef
= 7; /* Microsoft ADPCM uses just 7 coefficients. */
1713 } aCoef
[7] = { { 256, 0 }, { 512, -256 }, { 0,0 }, { 192,64 }, { 240,0 }, { 460, -208 }, { 392,-232 } };
1714 lsmash_bs_put_le16( bs
, wSamplesPerBlock
);
1715 lsmash_bs_put_le16( bs
, wNumCoef
);
1716 for( int i
= 0; i
< 7; i
++ )
1718 lsmash_bs_put_le16( bs
, aCoef
[i
].iCoef1
);
1719 lsmash_bs_put_le16( bs
, aCoef
[i
].iCoef2
);
1722 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ADPCM17_AUDIO
) )
1724 /* IMAADPCMWAVEFORMAT */
1725 wfx
.wFormatTag
= 0x0011; /* WAVE_FORMAT_DVI_ADPCM / WAVE_FORMAT_IMA_ADPCM */
1727 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1729 return LSMASH_ERR_MEMORY_ALLOC
;
1730 uint16_t wSamplesPerBlock
= samples_per_packet
;
1731 lsmash_bs_put_le16( bs
, wSamplesPerBlock
);
1733 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_GSM49_AUDIO
) )
1735 /* GSM610WAVEFORMAT */
1736 wfx
.wFormatTag
= 0x0031; /* WAVE_FORMAT_GSM610 */
1738 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1740 return LSMASH_ERR_MEMORY_ALLOC
;
1741 uint16_t wSamplesPerBlock
= samples_per_packet
;
1742 lsmash_bs_put_le16( bs
, wSamplesPerBlock
);
1744 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
1745 || lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MP3_AUDIO
) )
1747 /* MPEGLAYER3WAVEFORMAT */
1748 wfx
.wFormatTag
= 0x0055; /* WAVE_FORMAT_MPEGLAYER3 */
1749 wfx
.nBlockAlign
= 1; /* ? */
1750 wfx
.wBitsPerSample
= 0; /* undefined */
1752 bs
= isom_create_waveform_audio_info( &wfx
, audio
->type
);
1754 return LSMASH_ERR_MEMORY_ALLOC
;
1755 uint16_t wID
= 1; /* MPEGLAYER3_ID_MPEG */
1756 uint32_t fdwFlags
= 0; /* We don't know whether the stream is padded or not here. */
1757 uint16_t nBlockSize
= 0; /* (144 * (bitrate / nSamplesPerSec) + padding) * nFramesPerBlock */
1758 uint16_t nFramesPerBlock
= 1; /* the number of audio frames per block */
1759 uint16_t nCodecDelay
= 0; /* Encoder delay in samples is unknown. */
1760 lsmash_bs_put_le16( bs
, wID
);
1761 lsmash_bs_put_le32( bs
, fdwFlags
);
1762 lsmash_bs_put_le16( bs
, nBlockSize
);
1763 lsmash_bs_put_le16( bs
, nFramesPerBlock
);
1764 lsmash_bs_put_le16( bs
, nCodecDelay
);
1769 return LSMASH_ERR_NAMELESS
;
1772 uint8_t *wfx_data
= lsmash_bs_export_data( bs
, &wfx_size
);
1773 lsmash_bs_cleanup( bs
);
1775 return LSMASH_ERR_NAMELESS
;
1776 if( wfx_size
!= ISOM_BASEBOX_COMMON_SIZE
+ 18 + wfx
.cbSize
)
1778 lsmash_free( wfx_data
);
1779 return LSMASH_ERR_NAMELESS
;
1781 int err
= isom_add_extension_binary( wave
, audio
->type
, LSMASH_BOX_PRECEDENCE_HM
, wfx_data
, wfx_size
);
1784 lsmash_free( wfx_data
);
1790 static int isom_set_qtff_sound_decompression_parameters
1792 isom_audio_entry_t
*audio
,
1793 lsmash_audio_summary_t
*summary
,
1794 lsmash_qt_audio_format_specific_flag
*format_flags
,
1795 uint32_t samples_per_packet
,
1796 uint32_t bytes_per_frame
,
1797 uint32_t sample_size
1800 /* A 'wave' extension itself shall be absent in the opaque CODEC specific info list.
1801 * So, create a 'wave' extension here and append it as an extension to the audio sample description. */
1802 isom_wave_t
*wave
= isom_add_wave( audio
);
1803 if( LSMASH_IS_NON_EXISTING_BOX( wave
) )
1804 return LSMASH_ERR_NAMELESS
;
1805 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_frma ( wave
) )
1806 || LSMASH_IS_BOX_ADDITION_FAILURE( isom_add_terminator( wave
) ) )
1808 lsmash_list_remove_entry_tail( &audio
->extensions
);
1809 return LSMASH_ERR_NAMELESS
;
1811 wave
->frma
->data_format
= audio
->type
.fourcc
;
1812 /* Append extensions from the opaque CODEC specific info list to 'wave' extension. */
1814 int waveform_audio_info_present
= 0;
1815 int requires_waveform_audio_info
= isom_is_waveform_audio( audio
->type
);
1816 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
1818 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
1820 return LSMASH_ERR_NAMELESS
;
1821 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
1822 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
1823 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
1824 switch( specific
->type
)
1826 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
:
1827 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
1828 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
:
1829 continue; /* These cannot be an extension for 'wave' extension. */
1830 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
:
1831 /* (Legacy?) ALAC might have an Audio Channel Layout Box inside 'wave' extension. */
1835 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
1837 if( (err
= isom_append_channel_layout_extension( specific
, wave
, summary
->channels
)) < 0 )
1843 assert( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
1844 || specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
);
1845 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
1847 return LSMASH_ERR_NAMELESS
;
1848 if( cs
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1850 lsmash_destroy_codec_specific_data( cs
);
1853 uint8_t *box_data
= cs
->data
.unstructured
;
1854 uint64_t box_size
= cs
->size
;
1855 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( box_data
[4], box_data
[5], box_data
[6], box_data
[7] );
1856 if( audio
->version
== 2 && fourcc
== QT_BOX_TYPE_ENDA
.fourcc
)
1858 /* Don't append a 'enda' extension if version == 2.
1859 * Endianness is indicated in QuickTime audio format specific flags. */
1860 if( box_size
>= ISOM_BASEBOX_COMMON_SIZE
+ 2 )
1862 /* Override endianness indicated in format specific flags. */
1863 if( box_data
[9] == 1 )
1864 *format_flags
&= ~QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN
;
1866 *format_flags
|= QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN
;
1868 lsmash_destroy_codec_specific_data( cs
);
1871 lsmash_box_type_t box_type
= isom_guess_audio_codec_specific_box_type( audio
->type
, fourcc
);
1872 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_WAVE
) )
1874 /* It is insane to appened a 'wave' extension to a 'wave' extension. */
1875 lsmash_destroy_codec_specific_data( cs
);
1878 box_type
= lsmash_form_qtff_box_type( box_type
.fourcc
);
1879 /* Determine 'precedence'. */
1880 uint64_t precedence
;
1881 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_FRMA
) )
1882 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_FRMA
;
1883 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ESDS
) )
1884 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_ESDS
;
1885 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ENDA
) )
1886 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_ENDA
;
1887 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_MP4A
) )
1888 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_MP4A
;
1889 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_TERMINATOR
) )
1890 precedence
= LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR
;
1892 precedence
= LSMASH_BOX_PRECEDENCE_HM
;
1893 /* Append the extension. */
1894 err
= isom_add_extension_binary( wave
, box_type
, precedence
, cs
->data
.unstructured
, cs
->size
);
1895 cs
->data
.unstructured
= NULL
; /* Avoid freeing the binary data of the extension. */
1896 lsmash_destroy_codec_specific_data( cs
);
1899 if( isom_is_waveform_audio( box_type
) )
1900 waveform_audio_info_present
= 1;
1905 if( requires_waveform_audio_info
&& !waveform_audio_info_present
1906 && (err
= isom_setup_waveform_audio_info( wave
, audio
, summary
, samples_per_packet
, bytes_per_frame
, sample_size
)) < 0 )
1911 static int isom_set_qtff_template_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
1913 audio
->manager
|= LSMASH_QTFF_BASE
;
1914 audio
->type
= lsmash_form_qtff_box_type( audio
->type
.fourcc
);
1915 audio
->version
= (summary
->channels
> 2 || summary
->frequency
> UINT16_MAX
) ? 2 : 1;
1916 /* Try to get QuickTime audio format specific flags. */
1917 lsmash_qt_audio_format_specific_flag format_flags
= QT_AUDIO_FORMAT_FLAG_BIG_ENDIAN
;
1918 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
1920 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
1922 || !specific
->data
.structured
)
1924 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
1925 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
1927 /* A format specific flags is found.
1928 * Force audio sample description version == 2. */
1929 format_flags
= ((lsmash_qt_audio_format_specific_flags_t
*)specific
->data
.structured
)->format_flags
;
1934 uint32_t samples_per_packet
;
1935 uint32_t bytes_per_frame
;
1936 uint32_t sample_size
;
1937 if( !((summary
->samples_in_frame
== 0 || summary
->bytes_per_frame
== 0 || summary
->sample_size
== 0)
1938 && isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio
, &samples_per_packet
, &bytes_per_frame
, &sample_size
)) )
1940 samples_per_packet
= summary
->samples_in_frame
;
1941 bytes_per_frame
= summary
->bytes_per_frame
;
1942 sample_size
= summary
->sample_size
;
1944 if( !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC3_AUDIO
)
1945 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC6_AUDIO
)
1946 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_AGSM_AUDIO
)
1947 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAW_AUDIO
)
1948 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ULAW_AUDIO
) )
1950 int err
= isom_set_qtff_sound_decompression_parameters( audio
, summary
, &format_flags
,
1951 samples_per_packet
, bytes_per_frame
, sample_size
);
1955 /* Set up common audio description fields. */
1956 audio
->samplesize
= 16;
1957 audio
->packet_size
= 0;
1958 if( audio
->version
== 2 )
1960 audio
->channelcount
= 3;
1961 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
;
1962 audio
->samplerate
= 0x00010000;
1963 audio
->sizeOfStructOnly
= 72;
1964 audio
->audioSampleRate
= (union {double d
; uint64_t i
;}){summary
->frequency
}.i
;
1965 audio
->numAudioChannels
= summary
->channels
;
1966 audio
->always7F000000
= 0x7F000000;
1967 audio
->constBitsPerChannel
= 0;
1968 audio
->constBytesPerAudioPacket
= bytes_per_frame
;
1969 audio
->constLPCMFramesPerAudioPacket
= samples_per_packet
;
1970 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
1972 switch( sample_size
)
1975 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA
;
1978 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA
;
1981 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA
;
1984 audio
->formatSpecificFlags
= QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA
;
1992 if( format_flags
& QT_AUDIO_FORMAT_FLAG_FLOAT
)
1993 format_flags
&= ~QT_AUDIO_FORMAT_FLAG_SIGNED_INTEGER
;
1994 if( format_flags
& QT_AUDIO_FORMAT_FLAG_PACKED
)
1995 format_flags
&= ~QT_AUDIO_FORMAT_FLAG_ALIGNED_HIGH
;
1996 audio
->formatSpecificFlags
= format_flags
;
1999 else /* if( audio->version == 1 ) */
2001 audio
->channelcount
= LSMASH_MIN( summary
->channels
, 2 );
2002 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_FIXED_COMPRESSION
;
2003 audio
->samplerate
= summary
->frequency
<< 16;
2004 audio
->samplesPerPacket
= samples_per_packet
;
2005 audio
->bytesPerPacket
= bytes_per_frame
/ summary
->channels
;
2006 audio
->bytesPerFrame
= bytes_per_frame
; /* sample_size field in stsz box is NOT used. */
2007 audio
->bytesPerSample
= 1 + (sample_size
!= 8);
2012 static void isom_set_samplerate_division_of_media_timescale( isom_audio_entry_t
*audio
, int strict
)
2014 isom_mdia_t
*mdia
= (isom_mdia_t
*)audio
->parent
->parent
->parent
->parent
; /* audio_entry->stsd->stbl->minf->mdia */
2015 if( lsmash_check_box_type_identical( mdia
->type
, ISOM_BOX_TYPE_MDIA
)
2016 && LSMASH_IS_EXISTING_BOX( mdia
->mdhd
) )
2018 /* Make an effort to match the timescale with samplerate, or be an integer multiple of it. */
2019 uint32_t orig_timescale
= ((isom_mdia_t
*)audio
->parent
->parent
->parent
->parent
)->mdhd
->timescale
;
2020 uint32_t timescale
= orig_timescale
;
2022 while( timescale
> UINT16_MAX
&& timescale
> 1 )
2024 if( timescale
% i
== 0 )
2029 if( timescale
!= orig_timescale
&& strict
)
2030 lsmash_log( NULL
, LSMASH_LOG_WARNING
, "samplerate does not match the media timescale.\n" );
2031 if( timescale
<= UINT16_MAX
&& timescale
> 1 )
2033 audio
->samplerate
= timescale
<< 16;
2037 audio
->samplerate
= 0;
2040 static int isom_set_isom_template_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
2042 audio
->version
= 0; /* reserved */
2043 audio
->revision_level
= 0; /* reserved */
2044 audio
->vendor
= 0; /* reserved */
2045 audio
->channelcount
= 2; /* template */
2046 audio
->samplesize
= 16; /* template */
2047 audio
->compression_ID
= 0; /* pre_defined */
2048 audio
->packet_size
= 0; /* reserved */
2049 /* template : default output audio sampling rate at playback */
2050 if( summary
->frequency
<= UINT16_MAX
)
2051 audio
->samplerate
= summary
->frequency
<< 16;
2053 isom_set_samplerate_division_of_media_timescale( audio
, 0 );
2057 static int isom_set_isom_amr_audio_description( isom_audio_entry_t
*audio
, int wb
)
2059 /* For AMR-NB and AMR-WB stream, these fields are not meaningful. */
2060 audio
->version
= 0; /* always 0 */
2061 audio
->revision_level
= 0; /* always 0 */
2062 audio
->vendor
= 0; /* always 0 */
2063 audio
->channelcount
= 2; /* always 2 although the actual number of channels is always 1 */
2064 audio
->samplesize
= 16; /* always 16 */
2065 audio
->compression_ID
= 0; /* always 0 */
2066 audio
->packet_size
= 0; /* always 0 */
2067 /* Set samplerate by trying to copy from Media Header Box of this media though the
2068 * actual samplerate is 8000 Hz for AMR-NB and 16000 Hz for AMR-WB.
2069 * 3GPP and 3GPP2 has no restriction for media timescale. Therefore, users should
2070 * set suitable media timescale by themselves within the bounds of common sense. */
2071 isom_set_samplerate_division_of_media_timescale( audio
, 1 );
2072 if( audio
->samplerate
== 0 )
2073 /* Set hard-coded but correct samplerate in the CODEC level. */
2074 audio
->samplerate
= wb
? 8000 : 16000;
2078 static int isom_set_isom_alac_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
2080 return isom_set_isom_template_audio_description( audio
, summary
);
2083 static int isom_set_qtff_alac_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
2085 return isom_set_qtff_template_audio_description( audio
, summary
);
2088 static int isom_set_isom_eac3_audio_description( isom_audio_entry_t
*audio
, lsmash_audio_summary_t
*summary
)
2090 return isom_set_isom_template_audio_description( audio
, summary
);
2093 static int isom_setup_audio_description( isom_stsd_t
*stsd
, lsmash_audio_summary_t
*summary
)
2095 if( LSMASH_IS_NON_EXISTING_BOX( stsd
->file
) || !summary
)
2096 return LSMASH_ERR_NAMELESS
;
2097 int err
= isom_check_valid_summary( (lsmash_summary_t
*)summary
);
2100 isom_audio_entry_t
*audio
= isom_add_audio_description( stsd
, summary
->sample_type
);
2101 if( LSMASH_IS_NON_EXISTING_BOX( audio
) )
2102 return LSMASH_ERR_NAMELESS
;
2103 audio
->data_reference_index
= summary
->data_ref_index
;
2104 lsmash_file_t
*file
= stsd
->file
;
2105 lsmash_codec_type_t audio_type
= audio
->type
;
2106 if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_MP4A_AUDIO
)
2107 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_MP4A_AUDIO
) )
2109 if( (LSMASH_IS_EXISTING_BOX( file
->ftyp
) && file
->ftyp
->major_brand
== ISOM_BRAND_TYPE_QT
)
2110 || (LSMASH_IS_NON_EXISTING_BOX( file
->ftyp
)
2111 && (file
->qt_compatible
|| (LSMASH_IS_EXISTING_BOX( file
->moov
) && LSMASH_IS_NON_EXISTING_BOX( file
->moov
->iods
)))) )
2112 err
= isom_set_qtff_mp4a_description( audio
, summary
);
2114 err
= isom_set_isom_mp4a_description( audio
, summary
);
2116 else if( isom_is_lpcm_audio( audio
) )
2117 err
= isom_set_qtff_lpcm_description( audio
, summary
);
2118 else if( file
->isom_compatible
&& lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_ALAC_AUDIO
) )
2119 err
= isom_set_isom_alac_audio_description( audio
, summary
);
2120 else if( file
->qt_compatible
&& lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
2121 err
= isom_set_qtff_alac_audio_description( audio
, summary
);
2122 else if( audio
->type
.fourcc
== ISOM_CODEC_TYPE_ALAC_AUDIO
.fourcc
)
2124 if( file
->qt_compatible
)
2125 err
= isom_set_qtff_alac_audio_description( audio
, summary
);
2127 err
= isom_set_isom_alac_audio_description( audio
, summary
);
2129 else if( isom_is_dts_audio( audio_type
) )
2130 err
= isom_set_isom_dts_audio_description( audio
, summary
);
2131 else if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_EC_3_AUDIO
) )
2132 err
= isom_set_isom_eac3_audio_description( audio
, summary
);
2133 else if( file
->qt_compatible
)
2134 err
= isom_set_qtff_template_audio_description( audio
, summary
);
2135 else if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_SAMR_AUDIO
) )
2136 err
= isom_set_isom_amr_audio_description( audio
, 0 );
2137 else if( lsmash_check_codec_type_identical( audio_type
, ISOM_CODEC_TYPE_SAWB_AUDIO
) )
2138 err
= isom_set_isom_amr_audio_description( audio
, 1 );
2140 err
= isom_set_isom_template_audio_description( audio
, summary
);
2143 err
= LSMASH_ERR_NAMELESS
;
2144 /* Don't use audio_type since audio->type might have changed. */
2145 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
2147 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
2150 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
2151 && specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
2152 continue; /* LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN + LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED is not supported. */
2153 switch( specific
->type
)
2155 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
:
2157 if( specific
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
2158 continue; /* Ignore since not fatal. */
2159 lsmash_qt_audio_common_t
*data
= (lsmash_qt_audio_common_t
*)specific
->data
.structured
;
2160 audio
->revision_level
= data
->revision_level
;
2161 audio
->vendor
= data
->vendor
;
2162 if( audio
->version
== 1
2163 && !isom_is_lpcm_audio( audio
)
2164 && data
->compression_ID
!= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
)
2166 /* Compressed audio must not be set to QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED. */
2167 audio
->compression_ID
= data
->compression_ID
;
2168 if( audio
->compression_ID
== QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
)
2170 /* For variable compression, bytesPerPacket and bytesPerFrame are reserved and should be set to 0. */
2171 audio
->bytesPerPacket
= 0;
2172 audio
->bytesPerFrame
= 0;
2177 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
:
2179 if( !file
->qt_compatible
2180 && !lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_ALAC_AUDIO
)
2181 && !lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
2183 if( (err
= isom_append_channel_layout_extension( specific
, audio
, summary
->channels
)) < 0 )
2187 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
:
2189 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2192 lsmash_codec_global_header_t
*data
= (lsmash_codec_global_header_t
*)cs
->data
.structured
;
2193 isom_glbl_t
*glbl
= isom_add_glbl( audio
);
2194 if( LSMASH_IS_NON_EXISTING_BOX( glbl
) )
2196 lsmash_destroy_codec_specific_data( cs
);
2199 glbl
->header_size
= data
->header_size
;
2200 glbl
->header_data
= lsmash_memdup( data
->header_data
, data
->header_size
);
2201 lsmash_destroy_codec_specific_data( cs
);
2202 if( !glbl
->header_data
)
2204 isom_remove_box_by_itself( glbl
);
2205 err
= LSMASH_ERR_MEMORY_ALLOC
;
2210 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
:
2211 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
:
2212 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
:
2213 break; /* shall be set up already */
2214 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
:
2215 if( file
->qt_compatible
)
2216 continue; /* shall be set up already */
2219 lsmash_codec_specific_t
*cs
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2222 if( cs
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2224 lsmash_destroy_codec_specific_data( cs
);
2227 uint8_t *box_data
= cs
->data
.unstructured
;
2228 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( box_data
[4], box_data
[5], box_data
[6], box_data
[7] );
2229 lsmash_box_type_t box_type
= isom_guess_audio_codec_specific_box_type( audio
->type
, fourcc
);
2230 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_WAVE
) )
2232 /* CODEC specific info shall be already inside 'wave' extension. */
2233 lsmash_destroy_codec_specific_data( cs
);
2236 /* Append the extension. */
2237 err
= isom_add_extension_binary( audio
, box_type
, LSMASH_BOX_PRECEDENCE_HM
, cs
->data
.unstructured
, cs
->size
);
2238 cs
->data
.unstructured
= NULL
; /* Avoid freeing the binary data of the extension. */
2239 lsmash_destroy_codec_specific_data( cs
);
2246 if( audio
->version
== 0 )
2247 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_NOT_COMPRESSED
;
2248 else if( audio
->version
== 2 )
2249 audio
->compression_ID
= QT_AUDIO_COMPRESSION_ID_VARIABLE_COMPRESSION
;
2252 isom_remove_box_by_itself( audio
);
2256 static int isom_setup_tx3g_description( isom_stsd_t
*stsd
, lsmash_summary_t
*summary
)
2258 isom_tx3g_entry_t
*tx3g
= isom_add_tx3g_description( stsd
);
2259 if( LSMASH_IS_NON_EXISTING_BOX( tx3g
) )
2260 return LSMASH_ERR_NAMELESS
;
2261 /* We create a dummy font record to make valid font_ID in the sample description.
2262 * The specification (3GPP TS 26.245) does not forbid the value 0 for the identifier,
2263 * but we set 1 to it as track_ID begins from 1. */
2264 tx3g
->data_reference_index
= summary
->data_ref_index
;
2265 tx3g
->font_ID
= 1; /* ID of the default font record */
2266 int err
= LSMASH_ERR_MEMORY_ALLOC
;
2267 isom_ftab_t
*ftab
= isom_add_ftab( tx3g
);
2268 if( LSMASH_IS_NON_EXISTING_BOX( ftab
) )
2270 err
= LSMASH_ERR_NAMELESS
;
2273 isom_font_record_t
*font
= lsmash_malloc( sizeof(isom_font_record_t
) );
2276 if( lsmash_list_add_entry( ftab
->list
, font
) < 0 )
2278 lsmash_free( font
);
2281 const char font_names
[] = "Serif,Sans-serif,Monospace";
2283 font
->font_name_length
= sizeof(font_names
);
2284 font
->font_name
= lsmash_memdup( font_names
, sizeof(font_names
) );
2285 if( !font
->font_name
)
2289 isom_remove_box_by_itself( tx3g
);
2293 static int isom_setup_qt_text_description( isom_stsd_t
*stsd
, lsmash_summary_t
*summary
)
2295 isom_qt_text_entry_t
*text
= isom_add_qt_text_description( stsd
);
2296 if( LSMASH_IS_NON_EXISTING_BOX( text
) )
2297 return LSMASH_ERR_NAMELESS
;
2298 text
->data_reference_index
= summary
->data_ref_index
;
2302 static int isom_setup_text_description( isom_stsd_t
*stsd
, lsmash_summary_t
*summary
)
2304 lsmash_codec_type_t sample_type
= summary
->sample_type
;
2305 if( lsmash_check_box_type_identical( sample_type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
2306 return isom_setup_tx3g_description( stsd
, summary
);
2307 else if( lsmash_check_box_type_identical( sample_type
, QT_CODEC_TYPE_TEXT_TEXT
) )
2308 return isom_setup_qt_text_description( stsd
, summary
);
2310 return LSMASH_ERR_NAMELESS
;
2313 int isom_setup_hint_description( isom_stsd_t
*stsd
, lsmash_hint_summary_t
*summary
)
2315 lsmash_codec_type_t sample_type
= summary
->sample_type
;
2316 if( LSMASH_IS_NON_EXISTING_BOX( stsd
->file
) || !summary
)
2317 return LSMASH_ERR_NAMELESS
;
2318 int err
= isom_check_valid_summary( (lsmash_summary_t
*)summary
);
2321 isom_hint_entry_t
*hint
= isom_add_hint_description( stsd
, sample_type
);
2322 if( LSMASH_IS_NON_EXISTING_BOX( hint
) )
2323 return LSMASH_ERR_NAMELESS
;
2324 hint
->data_reference_index
= summary
->data_ref_index
;
2325 /* configure the sample description */
2326 lsmash_codec_type_t hint_type
= hint
->type
;
2327 if( lsmash_check_codec_type_identical(hint_type
, ISOM_CODEC_TYPE_RRTP_HINT
) )
2329 /* go through list of codec specific datas associated with this summary */
2330 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
2332 lsmash_codec_specific_t
*specific
= (lsmash_codec_specific_t
*)entry
->data
;
2335 err
= LSMASH_ERR_NAMELESS
;
2338 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_RTP_HINT_COMMON
)
2340 lsmash_isom_rtp_reception_hint_t
* rtp_param
;
2341 rtp_param
= (lsmash_isom_rtp_reception_hint_t
*)specific
->data
.structured
;
2342 if( rtp_param
->timescale
== 0 )
2343 return LSMASH_ERR_INVALID_DATA
;
2344 err
= isom_set_hint_summary( hint
, summary
);
2347 isom_tims_t
*tims
= isom_add_tims( hint
);
2348 isom_tsro_t
*tsro
= isom_add_tsro( hint
);
2349 isom_tssy_t
*tssy
= isom_add_tssy( hint
);
2350 if( LSMASH_IS_NON_EXISTING_BOX( tims
)
2351 || LSMASH_IS_NON_EXISTING_BOX( tsro
)
2352 || LSMASH_IS_NON_EXISTING_BOX( tssy
) )
2353 return LSMASH_ERR_NAMELESS
;
2354 tims
->timescale
= rtp_param
->timescale
;
2355 tsro
->offset
= rtp_param
->time_offset
;
2356 tssy
->reserved
= rtp_param
->reserved_timestamp_sync
>> 2;
2357 tssy
->timestamp_sync
= rtp_param
->reserved_timestamp_sync
& 0x03;
2362 return LSMASH_ERR_PATCH_WELCOME
;
2368 int isom_setup_sample_description( isom_stsd_t
*stsd
, lsmash_media_type media_type
, lsmash_summary_t
*summary
)
2370 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
2371 return isom_setup_visual_description( stsd
, (lsmash_video_summary_t
*)summary
);
2372 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
2373 return isom_setup_audio_description( stsd
, (lsmash_audio_summary_t
*)summary
);
2374 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
2375 return isom_setup_text_description( stsd
, (lsmash_summary_t
*)summary
);
2376 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_HINT_TRACK
)
2377 return isom_setup_hint_description( stsd
, (lsmash_hint_summary_t
*)summary
);
2379 return LSMASH_ERR_NAMELESS
;
2382 static lsmash_codec_specific_data_type
isom_get_codec_specific_data_type( lsmash_compact_box_type_t extension_fourcc
)
2384 static struct codec_specific_data_type_table_tag
2386 lsmash_compact_box_type_t extension_fourcc
;
2387 lsmash_codec_specific_data_type data_type
;
2388 } codec_specific_data_type_table
[32] = { { 0, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
} };
2389 if( codec_specific_data_type_table
[0].data_type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
)
2392 #define ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( extension_type, data_type ) \
2393 codec_specific_data_type_table[i++] = (struct codec_specific_data_type_table_tag){ extension_type.fourcc, data_type }
2394 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264
);
2395 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_HEVC
);
2396 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
);
2397 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
);
2398 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
);
2399 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
);
2400 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC
);
2401 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG
);
2402 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
);
2403 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
);
2404 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ALAC, LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_ALAC );
2405 //ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_ESDS, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
2406 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
);
2407 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
);
2408 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
);
2409 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_GAMMA_LEVEL
);
2410 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CLLI
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_CONTENT_LIGHT_LEVEL_INFO
);
2411 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_MDCV
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_MASTERING_DISPLAY_COLOR_VOLUME
);
2412 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
);
2413 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
);
2414 ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
);
2415 #undef ADD_CODEC_SPECIFIC_DATA_TYPE_TABLE_ELEMENT
2417 lsmash_codec_specific_data_type data_type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
;
2418 for( int i
= 0; codec_specific_data_type_table
[i
].data_type
!= LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
; i
++ )
2419 if( extension_fourcc
== codec_specific_data_type_table
[i
].extension_fourcc
)
2421 data_type
= codec_specific_data_type_table
[i
].data_type
;
2427 lsmash_summary_t
*isom_create_video_summary_from_description( isom_sample_entry_t
*sample_entry
)
2429 if( LSMASH_IS_NON_EXISTING_BOX( sample_entry
) )
2431 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)sample_entry
;
2432 lsmash_video_summary_t
*summary
= (lsmash_video_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_VIDEO
);
2435 summary
->sample_type
= visual
->type
;
2436 summary
->data_ref_index
= visual
->data_reference_index
;
2437 summary
->width
= visual
->width
;
2438 summary
->height
= visual
->height
;
2439 summary
->depth
= visual
->depth
;
2440 memcpy( summary
->compressorname
, visual
->compressorname
, 32 );
2441 summary
->compressorname
[32] = '\0';
2442 if( isom_is_qt_video( summary
->sample_type
) )
2444 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
,
2445 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2448 lsmash_qt_video_common_t
*data
= (lsmash_qt_video_common_t
*)specific
->data
.structured
;
2449 data
->revision_level
= visual
->revision_level
;
2450 data
->vendor
= visual
->vendor
;
2451 data
->temporalQuality
= visual
->temporalQuality
;
2452 data
->spatialQuality
= visual
->spatialQuality
;
2453 data
->horizontal_resolution
= visual
->horizresolution
;
2454 data
->vertical_resolution
= visual
->vertresolution
;
2455 data
->dataSize
= visual
->dataSize
;
2456 data
->frame_count
= visual
->frame_count
;
2457 data
->color_table_ID
= visual
->color_table_ID
;
2458 if( visual
->color_table_ID
== 0 )
2460 isom_qt_color_table_t
*src_ct
= &visual
->color_table
;
2461 if( !src_ct
->array
)
2463 lsmash_destroy_codec_specific_data( specific
);
2466 uint16_t element_count
= LSMASH_MIN( src_ct
->size
+ 1, 256 );
2467 lsmash_qt_color_table_t
*dst_ct
= &data
->color_table
;
2468 dst_ct
->seed
= src_ct
->seed
;
2469 dst_ct
->flags
= src_ct
->flags
;
2470 dst_ct
->size
= src_ct
->size
;
2471 for( uint16_t i
= 0; i
< element_count
; i
++ )
2473 dst_ct
->array
[i
].unused
= src_ct
->array
[i
].value
;
2474 dst_ct
->array
[i
].r
= src_ct
->array
[i
].r
;
2475 dst_ct
->array
[i
].g
= src_ct
->array
[i
].g
;
2476 dst_ct
->array
[i
].b
= src_ct
->array
[i
].b
;
2479 if( lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2481 lsmash_destroy_codec_specific_data( specific
);
2485 for( lsmash_entry_t
*entry
= visual
->extensions
.head
; entry
; entry
= entry
->next
)
2487 isom_box_t
*box
= (isom_box_t
*)entry
->data
;
2488 if( LSMASH_IS_NON_EXISTING_BOX( box
) )
2490 if( !(box
->manager
& LSMASH_BINARY_CODED_BOX
) )
2492 lsmash_codec_specific_t
*specific
= NULL
;
2493 if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_CLAP
) )
2495 isom_clap_t
*clap
= (isom_clap_t
*)box
;
2496 summary
->clap
.width
.n
= clap
->cleanApertureWidthN
;
2497 summary
->clap
.width
.d
= clap
->cleanApertureWidthD
;
2498 summary
->clap
.height
.n
= clap
->cleanApertureHeightN
;
2499 summary
->clap
.height
.d
= clap
->cleanApertureHeightD
;
2500 summary
->clap
.horizontal_offset
.n
= clap
->horizOffN
;
2501 summary
->clap
.horizontal_offset
.d
= clap
->horizOffD
;
2502 summary
->clap
.vertical_offset
.n
= clap
->vertOffN
;
2503 summary
->clap
.vertical_offset
.d
= clap
->vertOffD
;
2506 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_PASP
) )
2508 isom_pasp_t
*pasp
= (isom_pasp_t
*)box
;
2509 summary
->par_h
= pasp
->hSpacing
;
2510 summary
->par_v
= pasp
->vSpacing
;
2513 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_COLR
)
2514 || lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_COLR
) )
2516 isom_colr_t
*colr
= (isom_colr_t
*)box
;
2517 summary
->color
.primaries_index
= colr
->primaries_index
;
2518 summary
->color
.transfer_index
= colr
->transfer_function_index
;
2519 summary
->color
.matrix_index
= colr
->matrix_index
;
2520 summary
->color
.full_range
= colr
->full_range_flag
;
2523 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_STSL
) )
2525 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_SAMPLE_SCALE
,
2526 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2529 isom_stsl_t
*stsl
= (isom_stsl_t
*)box
;
2530 lsmash_isom_sample_scale_t
*data
= (lsmash_isom_sample_scale_t
*)specific
->data
.structured
;
2531 data
->constraint_flag
= stsl
->constraint_flag
;
2532 data
->scale_method
= stsl
->scale_method
;
2533 data
->display_center_x
= stsl
->display_center_x
;
2534 data
->display_center_y
= stsl
->display_center_y
;
2536 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_BTRT
) )
2538 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_H264_BITRATE
,
2539 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2542 isom_btrt_t
*btrt
= (isom_btrt_t
*)box
;
2543 lsmash_h264_bitrate_t
*data
= (lsmash_h264_bitrate_t
*)specific
->data
.structured
;
2544 data
->bufferSizeDB
= btrt
->bufferSizeDB
;
2545 data
->maxBitrate
= btrt
->maxBitrate
;
2546 data
->avgBitrate
= btrt
->avgBitrate
;
2548 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_FIEL
) )
2550 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_FIELD_INFO
,
2551 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2554 isom_fiel_t
*fiel
= (isom_fiel_t
*)box
;
2555 lsmash_qt_field_info_t
*data
= (lsmash_qt_field_info_t
*)specific
->data
.structured
;
2556 data
->fields
= fiel
->fields
;
2557 data
->detail
= fiel
->detail
;
2559 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CSPC
) )
2561 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_PIXEL_FORMAT
,
2562 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2565 isom_cspc_t
*cspc
= (isom_cspc_t
*)box
;
2566 lsmash_qt_pixel_format_t
*data
= (lsmash_qt_pixel_format_t
*)specific
->data
.structured
;
2567 data
->pixel_format
= cspc
->pixel_format
;
2569 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_SGBT
) )
2571 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_SIGNIFICANT_BITS
,
2572 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2575 isom_sgbt_t
*sgbt
= (isom_sgbt_t
*)box
;
2576 lsmash_qt_significant_bits_t
*data
= (lsmash_qt_significant_bits_t
*)specific
->data
.structured
;
2577 data
->significantBits
= sgbt
->significantBits
;
2579 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_GLBL
) )
2581 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_CODEC_GLOBAL_HEADER
,
2582 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2585 isom_glbl_t
*glbl
= (isom_glbl_t
*)box
;
2586 lsmash_codec_global_header_t
*data
= (lsmash_codec_global_header_t
*)specific
->data
.structured
;
2587 data
->header_size
= glbl
->header_size
;
2588 data
->header_data
= lsmash_memdup( glbl
->header_data
, glbl
->header_size
);
2589 if( !data
->header_data
)
2591 lsmash_destroy_codec_specific_data( specific
);
2595 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CLLI
) )
2597 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_CONTENT_LIGHT_LEVEL_INFO
,
2598 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2601 isom_clli_t
*clli
= (isom_clli_t
*)box
;
2602 lsmash_qt_content_light_level_info_t
*data
= (lsmash_qt_content_light_level_info_t
*)specific
->data
.structured
;
2603 data
->max_content_light_level
= clli
->max_content_light_level
;
2604 data
->max_pic_average_light_level
= clli
->max_pic_average_light_level
;
2606 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_MDCV
) )
2608 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_MASTERING_DISPLAY_COLOR_VOLUME
,
2609 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2612 isom_mdcv_t
*mdcv
= (isom_mdcv_t
*)box
;
2613 lsmash_qt_mastering_display_color_volume_t
*data
= (lsmash_qt_mastering_display_color_volume_t
*)specific
->data
.structured
;
2614 data
->display_primaries_g_x
= mdcv
->display_primaries_g_x
;
2615 data
->display_primaries_g_y
= mdcv
->display_primaries_g_y
;
2616 data
->display_primaries_b_x
= mdcv
->display_primaries_b_x
;
2617 data
->display_primaries_b_y
= mdcv
->display_primaries_b_y
;
2618 data
->display_primaries_r_x
= mdcv
->display_primaries_r_x
;
2619 data
->display_primaries_r_y
= mdcv
->display_primaries_r_y
;
2620 data
->white_point_x
= mdcv
->white_point_x
;
2621 data
->white_point_y
= mdcv
->white_point_y
;
2622 data
->max_display_mastering_luminance
= mdcv
->max_display_mastering_luminance
;
2623 data
->min_display_mastering_luminance
= mdcv
->min_display_mastering_luminance
;
2627 if( lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2629 lsmash_destroy_codec_specific_data( specific
);
2635 if( box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2637 uint8_t *data
= box
->binary
;
2638 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
2639 lsmash_codec_specific_data_type type
= isom_get_codec_specific_data_type( fourcc
);
2640 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2643 specific
->size
= box
->size
;
2644 specific
->data
.unstructured
= lsmash_memdup( box
->binary
, box
->size
);
2645 if( !specific
->data
.unstructured
2646 || lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2648 lsmash_destroy_codec_specific_data( specific
);
2653 return (lsmash_summary_t
*)summary
;
2655 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
2659 static int isom_append_structured_mp4sys_decoder_config( lsmash_codec_specific_list_t
*opaque
, isom_esds_t
*esds
)
2661 lsmash_bs_t
*bs
= lsmash_bs_create();
2663 return LSMASH_ERR_MEMORY_ALLOC
;
2664 /* Put box size, type, version and flags fields. */
2665 lsmash_bs_put_be32( bs
, 0 );
2666 lsmash_bs_put_be32( bs
, ISOM_BOX_TYPE_ESDS
.fourcc
);
2667 lsmash_bs_put_be32( bs
, 0 );
2668 /* Put ES Descriptor. */
2669 mp4sys_update_descriptor_size( esds
->ES
);
2670 mp4sys_write_descriptor( bs
, esds
->ES
);
2671 /* Export ES Descriptor Box as binary string. */
2673 uint8_t *esds_data
= lsmash_bs_export_data( bs
, &esds_size
);
2674 lsmash_bs_cleanup( bs
);
2676 return LSMASH_ERR_NAMELESS
;
2677 /* Update box size. */
2678 LSMASH_SET_BE32( esds_data
, esds_size
);
2679 lsmash_codec_specific_data_type type
= isom_get_codec_specific_data_type( ISOM_BOX_TYPE_ESDS
.fourcc
);
2680 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2683 lsmash_free( esds_data
);
2684 return LSMASH_ERR_NAMELESS
;
2686 specific
->data
.unstructured
= esds_data
;
2687 specific
->size
= esds_size
;
2688 /* Convert unstructured CODEC specific data format into structured, and append it to the opaque list. */
2689 lsmash_codec_specific_t
*conv
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2690 lsmash_destroy_codec_specific_data( specific
);
2692 return LSMASH_ERR_NAMELESS
;
2693 if( lsmash_list_add_entry( &opaque
->list
, conv
) < 0 )
2695 lsmash_destroy_codec_specific_data( conv
);
2696 return LSMASH_ERR_MEMORY_ALLOC
;
2701 lsmash_summary_t
*isom_create_audio_summary_from_description( isom_sample_entry_t
*sample_entry
)
2703 if( LSMASH_IS_NON_EXISTING_BOX( sample_entry
->file
)
2704 || LSMASH_IS_NON_EXISTING_BOX( sample_entry
->parent
) )
2706 isom_audio_entry_t
*audio
= (isom_audio_entry_t
*)sample_entry
;
2707 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO
);
2710 summary
->sample_type
= audio
->type
;
2711 summary
->data_ref_index
= audio
->data_reference_index
;
2712 summary
->sample_size
= audio
->samplesize
;
2713 summary
->channels
= audio
->channelcount
;
2714 summary
->frequency
= audio
->samplerate
>> 16;
2715 if( ((isom_stsd_t
*)audio
->parent
)->version
== 0
2716 && audio
->file
->qt_compatible
2717 && isom_is_qt_audio( audio
->type
) )
2719 if( audio
->version
== 0 )
2720 isom_get_implicit_qt_fixed_comp_audio_sample_quants( audio
, &summary
->samples_in_frame
, &summary
->bytes_per_frame
, &summary
->sample_size
);
2721 else if( audio
->version
== 1 )
2723 summary
->channels
= audio
->bytesPerPacket
? audio
->bytesPerFrame
/ audio
->bytesPerPacket
: audio
->channelcount
;
2724 summary
->sample_size
= audio
->bytesPerPacket
* 8;
2725 summary
->samples_in_frame
= audio
->samplesPerPacket
;
2726 summary
->bytes_per_frame
= audio
->bytesPerFrame
;
2728 else if( audio
->version
== 2 )
2730 summary
->frequency
= (union {uint64_t i
; double d
;}){audio
->audioSampleRate
}.d
;
2731 summary
->channels
= audio
->numAudioChannels
;
2732 summary
->sample_size
= audio
->constBitsPerChannel
;
2733 summary
->samples_in_frame
= audio
->constLPCMFramesPerAudioPacket
;
2734 summary
->bytes_per_frame
= audio
->constBytesPerAudioPacket
;
2736 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
,
2737 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2740 lsmash_qt_audio_common_t
*common
= (lsmash_qt_audio_common_t
*)specific
->data
.structured
;
2741 common
->revision_level
= audio
->revision_level
;
2742 common
->vendor
= audio
->vendor
;
2743 common
->compression_ID
= audio
->compression_ID
;
2744 if( lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2746 lsmash_destroy_codec_specific_data( specific
);
2749 if( isom_is_lpcm_audio( audio
) )
2751 specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
,
2752 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2755 lsmash_qt_audio_format_specific_flags_t
*data
= (lsmash_qt_audio_format_specific_flags_t
*)specific
->data
.structured
;
2756 if( audio
->version
== 2 )
2757 data
->format_flags
= audio
->formatSpecificFlags
;
2760 data
->format_flags
= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
| QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
;
2761 /* Here, don't override samplesize.
2762 * We should trust samplesize field in the description for misused CODEC indentifier. */
2763 lsmash_codec_type_t audio_type
= audio
->type
;
2764 if( lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_TWOS_AUDIO
)
2765 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_NONE_AUDIO
)
2766 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_NOT_SPECIFIED
) )
2768 if( summary
->sample_size
<= 8 )
2769 data
->format_flags
&= ~(QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
| QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
);
2773 if( lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_FL32_AUDIO
)
2774 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_FL64_AUDIO
) )
2776 data
->format_flags
&= ~QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER
;
2777 data
->format_flags
|= QT_LPCM_FORMAT_FLAG_FLOAT
;
2779 else if( lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_23NI_AUDIO
)
2780 || lsmash_check_codec_type_identical( audio_type
, QT_CODEC_TYPE_SOWT_AUDIO
) )
2781 data
->format_flags
&= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
2784 isom_wave_t
*wave
= (isom_wave_t
*)isom_get_extension_box_format( &audio
->extensions
, QT_BOX_TYPE_WAVE
);
2785 if( LSMASH_IS_EXISTING_BOX( wave
->enda
) )
2787 if( wave
->enda
->littleEndian
)
2788 data
->format_flags
&= ~QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
2790 data
->format_flags
|= QT_LPCM_FORMAT_FLAG_BIG_ENDIAN
;
2792 if( lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2794 lsmash_destroy_codec_specific_data( specific
);
2798 else if( audio
->version
== 2
2799 && (lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_ALAC_AUDIO
)
2800 || lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAC_AUDIO
)) )
2801 switch( audio
->formatSpecificFlags
)
2803 case QT_ALAC_FORMAT_FLAG_16BIT_SOURCE_DATA
:
2804 summary
->sample_size
= 16;
2806 case QT_ALAC_FORMAT_FLAG_20BIT_SOURCE_DATA
:
2807 summary
->sample_size
= 20;
2809 case QT_ALAC_FORMAT_FLAG_24BIT_SOURCE_DATA
:
2810 summary
->sample_size
= 24;
2812 case QT_ALAC_FORMAT_FLAG_32BIT_SOURCE_DATA
:
2813 summary
->sample_size
= 32;
2819 else if( lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_SAMR_AUDIO
) )
2821 summary
->channels
= 1;
2822 summary
->frequency
= 8000;
2824 else if( lsmash_check_codec_type_identical( audio
->type
, ISOM_CODEC_TYPE_SAWB_AUDIO
) )
2826 summary
->channels
= 1;
2827 summary
->frequency
= 16000;
2829 uint32_t actual_sampling_rate
= 0;
2830 for( lsmash_entry_t
*entry
= audio
->extensions
.head
; entry
; entry
= entry
->next
)
2832 isom_box_t
*box
= (isom_box_t
*)entry
->data
;
2833 if( LSMASH_IS_NON_EXISTING_BOX( box
) )
2835 if( !(box
->manager
& LSMASH_BINARY_CODED_BOX
) )
2837 if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CHAN
) )
2839 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_CHANNEL_LAYOUT
,
2840 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
2843 isom_chan_t
*chan
= (isom_chan_t
*)box
;
2844 lsmash_qt_audio_channel_layout_t
*data
= (lsmash_qt_audio_channel_layout_t
*)specific
->data
.structured
;
2845 data
->channelLayoutTag
= chan
->channelLayoutTag
;
2846 data
->channelBitmap
= chan
->channelBitmap
;
2847 if( lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2849 lsmash_destroy_codec_specific_data( specific
);
2853 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_ESDS
)
2854 || lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ESDS
) )
2856 isom_esds_t
*esds
= (isom_esds_t
*)box
;
2857 if( mp4sys_setup_summary_from_DecoderSpecificInfo( summary
, esds
->ES
) < 0
2858 || isom_append_structured_mp4sys_decoder_config( summary
->opaque
, esds
) < 0 )
2861 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_SRAT
) )
2863 isom_srat_t
*srat
= (isom_srat_t
*)box
;
2864 actual_sampling_rate
= srat
->sampling_rate
;
2866 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_WAVE
) )
2868 /* Don't append 'wave' extension itself to the opaque CODEC specific info list. */
2869 isom_wave_t
*wave
= (isom_wave_t
*)box
;
2870 lsmash_bs_t
*bs
= lsmash_bs_create();
2873 for( lsmash_entry_t
*wave_entry
= wave
->extensions
.head
; wave_entry
; wave_entry
= wave_entry
->next
)
2875 isom_box_t
*wave_ext
= (isom_box_t
*)wave_entry
->data
;
2876 if( LSMASH_IS_NON_EXISTING_BOX( wave_ext
) )
2878 lsmash_box_type_t box_type
= LSMASH_BOX_TYPE_INITIALIZER
;
2879 if( !(wave_ext
->manager
& LSMASH_BINARY_CODED_BOX
) )
2881 box_type
= wave_ext
->type
;
2882 if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ENDA
) )
2884 isom_enda_t
*enda
= (isom_enda_t
*)wave_ext
;
2885 isom_bs_put_box_common( bs
, enda
);
2886 lsmash_bs_put_be16( bs
, enda
->littleEndian
);
2888 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_MP4A
) )
2890 isom_mp4a_t
*mp4a
= (isom_mp4a_t
*)wave_ext
;
2891 isom_bs_put_box_common( bs
, mp4a
);
2892 lsmash_bs_put_be32( bs
, mp4a
->unknown
);
2894 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_CHAN
) )
2896 isom_chan_t
*chan
= (isom_chan_t
*)wave_ext
;
2897 isom_bs_put_box_common( bs
, chan
);
2898 lsmash_bs_put_be32( bs
, chan
->channelLayoutTag
);
2899 lsmash_bs_put_be32( bs
, chan
->channelBitmap
);
2900 lsmash_bs_put_be32( bs
, chan
->numberChannelDescriptions
);
2901 if( chan
->channelDescriptions
)
2902 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
2904 isom_channel_description_t
*channelDescriptions
= (isom_channel_description_t
*)(&chan
->channelDescriptions
[i
]);
2905 lsmash_bs_put_be32( bs
, channelDescriptions
->channelLabel
);
2906 lsmash_bs_put_be32( bs
, channelDescriptions
->channelFlags
);
2907 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[0] );
2908 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[1] );
2909 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[2] );
2912 else if( lsmash_check_box_type_identical( box_type
, QT_BOX_TYPE_ESDS
) )
2914 isom_esds_t
*esds
= (isom_esds_t
*)wave_ext
;
2915 if( LSMASH_IS_NON_EXISTING_BOX( esds
)
2916 || mp4sys_setup_summary_from_DecoderSpecificInfo( summary
, esds
->ES
) < 0
2917 || isom_append_structured_mp4sys_decoder_config( summary
->opaque
, esds
) < 0 )
2919 lsmash_bs_cleanup( bs
);
2925 /* Skip Format Box and Terminator Box since they are mandatory and fixed structure. */
2930 if( wave_ext
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2932 uint8_t *data
= wave_ext
->binary
;
2933 box_type
.fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
2934 lsmash_bs_put_bytes( bs
, wave_ext
->size
, wave_ext
->binary
);
2936 /* Export as binary string. */
2938 uint8_t *box_data
= lsmash_bs_export_data( bs
, &box_size
);
2939 lsmash_bs_empty( bs
);
2942 lsmash_bs_cleanup( bs
);
2945 /* Append as an unstructured CODEC specific info. */
2946 lsmash_codec_specific_data_type type
;
2947 if( box_type
.fourcc
== QT_BOX_TYPE_CHAN
.fourcc
)
2948 /* Complete audio channel layout is stored as binary string.
2949 * We distinguish it from one of the outside of 'wave' extension here. */
2950 type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
;
2953 type
= isom_get_codec_specific_data_type( box_type
.fourcc
);
2954 if( type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
)
2955 type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_DECOMPRESSION_PARAMETERS
;
2957 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2960 lsmash_free( box_data
);
2961 lsmash_bs_cleanup( bs
);
2964 specific
->data
.unstructured
= box_data
;
2965 specific
->size
= box_size
;
2966 if( lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2968 lsmash_destroy_codec_specific_data( specific
);
2969 lsmash_bs_cleanup( bs
);
2973 lsmash_bs_cleanup( bs
);
2978 if( box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
2980 uint8_t *data
= box
->binary
;
2981 lsmash_compact_box_type_t fourcc
= LSMASH_4CC( data
[4], data
[5], data
[6], data
[7] );
2982 lsmash_codec_specific_data_type type
= isom_get_codec_specific_data_type( fourcc
);
2983 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( type
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
2986 specific
->size
= box
->size
;
2987 specific
->data
.unstructured
= lsmash_memdup( box
->binary
, box
->size
);
2988 if( !specific
->data
.unstructured
2989 || lsmash_list_add_entry( &summary
->opaque
->list
, specific
) < 0 )
2991 lsmash_destroy_codec_specific_data( specific
);
2994 if( specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
2995 || specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
2996 || specific
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
)
2998 specific
= lsmash_convert_codec_specific_format( specific
, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
);
3001 switch( specific
->type
)
3003 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS
:
3005 lsmash_dts_specific_parameters_t
*param
= (lsmash_dts_specific_parameters_t
*)specific
->data
.structured
;
3006 summary
->sample_size
= param
->pcmSampleDepth
;
3007 summary
->samples_in_frame
= (summary
->frequency
* (512 << param
->FrameDuration
)) / param
->DTSSamplingFrequency
;
3010 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_AC_3
:
3012 lsmash_ac3_specific_parameters_t
*param
= (lsmash_ac3_specific_parameters_t
*)specific
->data
.structured
;
3013 summary
->frequency
= ac3_get_sample_rate( param
);
3014 summary
->channels
= ac3_get_channel_count( param
);
3015 summary
->samples_in_frame
= 1536;
3018 case LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_EC_3
:
3020 lsmash_eac3_specific_parameters_t
*param
= (lsmash_eac3_specific_parameters_t
*)specific
->data
.structured
;
3021 eac3_update_sample_rate( &summary
->frequency
, param
, NULL
);
3022 eac3_update_channel_count( &summary
->channels
, param
);
3023 summary
->samples_in_frame
= 1536;
3029 lsmash_destroy_codec_specific_data( specific
);
3033 /* Set the actual sampling rate. */
3034 if( actual_sampling_rate
)
3035 summary
->frequency
= actual_sampling_rate
;
3036 return (lsmash_summary_t
*)summary
;
3038 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
3042 lsmash_codec_specific_t
*lsmash_get_codec_specific_data( lsmash_summary_t
*summary
, uint32_t extension_number
)
3044 if( !summary
|| !summary
->opaque
)
3047 for( lsmash_entry_t
*entry
= summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
3048 if( ++i
== extension_number
)
3049 return (lsmash_codec_specific_t
*)entry
->data
;
3053 uint32_t lsmash_count_codec_specific_data( lsmash_summary_t
*summary
)
3055 if( !summary
|| !summary
->opaque
)
3057 return summary
->opaque
->list
.entry_count
;
3060 int isom_compare_opaque_extensions( lsmash_summary_t
*a
, lsmash_summary_t
*b
)
3063 uint32_t in_number_of_extensions
= lsmash_count_codec_specific_data( a
);
3064 uint32_t out_number_of_extensions
= lsmash_count_codec_specific_data( b
);
3065 if( out_number_of_extensions
!= in_number_of_extensions
)
3067 uint32_t active_number_of_extensions
= in_number_of_extensions
;
3068 uint32_t identical_count
= 0;
3069 for( uint32_t j
= 1; j
<= in_number_of_extensions
; j
++ )
3071 lsmash_codec_specific_t
*in_cs_orig
= lsmash_get_codec_specific_data( a
, j
);
3072 lsmash_codec_specific_t
*in_cs
;
3073 lsmash_codec_specific_format compare_format
= LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
;
3074 if( in_cs_orig
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
3076 if( in_cs_orig
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
3077 || in_cs_orig
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
3078 || in_cs_orig
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_FORMAT_SPECIFIC_FLAGS
)
3080 compare_format
= LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
;
3085 in_cs
= lsmash_convert_codec_specific_format( in_cs_orig
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
3088 /* We don't support the format converter of this data type. */
3089 --active_number_of_extensions
;
3096 for( uint32_t k
= 1; k
<= out_number_of_extensions
; k
++ )
3098 lsmash_codec_specific_t
*out_cs_orig
= lsmash_get_codec_specific_data( b
, k
);
3099 if( out_cs_orig
->type
!= in_cs_orig
->type
)
3101 lsmash_codec_specific_t
*out_cs
;
3102 if( out_cs_orig
->format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
3104 if( compare_format
== LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED
)
3105 out_cs
= out_cs_orig
;
3108 out_cs
= lsmash_convert_codec_specific_format( out_cs_orig
, LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
3114 out_cs
= out_cs_orig
;
3116 if( compare_format
== LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
)
3117 identical
= out_cs
->size
== in_cs
->size
&& !memcmp( out_cs
->data
.unstructured
, in_cs
->data
.unstructured
, in_cs
->size
);
3120 if( in_cs
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_VIDEO_COMMON
)
3122 lsmash_qt_video_common_t
*in_data
= (lsmash_qt_video_common_t
*)in_cs
->data
.structured
;
3123 lsmash_qt_video_common_t
*out_data
= (lsmash_qt_video_common_t
*)out_cs
->data
.structured
;
3124 identical
= in_data
->revision_level
== out_data
->revision_level
3125 && in_data
->vendor
== out_data
->vendor
3126 && in_data
->temporalQuality
== out_data
->temporalQuality
3127 && in_data
->spatialQuality
== out_data
->spatialQuality
3128 && in_data
->horizontal_resolution
== out_data
->horizontal_resolution
3129 && in_data
->vertical_resolution
== out_data
->vertical_resolution
3130 && in_data
->dataSize
== out_data
->dataSize
3131 && in_data
->frame_count
== out_data
->frame_count
3132 && in_data
->color_table_ID
== out_data
->color_table_ID
;
3134 else if( in_cs
->type
== LSMASH_CODEC_SPECIFIC_DATA_TYPE_QT_AUDIO_COMMON
)
3136 lsmash_qt_audio_common_t
*in_data
= (lsmash_qt_audio_common_t
*)in_cs
->data
.structured
;
3137 lsmash_qt_audio_common_t
*out_data
= (lsmash_qt_audio_common_t
*)out_cs
->data
.structured
;
3138 identical
= in_data
->revision_level
== out_data
->revision_level
3139 && in_data
->vendor
== out_data
->vendor
3140 && in_data
->compression_ID
== out_data
->compression_ID
;
3144 lsmash_qt_audio_format_specific_flags_t
*in_data
= (lsmash_qt_audio_format_specific_flags_t
*)in_cs
->data
.structured
;
3145 lsmash_qt_audio_format_specific_flags_t
*out_data
= (lsmash_qt_audio_format_specific_flags_t
*)out_cs
->data
.structured
;
3146 identical
= (in_data
->format_flags
== out_data
->format_flags
);
3149 if( out_cs
!= out_cs_orig
)
3150 lsmash_destroy_codec_specific_data( out_cs
);
3157 if( in_cs
!= in_cs_orig
)
3158 lsmash_destroy_codec_specific_data( in_cs
);
3160 return (identical_count
!= active_number_of_extensions
);
3163 int isom_get_implicit_qt_fixed_comp_audio_sample_quants
3165 isom_audio_entry_t
*audio
,
3166 uint32_t *samples_per_packet
,
3167 uint32_t *constant_bytes_per_frame
,
3168 uint32_t *sample_size
3171 if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC3_AUDIO
) )
3173 *samples_per_packet
= 6;
3174 *constant_bytes_per_frame
= 2 * audio
->channelcount
;
3177 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_MAC6_AUDIO
) )
3179 *samples_per_packet
= 6;
3180 *constant_bytes_per_frame
= audio
->channelcount
;
3183 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ADPCM17_AUDIO
) )
3185 *samples_per_packet
= 64;
3186 *constant_bytes_per_frame
= 34 * audio
->channelcount
;
3189 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_AGSM_AUDIO
) )
3191 *samples_per_packet
= 160;
3192 *constant_bytes_per_frame
= 33;
3195 else if( lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ALAW_AUDIO
)
3196 || lsmash_check_codec_type_identical( audio
->type
, QT_CODEC_TYPE_ULAW_AUDIO
) )
3198 *samples_per_packet
= 1;
3199 *constant_bytes_per_frame
= audio
->channelcount
;
3207 int hint_update_bitrate( isom_stbl_t
*stbl
, isom_mdhd_t
*mdhd
, uint32_t sample_description_index
)
3209 uint32_t bufferSizeDB
;
3210 uint32_t maxBitrate
= 0;
3211 uint32_t avgBitrate
= 0;
3212 int err
= isom_calculate_bitrate_description( stbl
, mdhd
, &bufferSizeDB
, &maxBitrate
, &avgBitrate
, sample_description_index
);
3213 isom_hmhd_t
*hmhd
= ((isom_mdia_t
*)(mdhd
->parent
))->minf
->hmhd
;
3214 hmhd
->maxbitrate
= maxBitrate
;
3215 hmhd
->avgbitrate
= avgBitrate
;
3216 hmhd
->avgPDUsize
= hmhd
->PDUcount
> 0 ? (hmhd
->combinedPDUsize
/ hmhd
->PDUcount
) : 0;
3220 isom_bitrate_updater_t isom_get_bitrate_updater
3222 isom_sample_entry_t
*sample_entry
3225 #define RETURN_BITRATE_UPDATER( func_name ) \
3227 extern int func_name( isom_stbl_t *, isom_mdhd_t *, uint32_t sample_description_index ); \
3230 lsmash_codec_type_t sample_type
= sample_entry
->type
;
3231 if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC1_VIDEO
)
3232 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC2_VIDEO
)
3233 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC3_VIDEO
)
3234 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_AVC4_VIDEO
)
3235 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_HVC1_VIDEO
)
3236 || lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_HEV1_VIDEO
) )
3237 RETURN_BITRATE_UPDATER( nalu_update_bitrate
)
3238 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4V_VIDEO
) )
3239 RETURN_BITRATE_UPDATER( mp4v_update_bitrate
)
3240 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4A_AUDIO
)
3241 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_MP4A_AUDIO
) )
3242 RETURN_BITRATE_UPDATER( mp4a_update_bitrate
)
3243 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_ALAC_AUDIO
)
3244 || lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_ALAC_AUDIO
) )
3245 RETURN_BITRATE_UPDATER( alac_update_bitrate
)
3246 else if( isom_is_dts_audio( sample_type
) )
3247 RETURN_BITRATE_UPDATER( dts_update_bitrate
)
3248 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_EC_3_AUDIO
) )
3249 RETURN_BITRATE_UPDATER( eac3_update_bitrate
)
3250 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_RRTP_HINT
) )
3251 RETURN_BITRATE_UPDATER( hint_update_bitrate
)
3252 else if( isom_is_waveform_audio( sample_type
) )
3253 RETURN_BITRATE_UPDATER( waveform_audio_update_bitrate
)
3256 #undef RETURN_BITRATE_UPDATER