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