h264: Fix infinite loop when series of byte stream end by
[L-SMASH.git] / core / print.c
blobc24e2f9cdc944b1943cfc69274ec8962821709f9
1 /*****************************************************************************
2 * print.c:
3 *****************************************************************************
4 * Copyright (C) 2010-2014 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #ifdef LSMASH_DEMUXER_ENABLED
25 #include "common/internal.h" /* must be placed first */
27 #include <stdlib.h>
28 #include <string.h>
29 #include <inttypes.h>
30 #include <stdarg.h> /* for isom_iprintf */
32 #include "box.h"
35 typedef int (*isom_print_box_t)( FILE *, lsmash_file_t *, isom_box_t *, int );
37 typedef struct
39 int level;
40 isom_box_t *box;
41 isom_print_box_t func;
42 } isom_print_entry_t;
44 static void isom_ifprintf_duration( FILE *fp, int indent, char *field_name, uint64_t duration, uint32_t timescale )
46 if( !timescale )
48 lsmash_ifprintf( fp, indent, "duration = %"PRIu64"\n", duration );
49 return;
51 int dur = duration / timescale;
52 int hour = (dur / 3600) % 24;
53 int min = (dur / 60) % 60;
54 int sec = dur % 60;
55 int ms = ((double)duration / timescale - (hour * 3600 + min * 60 + sec)) * 1e3 + 0.5;
56 static char str[32];
57 sprintf( str, "%02d:%02d:%02d.%03d", hour, min, sec, ms );
58 lsmash_ifprintf( fp, indent, "%s = %"PRIu64" (%s)\n", field_name, duration, str );
61 static char *isom_mp4time2utc( uint64_t mp4time )
63 int year_offset = mp4time / 31536000;
64 int leap_years = year_offset / 4 + ((mp4time / 86400) > 366); /* 1904 itself is leap year */
65 int day = (mp4time / 86400) - (year_offset * 365) - leap_years + 1;
66 while( day < 1 )
68 --year_offset;
69 leap_years = year_offset / 4 + ((mp4time / 86400) > 366);
70 day = (mp4time / 86400) - (year_offset * 365) - leap_years + 1;
72 int year = 1904 + year_offset;
73 int is_leap = (!(year % 4) && (year % 100)) || !(year % 400);
74 static const int month_days[13] = { 29, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
75 int month;
76 for( month = 1; month <= 12; month++ )
78 int i = (month == 2 && is_leap) ? 0 : month;
79 if( day <= month_days[i] )
80 break;
81 day -= month_days[i];
83 int hour = (mp4time / 3600) % 24;
84 int min = (mp4time / 60) % 60;
85 int sec = mp4time % 60;
86 static char utc[64];
87 sprintf( utc, "UTC %d/%02d/%02d, %02d:%02d:%02d\n", year, month, day, hour, min, sec );
88 return utc;
91 static void isom_ifprintf_matrix( FILE *fp, int indent, int32_t *matrix )
93 lsmash_ifprintf( fp, indent, "| a, b, u | | %f, %f, %f |\n", lsmash_fixed2double( matrix[0], 16 ),
94 lsmash_fixed2double( matrix[1], 16 ),
95 lsmash_fixed2double( matrix[2], 30 ) );
96 lsmash_ifprintf( fp, indent, "| c, d, v | = | %f, %f, %f |\n", lsmash_fixed2double( matrix[3], 16 ),
97 lsmash_fixed2double( matrix[4], 16 ),
98 lsmash_fixed2double( matrix[5], 30 ) );
99 lsmash_ifprintf( fp, indent, "| x, y, w | | %f, %f, %f |\n", lsmash_fixed2double( matrix[6], 16 ),
100 lsmash_fixed2double( matrix[7], 16 ),
101 lsmash_fixed2double( matrix[8], 30 ) );
104 static void isom_ifprintf_rgb_color( FILE *fp, int indent, uint16_t *color )
106 lsmash_ifprintf( fp, indent, "{ R, G, B } = { %"PRIu16", %"PRIu16", %"PRIu16" }\n", color[0], color[1], color[2] );
109 static void isom_ifprintf_rgba_color( FILE *fp, int indent, uint8_t *color )
111 lsmash_ifprintf( fp, indent, "{ R, G, B, A } = { %"PRIu8", %"PRIu8", %"PRIu8", %"PRIu8" }\n", color[0], color[1], color[2], color[3] );
114 static char *isom_unpack_iso_language( uint16_t language )
116 static char unpacked[4];
117 unpacked[0] = ((language >> 10) & 0x1f) + 0x60;
118 unpacked[1] = ((language >> 5) & 0x1f) + 0x60;
119 unpacked[2] = ( language & 0x1f) + 0x60;
120 unpacked[3] = 0;
121 return unpacked;
124 static void isom_ifprintf_sample_description_common_reserved( FILE *fp, int indent, uint8_t *reserved )
126 uint64_t temp = ((uint64_t)reserved[0] << 40)
127 | ((uint64_t)reserved[1] << 32)
128 | ((uint64_t)reserved[2] << 24)
129 | ((uint64_t)reserved[3] << 16)
130 | ((uint64_t)reserved[4] << 8)
131 | (uint64_t)reserved[5];
132 lsmash_ifprintf( fp, indent, "reserved = 0x%012"PRIx64"\n", temp );
135 static void isom_ifprintf_sample_flags( FILE *fp, int indent, char *field_name, isom_sample_flags_t *flags )
137 uint32_t temp = (flags->reserved << 28)
138 | (flags->is_leading << 26)
139 | (flags->sample_depends_on << 24)
140 | (flags->sample_is_depended_on << 22)
141 | (flags->sample_has_redundancy << 20)
142 | (flags->sample_padding_value << 17)
143 | (flags->sample_is_non_sync_sample << 16)
144 | flags->sample_degradation_priority;
145 lsmash_ifprintf( fp, indent++, "%s = 0x%08"PRIx32"\n", field_name, temp );
146 if( flags->is_leading & ISOM_SAMPLE_IS_UNDECODABLE_LEADING ) lsmash_ifprintf( fp, indent, "undecodable leading\n" );
147 else if( flags->is_leading & ISOM_SAMPLE_IS_NOT_LEADING ) lsmash_ifprintf( fp, indent, "non-leading\n" );
148 else if( flags->is_leading & ISOM_SAMPLE_IS_DECODABLE_LEADING ) lsmash_ifprintf( fp, indent, "decodable leading\n" );
149 if( flags->sample_depends_on & ISOM_SAMPLE_IS_INDEPENDENT ) lsmash_ifprintf( fp, indent, "independent\n" );
150 else if( flags->sample_depends_on & ISOM_SAMPLE_IS_NOT_INDEPENDENT ) lsmash_ifprintf( fp, indent, "dependent\n" );
151 if( flags->sample_is_depended_on & ISOM_SAMPLE_IS_NOT_DISPOSABLE ) lsmash_ifprintf( fp, indent, "non-disposable\n" );
152 else if( flags->sample_is_depended_on & ISOM_SAMPLE_IS_DISPOSABLE ) lsmash_ifprintf( fp, indent, "disposable\n" );
153 if( flags->sample_has_redundancy & ISOM_SAMPLE_HAS_REDUNDANCY ) lsmash_ifprintf( fp, indent, "redundant\n" );
154 else if( flags->sample_has_redundancy & ISOM_SAMPLE_HAS_NO_REDUNDANCY ) lsmash_ifprintf( fp, indent, "non-redundant\n" );
155 if( flags->sample_padding_value )
156 lsmash_ifprintf( fp, indent, "padding_bits = %"PRIu8"\n", flags->sample_padding_value );
157 lsmash_ifprintf( fp, indent, flags->sample_is_non_sync_sample ? "non-sync sample\n" : "sync sample\n" );
158 lsmash_ifprintf( fp, indent, "degradation_priority = %"PRIu16"\n", flags->sample_degradation_priority );
161 static inline int isom_print_simple( FILE *fp, isom_box_t *box, int level, char *name )
163 int indent = level;
164 if( box->type.fourcc != ISOM_BOX_TYPE_UUID.fourcc )
166 lsmash_ifprintf( fp, indent++, "[%s: %s]\n", isom_4cc2str( box->type.fourcc ), name );
167 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
168 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
170 else
172 lsmash_ifprintf( fp, indent++, "[uuid: UUID Box]\n" );
173 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
174 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
175 lsmash_ifprintf( fp, indent++, "usertype\n" );
176 if( isom_is_printable_4cc( box->type.user.fourcc ) )
177 lsmash_ifprintf( fp, indent, "type = %s\n", isom_4cc2str( box->type.user.fourcc ) );
178 lsmash_ifprintf( fp, indent, "name = %s\n", name );
179 lsmash_ifprintf( fp, indent, "uuid = 0x%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"0x%08"PRIx32"\n",
180 box->type.user.fourcc,
181 (box->type.user.id[0] << 8) | box->type.user.id[1], (box->type.user.id[2] << 8) | box->type.user.id[3],
182 (box->type.user.id[4] << 8) | box->type.user.id[5], (box->type.user.id[6] << 8) | box->type.user.id[7],
183 (box->type.user.id[8] << 24) | (box->type.user.id[9] << 16) | (box->type.user.id[10] << 8) | box->type.user.id[11] );
185 return 0;
188 static void isom_print_basebox_common( FILE *fp, int indent, isom_box_t *box, char *name )
190 isom_print_simple( fp, box, indent, name );
193 static void isom_print_fullbox_common( FILE *fp, int indent, isom_box_t *box, char *name )
195 isom_print_simple( fp, box, indent++, name );
196 lsmash_ifprintf( fp, indent, "version = %"PRIu8"\n", box->version );
197 lsmash_ifprintf( fp, indent, "flags = 0x%06"PRIx32"\n", box->flags & 0x00ffffff );
200 static void isom_print_box_common( FILE *fp, int indent, isom_box_t *box, char *name )
202 isom_box_t *parent = box->parent;
203 if( parent && lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
205 isom_print_basebox_common( fp, indent, box, name );
206 return;
208 if( isom_is_fullbox( box ) )
209 isom_print_fullbox_common( fp, indent, box, name );
210 else
211 isom_print_basebox_common( fp, indent, box, name );
214 static int isom_print_unknown( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
216 int indent = level;
217 if( box->type.fourcc != ISOM_BOX_TYPE_UUID.fourcc )
219 lsmash_ifprintf( fp, indent++, "[%s]\n", isom_4cc2str( box->type.fourcc ) );
220 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
221 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
223 else
225 lsmash_ifprintf( fp, indent++, "[uuid: UUID Box]\n" );
226 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
227 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
228 lsmash_ifprintf( fp, indent++, "usertype\n" );
229 if( isom_is_printable_4cc( box->type.user.fourcc ) )
230 lsmash_ifprintf( fp, indent, "type = %s\n", isom_4cc2str( box->type.user.fourcc ) );
231 lsmash_ifprintf( fp, indent, "uuid = 0x%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"%08"PRIx32"\n",
232 box->type.user.fourcc,
233 (box->type.user.id[0] << 8) | box->type.user.id[1], (box->type.user.id[2] << 8) | box->type.user.id[3],
234 (box->type.user.id[4] << 8) | box->type.user.id[5], (box->type.user.id[6] << 8) | box->type.user.id[7],
235 (box->type.user.id[8] << 24) | (box->type.user.id[9] << 16) | (box->type.user.id[10] << 8) | box->type.user.id[11] );
237 return 0;
240 static void isom_print_brand_description( FILE *fp, lsmash_brand_type brand )
242 if( brand == 0 )
243 return;
244 static const struct
246 lsmash_brand_type brand;
247 char *description;
248 } brand_description_table[] =
250 { ISOM_BRAND_TYPE_3G2A, "3GPP2" },
251 { ISOM_BRAND_TYPE_3GE6, "3GPP Release 6 Extended Presentation Profile" },
252 { ISOM_BRAND_TYPE_3GE9, "3GPP Release 9 Extended Presentation Profile" },
253 { ISOM_BRAND_TYPE_3GF9, "3GPP Release 9 File-delivery Server Profile" },
254 { ISOM_BRAND_TYPE_3GG6, "3GPP Release 6 General Profile" },
255 { ISOM_BRAND_TYPE_3GG9, "3GPP Release 9 General Profile" },
256 { ISOM_BRAND_TYPE_3GH9, "3GPP Release 9 Adaptive Streaming Profile" },
257 { ISOM_BRAND_TYPE_3GM9, "3GPP Release 9 Media Segment Profile" },
258 { ISOM_BRAND_TYPE_3GP4, "3GPP Release 4" },
259 { ISOM_BRAND_TYPE_3GP5, "3GPP Release 5" },
260 { ISOM_BRAND_TYPE_3GP6, "3GPP Release 6 Basic Profile" },
261 { ISOM_BRAND_TYPE_3GP7, "3GPP Release 7" },
262 { ISOM_BRAND_TYPE_3GP8, "3GPP Release 8" },
263 { ISOM_BRAND_TYPE_3GP9, "3GPP Release 9 Basic Profile" },
264 { ISOM_BRAND_TYPE_3GR6, "3GPP Release 6 Progressive Download Profile" },
265 { ISOM_BRAND_TYPE_3GR9, "3GPP Release 9 Progressive Download Profile" },
266 { ISOM_BRAND_TYPE_3GS6, "3GPP Release 6 Streaming Server Profile" },
267 { ISOM_BRAND_TYPE_3GS9, "3GPP Release 9 Streaming Server Profile" },
268 { ISOM_BRAND_TYPE_3GT9, "3GPP Release 9 Media Stream Recording Profile" },
269 { ISOM_BRAND_TYPE_ARRI, "ARRI Digital Camera" },
270 { ISOM_BRAND_TYPE_CAEP, "Canon Digital Camera" },
271 { ISOM_BRAND_TYPE_CDES, "Convergent Designs" },
272 { ISOM_BRAND_TYPE_LCAG, "Leica digital camera" },
273 { ISOM_BRAND_TYPE_M4A , "iTunes MPEG-4 audio protected or not" },
274 { ISOM_BRAND_TYPE_M4B , "iTunes AudioBook protected or not" },
275 { ISOM_BRAND_TYPE_M4P , "MPEG-4 protected audio" },
276 { ISOM_BRAND_TYPE_M4V , "MPEG-4 protected audio+video" },
277 { ISOM_BRAND_TYPE_MFSM, "Media File for Samsung video Metadata" },
278 { ISOM_BRAND_TYPE_MPPI, "Photo Player Multimedia Application Format" },
279 { ISOM_BRAND_TYPE_ROSS, "Ross Video" },
280 { ISOM_BRAND_TYPE_AVC1, "Advanced Video Coding extensions" },
281 { ISOM_BRAND_TYPE_BBXM, "Blinkbox Master File" },
282 { ISOM_BRAND_TYPE_CAQV, "Casio Digital Camera" },
283 { ISOM_BRAND_TYPE_CCFF, "Common container file format" },
284 { ISOM_BRAND_TYPE_DA0A, "DMB AF" },
285 { ISOM_BRAND_TYPE_DA0B, "DMB AF" },
286 { ISOM_BRAND_TYPE_DA1A, "DMB AF" },
287 { ISOM_BRAND_TYPE_DA1B, "DMB AF" },
288 { ISOM_BRAND_TYPE_DA2A, "DMB AF" },
289 { ISOM_BRAND_TYPE_DA2B, "DMB AF" },
290 { ISOM_BRAND_TYPE_DA3A, "DMB AF" },
291 { ISOM_BRAND_TYPE_DA3B, "DMB AF" },
292 { ISOM_BRAND_TYPE_DASH, "Indexed self-initializing Media Segment" },
293 { ISOM_BRAND_TYPE_DBY1, "MP4 files with Dolby content" },
294 { ISOM_BRAND_TYPE_DMB1, "DMB AF" },
295 { ISOM_BRAND_TYPE_DSMS, "Self-initializing Media Segment" },
296 { ISOM_BRAND_TYPE_DV1A, "DMB AF" },
297 { ISOM_BRAND_TYPE_DV1B, "DMB AF" },
298 { ISOM_BRAND_TYPE_DV2A, "DMB AF" },
299 { ISOM_BRAND_TYPE_DV2B, "DMB AF" },
300 { ISOM_BRAND_TYPE_DV3A, "DMB AF" },
301 { ISOM_BRAND_TYPE_DV3B, "DMB AF" },
302 { ISOM_BRAND_TYPE_DVR1, "DVB RTP" },
303 { ISOM_BRAND_TYPE_DVT1, "DVB Transport Stream" },
304 { ISOM_BRAND_TYPE_IFRM, "Apple iFrame" },
305 { ISOM_BRAND_TYPE_ISC2, "Files encrypted according to ISMACryp 2.0" },
306 { ISOM_BRAND_TYPE_ISO2, "ISO Base Media file format version 2" },
307 { ISOM_BRAND_TYPE_ISO3, "ISO Base Media file format version 3" },
308 { ISOM_BRAND_TYPE_ISO4, "ISO Base Media file format version 4" },
309 { ISOM_BRAND_TYPE_ISO5, "ISO Base Media file format version 5" },
310 { ISOM_BRAND_TYPE_ISO6, "ISO Base Media file format version 6" },
311 { ISOM_BRAND_TYPE_ISO7, "ISO Base Media file format version 7" },
312 { ISOM_BRAND_TYPE_ISOM, "ISO Base Media file format version 1" },
313 { ISOM_BRAND_TYPE_JPSI, "The JPSearch data interchange format" },
314 { ISOM_BRAND_TYPE_LMSG, "last Media Segment indicator" },
315 { ISOM_BRAND_TYPE_MJ2S, "Motion JPEG 2000 simple profile" },
316 { ISOM_BRAND_TYPE_MJP2, "Motion JPEG 2000, general profile" },
317 { ISOM_BRAND_TYPE_MP21, "MPEG-21" },
318 { ISOM_BRAND_TYPE_MP41, "MP4 version 1" },
319 { ISOM_BRAND_TYPE_MP42, "MP4 version 2" },
320 { ISOM_BRAND_TYPE_MP71, "MPEG-7 file-level metadata" },
321 { ISOM_BRAND_TYPE_MSDH, "Media Segment" },
322 { ISOM_BRAND_TYPE_MSIX, "Indexed Media Segment" },
323 { ISOM_BRAND_TYPE_NIKO, "Nikon Digital Camera" },
324 { ISOM_BRAND_TYPE_ODCF, "OMA DCF" },
325 { ISOM_BRAND_TYPE_OPF2, "OMA PDCF" },
326 { ISOM_BRAND_TYPE_OPX2, "OMA Adapted PDCF" },
327 { ISOM_BRAND_TYPE_PANA, "Panasonic Digital Camera" },
328 { ISOM_BRAND_TYPE_PIFF, "Protected Interoperable File Format" },
329 { ISOM_BRAND_TYPE_PNVI, "Panasonic Video Intercom" },
330 { ISOM_BRAND_TYPE_QT , "QuickTime file format" },
331 { ISOM_BRAND_TYPE_RISX, "Representation Index Segment" },
332 { ISOM_BRAND_TYPE_SDV , "SD Video" },
333 { ISOM_BRAND_TYPE_SIMS, "Sub-Indexed Media Segment" },
334 { ISOM_BRAND_TYPE_SISX, "Single Index Segment" },
335 { ISOM_BRAND_TYPE_SSSS, "Subsegment Index Segment" },
336 { 0, NULL }
338 for( int i = 0; brand_description_table[i].description; i++ )
339 if( brand == brand_description_table[i].brand )
341 fprintf( fp, " : %s\n", brand_description_table[i].description );
342 return;
344 fprintf( fp, "\n" );
347 static void isom_print_file_type
349 FILE *fp,
350 int indent,
351 uint32_t major_brand,
352 uint32_t minor_version,
353 uint32_t brand_count,
354 uint32_t *compatible_brands
357 lsmash_ifprintf( fp, indent, "major_brand = %s", isom_4cc2str( major_brand ) );
358 isom_print_brand_description( fp, major_brand );
359 lsmash_ifprintf( fp, indent, "minor_version = %"PRIu32"\n", minor_version );
360 lsmash_ifprintf( fp, indent++, "compatible_brands\n" );
361 for( uint32_t i = 0; i < brand_count; i++ )
363 if( compatible_brands[i] )
365 lsmash_ifprintf( fp, indent, "brand[%"PRIu32"] = %s", i, isom_4cc2str( compatible_brands[i] ) );
366 isom_print_brand_description( fp, compatible_brands[i] );
368 else
369 lsmash_ifprintf( fp, indent, "brand[%"PRIu32"] = (void)\n", i );
373 static int isom_print_ftyp( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
375 isom_ftyp_t *ftyp = (isom_ftyp_t *)box;
376 int indent = level;
377 isom_print_box_common( fp, indent++, box, "File Type Box" );
378 isom_print_file_type( fp, indent, ftyp->major_brand, ftyp->minor_version, ftyp->brand_count, ftyp->compatible_brands );
379 return 0;
382 static int isom_print_styp( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
384 /* Print 'valid' if this box is the first box in a file. */
385 int valid;
386 if( file->print
387 && file->print->head
388 && file->print->head->data )
389 valid = (box == ((isom_print_entry_t *)file->print->head->data)->box);
390 else
391 valid = 0;
392 char *name = valid ? "Segment Type Box (valid)" : "Segment Type Box";
393 isom_styp_t *styp = (isom_styp_t *)box;
394 int indent = level;
395 isom_print_box_common( fp, indent++, box, name );
396 isom_print_file_type( fp, indent, styp->major_brand, styp->minor_version, styp->brand_count, styp->compatible_brands );
397 return 0;
400 static int isom_print_sidx( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
402 if( !((isom_sidx_t *)box)->list )
403 return -1;
404 isom_sidx_t *sidx = (isom_sidx_t *)box;
405 int indent = level;
406 isom_print_box_common( fp, indent++, box, "Segment Index Box" );
407 lsmash_ifprintf( fp, indent, "reference_ID = %"PRIu32"\n", sidx->reference_ID );
408 lsmash_ifprintf( fp, indent, "timescale = %"PRIu32"\n", sidx->timescale );
409 lsmash_ifprintf( fp, indent, "earliest_presentation_time = %"PRIu64"\n", sidx->earliest_presentation_time );
410 lsmash_ifprintf( fp, indent, "first_offset = %"PRIu64"\n", sidx->first_offset );
411 lsmash_ifprintf( fp, indent, "reserved = %"PRIu16"\n", sidx->reserved );
412 lsmash_ifprintf( fp, indent, "reference_count = %"PRIu16"\n", sidx->reference_count );
413 uint32_t i = 0;
414 for( lsmash_entry_t *entry = sidx->list->head; entry; entry = entry->next )
416 isom_sidx_referenced_item_t *data = (isom_sidx_referenced_item_t *)entry->data;
417 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
418 lsmash_ifprintf( fp, indent, "reference_type = %"PRIu8" (%s)\n", data->reference_type, data->reference_type ? "index" : "media" );
419 lsmash_ifprintf( fp, indent, "reference_size = %"PRIu32"\n", data->reference_size );
420 lsmash_ifprintf( fp, indent, "subsegment_duration = %"PRIu32"\n", data->subsegment_duration );
421 lsmash_ifprintf( fp, indent, "starts_with_SAP = %"PRIu8"%s\n", data->starts_with_SAP, data->starts_with_SAP ? " (yes)" : "" );
422 lsmash_ifprintf( fp, indent, "SAP_type = %"PRIu8"%s\n", data->SAP_type, data->SAP_type == 0 ? " (unknown)" : "" );
423 lsmash_ifprintf( fp, indent--, "SAP_delta_time = %"PRIu32"\n", data->SAP_delta_time );
425 return 0;
428 static int isom_print_moov( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
430 return isom_print_simple( fp, box, level, "Movie Box" );
433 static int isom_print_mvhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
435 isom_mvhd_t *mvhd = (isom_mvhd_t *)box;
436 int indent = level;
437 isom_print_box_common( fp, indent++, box, "Movie Header Box" );
438 lsmash_ifprintf( fp, indent, "creation_time = %s", isom_mp4time2utc( mvhd->creation_time ) );
439 lsmash_ifprintf( fp, indent, "modification_time = %s", isom_mp4time2utc( mvhd->modification_time ) );
440 lsmash_ifprintf( fp, indent, "timescale = %"PRIu32"\n", mvhd->timescale );
441 isom_ifprintf_duration( fp, indent, "duration", mvhd->duration, mvhd->timescale );
442 lsmash_ifprintf( fp, indent, "rate = %f\n", lsmash_fixed2double( mvhd->rate, 16 ) );
443 lsmash_ifprintf( fp, indent, "volume = %f\n", lsmash_fixed2double( mvhd->volume, 8 ) );
444 lsmash_ifprintf( fp, indent, "reserved = 0x%04"PRIx16"\n", mvhd->reserved );
445 if( file->qt_compatible )
447 lsmash_ifprintf( fp, indent, "preferredLong1 = 0x%08"PRIx32"\n", mvhd->preferredLong[0] );
448 lsmash_ifprintf( fp, indent, "preferredLong2 = 0x%08"PRIx32"\n", mvhd->preferredLong[1] );
449 lsmash_ifprintf( fp, indent, "transformation matrix\n" );
450 isom_ifprintf_matrix( fp, indent + 1, mvhd->matrix );
451 lsmash_ifprintf( fp, indent, "previewTime = %"PRId32"\n", mvhd->previewTime );
452 lsmash_ifprintf( fp, indent, "previewDuration = %"PRId32"\n", mvhd->previewDuration );
453 lsmash_ifprintf( fp, indent, "posterTime = %"PRId32"\n", mvhd->posterTime );
454 lsmash_ifprintf( fp, indent, "selectionTime = %"PRId32"\n", mvhd->selectionTime );
455 lsmash_ifprintf( fp, indent, "selectionDuration = %"PRId32"\n", mvhd->selectionDuration );
456 lsmash_ifprintf( fp, indent, "currentTime = %"PRId32"\n", mvhd->currentTime );
458 else
460 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", mvhd->preferredLong[0] );
461 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", mvhd->preferredLong[1] );
462 lsmash_ifprintf( fp, indent, "transformation matrix\n" );
463 isom_ifprintf_matrix( fp, indent + 1, mvhd->matrix );
464 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", mvhd->previewTime );
465 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", mvhd->previewDuration );
466 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", mvhd->posterTime );
467 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", mvhd->selectionTime );
468 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", mvhd->selectionDuration );
469 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", mvhd->currentTime );
471 lsmash_ifprintf( fp, indent, "next_track_ID = %"PRIu32"\n", mvhd->next_track_ID );
472 return 0;
475 static void isom_pring_qt_color_table( FILE *fp, int indent, isom_qt_color_table_t *color_table )
477 isom_qt_color_array_t *array = color_table->array;
478 if( !array )
479 return;
480 lsmash_ifprintf( fp, indent, "ctSeed = %"PRIu32"\n", color_table->seed );
481 lsmash_ifprintf( fp, indent, "ctFlags = 0x%04"PRIx16"\n", color_table->flags );
482 lsmash_ifprintf( fp, indent, "ctSize = %"PRIu16"\n", color_table->size );
483 lsmash_ifprintf( fp, indent++, "ctTable\n" );
484 for( uint16_t i = 0; i <= color_table->size; i++ )
485 lsmash_ifprintf( fp, indent,
486 "color[%"PRIu16"] = { 0x%04"PRIx16", 0x%04"PRIx16", 0x%04"PRIx16", 0x%04"PRIx16" }\n",
487 i, array[i].value, array[i].r, array[i].g, array[i].b );
490 static int isom_print_ctab( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
492 isom_ctab_t *ctab = (isom_ctab_t *)box;
493 int indent = level;
494 isom_print_box_common( fp, indent, box, "Color Table Box" );
495 isom_pring_qt_color_table( fp, indent + 1, &ctab->color_table );
496 return 0;
499 static int isom_print_iods( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
501 extern void mp4sys_print_descriptor( FILE *, void *, int );
502 isom_iods_t *iods = (isom_iods_t *)box;
503 int indent = level;
504 isom_print_box_common( fp, indent, box, "Object Descriptor Box" );
505 mp4sys_print_descriptor( fp, iods->OD, indent + 1 );
506 return 0;
509 static int isom_print_trak( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
511 return isom_print_simple( fp, box, level, "Track Box" );
514 static int isom_print_tkhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
516 isom_tkhd_t *tkhd = (isom_tkhd_t *)box;
517 int indent = level;
518 isom_print_box_common( fp, indent++, box, "Track Header Box" );
519 ++indent;
520 if( tkhd->flags & ISOM_TRACK_ENABLED )
521 lsmash_ifprintf( fp, indent, "Track enabled\n" );
522 else
523 lsmash_ifprintf( fp, indent, "Track disabled\n" );
524 if( tkhd->flags & ISOM_TRACK_IN_MOVIE )
525 lsmash_ifprintf( fp, indent, "Track in movie\n" );
526 if( tkhd->flags & ISOM_TRACK_IN_PREVIEW )
527 lsmash_ifprintf( fp, indent, "Track in preview\n" );
528 if( file->qt_compatible && (tkhd->flags & QT_TRACK_IN_POSTER) )
529 lsmash_ifprintf( fp, indent, "Track in poster\n" );
530 lsmash_ifprintf( fp, --indent, "creation_time = %s", isom_mp4time2utc( tkhd->creation_time ) );
531 lsmash_ifprintf( fp, indent, "modification_time = %s", isom_mp4time2utc( tkhd->modification_time ) );
532 lsmash_ifprintf( fp, indent, "track_ID = %"PRIu32"\n", tkhd->track_ID );
533 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", tkhd->reserved1 );
534 if( file->moov && file->moov->mvhd )
535 isom_ifprintf_duration( fp, indent, "duration", tkhd->duration, file->moov->mvhd->timescale );
536 else
537 isom_ifprintf_duration( fp, indent, "duration", tkhd->duration, 0 );
538 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", tkhd->reserved2[0] );
539 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", tkhd->reserved2[1] );
540 lsmash_ifprintf( fp, indent, "layer = %"PRId16"\n", tkhd->layer );
541 lsmash_ifprintf( fp, indent, "alternate_group = %"PRId16"\n", tkhd->alternate_group );
542 lsmash_ifprintf( fp, indent, "volume = %f\n", lsmash_fixed2double( tkhd->volume, 8 ) );
543 lsmash_ifprintf( fp, indent, "reserved = 0x%04"PRIx16"\n", tkhd->reserved3 );
544 lsmash_ifprintf( fp, indent, "transformation matrix\n" );
545 isom_ifprintf_matrix( fp, indent + 1, tkhd->matrix );
546 lsmash_ifprintf( fp, indent, "width = %f\n", lsmash_fixed2double( tkhd->width, 16 ) );
547 lsmash_ifprintf( fp, indent, "height = %f\n", lsmash_fixed2double( tkhd->height, 16 ) );
548 return 0;
551 static int isom_print_tapt( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
553 return isom_print_simple( fp, box, level, "Track Aperture Mode Dimensions Box" );
556 static int isom_print_clef( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
558 isom_clef_t *clef = (isom_clef_t *)box;
559 int indent = level;
560 isom_print_box_common( fp, indent++, box, "Track Clean Aperture Dimensions Box" );
561 lsmash_ifprintf( fp, indent, "width = %f\n", lsmash_fixed2double( clef->width, 16 ) );
562 lsmash_ifprintf( fp, indent, "height = %f\n", lsmash_fixed2double( clef->height, 16 ) );
563 return 0;
566 static int isom_print_prof( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
568 isom_prof_t *prof = (isom_prof_t *)box;
569 int indent = level;
570 isom_print_box_common( fp, indent++, box, "Track Production Aperture Dimensions Box" );
571 lsmash_ifprintf( fp, indent, "width = %f\n", lsmash_fixed2double( prof->width, 16 ) );
572 lsmash_ifprintf( fp, indent, "height = %f\n", lsmash_fixed2double( prof->height, 16 ) );
573 return 0;
576 static int isom_print_enof( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
578 isom_enof_t *enof = (isom_enof_t *)box;
579 int indent = level;
580 isom_print_box_common( fp, indent++, box, "Track Encoded Pixels Dimensions Box" );
581 lsmash_ifprintf( fp, indent, "width = %f\n", lsmash_fixed2double( enof->width, 16 ) );
582 lsmash_ifprintf( fp, indent, "height = %f\n", lsmash_fixed2double( enof->height, 16 ) );
583 return 0;
586 static int isom_print_edts( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
588 return isom_print_simple( fp, box, level, "Edit Box" );
591 static int isom_print_elst( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
593 isom_elst_t *elst = (isom_elst_t *)box;
594 int indent = level;
595 uint32_t i = 0;
596 isom_print_box_common( fp, indent++, box, "Edit List Box" );
597 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", elst->list->entry_count );
598 for( lsmash_entry_t *entry = elst->list->head; entry; entry = entry->next )
600 isom_elst_entry_t *data = (isom_elst_entry_t *)entry->data;
601 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
602 lsmash_ifprintf( fp, indent, "segment_duration = %"PRIu64"\n", data->segment_duration );
603 lsmash_ifprintf( fp, indent, "media_time = %"PRId64"\n", data->media_time );
604 lsmash_ifprintf( fp, indent--, "media_rate = %f\n", lsmash_fixed2double( data->media_rate, 16 ) );
606 return 0;
609 static int isom_print_tref( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
611 return isom_print_simple( fp, box, level, "Track Reference Box" );
614 static int isom_print_track_reference_type( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
616 isom_tref_type_t *ref = (isom_tref_type_t *)box;
617 int indent = level;
618 isom_print_box_common( fp, indent++, box, "Track Reference Type Box" );
619 for( uint32_t i = 0; i < ref->ref_count; i++ )
620 lsmash_ifprintf( fp, indent, "track_ID[%"PRIu32"] = %"PRIu32"\n", i, ref->track_ID[i] );
621 return 0;
624 static int isom_print_mdia( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
626 return isom_print_simple( fp, box, level, "Media Box" );
629 static int isom_print_mdhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
631 isom_mdhd_t *mdhd = (isom_mdhd_t *)box;
632 int indent = level;
633 isom_print_box_common( fp, indent++, box, "Media Header Box" );
634 lsmash_ifprintf( fp, indent, "creation_time = %s", isom_mp4time2utc( mdhd->creation_time ) );
635 lsmash_ifprintf( fp, indent, "modification_time = %s", isom_mp4time2utc( mdhd->modification_time ) );
636 lsmash_ifprintf( fp, indent, "timescale = %"PRIu32"\n", mdhd->timescale );
637 isom_ifprintf_duration( fp, indent, "duration", mdhd->duration, mdhd->timescale );
638 if( mdhd->language >= 0x800 )
639 lsmash_ifprintf( fp, indent, "language = %s\n", isom_unpack_iso_language( mdhd->language ) );
640 else
641 lsmash_ifprintf( fp, indent, "language = %"PRIu16"\n", mdhd->language );
642 if( file->qt_compatible )
643 lsmash_ifprintf( fp, indent, "quality = %"PRId16"\n", mdhd->quality );
644 else
645 lsmash_ifprintf( fp, indent, "pre_defined = 0x%04"PRIx16"\n", mdhd->quality );
646 return 0;
649 static int isom_print_hdlr( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
651 isom_hdlr_t *hdlr = (isom_hdlr_t *)box;
652 int indent = level;
653 char *str = lsmash_malloc( hdlr->componentName_length + 1 );
654 if( !str )
655 return LSMASH_ERR_MEMORY_ALLOC;
656 memcpy( str, hdlr->componentName, hdlr->componentName_length );
657 str[hdlr->componentName_length] = 0;
658 isom_print_box_common( fp, indent++, box, "Handler Reference Box" );
659 if( file->qt_compatible )
661 lsmash_ifprintf( fp, indent, "componentType = %s\n", isom_4cc2str( hdlr->componentType ) );
662 lsmash_ifprintf( fp, indent, "componentSubtype = %s\n", isom_4cc2str( hdlr->componentSubtype ) );
663 lsmash_ifprintf( fp, indent, "componentManufacturer = %s\n", isom_4cc2str( hdlr->componentManufacturer ) );
664 lsmash_ifprintf( fp, indent, "componentFlags = 0x%08"PRIx32"\n", hdlr->componentFlags );
665 lsmash_ifprintf( fp, indent, "componentFlagsMask = 0x%08"PRIx32"\n", hdlr->componentFlagsMask );
666 if( hdlr->componentName_length )
667 lsmash_ifprintf( fp, indent, "componentName = %s\n", &str[1] );
668 else
669 lsmash_ifprintf( fp, indent, "componentName = \n" );
671 else
673 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", hdlr->componentType );
674 lsmash_ifprintf( fp, indent, "handler_type = %s\n", isom_4cc2str( hdlr->componentSubtype ) );
675 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", hdlr->componentManufacturer );
676 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", hdlr->componentFlags );
677 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", hdlr->componentFlagsMask );
678 lsmash_ifprintf( fp, indent, "name = %s\n", str );
680 lsmash_free( str );
681 return 0;
684 static int isom_print_minf( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
686 return isom_print_simple( fp, box, level, "Media Information Box" );
689 static int isom_print_vmhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
691 isom_vmhd_t *vmhd = (isom_vmhd_t *)box;
692 int indent = level;
693 isom_print_box_common( fp, indent++, box, "Video Media Header Box" );
694 lsmash_ifprintf( fp, indent, "graphicsmode = %"PRIu16"\n", vmhd->graphicsmode );
695 lsmash_ifprintf( fp, indent, "opcolor\n" );
696 isom_ifprintf_rgb_color( fp, indent + 1, vmhd->opcolor );
697 return 0;
700 static int isom_print_smhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
702 isom_smhd_t *smhd = (isom_smhd_t *)box;
703 int indent = level;
704 isom_print_box_common( fp, indent++, box, "Sound Media Header Box" );
705 lsmash_ifprintf( fp, indent, "balance = %f\n", lsmash_fixed2double( smhd->balance, 8 ) );
706 lsmash_ifprintf( fp, indent, "reserved = 0x%04"PRIx16"\n", smhd->reserved );
707 return 0;
710 static int isom_print_hmhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
712 isom_hmhd_t *hmhd = (isom_hmhd_t *)box;
713 int indent = level;
714 isom_print_box_common( fp, indent++, box, "Hint Media Header Box" );
715 lsmash_ifprintf( fp, indent, "maxPDUsize = %"PRIu16"\n", hmhd->maxPDUsize );
716 lsmash_ifprintf( fp, indent, "avgPDUsize = %"PRIu16"\n", hmhd->avgPDUsize );
717 lsmash_ifprintf( fp, indent, "maxbitrate = %"PRIu32"\n", hmhd->maxbitrate );
718 lsmash_ifprintf( fp, indent, "avgbitrate = %"PRIu32"\n", hmhd->avgbitrate );
719 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", hmhd->reserved );
720 return 0;
723 static int isom_print_nmhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
725 isom_print_box_common( fp, level, box, "Null Media Header Box" );
726 return 0;
729 static int isom_print_gmhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
731 return isom_print_simple( fp, box, level, "Generic Media Information Header Box" );
734 static int isom_print_gmin( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
736 isom_gmin_t *gmin = (isom_gmin_t *)box;
737 int indent = level;
738 isom_print_box_common( fp, indent++, box, "Generic Media Information Box" );
739 lsmash_ifprintf( fp, indent, "graphicsmode = %"PRIu16"\n", gmin->graphicsmode );
740 lsmash_ifprintf( fp, indent, "opcolor\n" );
741 isom_ifprintf_rgb_color( fp, indent + 1, gmin->opcolor );
742 lsmash_ifprintf( fp, indent, "balance = %f\n", lsmash_fixed2double( gmin->balance, 8 ) );
743 lsmash_ifprintf( fp, indent, "reserved = 0x%04"PRIx16"\n", gmin->reserved );
744 return 0;
747 static int isom_print_text( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
749 isom_text_t *text = (isom_text_t *)box;
750 int indent = level;
751 isom_print_box_common( fp, indent++, box, "Text Media Information Box" );
752 lsmash_ifprintf( fp, indent, "Unknown matrix\n" );
753 isom_ifprintf_matrix( fp, indent + 1, text->matrix );
754 return 0;
757 static int isom_print_dinf( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
759 return isom_print_simple( fp, box, level, "Data Information Box" );
762 static int isom_print_dref( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
764 isom_dref_t *dref = (isom_dref_t *)box;
765 int indent = level;
766 isom_print_box_common( fp, indent++, box, "Data Reference Box" );
767 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu16"\n", dref->list.entry_count );
768 return 0;
771 static int isom_print_url( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
773 isom_dref_entry_t *url = (isom_dref_entry_t *)box;
774 int indent = level;
775 isom_print_box_common( fp, indent++, box, "Data Entry Url Box" );
776 if( url->flags & 0x000001 )
777 lsmash_ifprintf( fp, indent, "location = in the same file\n" );
778 else
779 lsmash_ifprintf( fp, indent, "location = %s\n", url->location );
780 return 0;
783 static int isom_print_stbl( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
785 return isom_print_simple( fp, box, level, "Sample Table Box" );
788 static int isom_print_stsd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
790 isom_stsd_t *stsd = (isom_stsd_t *)box;
791 int indent = level;
792 isom_print_box_common( fp, indent++, box, "Sample Description Box" );
793 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", stsd->entry_count );
794 return 0;
797 static int isom_print_visual_description( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
799 isom_visual_entry_t *visual = (isom_visual_entry_t *)box;
800 int indent = level;
801 lsmash_ifprintf( fp, indent++, "[%s: Visual Description]\n", isom_4cc2str( visual->type.fourcc ) );
802 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", visual->pos );
803 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", visual->size );
804 isom_ifprintf_sample_description_common_reserved( fp, indent, visual->reserved );
805 lsmash_ifprintf( fp, indent, "data_reference_index = %"PRIu16"\n", visual->data_reference_index );
806 if( file->qt_compatible )
808 lsmash_ifprintf( fp, indent, "version = %"PRId16"\n", visual->version );
809 lsmash_ifprintf( fp, indent, "revision_level = %"PRId16"\n", visual->revision_level );
810 lsmash_ifprintf( fp, indent, "vendor = %s\n", isom_4cc2str( visual->vendor ) );
811 lsmash_ifprintf( fp, indent, "temporalQuality = %"PRIu32"\n", visual->temporalQuality );
812 lsmash_ifprintf( fp, indent, "spatialQuality = %"PRIu32"\n", visual->spatialQuality );
813 lsmash_ifprintf( fp, indent, "width = %"PRIu16"\n", visual->width );
814 lsmash_ifprintf( fp, indent, "height = %"PRIu16"\n", visual->height );
815 lsmash_ifprintf( fp, indent, "horizresolution = %f\n", lsmash_fixed2double( visual->horizresolution, 16 ) );
816 lsmash_ifprintf( fp, indent, "vertresolution = %f\n", lsmash_fixed2double( visual->vertresolution, 16 ) );
817 lsmash_ifprintf( fp, indent, "dataSize = %"PRIu32"\n", visual->dataSize );
818 lsmash_ifprintf( fp, indent, "frame_count = %"PRIu16"\n", visual->frame_count );
819 lsmash_ifprintf( fp, indent, "compressorname_length = %"PRIu8"\n", visual->compressorname[0] );
820 lsmash_ifprintf( fp, indent, "compressorname = %s\n", visual->compressorname + 1 );
821 lsmash_ifprintf( fp, indent, "depth = 0x%04"PRIx16, visual->depth );
822 if( visual->depth == 32 )
823 fprintf( fp, " (colour with alpha)\n" );
824 else if( visual->depth >= 33 && visual->depth <= 40 )
825 fprintf( fp, " (grayscale with no alpha)\n" );
826 else
827 fprintf( fp, "\n" );
828 lsmash_ifprintf( fp, indent, "color_table_ID = %"PRId16"\n", visual->color_table_ID );
829 if( visual->color_table_ID == 0 )
830 isom_pring_qt_color_table( fp, indent, &visual->color_table );
832 else
834 lsmash_ifprintf( fp, indent, "pre_defined = 0x%04"PRIx16"\n", visual->version );
835 lsmash_ifprintf( fp, indent, "reserved = 0x%04"PRIx16"\n", visual->revision_level );
836 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", visual->vendor );
837 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", visual->temporalQuality );
838 lsmash_ifprintf( fp, indent, "pre_defined = 0x%08"PRIx32"\n", visual->spatialQuality );
839 lsmash_ifprintf( fp, indent, "width = %"PRIu16"\n", visual->width );
840 lsmash_ifprintf( fp, indent, "height = %"PRIu16"\n", visual->height );
841 lsmash_ifprintf( fp, indent, "horizresolution = %f\n", lsmash_fixed2double( visual->horizresolution, 16 ) );
842 lsmash_ifprintf( fp, indent, "vertresolution = %f\n", lsmash_fixed2double( visual->vertresolution, 16 ) );
843 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", visual->dataSize );
844 lsmash_ifprintf( fp, indent, "frame_count = %"PRIu16"\n", visual->frame_count );
845 lsmash_ifprintf( fp, indent, "compressorname_length = %"PRIu8"\n", visual->compressorname[0] );
846 lsmash_ifprintf( fp, indent, "compressorname = %s\n", visual->compressorname + 1 );
847 lsmash_ifprintf( fp, indent, "depth = 0x%04"PRIx16, visual->depth );
848 if( visual->depth == 0x0018 )
849 fprintf( fp, " (colour with no alpha)\n" );
850 else if( visual->depth == 0x0028 )
851 fprintf( fp, " (grayscale with no alpha)\n" );
852 else if( visual->depth == 0x0020 )
853 fprintf( fp, " (gray or colour with alpha)\n" );
854 else
855 fprintf( fp, "\n" );
856 lsmash_ifprintf( fp, indent, "pre_defined = 0x%04"PRIx16"\n", visual->color_table_ID );
858 return 0;
861 static int isom_print_glbl( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
863 isom_glbl_t *glbl = (isom_glbl_t *)box;
864 int indent = level;
865 isom_print_box_common( fp, indent++, box, "Global Header Box" );
866 if( glbl->header_data )
868 lsmash_ifprintf( fp, indent, "global_header[]\n" );
869 for( uint32_t i = 0; i < glbl->header_size; i += 8 )
871 lsmash_ifprintf( fp, indent + 1, "" );
872 for( uint32_t j = 0; ; j++ )
873 if( j == 7 || (i + j == glbl->header_size - 1) )
875 fprintf( fp, "0x%02"PRIx8"\n", glbl->header_data[i + j] );
876 break;
878 else
879 fprintf( fp, "0x%02"PRIx8" ", glbl->header_data[i + j] );
882 return 0;
885 static int isom_print_clap( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
887 isom_clap_t *clap = (isom_clap_t *)box;
888 int indent = level;
889 isom_print_box_common( fp, indent++, box, "Clean Aperture Box" );
890 lsmash_ifprintf( fp, indent, "cleanApertureWidthN = %"PRIu32"\n", clap->cleanApertureWidthN );
891 lsmash_ifprintf( fp, indent, "cleanApertureWidthD = %"PRIu32"\n", clap->cleanApertureWidthD );
892 lsmash_ifprintf( fp, indent, "cleanApertureHeightN = %"PRIu32"\n", clap->cleanApertureHeightN );
893 lsmash_ifprintf( fp, indent, "cleanApertureHeightD = %"PRIu32"\n", clap->cleanApertureHeightD );
894 lsmash_ifprintf( fp, indent, "horizOffN = %"PRId32"\n", clap->horizOffN );
895 lsmash_ifprintf( fp, indent, "horizOffD = %"PRIu32"\n", clap->horizOffD );
896 lsmash_ifprintf( fp, indent, "vertOffN = %"PRId32"\n", clap->vertOffN );
897 lsmash_ifprintf( fp, indent, "vertOffD = %"PRIu32"\n", clap->vertOffD );
898 return 0;
901 static int isom_print_pasp( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
903 isom_pasp_t *pasp = (isom_pasp_t *)box;
904 int indent = level;
905 isom_print_box_common( fp, indent++, box, "Pixel Aspect Ratio Box" );
906 lsmash_ifprintf( fp, indent, "hSpacing = %"PRIu32"\n", pasp->hSpacing );
907 lsmash_ifprintf( fp, indent, "vSpacing = %"PRIu32"\n", pasp->vSpacing );
908 return 0;
911 static int isom_print_colr( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
913 isom_colr_t *colr = (isom_colr_t *)box;
914 int indent = level;
915 isom_print_box_common( fp, indent++, box, colr->manager & LSMASH_QTFF_BASE ? "Color Parameter Box" : "Colour Information Box" );
916 lsmash_ifprintf( fp, indent, "color_parameter_type = %s\n", isom_4cc2str( colr->color_parameter_type ) );
917 if( colr->color_parameter_type == QT_COLOR_PARAMETER_TYPE_NCLC
918 || colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
920 lsmash_ifprintf( fp, indent, "primaries_index = %"PRIu16"\n", colr->primaries_index );
921 lsmash_ifprintf( fp, indent, "transfer_function_index = %"PRIu16"\n", colr->transfer_function_index );
922 lsmash_ifprintf( fp, indent, "matrix_index = %"PRIu16"\n", colr->matrix_index );
923 if( colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
925 if( colr->manager & LSMASH_INCOMPLETE_BOX )
927 lsmash_ifprintf( fp, indent, "full_range_flag = N/A\n" );
928 lsmash_ifprintf( fp, indent, "reserved = N/A\n" );
930 else
932 lsmash_ifprintf( fp, indent, "full_range_flag = %"PRIu8"\n", colr->full_range_flag );
933 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx8"\n", colr->reserved );
937 return 0;
940 static int isom_print_gama( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
942 isom_gama_t *gama = (isom_gama_t *)box;
943 int indent = level;
944 isom_print_box_common( fp, indent++, box, "Gamma Level Box" );
945 if( gama->level == 0x00023333 )
946 lsmash_ifprintf( fp, indent, "level = 2.2 (standard television video gamma)\n" );
947 else
949 lsmash_ifprintf( fp, indent, "level = %f", lsmash_fixed2double( gama->level, 16 ) );
950 if( gama->level == 0 )
951 fprintf( fp, " (platform's standard gamma)" );
952 else if( gama->level == 0xffffffff )
953 fprintf( fp, " (no gamma-correction)" );
954 fprintf( fp, "\n" );
956 return 0;
959 static int isom_print_fiel( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
961 isom_fiel_t *fiel = (isom_fiel_t *)box;
962 int indent = level;
963 isom_print_box_common( fp, indent++, box, "Field/Frame Information Box" );
964 lsmash_ifprintf( fp, indent, "fields = %"PRIu8" (%s)\n", fiel->fields, fiel->fields > 1 ? "interlaced" : "progressive scan" );
965 lsmash_ifprintf( fp, indent, "detail = %"PRIu8, fiel->detail );
966 if( fiel->fields > 1 )
968 static const char *field_orderings[5] =
969 { "unknown", "temporal top first", "temporal bottom first", "spatial first line early", "spatial first line late" };
970 int ordering = 0;
971 if( fiel->fields == 2 )
973 if( fiel->detail == QT_FIELD_ORDERINGS_TEMPORAL_TOP_FIRST )
974 ordering = 1;
975 else if( fiel->detail == QT_FIELD_ORDERINGS_TEMPORAL_BOTTOM_FIRST )
976 ordering = 2;
977 else if( fiel->detail == QT_FIELD_ORDERINGS_SPATIAL_FIRST_LINE_EARLY )
978 ordering = 3;
979 else if( fiel->detail == QT_FIELD_ORDERINGS_SPATIAL_FIRST_LINE_LATE )
980 ordering = 4;
982 fprintf( fp, " (%s)\n", field_orderings[ordering] );
984 else
985 fprintf( fp, "\n" );
986 return 0;
989 static int isom_print_cspc( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
991 isom_cspc_t *cspc = (isom_cspc_t *)box;
992 int indent = level;
993 isom_print_box_common( fp, indent++, box, "Colorspace Box" );
994 static const struct
996 lsmash_qt_pixel_format pixel_format;
997 char *description;
998 } unprintable_pixel_format_table[] =
1000 { QT_PIXEL_FORMAT_TYPE_1_MONOCHROME, "1 bit indexed" },
1001 { QT_PIXEL_FORMAT_TYPE_2_INDEXED, "2 bit indexed" },
1002 { QT_PIXEL_FORMAT_TYPE_4_INDEXED, "4 bit indexed" },
1003 { QT_PIXEL_FORMAT_TYPE_8_INDEXED, "8 bit indexed" },
1004 { QT_PIXEL_FORMAT_TYPE_1_INDEXED_GRAY_WHITE_IS_ZERO, "1 bit indexed gray, white is zero" },
1005 { QT_PIXEL_FORMAT_TYPE_2_INDEXED_GRAY_WHITE_IS_ZERO, "2 bit indexed gray, white is zero" },
1006 { QT_PIXEL_FORMAT_TYPE_4_INDEXED_GRAY_WHITE_IS_ZERO, "4 bit indexed gray, white is zero" },
1007 { QT_PIXEL_FORMAT_TYPE_8_INDEXED_GRAY_WHITE_IS_ZERO, "8 bit indexed gray, white is zero" },
1008 { QT_PIXEL_FORMAT_TYPE_16BE555, "16 bit BE RGB 555" },
1009 { QT_PIXEL_FORMAT_TYPE_24RGB, "24 bit RGB" },
1010 { QT_PIXEL_FORMAT_TYPE_32ARGB, "32 bit ARGB" },
1011 { 0, NULL }
1013 for( int i = 0; unprintable_pixel_format_table[i].pixel_format; i++ )
1014 if( cspc->pixel_format == unprintable_pixel_format_table[i].pixel_format )
1016 lsmash_ifprintf( fp, indent, "pixel_format = 0x%08"PRIx32" (%s)\n", cspc->pixel_format, unprintable_pixel_format_table[i].description );
1017 return 0;
1019 lsmash_ifprintf( fp, indent, "pixel_format = %s\n", isom_4cc2str( cspc->pixel_format ) );
1020 return 0;
1023 static int isom_print_sgbt( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1025 isom_sgbt_t *sgbt = (isom_sgbt_t *)box;
1026 int indent = level;
1027 isom_print_box_common( fp, indent++, box, "Significant Bits Box" );
1028 lsmash_ifprintf( fp, indent, "significantBits = %"PRIu8"\n", sgbt->significantBits );
1029 return 0;
1032 static int isom_print_stsl( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1034 isom_stsl_t *stsl = (isom_stsl_t *)box;
1035 int indent = level;
1036 isom_print_box_common( fp, indent++, box, "Sample Scale Box" );
1037 lsmash_ifprintf( fp, indent, "constraint_flag = %s\n", (stsl->constraint_flag & 0x01) ? "on" : "off" );
1038 lsmash_ifprintf( fp, indent, "scale_method = " );
1039 if( stsl->scale_method == ISOM_SCALE_METHOD_FILL )
1040 fprintf( fp, "'fill'\n" );
1041 else if( stsl->scale_method == ISOM_SCALE_METHOD_HIDDEN )
1042 fprintf( fp, "'hidden'\n" );
1043 else if( stsl->scale_method == ISOM_SCALE_METHOD_MEET )
1044 fprintf( fp, "'meet'\n" );
1045 else if( stsl->scale_method == ISOM_SCALE_METHOD_SLICE_X )
1046 fprintf( fp, "'slice' in the x-coodinate\n" );
1047 else if( stsl->scale_method == ISOM_SCALE_METHOD_SLICE_Y )
1048 fprintf( fp, "'slice' in the y-coodinate\n" );
1049 lsmash_ifprintf( fp, indent, "display_center_x = %"PRIu16"\n", stsl->display_center_x );
1050 lsmash_ifprintf( fp, indent, "display_center_y = %"PRIu16"\n", stsl->display_center_y );
1051 return 0;
1054 static int isom_print_audio_description( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1056 isom_audio_entry_t *audio = (isom_audio_entry_t *)box;
1057 int indent = level;
1058 lsmash_ifprintf( fp, indent++, "[%s: Audio Description]\n", isom_4cc2str( audio->type.fourcc ) );
1059 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", audio->pos );
1060 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", audio->size );
1061 isom_ifprintf_sample_description_common_reserved( fp, indent, audio->reserved );
1062 lsmash_ifprintf( fp, indent, "data_reference_index = %"PRIu16"\n", audio->data_reference_index );
1063 if( file->qt_compatible )
1065 lsmash_ifprintf( fp, indent, "version = %"PRId16"\n", audio->version );
1066 lsmash_ifprintf( fp, indent, "revision_level = %"PRId16"\n", audio->revision_level );
1067 lsmash_ifprintf( fp, indent, "vendor = %s\n", isom_4cc2str( audio->vendor ) );
1068 lsmash_ifprintf( fp, indent, "channelcount = %"PRIu16"\n", audio->channelcount );
1069 lsmash_ifprintf( fp, indent, "samplesize = %"PRIu16"\n", audio->samplesize );
1070 lsmash_ifprintf( fp, indent, "compression_ID = %"PRId16"\n", audio->compression_ID );
1071 lsmash_ifprintf( fp, indent, "packet_size = %"PRIu16"\n", audio->packet_size );
1073 else
1075 lsmash_ifprintf( fp, indent, "reserved = 0x%04"PRIx16"\n", audio->version );
1076 lsmash_ifprintf( fp, indent, "reserved = 0x%04"PRIx16"\n", audio->revision_level );
1077 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", audio->vendor );
1078 lsmash_ifprintf( fp, indent, "channelcount = %"PRIu16"\n", audio->channelcount );
1079 lsmash_ifprintf( fp, indent, "samplesize = %"PRIu16"\n", audio->samplesize );
1080 lsmash_ifprintf( fp, indent, "pre_defined = %"PRId16"\n", audio->compression_ID );
1081 lsmash_ifprintf( fp, indent, "reserved = %"PRIu16"\n", audio->packet_size );
1083 lsmash_ifprintf( fp, indent, "samplerate = %f\n", lsmash_fixed2double( audio->samplerate, 16 ) );
1084 if( audio->version == 1 && (audio->manager & LSMASH_QTFF_BASE) )
1086 lsmash_ifprintf( fp, indent, "samplesPerPacket = %"PRIu32"\n", audio->samplesPerPacket );
1087 lsmash_ifprintf( fp, indent, "bytesPerPacket = %"PRIu32"\n", audio->bytesPerPacket );
1088 lsmash_ifprintf( fp, indent, "bytesPerFrame = %"PRIu32"\n", audio->bytesPerFrame );
1089 lsmash_ifprintf( fp, indent, "bytesPerSample = %"PRIu32"\n", audio->bytesPerSample );
1091 else if( audio->version == 2 )
1093 lsmash_ifprintf( fp, indent, "sizeOfStructOnly = %"PRIu32"\n", audio->sizeOfStructOnly );
1094 lsmash_ifprintf( fp, indent, "audioSampleRate = %lf\n", lsmash_int2float64( audio->audioSampleRate ) );
1095 lsmash_ifprintf( fp, indent, "numAudioChannels = %"PRIu32"\n", audio->numAudioChannels );
1096 lsmash_ifprintf( fp, indent, "always7F000000 = 0x%08"PRIx32"\n", audio->always7F000000 );
1097 lsmash_ifprintf( fp, indent, "constBitsPerChannel = %"PRIu32"\n", audio->constBitsPerChannel );
1098 lsmash_ifprintf( fp, indent++, "formatSpecificFlags = 0x%08"PRIx32"\n", audio->formatSpecificFlags );
1099 if( isom_is_lpcm_audio( audio ) )
1101 lsmash_ifprintf( fp, indent, "sample format: " );
1102 if( audio->formatSpecificFlags & QT_LPCM_FORMAT_FLAG_FLOAT )
1103 fprintf( fp, "floating point\n" );
1104 else
1106 fprintf( fp, "integer\n" );
1107 lsmash_ifprintf( fp, indent, "signedness: " );
1108 fprintf( fp, audio->formatSpecificFlags & QT_LPCM_FORMAT_FLAG_SIGNED_INTEGER ? "signed\n" : "unsigned\n" );
1110 if( audio->constBytesPerAudioPacket != 1 )
1112 lsmash_ifprintf( fp, indent, "endianness: " );
1113 fprintf( fp, audio->formatSpecificFlags & QT_LPCM_FORMAT_FLAG_BIG_ENDIAN ? "big\n" : "little\n" );
1115 lsmash_ifprintf( fp, indent, "packed: " );
1116 if( audio->formatSpecificFlags & QT_LPCM_FORMAT_FLAG_PACKED )
1117 fprintf( fp, "yes\n" );
1118 else
1120 fprintf( fp, "no\n" );
1121 lsmash_ifprintf( fp, indent, "alignment: " );
1122 fprintf( fp, audio->formatSpecificFlags & QT_LPCM_FORMAT_FLAG_ALIGNED_HIGH ? "high\n" : "low\n" );
1124 if( audio->numAudioChannels > 1 )
1126 lsmash_ifprintf( fp, indent, "interleved: " );
1127 fprintf( fp, audio->formatSpecificFlags & QT_LPCM_FORMAT_FLAG_NON_INTERLEAVED ? "no\n" : "yes\n" );
1130 lsmash_ifprintf( fp, --indent, "constBytesPerAudioPacket = %"PRIu32"\n", audio->constBytesPerAudioPacket );
1131 lsmash_ifprintf( fp, indent, "constLPCMFramesPerAudioPacket = %"PRIu32"\n", audio->constLPCMFramesPerAudioPacket );
1133 return 0;
1136 static int isom_print_wave( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1138 return isom_print_simple( fp, box, level, "Sound Information Decompression Parameters Box" );
1141 static int isom_print_frma( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1143 isom_frma_t *frma = (isom_frma_t *)box;
1144 int indent = level;
1145 isom_print_box_common( fp, indent++, box, "Format Box" );
1146 lsmash_ifprintf( fp, indent, "data_format = %s\n", isom_4cc2str( frma->data_format ) );
1147 return 0;
1150 static int isom_print_enda( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1152 isom_enda_t *enda = (isom_enda_t *)box;
1153 int indent = level;
1154 isom_print_box_common( fp, indent++, box, "Audio Endian Box" );
1155 lsmash_ifprintf( fp, indent, "littleEndian = %s\n", enda->littleEndian ? "yes" : "no" );
1156 return 0;
1159 static int isom_print_terminator( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1161 isom_terminator_t *terminator = (isom_terminator_t *)box;
1162 int indent = level;
1163 lsmash_ifprintf( fp, indent++, "[0x00000000: Terminator Box]\n" );
1164 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", terminator->pos );
1165 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", terminator->size );
1166 return 0;
1169 static int isom_print_chan( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1171 isom_chan_t *chan = (isom_chan_t *)box;
1172 int indent = level;
1173 isom_print_box_common( fp, indent++, box, "Audio Channel Layout Box" );
1174 lsmash_ifprintf( fp, indent, "channelLayoutTag = 0x%08"PRIx32"\n", chan->channelLayoutTag );
1175 lsmash_ifprintf( fp, indent, "channelBitmap = 0x%08"PRIx32"\n", chan->channelBitmap );
1176 lsmash_ifprintf( fp, indent, "numberChannelDescriptions = %"PRIu32"\n", chan->numberChannelDescriptions );
1177 if( chan->numberChannelDescriptions )
1179 isom_channel_description_t *desc = chan->channelDescriptions;
1180 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
1182 lsmash_ifprintf( fp, indent++, "ChannelDescriptions[%"PRIu32"]\n", i );
1183 lsmash_ifprintf( fp, indent, "channelLabel = 0x%08"PRIx32"\n", desc->channelLabel );
1184 lsmash_ifprintf( fp, indent, "channelFlags = 0x%08"PRIx32"\n", desc->channelFlags );
1185 for( int j = 0; j < 3; j++ )
1186 lsmash_ifprintf( fp, indent, "coordinates[%d] = %f\n", j, lsmash_int2float32( desc->coordinates[j] ) );
1187 --indent;
1190 return 0;
1193 static int isom_print_srat( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1195 isom_srat_t *srat = (isom_srat_t *)box;
1196 int indent = level;
1197 isom_print_box_common( fp, indent++, box, "Sampling Rate Box" );
1198 lsmash_ifprintf( fp, indent, "sampling_rate = %"PRIu32"\n", srat->sampling_rate );
1199 return 0;
1202 static int isom_print_text_description( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1204 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)box;
1205 int indent = level;
1206 lsmash_ifprintf( fp, indent++, "[text: QuickTime Text Description]\n" );
1207 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", text->pos );
1208 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", text->size );
1209 isom_ifprintf_sample_description_common_reserved( fp, indent, text->reserved );
1210 lsmash_ifprintf( fp, indent, "data_reference_index = %"PRIu16"\n", text->data_reference_index );
1211 lsmash_ifprintf( fp, indent, "displayFlags = 0x%08"PRId32"\n", text->displayFlags );
1212 lsmash_ifprintf( fp, indent, "textJustification = %"PRId32"\n", text->textJustification );
1213 lsmash_ifprintf( fp, indent, "bgColor\n" );
1214 isom_ifprintf_rgb_color( fp, indent + 1, text->bgColor );
1215 lsmash_ifprintf( fp, indent, "top = %"PRId16"\n", text->top );
1216 lsmash_ifprintf( fp, indent, "left = %"PRId16"\n", text->left );
1217 lsmash_ifprintf( fp, indent, "bottom = %"PRId16"\n", text->bottom );
1218 lsmash_ifprintf( fp, indent, "right = %"PRId16"\n", text->right );
1219 lsmash_ifprintf( fp, indent, "scrpStartChar = %"PRId32"\n", text->scrpStartChar );
1220 lsmash_ifprintf( fp, indent, "scrpHeight = %"PRId16"\n", text->scrpHeight );
1221 lsmash_ifprintf( fp, indent, "scrpAscent = %"PRId16"\n", text->scrpAscent );
1222 lsmash_ifprintf( fp, indent, "scrpFont = %"PRId16"\n", text->scrpFont );
1223 lsmash_ifprintf( fp, indent, "scrpFace = %"PRIu16"\n", text->scrpFace );
1224 lsmash_ifprintf( fp, indent, "scrpSize = %"PRId16"\n", text->scrpSize );
1225 lsmash_ifprintf( fp, indent, "scrpColor\n" );
1226 isom_ifprintf_rgb_color( fp, indent + 1, text->scrpColor );
1227 if( text->font_name_length )
1228 lsmash_ifprintf( fp, indent, "font_name = %s\n", text->font_name );
1229 return 0;
1232 static int isom_print_tx3g_description( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1234 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)box;
1235 int indent = level;
1236 lsmash_ifprintf( fp, indent++, "[tx3g: Timed Text Description]\n" );
1237 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", tx3g->pos );
1238 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", tx3g->size );
1239 isom_ifprintf_sample_description_common_reserved( fp, indent, tx3g->reserved );
1240 lsmash_ifprintf( fp, indent, "data_reference_index = %"PRIu16"\n", tx3g->data_reference_index );
1241 lsmash_ifprintf( fp, indent, "displayFlags = 0x%08"PRId32"\n", tx3g->displayFlags );
1242 lsmash_ifprintf( fp, indent, "horizontal_justification = %"PRId8"\n", tx3g->horizontal_justification );
1243 lsmash_ifprintf( fp, indent, "vertical_justification = %"PRId8"\n", tx3g->vertical_justification );
1244 lsmash_ifprintf( fp, indent, "background_color_rgba\n" );
1245 isom_ifprintf_rgba_color( fp, indent + 1, tx3g->background_color_rgba );
1246 lsmash_ifprintf( fp, indent, "top = %"PRId16"\n", tx3g->top );
1247 lsmash_ifprintf( fp, indent, "left = %"PRId16"\n", tx3g->left );
1248 lsmash_ifprintf( fp, indent, "bottom = %"PRId16"\n", tx3g->bottom );
1249 lsmash_ifprintf( fp, indent, "right = %"PRId16"\n", tx3g->right );
1250 lsmash_ifprintf( fp, indent, "startChar = %"PRIu16"\n", tx3g->startChar );
1251 lsmash_ifprintf( fp, indent, "endChar = %"PRIu16"\n", tx3g->endChar );
1252 lsmash_ifprintf( fp, indent, "font_ID = %"PRIu16"\n", tx3g->font_ID );
1253 lsmash_ifprintf( fp, indent, "face_style_flags = %"PRIu8"\n", tx3g->face_style_flags );
1254 lsmash_ifprintf( fp, indent, "font_size = %"PRIu8"\n", tx3g->font_size );
1255 lsmash_ifprintf( fp, indent, "text_color_rgba\n" );
1256 isom_ifprintf_rgba_color( fp, indent + 1, tx3g->text_color_rgba );
1257 return 0;
1260 static int isom_print_ftab( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1262 if( !((isom_ftab_t *)box)->list )
1263 return LSMASH_ERR_INVALID_DATA;
1264 isom_ftab_t *ftab = (isom_ftab_t *)box;
1265 int indent = level;
1266 uint16_t i = 0;
1267 isom_print_box_common( fp, indent++, box, "Font Table Box" );
1268 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu16"\n", ftab->list->entry_count );
1269 for( lsmash_entry_t *entry = ftab->list->head; entry; entry = entry->next )
1271 isom_font_record_t *data = (isom_font_record_t *)entry->data;
1272 lsmash_ifprintf( fp, indent++, "entry[%"PRIu16"]\n", i++ );
1273 lsmash_ifprintf( fp, indent, "font_ID = %"PRIu16"\n", data->font_ID );
1274 if( data->font_name_length )
1275 lsmash_ifprintf( fp, indent, "font_name = %s\n", data->font_name );
1276 --indent;
1278 return 0;
1281 static int isom_print_mp4s_description( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1283 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)box;
1284 int indent = level;
1285 lsmash_ifprintf( fp, indent++, "[%s: MPEG-4 Systems Description]\n", isom_4cc2str( mp4s->type.fourcc ) );
1286 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", mp4s->pos );
1287 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", mp4s->size );
1288 isom_ifprintf_sample_description_common_reserved( fp, indent, mp4s->reserved );
1289 lsmash_ifprintf( fp, indent, "data_reference_index = %"PRIu16"\n", mp4s->data_reference_index );
1290 return 0;
1293 static int isom_print_sample_description_extesion( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1295 extern int mp4sys_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1296 extern int h264_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1297 extern int hevc_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1298 extern int h264_print_bitrate( FILE *, lsmash_file_t *, isom_box_t *, int );
1299 extern int vc1_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1300 extern int ac3_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1301 extern int eac3_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1302 extern int dts_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1303 extern int alac_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1304 extern int wma_print_codec_specific( FILE *, lsmash_file_t *, isom_box_t *, int );
1305 static struct print_description_extension_table_tag
1307 lsmash_box_type_t type;
1308 int (*print_func)( FILE *, lsmash_file_t *, isom_box_t *, int );
1309 } print_description_extension_table[32] = { { LSMASH_BOX_TYPE_INITIALIZER, NULL } };
1310 if( !print_description_extension_table[0].print_func )
1312 /* Initialize the table. */
1313 int i = 0;
1314 #define ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( type, func ) \
1315 print_description_extension_table[i++] = (struct print_description_extension_table_tag){ type, func }
1316 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, isom_print_clap );
1317 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, isom_print_pasp );
1318 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, isom_print_stsl );
1319 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, isom_print_colr );
1320 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_COLR, isom_print_colr );
1321 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, isom_print_gama );
1322 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, isom_print_fiel );
1323 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, isom_print_cspc );
1324 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, isom_print_sgbt );
1325 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, isom_print_ctab );
1326 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, isom_print_glbl );
1327 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, isom_print_wave );
1328 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, isom_print_chan );
1329 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, mp4sys_print_codec_specific );
1330 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, h264_print_codec_specific );
1331 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, h264_print_bitrate );
1332 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, hevc_print_codec_specific );
1333 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, vc1_print_codec_specific );
1334 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, ac3_print_codec_specific );
1335 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, eac3_print_codec_specific );
1336 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, dts_print_codec_specific );
1337 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, alac_print_codec_specific );
1338 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX, wma_print_codec_specific );
1339 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, isom_print_ftab );
1340 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_ESDS, mp4sys_print_codec_specific );
1341 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( QT_BOX_TYPE_ALAC, alac_print_codec_specific );
1342 ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
1343 #undef ADD_PRINT_DESCRIPTION_EXTENSION_TABLE_ELEMENT
1345 for( int i = 0; print_description_extension_table[i].print_func; i++ )
1346 if( lsmash_check_box_type_identical( box->type, print_description_extension_table[i].type ) )
1347 return print_description_extension_table[i].print_func( fp, file, box, level );
1348 return isom_print_unknown( fp, file, box, level );
1351 static int isom_print_stts( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1353 if( !((isom_stts_t *)box)->list )
1354 return LSMASH_ERR_INVALID_DATA;
1355 isom_stts_t *stts = (isom_stts_t *)box;
1356 int indent = level;
1357 uint32_t i = 0;
1358 isom_print_box_common( fp, indent++, box, "Decoding Time to Sample Box" );
1359 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", stts->list->entry_count );
1360 for( lsmash_entry_t *entry = stts->list->head; entry; entry = entry->next )
1362 isom_stts_entry_t *data = (isom_stts_entry_t *)entry->data;
1363 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1364 lsmash_ifprintf( fp, indent, "sample_count = %"PRIu32"\n", data->sample_count );
1365 lsmash_ifprintf( fp, indent--, "sample_delta = %"PRIu32"\n", data->sample_delta );
1367 return 0;
1370 static int isom_print_ctts( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1372 if( !((isom_ctts_t *)box)->list )
1373 return LSMASH_ERR_INVALID_DATA;
1374 isom_ctts_t *ctts = (isom_ctts_t *)box;
1375 int indent = level;
1376 uint32_t i = 0;
1377 isom_print_box_common( fp, indent++, box, "Composition Time to Sample Box" );
1378 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", ctts->list->entry_count );
1379 if( file->qt_compatible || ctts->version == 1 )
1380 for( lsmash_entry_t *entry = ctts->list->head; entry; entry = entry->next )
1382 isom_ctts_entry_t *data = (isom_ctts_entry_t *)entry->data;
1383 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1384 lsmash_ifprintf( fp, indent, "sample_count = %"PRIu32"\n", data->sample_count );
1385 lsmash_ifprintf( fp, indent--, "sample_offset = %"PRId32"\n", (union {uint32_t ui; int32_t si;}){ data->sample_offset }.si );
1387 else
1388 for( lsmash_entry_t *entry = ctts->list->head; entry; entry = entry->next )
1390 isom_ctts_entry_t *data = (isom_ctts_entry_t *)entry->data;
1391 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1392 lsmash_ifprintf( fp, indent, "sample_count = %"PRIu32"\n", data->sample_count );
1393 lsmash_ifprintf( fp, indent--, "sample_offset = %"PRIu32"\n", data->sample_offset );
1395 return 0;
1398 static int isom_print_cslg( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1400 isom_cslg_t *cslg = (isom_cslg_t *)box;
1401 int indent = level;
1402 if( file->qt_compatible )
1404 isom_print_box_common( fp, indent++, box, "Composition Shift Least Greatest Box" );
1405 lsmash_ifprintf( fp, indent, "compositionOffsetToDTDDeltaShift = %"PRId32"\n", cslg->compositionToDTSShift );
1406 lsmash_ifprintf( fp, indent, "leastDecodeToDisplayDelta = %"PRId32"\n", cslg->leastDecodeToDisplayDelta );
1407 lsmash_ifprintf( fp, indent, "greatestDecodeToDisplayDelta = %"PRId32"\n", cslg->greatestDecodeToDisplayDelta );
1408 lsmash_ifprintf( fp, indent, "displayStartTime = %"PRId32"\n", cslg->compositionStartTime );
1409 lsmash_ifprintf( fp, indent, "displayEndTime = %"PRId32"\n", cslg->compositionEndTime );
1411 else
1413 isom_print_box_common( fp, indent++, box, "Composition to Decode Box" );
1414 lsmash_ifprintf( fp, indent, "compositionToDTSShift = %"PRId32"\n", cslg->compositionToDTSShift );
1415 lsmash_ifprintf( fp, indent, "leastDecodeToDisplayDelta = %"PRId32"\n", cslg->leastDecodeToDisplayDelta );
1416 lsmash_ifprintf( fp, indent, "greatestDecodeToDisplayDelta = %"PRId32"\n", cslg->greatestDecodeToDisplayDelta );
1417 lsmash_ifprintf( fp, indent, "compositionStartTime = %"PRId32"\n", cslg->compositionStartTime );
1418 lsmash_ifprintf( fp, indent, "compositionEndTime = %"PRId32"\n", cslg->compositionEndTime );
1420 return 0;
1423 static int isom_print_stss( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1425 if( !((isom_stss_t *)box)->list )
1426 return LSMASH_ERR_INVALID_DATA;
1427 isom_stss_t *stss = (isom_stss_t *)box;
1428 int indent = level;
1429 uint32_t i = 0;
1430 isom_print_box_common( fp, indent++, box, "Sync Sample Box" );
1431 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", stss->list->entry_count );
1432 for( lsmash_entry_t *entry = stss->list->head; entry; entry = entry->next )
1433 lsmash_ifprintf( fp, indent, "sample_number[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_stss_entry_t *)entry->data)->sample_number );
1434 return 0;
1437 static int isom_print_stps( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1439 if( !((isom_stps_t *)box)->list )
1440 return LSMASH_ERR_INVALID_DATA;
1441 isom_stps_t *stps = (isom_stps_t *)box;
1442 int indent = level;
1443 uint32_t i = 0;
1444 isom_print_box_common( fp, indent++, box, "Partial Sync Sample Box" );
1445 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", stps->list->entry_count );
1446 for( lsmash_entry_t *entry = stps->list->head; entry; entry = entry->next )
1447 lsmash_ifprintf( fp, indent, "sample_number[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_stps_entry_t *)entry->data)->sample_number );
1448 return 0;
1451 static int isom_print_sdtp( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1453 if( !((isom_sdtp_t *)box)->list )
1454 return LSMASH_ERR_INVALID_DATA;
1455 isom_sdtp_t *sdtp = (isom_sdtp_t *)box;
1456 int indent = level;
1457 uint32_t i = 0;
1458 isom_print_box_common( fp, indent++, box, "Independent and Disposable Samples Box" );
1459 for( lsmash_entry_t *entry = sdtp->list->head; entry; entry = entry->next )
1461 isom_sdtp_entry_t *data = (isom_sdtp_entry_t *)entry->data;
1462 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1463 if( data->is_leading || data->sample_depends_on || data->sample_is_depended_on || data->sample_has_redundancy )
1465 if( file->avc_extensions )
1467 if( data->is_leading & ISOM_SAMPLE_IS_UNDECODABLE_LEADING )
1468 lsmash_ifprintf( fp, indent, "undecodable leading\n" );
1469 else if( data->is_leading & ISOM_SAMPLE_IS_NOT_LEADING )
1470 lsmash_ifprintf( fp, indent, "non-leading\n" );
1471 else if( data->is_leading & ISOM_SAMPLE_IS_DECODABLE_LEADING )
1472 lsmash_ifprintf( fp, indent, "decodable leading\n" );
1474 else if( data->is_leading & QT_SAMPLE_EARLIER_PTS_ALLOWED )
1475 lsmash_ifprintf( fp, indent, "early display times allowed\n" );
1476 if( data->sample_depends_on & ISOM_SAMPLE_IS_INDEPENDENT )
1477 lsmash_ifprintf( fp, indent, "independent\n" );
1478 else if( data->sample_depends_on & ISOM_SAMPLE_IS_NOT_INDEPENDENT )
1479 lsmash_ifprintf( fp, indent, "dependent\n" );
1480 if( data->sample_is_depended_on & ISOM_SAMPLE_IS_NOT_DISPOSABLE )
1481 lsmash_ifprintf( fp, indent, "non-disposable\n" );
1482 else if( data->sample_is_depended_on & ISOM_SAMPLE_IS_DISPOSABLE )
1483 lsmash_ifprintf( fp, indent, "disposable\n" );
1484 if( data->sample_has_redundancy & ISOM_SAMPLE_HAS_REDUNDANCY )
1485 lsmash_ifprintf( fp, indent, "redundant\n" );
1486 else if( data->sample_has_redundancy & ISOM_SAMPLE_HAS_NO_REDUNDANCY )
1487 lsmash_ifprintf( fp, indent, "non-redundant\n" );
1489 else
1490 lsmash_ifprintf( fp, indent, "no description\n" );
1491 --indent;
1493 return 0;
1496 static int isom_print_stsc( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1498 if( !((isom_stsc_t *)box)->list )
1499 return LSMASH_ERR_INVALID_DATA;
1500 isom_stsc_t *stsc = (isom_stsc_t *)box;
1501 int indent = level;
1502 uint32_t i = 0;
1503 isom_print_box_common( fp, indent++, box, "Sample To Chunk Box" );
1504 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", stsc->list->entry_count );
1505 for( lsmash_entry_t *entry = stsc->list->head; entry; entry = entry->next )
1507 isom_stsc_entry_t *data = (isom_stsc_entry_t *)entry->data;
1508 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1509 lsmash_ifprintf( fp, indent, "first_chunk = %"PRIu32"\n", data->first_chunk );
1510 lsmash_ifprintf( fp, indent, "samples_per_chunk = %"PRIu32"\n", data->samples_per_chunk );
1511 lsmash_ifprintf( fp, indent--, "sample_description_index = %"PRIu32"\n", data->sample_description_index );
1513 return 0;
1516 static int isom_print_stsz( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1518 isom_stsz_t *stsz = (isom_stsz_t *)box;
1519 int indent = level;
1520 uint32_t i = 0;
1521 isom_print_box_common( fp, indent++, box, "Sample Size Box" );
1522 if( !stsz->sample_size )
1523 lsmash_ifprintf( fp, indent, "sample_size = 0 (variable)\n" );
1524 else
1525 lsmash_ifprintf( fp, indent, "sample_size = %"PRIu32" (constant)\n", stsz->sample_size );
1526 lsmash_ifprintf( fp, indent, "sample_count = %"PRIu32"\n", stsz->sample_count );
1527 if( !stsz->sample_size && stsz->list )
1528 for( lsmash_entry_t *entry = stsz->list->head; entry; entry = entry->next )
1530 isom_stsz_entry_t *data = (isom_stsz_entry_t *)entry->data;
1531 lsmash_ifprintf( fp, indent, "entry_size[%"PRIu32"] = %"PRIu32"\n", i++, data->entry_size );
1533 return 0;
1536 static int isom_print_stco( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1538 if( !((isom_stco_t *)box)->list )
1539 return LSMASH_ERR_INVALID_DATA;
1540 isom_stco_t *stco = (isom_stco_t *)box;
1541 int indent = level;
1542 uint32_t i = 0;
1543 isom_print_box_common( fp, indent++, box, "Chunk Offset Box" );
1544 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", stco->list->entry_count );
1545 if( lsmash_check_box_type_identical( stco->type, ISOM_BOX_TYPE_STCO ) )
1547 for( lsmash_entry_t *entry = stco->list->head; entry; entry = entry->next )
1548 lsmash_ifprintf( fp, indent, "chunk_offset[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_stco_entry_t *)entry->data)->chunk_offset );
1550 else
1552 for( lsmash_entry_t *entry = stco->list->head; entry; entry = entry->next )
1553 lsmash_ifprintf( fp, indent, "chunk_offset[%"PRIu32"] = %"PRIu64"\n", i++, ((isom_co64_entry_t *)entry->data)->chunk_offset );
1555 return 0;
1558 static int isom_print_sgpd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1560 if( !((isom_sgpd_t *)box)->list )
1561 return LSMASH_ERR_INVALID_DATA;
1562 isom_sgpd_t *sgpd = (isom_sgpd_t *)box;
1563 int indent = level;
1564 uint32_t i = 0;
1565 isom_print_box_common( fp, indent++, box, "Sample Group Description Box" );
1566 lsmash_ifprintf( fp, indent, "grouping_type = %s\n", isom_4cc2str( sgpd->grouping_type ) );
1567 if( sgpd->version == 1 )
1569 lsmash_ifprintf( fp, indent, "default_length = %"PRIu32, sgpd->default_length );
1570 fprintf( fp, " %s\n", sgpd->default_length ? "(constant)" : "(variable)" );
1572 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", sgpd->list->entry_count );
1573 switch( sgpd->grouping_type )
1575 case ISOM_GROUP_TYPE_RAP :
1576 for( lsmash_entry_t *entry = sgpd->list->head; entry; entry = entry->next )
1578 if( sgpd->version == 1 && !sgpd->default_length )
1579 lsmash_ifprintf( fp, indent, "description_length[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_rap_entry_t *)entry->data)->description_length );
1580 else
1582 isom_rap_entry_t *rap = (isom_rap_entry_t *)entry->data;
1583 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1584 lsmash_ifprintf( fp, indent, "num_leading_samples_known = %"PRIu8"\n", rap->num_leading_samples_known );
1585 lsmash_ifprintf( fp, indent--, "num_leading_samples = %"PRIu8"\n", rap->num_leading_samples );
1588 break;
1589 case ISOM_GROUP_TYPE_ROLL :
1590 case ISOM_GROUP_TYPE_PROL :
1591 for( lsmash_entry_t *entry = sgpd->list->head; entry; entry = entry->next )
1593 if( sgpd->version == 1 && !sgpd->default_length )
1594 lsmash_ifprintf( fp, indent, "description_length[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_roll_entry_t *)entry->data)->description_length );
1595 else
1596 lsmash_ifprintf( fp, indent, "roll_distance[%"PRIu32"] = %"PRId16"\n", i++, ((isom_roll_entry_t *)entry->data)->roll_distance );
1598 break;
1599 default :
1600 break;
1602 return 0;
1605 static int isom_print_sbgp( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1607 if( !((isom_sbgp_t *)box)->list )
1608 return LSMASH_ERR_INVALID_DATA;
1609 isom_sbgp_t *sbgp = (isom_sbgp_t *)box;
1610 int indent = level;
1611 int is_fragment = sbgp->parent && lsmash_check_box_type_identical( sbgp->parent->type, ISOM_BOX_TYPE_TRAF );
1612 uint32_t i = 0;
1613 isom_print_box_common( fp, indent++, box, "Sample to Group Box" );
1614 lsmash_ifprintf( fp, indent, "grouping_type = %s\n", isom_4cc2str( sbgp->grouping_type ) );
1615 if( sbgp->version == 1 )
1616 lsmash_ifprintf( fp, indent, "grouping_type_parameter = %s\n", isom_4cc2str( sbgp->grouping_type_parameter ) );
1617 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", sbgp->list->entry_count );
1618 for( lsmash_entry_t *entry = sbgp->list->head; entry; entry = entry->next )
1620 isom_group_assignment_entry_t *data = (isom_group_assignment_entry_t *)entry->data;
1621 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1622 lsmash_ifprintf( fp, indent, "sample_count = %"PRIu32"\n", data->sample_count );
1623 lsmash_ifprintf( fp, indent--, "group_description_index = %"PRIu32, data->group_description_index );
1624 if( is_fragment && data->group_description_index >= 0x10000 )
1625 fprintf( fp, " (i.e. %"PRIu32" for this fragment-local group)", data->group_description_index - 0x10000 );
1626 if( !data->group_description_index )
1627 fprintf( fp, " (not in this grouping type)\n" );
1628 else
1629 fprintf( fp, "\n" );
1631 return 0;
1634 static int isom_print_udta( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1636 return isom_print_simple( fp, box, level, "User Data Box" );
1639 static int isom_print_chpl( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1641 isom_chpl_t *chpl = (isom_chpl_t *)box;
1642 uint32_t timescale;
1643 if( !chpl->version )
1645 if( !file->moov || !file->moov->mvhd )
1646 return LSMASH_ERR_INVALID_DATA;
1647 timescale = file->moov->mvhd->timescale;
1649 else
1650 timescale = 10000000;
1651 int indent = level;
1652 uint32_t i = 0;
1653 isom_print_box_common( fp, indent++, box, "Chapter List Box" );
1654 if( chpl->version == 1 )
1656 lsmash_ifprintf( fp, indent, "unknown = 0x%02"PRIx8"\n", chpl->unknown );
1657 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", chpl->list->entry_count );
1659 else
1660 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu8"\n", (uint8_t)chpl->list->entry_count );
1661 for( lsmash_entry_t *entry = chpl->list->head; entry; entry = entry->next )
1663 isom_chpl_entry_t *data = (isom_chpl_entry_t *)entry->data;
1664 int64_t start_time = data->start_time / timescale;
1665 int hh = start_time / 3600;
1666 int mm = (start_time / 60) % 60;
1667 int ss = start_time % 60;
1668 int ms = ((data->start_time / (double)timescale) - hh * 3600 - mm * 60 - ss) * 1e3 + 0.5;
1669 int with_bom = 0;
1670 if( !memcmp( data->chapter_name, "\xEF\xBB\xBF", 3 ) ) /* detect BOM */
1672 data->chapter_name += 3;
1673 with_bom = 1;
1675 lsmash_ifprintf( fp, indent++, "chapter[%"PRIu32"]\n", i++ );
1676 lsmash_ifprintf( fp, indent, "start_time = %02d:%02d:%02d.%03d\n", hh, mm, ss, ms );
1677 lsmash_ifprintf( fp, indent--, with_bom ? "chapter_name = %s ( it has BOM in it )\n" : "chapter_name = %s\n", data->chapter_name );
1679 return 0;
1682 static int isom_print_meta( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1684 int indent = level;
1685 if( !(box->manager & LSMASH_QTFF_BASE) )
1687 isom_print_basebox_common( fp, indent++, box, "Meta Box" );
1688 lsmash_ifprintf( fp, indent, "version = %"PRIu8"\n", box->version );
1689 lsmash_ifprintf( fp, indent, "flags = 0x%06"PRIx32"\n", box->flags & 0x00ffffff );
1691 else
1692 isom_print_basebox_common( fp, indent, box, "Metadata Box" );
1693 return 0;
1696 static int isom_print_keys( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1698 if( !((isom_keys_t *)box)->list )
1699 return LSMASH_ERR_INVALID_DATA;
1700 isom_keys_t *keys = (isom_keys_t *)box;
1701 int indent = level;
1702 uint32_t i = 1;
1703 isom_print_box_common( fp, indent++, box, "Metadata Item Keys Box" );
1704 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", keys->list->entry_count );
1705 for( lsmash_entry_t *entry = keys->list->head; entry; entry = entry->next )
1707 isom_keys_entry_t *data = (isom_keys_entry_t *)entry->data;
1708 lsmash_ifprintf( fp, indent++, "[key %"PRIu32"]\n", i++ );
1709 lsmash_ifprintf( fp, indent, "key_size = %"PRIu32"\n", data->key_size );
1710 lsmash_ifprintf( fp, indent, "key_namespace = %s\n", isom_4cc2str( data->key_namespace ) );
1711 uint32_t value_length = data->key_size - 8;
1712 char *str = lsmash_malloc( value_length + 1 );
1713 if( !str )
1714 return LSMASH_ERR_MEMORY_ALLOC;
1715 memcpy( str, data->key_value, value_length );
1716 str[value_length] = 0;
1717 lsmash_ifprintf( fp, indent--, "key_value = %s\n", str );
1718 lsmash_free( str );
1720 return 0;
1723 static int isom_print_ilst( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1725 return isom_print_simple( fp, box, level, "Metadata Item List Box" );
1728 static int isom_print_metaitem( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1730 isom_metaitem_t *metaitem = (isom_metaitem_t *)box;
1731 if( box->parent && box->parent->parent && (box->parent->parent->manager & LSMASH_QTFF_BASE) )
1733 int indent = level;
1734 lsmash_ifprintf( fp, indent++, "[key_index %"PRIu32": Metadata Item Box]\n", box->type.fourcc );
1735 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
1736 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
1737 return 0;
1739 static const struct
1741 lsmash_itunes_metadata_item item;
1742 char *name;
1743 } metaitem_table[] =
1745 { ITUNES_METADATA_ITEM_ALBUM_NAME, "Album Name" },
1746 { ITUNES_METADATA_ITEM_ARTIST, "Artist" },
1747 { ITUNES_METADATA_ITEM_USER_COMMENT, "User Comment" },
1748 { ITUNES_METADATA_ITEM_RELEASE_DATE, "Release Date" },
1749 { ITUNES_METADATA_ITEM_ENCODED_BY, "Encoded By" },
1750 { ITUNES_METADATA_ITEM_USER_GENRE, "User Genre" },
1751 { ITUNES_METADATA_ITEM_GROUPING, "Grouping" },
1752 { ITUNES_METADATA_ITEM_LYRICS, "Lyrics" },
1753 { ITUNES_METADATA_ITEM_TITLE, "Title" },
1754 { ITUNES_METADATA_ITEM_ENCODING_TOOL, "Encoding Tool" },
1755 { ITUNES_METADATA_ITEM_COMPOSER, "Composer" },
1756 { ITUNES_METADATA_ITEM_ALBUM_ARTIST, "Album Artist" },
1757 { ITUNES_METADATA_ITEM_PODCAST_CATEGORY, "Podcast Category" },
1758 { ITUNES_METADATA_ITEM_COVER_ART, "Cover Art" },
1759 { ITUNES_METADATA_ITEM_DISC_COMPILATION, "Disc Compilation" },
1760 { ITUNES_METADATA_ITEM_COPYRIGHT, "Copyright" },
1761 { ITUNES_METADATA_ITEM_DESCRIPTION, "Description" },
1762 { ITUNES_METADATA_ITEM_DISC_NUMBER, "Disc Number" },
1763 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID, "Episode Global Unique ID" },
1764 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE, "Pre-defined Genre" },
1765 { ITUNES_METADATA_ITEM_GROUPING_DRAFT, "Grouping (Overall work like TIT1 in ID3)" },
1766 { ITUNES_METADATA_ITEM_HIGH_DEFINITION_VIDEO, "High Definition Video" },
1767 { ITUNES_METADATA_ITEM_PODCAST_KEYWORD, "Podcast Keyword" },
1768 { ITUNES_METADATA_ITEM_LONG_DESCRIPTION, "Long Description" },
1769 { ITUNES_METADATA_ITEM_PODCAST, "Podcast" },
1770 { ITUNES_METADATA_ITEM_GAPLESS_PLAYBACK, "Gapless Playback" },
1771 { ITUNES_METADATA_ITEM_PURCHASE_DATE, "Purchase Date" },
1772 { ITUNES_METADATA_ITEM_PODCAST_URL, "Podcast URL" },
1773 { ITUNES_METADATA_ITEM_CONTENT_RATING, "Content Rating" },
1774 { ITUNES_METADATA_ITEM_MEDIA_TYPE, "Media Type" },
1775 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE, "Beats Per Minute" },
1776 { ITUNES_METADATA_ITEM_TRACK_NUMBER, "Track Number" },
1777 { ITUNES_METADATA_ITEM_TV_EPISODE_ID, "TV Episode ID" },
1778 { ITUNES_METADATA_ITEM_TV_EPISODE, "TV Episode" },
1779 { ITUNES_METADATA_ITEM_TV_NETWORK, "TV Network" },
1780 { ITUNES_METADATA_ITEM_TV_SHOW_NAME, "TV Show Name" },
1781 { ITUNES_METADATA_ITEM_TV_SEASON, "TV Season" },
1782 { ITUNES_METADATA_ITEM_ITUNES_PURCHASE_ACCOUNT_ID, "iTunes Account Used for Purchase" },
1783 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE, "iTunes Account Type" },
1784 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID, "iTunes Artist ID" },
1785 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID, "iTunes Composer ID" },
1786 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID, "iTunes Catalog ID" },
1787 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID, "iTunes TV Genre ID" },
1788 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID, "iTunes Playlist ID" },
1789 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE, "iTunes Country Code" },
1790 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM, "Sort Album" },
1791 { ITUNES_METADATA_ITEM_ITUNES_SORT_ARTIST, "Sort Artist" },
1792 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM_ARTIST, "Sort Album Artist" },
1793 { ITUNES_METADATA_ITEM_ITUNES_SORT_COMPOSER, "Sort Composer" },
1794 { ITUNES_METADATA_ITEM_ITUNES_SORT_NAME, "Sort Name" },
1795 { ITUNES_METADATA_ITEM_ITUNES_SORT_SHOW, "Sort Show" },
1796 { ITUNES_METADATA_ITEM_CUSTOM, "Custom Metadata Item" },
1797 { 0, NULL }
1799 char *name = NULL;
1800 int i;
1801 for( i = 0; metaitem_table[i].name; i++ )
1802 if( metaitem->type.fourcc == metaitem_table[i].item )
1804 name = metaitem_table[i].name;
1805 break;
1807 if( !name )
1808 name = "Unknown";
1809 uint32_t name_length = strlen( name );
1810 uint32_t display_name_length = name_length + 20;
1811 char *display_name = lsmash_malloc( display_name_length + 1 );
1812 if( !display_name )
1813 return LSMASH_ERR_MEMORY_ALLOC;
1814 memcpy( display_name, "Metadata Item Box (", 19 );
1815 memcpy( display_name + 19, name, name_length );
1816 display_name[display_name_length - 1] = ')';
1817 display_name[display_name_length] = 0;
1818 int ret = isom_print_simple( fp, box, level, display_name );
1819 lsmash_free( display_name );
1820 return ret;
1823 static int isom_print_name( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1825 isom_name_t *name = (isom_name_t *)box;
1826 int indent = level;
1827 isom_print_box_common( fp, indent++, box, "Name Box" );
1828 char *str = lsmash_malloc( name->name_length + 1 );
1829 if( !str )
1830 return LSMASH_ERR_MEMORY_ALLOC;
1831 memcpy( str, name->name, name->name_length );
1832 str[name->name_length] = 0;
1833 lsmash_ifprintf( fp, indent, "name = %s\n", str );
1834 lsmash_free( str );
1835 return 0;
1838 static int isom_print_mean( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1840 isom_mean_t *mean = (isom_mean_t *)box;
1841 int indent = level;
1842 isom_print_box_common( fp, indent++, box, "Mean Box" );
1843 char *str = lsmash_malloc( mean->meaning_string_length + 1 );
1844 if( !str )
1845 return LSMASH_ERR_MEMORY_ALLOC;
1846 memcpy( str, mean->meaning_string, mean->meaning_string_length );
1847 str[mean->meaning_string_length] = 0;
1848 lsmash_ifprintf( fp, indent, "meaning_string = %s\n", str );
1849 lsmash_free( str );
1850 return 0;
1853 static int isom_print_data( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1855 isom_data_t *data = (isom_data_t *)box;
1856 int indent = level;
1857 isom_print_box_common( fp, indent++, box, "Data Box" );
1858 if( box->parent && box->parent->parent && box->parent->parent->parent
1859 && (box->parent->parent->parent->manager & LSMASH_QTFF_BASE) )
1861 uint32_t type_set_indicator = data->reserved >> 8;
1862 uint32_t well_known_type = ((data->reserved << 16) | (data->type_set_identifier << 8) | data->type_code) & 0xffffff;
1863 char *well_known_type_name = "Unknown";
1864 static const struct
1866 uint32_t type;
1867 char *name;
1868 } well_known_type_table[] =
1870 { 0, "reserved" },
1871 { 1, "UTF-8" },
1872 { 2, "UTF-16 BE" },
1873 { 3, "S/JIS" },
1874 { 4, "UTF-8 sort" },
1875 { 5, "UTF-16 sort" },
1876 { 13, "JPEG in a JFIF wrapper" },
1877 { 14, "PNG in a PNG wrapper" },
1878 { 21, "BE Signed Integer" },
1879 { 22, "BE Unsigned Integer" },
1880 { 23, "BE Float32" },
1881 { 24, "BE Float64" },
1882 { 27, "BMP (Windows bitmap format graphics)" },
1883 { 28, "QuickTime Metadata box" },
1884 { UINT32_MAX }
1886 int table_index;
1887 for( table_index = 0; well_known_type_table[table_index].type != UINT32_MAX; table_index++ )
1888 if( well_known_type == well_known_type_table[table_index].type )
1890 well_known_type_name = well_known_type_table[table_index].name;
1891 break;
1893 lsmash_ifprintf( fp, indent, "type_set_indicator = %"PRIu8"\n", type_set_indicator );
1894 lsmash_ifprintf( fp, indent, "well_known_type = %"PRIu32" (%s)\n", well_known_type, well_known_type_name );
1895 lsmash_ifprintf( fp, indent, "locale_indicator = %"PRIu32"\n", data->the_locale );
1896 if( data->value_length == 0 )
1898 lsmash_ifprintf( fp, indent, "value = (null)\n" );
1899 return 0;
1901 if( well_known_type == 1 )
1903 /* UTF-8 without any count or null terminator */
1904 char *str = lsmash_malloc( data->value_length + 1 );
1905 if( !str )
1906 return LSMASH_ERR_MEMORY_ALLOC;
1907 memcpy( str, data->value, data->value_length );
1908 str[data->value_length] = 0;
1909 lsmash_ifprintf( fp, indent, "value = %s\n", str );
1910 lsmash_free( str );
1912 else if( well_known_type == 13 || well_known_type == 14 || well_known_type == 27 )
1913 lsmash_ifprintf( fp, indent, "value = (binary data)\n" );
1914 else if( well_known_type == 21 && data->value_length <= 4 )
1915 /* a big-endian signed integer in 1,2,3 or 4 bytes */
1916 goto show_in_signed_integer;
1917 else if( well_known_type == 22 && data->value_length <= 4 )
1919 /* a big-endian unsigned integer in 1,2,3 or 4 bytes */
1920 uint32_t integer = data->value[0];
1921 for( uint32_t i = 1; i < data->value_length; i++ )
1922 integer = (integer << 8) | data->value[i];
1923 lsmash_ifprintf( fp, indent, "value = %"PRIu32"\n", integer );
1925 else if( well_known_type == 23 && data->value_length == 4 )
1927 /* a big-endian 32-bit floating point value (IEEE754) */
1928 uint32_t float32 = LSMASH_GET_BE32( data->value );
1929 lsmash_ifprintf( fp, indent, "value = %f\n", lsmash_int2float32( float32 ) );
1931 else if( well_known_type == 24 && data->value_length == 8 )
1933 /* a big-endian 64-bit floating point value (IEEE754) */
1934 uint64_t float64 = LSMASH_GET_BE64( data->value );
1935 lsmash_ifprintf( fp, indent, "value = %lf\n", lsmash_int2float64( float64 ) );
1937 else
1938 goto show_in_binary;
1940 else
1942 char *basic_data_type_name = "Unknown";
1943 static const struct
1945 uint32_t type;
1946 char *name;
1947 } basic_data_type_table[] =
1949 { 0, "Implicit" },
1950 { 1, "UTF-8" },
1951 { 2, "UTF-16 BE" },
1952 { 3, "S/JIS" },
1953 { 6, "HTML" },
1954 { 7, "XML" },
1955 { 8, "UUID" },
1956 { 9, "ISRC" },
1957 { 10, "MI3P" },
1958 { 12, "GIF" },
1959 { 13, "JPEG in a JFIF wrapper" },
1960 { 14, "PNG in a PNG wrapper" },
1961 { 15, "URL" },
1962 { 16, "duration" },
1963 { 17, "date/time" },
1964 { 18, "Genres" },
1965 { 21, "BE Signed Integer" },
1966 { 24, "RIAA-PA (RIAA Parental advisory)" },
1967 { 25, "UPC (Universal Product Code)" },
1968 { 27, "BMP (Windows bitmap format graphics)" },
1969 { UINT32_MAX }
1971 int table_index;
1972 for( table_index = 0; basic_data_type_table[table_index].type != UINT32_MAX; table_index++ )
1973 if( data->type_code == basic_data_type_table[table_index].type )
1975 basic_data_type_name = basic_data_type_table[table_index].name;
1976 break;
1978 lsmash_ifprintf( fp, indent, "reserved = %"PRIu16"\n", data->reserved );
1979 lsmash_ifprintf( fp, indent, "type_set_identifier = %"PRIu8"%s\n",
1980 data->type_set_identifier,
1981 data->type_set_identifier ? "" : " (basic type set)" );
1982 lsmash_ifprintf( fp, indent, "type_code = %"PRIu8" (%s)\n", data->type_code, basic_data_type_name );
1983 lsmash_ifprintf( fp, indent, "the_locale = %"PRIu32"\n", data->the_locale );
1984 if( data->value_length == 0 )
1986 lsmash_ifprintf( fp, indent, "value = (null)\n" );
1987 return 0;
1989 if( data->type_code == 6 || data->type_code == 7
1990 || data->type_code == 12 || data->type_code == 13
1991 || data->type_code == 14 || data->type_code == 27 )
1992 lsmash_ifprintf( fp, indent, "value = (binary data)\n" );
1993 else if( data->type_code == 8 && data->value_length == 16 )
1994 /* UUID */
1995 lsmash_ifprintf( fp, indent, "value = 0x%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"0x%08"PRIx32"\n",
1996 LSMASH_GET_BE32( &data->value[ 0] ),
1997 LSMASH_GET_BE16( &data->value[ 4] ),
1998 LSMASH_GET_BE16( &data->value[ 6] ),
1999 LSMASH_GET_BE16( &data->value[ 8] ),
2000 LSMASH_GET_BE16( &data->value[10] ),
2001 LSMASH_GET_BE32( &data->value[12] ) );
2002 else if( data->type_code == 16 && data->value_length == 4 )
2004 /* duration in milliseconds */
2005 uint32_t duration = LSMASH_GET_BE32( data->value );
2006 lsmash_ifprintf( fp, indent, "value = %"PRIu32" milliseconds\n", duration );
2008 else if( data->type_code == 17 && (data->value_length == 4 || data->value_length == 8) )
2010 /* UTC, counting seconds since midnight on 1 January, 1904 */
2011 uint64_t mp4time = data->value_length == 8
2012 ? LSMASH_GET_BE64( data->value )
2013 : LSMASH_GET_BE32( data->value );
2014 isom_mp4time2utc( mp4time );
2016 else if( data->type_code == 21 && data->value_length <= 8 )
2017 /* a big-endian signed integer in 1,2,3,4 or 8 bytes */
2018 goto show_in_signed_integer;
2019 else if( data->type_code == 24 )
2021 /* RIAA-PA (RIAA Parental advisory) 8-bit integer */
2022 lsmash_ifprintf( fp, indent, "value = %"PRIu8, data->value[0] );
2023 if( data->value[0] == (uint8_t)-1 )
2024 fprintf( fp, " (no)" );
2025 else if( data->value[0] == 1 )
2026 fprintf( fp, " (yes)" );
2027 else if( data->value[0] == 0 )
2028 fprintf( fp, " (unspecified)" );
2029 fprintf( fp, "\n" );
2031 else if( data->type_code == 1 || data->type_code == 2 || data->type_code == 3
2032 || data->type_code == 9 || data->type_code == 10 || data->type_code == 15
2033 || data->type_code == 25 )
2035 /* String */
2036 char *str = lsmash_malloc( data->value_length + 1 );
2037 if( !str )
2038 return LSMASH_ERR_MEMORY_ALLOC;
2039 memcpy( str, data->value, data->value_length );
2040 str[data->value_length] = 0;
2041 lsmash_ifprintf( fp, indent, "value = %s\n", str );
2042 lsmash_free( str );
2044 else
2045 goto show_in_binary;
2047 return 0;
2048 show_in_signed_integer:;
2049 uint64_t integer = data->value[0];
2050 uint64_t max_value = 0xff;
2051 for( uint32_t i = 1; i < data->value_length; i++ )
2053 integer = (integer << 8) | data->value[i];
2054 max_value = (max_value << 8) | 0xff;
2056 lsmash_ifprintf( fp, indent, "value = %"PRId64"\n", (int64_t)(integer | (integer > (max_value >> 1) ? ~max_value : 0)) );
2057 return 0;
2058 show_in_binary:
2059 lsmash_ifprintf( fp, indent, "value = " );
2060 if( data->value_length )
2062 fprintf( fp, "0x" );
2063 for( uint32_t i = 0; i < data->value_length; i++ )
2064 fprintf( fp, "%02"PRIx8, data->value[i] );
2066 fprintf( fp, "\n" );
2067 return 0;
2070 static int isom_print_WLOC( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2072 isom_WLOC_t *WLOC = (isom_WLOC_t *)box;
2073 int indent = level;
2074 isom_print_box_common( fp, indent++, box, "Window Location Box" );
2075 lsmash_ifprintf( fp, indent, "x = %"PRIu16"\n", WLOC->x );
2076 lsmash_ifprintf( fp, indent, "y = %"PRIu16"\n", WLOC->y );
2077 return 0;
2080 static int isom_print_LOOP( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2082 isom_LOOP_t *LOOP = (isom_LOOP_t *)box;
2083 int indent = level;
2084 isom_print_box_common( fp, indent++, box, "Looping Box" );
2085 lsmash_ifprintf( fp, indent, "looping_mode = %"PRIu32, LOOP->looping_mode );
2086 switch( LOOP->looping_mode )
2088 case 0 :
2089 fprintf( fp, " (none)\n" );
2090 break;
2091 case 1 :
2092 fprintf( fp, " (looping)\n" );
2093 break;
2094 case 2 :
2095 fprintf( fp, " (palindromic looping)\n" );
2096 break;
2097 default :
2098 fprintf( fp, "\n" );
2099 break;
2101 return 0;
2104 static int isom_print_SelO( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2106 isom_SelO_t *SelO = (isom_SelO_t *)box;
2107 int indent = level;
2108 isom_print_box_common( fp, indent++, box, "Play Selection Only Box" );
2109 lsmash_ifprintf( fp, indent, "selection_only = %"PRIu8"\n", SelO->selection_only );
2110 return 0;
2113 static int isom_print_AllF( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2115 isom_AllF_t *AllF = (isom_AllF_t *)box;
2116 int indent = level;
2117 isom_print_box_common( fp, indent++, box, "Play All Frames Box" );
2118 lsmash_ifprintf( fp, indent, "play_all_frames = %"PRIu8"\n", AllF->play_all_frames );
2119 return 0;
2122 static int isom_print_cprt( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2124 isom_cprt_t *cprt = (isom_cprt_t *)box;
2125 int indent = level;
2126 char *str = lsmash_malloc( cprt->notice_length + 1 );
2127 if( !str )
2128 return LSMASH_ERR_MEMORY_ALLOC;
2129 memcpy( str, cprt->notice, cprt->notice_length );
2130 str[cprt->notice_length] = 0;
2131 isom_print_box_common( fp, indent++, box, "Copyright Box" );
2132 lsmash_ifprintf( fp, indent, "language = %s\n", isom_unpack_iso_language( cprt->language ) );
2133 lsmash_ifprintf( fp, indent, "notice = %s\n", str );
2134 lsmash_free( str );
2135 return 0;
2138 static int isom_print_mvex( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2140 return isom_print_simple( fp, box, level, "Movie Extends Box" );
2143 static int isom_print_mehd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2145 isom_mehd_t *mehd = (isom_mehd_t *)box;
2146 int indent = level;
2147 isom_print_box_common( fp, indent++, box, "Movie Extends Header Box" );
2148 if( file->moov && file->moov->mvhd )
2149 isom_ifprintf_duration( fp, indent, "fragment_duration", mehd->fragment_duration, file->moov->mvhd->timescale );
2150 else
2151 isom_ifprintf_duration( fp, indent, "fragment_duration", mehd->fragment_duration, 0 );
2152 return 0;
2155 static int isom_print_trex( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2157 isom_trex_t *trex = (isom_trex_t *)box;
2158 int indent = level;
2159 isom_print_box_common( fp, indent++, box, "Track Extends Box" );
2160 lsmash_ifprintf( fp, indent, "track_ID = %"PRIu32"\n", trex->track_ID );
2161 lsmash_ifprintf( fp, indent, "default_sample_description_index = %"PRIu32"\n", trex->default_sample_description_index );
2162 lsmash_ifprintf( fp, indent, "default_sample_duration = %"PRIu32"\n", trex->default_sample_duration );
2163 lsmash_ifprintf( fp, indent, "default_sample_size = %"PRIu32"\n", trex->default_sample_size );
2164 isom_ifprintf_sample_flags( fp, indent, "default_sample_flags", &trex->default_sample_flags );
2165 return 0;
2168 static int isom_print_moof( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2170 return isom_print_simple( fp, box, level, "Movie Fragment Box" );
2173 static int isom_print_mfhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2175 isom_mfhd_t *mfhd = (isom_mfhd_t *)box;
2176 int indent = level;
2177 isom_print_box_common( fp, indent++, box, "Movie Fragment Header Box" );
2178 lsmash_ifprintf( fp, indent, "sequence_number = %"PRIu32"\n", mfhd->sequence_number );
2179 return 0;
2182 static int isom_print_traf( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2184 return isom_print_simple( fp, box, level, "Track Fragment Box" );
2187 static int isom_print_tfhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2189 isom_tfhd_t *tfhd = (isom_tfhd_t *)box;
2190 int indent = level;
2191 isom_print_box_common( fp, indent++, box, "Track Fragment Header Box" );
2192 ++indent;
2193 if( tfhd->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) lsmash_ifprintf( fp, indent, "base-data-offset-present\n" );
2194 if( tfhd->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) lsmash_ifprintf( fp, indent, "sample-description-index-present\n" );
2195 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) lsmash_ifprintf( fp, indent, "default-sample-duration-present\n" );
2196 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) lsmash_ifprintf( fp, indent, "default-sample-size-present\n" );
2197 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) lsmash_ifprintf( fp, indent, "default-sample-flags-present\n" );
2198 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_BASE_IS_MOOF ) lsmash_ifprintf( fp, indent, "default-base-is-moof\n" );
2199 lsmash_ifprintf( fp, --indent, "track_ID = %"PRIu32"\n", tfhd->track_ID );
2200 if( tfhd->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT )
2201 lsmash_ifprintf( fp, indent, "base_data_offset = %"PRIu64"\n", tfhd->base_data_offset );
2202 if( tfhd->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT )
2203 lsmash_ifprintf( fp, indent, "sample_description_index = %"PRIu32"\n", tfhd->sample_description_index );
2204 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT )
2205 lsmash_ifprintf( fp, indent, "default_sample_duration = %"PRIu32"\n", tfhd->default_sample_duration );
2206 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT )
2207 lsmash_ifprintf( fp, indent, "default_sample_size = %"PRIu32"\n", tfhd->default_sample_size );
2208 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT )
2209 isom_ifprintf_sample_flags( fp, indent, "default_sample_flags", &tfhd->default_sample_flags );
2210 return 0;
2213 static int isom_print_tfdt( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2215 isom_tfdt_t *tfdt = (isom_tfdt_t *)box;
2216 int indent = level;
2217 isom_print_box_common( fp, indent++, box, "Track Fragment Base Media Decode Time Box" );
2218 lsmash_ifprintf( fp, indent, "baseMediaDecodeTime = %"PRIu64"\n", tfdt->baseMediaDecodeTime );
2219 return 0;
2222 static int isom_print_trun( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2224 isom_trun_t *trun = (isom_trun_t *)box;
2225 int indent = level;
2226 isom_print_box_common( fp, indent++, box, "Track Fragment Run Box" );
2227 ++indent;
2228 if( trun->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) lsmash_ifprintf( fp, indent, "data-offset-present\n" );
2229 if( trun->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) lsmash_ifprintf( fp, indent, "first-sample-flags-present\n" );
2230 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) lsmash_ifprintf( fp, indent, "sample-duration-present\n" );
2231 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) lsmash_ifprintf( fp, indent, "sample-size-present\n" );
2232 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) lsmash_ifprintf( fp, indent, "sample-flags-present\n" );
2233 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) lsmash_ifprintf( fp, indent, "sample-composition-time-offsets-present\n" );
2234 lsmash_ifprintf( fp, --indent, "sample_count = %"PRIu32"\n", trun->sample_count );
2235 if( trun->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT )
2236 lsmash_ifprintf( fp, indent, "data_offset = %"PRId32"\n", trun->data_offset );
2237 if( trun->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT )
2238 isom_ifprintf_sample_flags( fp, indent, "first_sample_flags", &trun->first_sample_flags );
2239 if( trun->optional )
2241 uint32_t i = 0;
2242 for( lsmash_entry_t *entry = trun->optional->head; entry; entry = entry->next )
2244 isom_trun_optional_row_t *row = (isom_trun_optional_row_t *)entry->data;
2245 lsmash_ifprintf( fp, indent++, "sample[%"PRIu32"]\n", i++ );
2246 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT )
2247 lsmash_ifprintf( fp, indent, "sample_duration = %"PRIu32"\n", row->sample_duration );
2248 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT )
2249 lsmash_ifprintf( fp, indent, "sample_size = %"PRIu32"\n", row->sample_size );
2250 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT )
2251 isom_ifprintf_sample_flags( fp, indent, "sample_flags", &row->sample_flags );
2252 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT )
2254 if( trun->version == 0 )
2255 lsmash_ifprintf( fp, indent, "sample_composition_time_offset = %"PRIu32"\n",
2256 row->sample_composition_time_offset );
2257 else
2258 lsmash_ifprintf( fp, indent, "sample_composition_time_offset = %"PRId32"\n",
2259 (union {uint32_t ui; int32_t si;}){ row->sample_composition_time_offset }.si );
2261 --indent;
2264 return 0;
2267 static int isom_print_free( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2269 return isom_print_simple( fp, box, level, "Free Space Box" );
2272 static int isom_print_mdat( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2274 return isom_print_simple( fp, box, level, "Media Data Box" );
2277 static int isom_print_mfra( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2279 return isom_print_simple( fp, box, level, "Movie Fragment Random Access Box" );
2282 static int isom_print_tfra( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2284 isom_tfra_t *tfra = (isom_tfra_t *)box;
2285 int indent = level;
2286 isom_print_box_common( fp, indent++, box, "Track Fragment Random Access Box" );
2287 lsmash_ifprintf( fp, indent, "track_ID = %"PRIu32"\n", tfra->track_ID );
2288 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", tfra->reserved );
2289 lsmash_ifprintf( fp, indent, "length_size_of_traf_num = %"PRIu8"\n", tfra->length_size_of_traf_num );
2290 lsmash_ifprintf( fp, indent, "length_size_of_trun_num = %"PRIu8"\n", tfra->length_size_of_trun_num );
2291 lsmash_ifprintf( fp, indent, "length_size_of_sample_num = %"PRIu8"\n", tfra->length_size_of_sample_num );
2292 lsmash_ifprintf( fp, indent, "number_of_entry = %"PRIu32"\n", tfra->number_of_entry );
2293 if( tfra->list )
2295 uint32_t i = 0;
2296 for( lsmash_entry_t *entry = tfra->list->head; entry; entry = entry->next )
2298 isom_tfra_location_time_entry_t *data = (isom_tfra_location_time_entry_t *)entry->data;
2299 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
2300 lsmash_ifprintf( fp, indent, "time = %"PRIu64"\n", data->time );
2301 lsmash_ifprintf( fp, indent, "moof_offset = %"PRIu64"\n", data->moof_offset );
2302 lsmash_ifprintf( fp, indent, "traf_number = %"PRIu32"\n", data->traf_number );
2303 lsmash_ifprintf( fp, indent, "trun_number = %"PRIu32"\n", data->trun_number );
2304 lsmash_ifprintf( fp, indent, "sample_number = %"PRIu32"\n", data->sample_number );
2305 --indent;
2308 return 0;
2311 static int isom_print_mfro( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2313 isom_mfro_t *mfro = (isom_mfro_t *)box;
2314 int indent = level;
2315 isom_print_box_common( fp, indent++, box, "Movie Fragment Random Access Offset Box" );
2316 lsmash_ifprintf( fp, indent, "size = %"PRIu32"\n", mfro->length );
2317 return 0;
2320 int lsmash_print_movie( lsmash_root_t *root, const char *filename )
2322 if( !root )
2323 return LSMASH_ERR_FUNCTION_PARAM;
2324 lsmash_file_t *file = root->file;
2325 if( !file
2326 || !file->print
2327 || !(file->flags & LSMASH_FILE_MODE_DUMP) )
2328 return LSMASH_ERR_FUNCTION_PARAM;
2329 FILE *destination;
2330 if( !strcmp( filename, "-" ) )
2331 destination = stdout;
2332 else
2334 destination = lsmash_fopen( filename, "wb" );
2335 if( !destination )
2336 return LSMASH_ERR_NAMELESS;
2338 fprintf( destination, "[File]\n" );
2339 fprintf( destination, " size = %"PRIu64"\n", file->size );
2340 for( lsmash_entry_t *entry = file->print->head; entry; entry = entry->next )
2342 isom_print_entry_t *data = (isom_print_entry_t *)entry->data;
2343 if( !data || !data->box )
2345 fclose( destination );
2346 return LSMASH_ERR_NAMELESS;
2348 int ret = data->func( destination, file, data->box, data->level );
2349 if( ret < 0 )
2351 fclose( destination );
2352 return ret;
2355 fclose( destination );
2356 return 0;
2359 static isom_print_box_t isom_select_print_func( isom_box_t *box )
2361 if( box->manager & LSMASH_UNKNOWN_BOX )
2362 return isom_print_unknown;
2363 if( box->parent )
2365 isom_box_t *parent = box->parent;
2366 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2368 lsmash_codec_type_t sample_type = box->type;
2369 if( lsmash_check_codec_type_identical( sample_type, LSMASH_CODEC_TYPE_RAW ) )
2371 if( box->manager & LSMASH_VIDEO_DESCRIPTION )
2372 return isom_print_visual_description;
2373 else if( box->manager & LSMASH_AUDIO_DESCRIPTION )
2374 return isom_print_audio_description;
2376 static struct print_description_table_tag
2378 lsmash_codec_type_t type;
2379 isom_print_box_t func;
2380 } print_description_table[160] = { { LSMASH_CODEC_TYPE_INITIALIZER, NULL } };
2381 if( !print_description_table[0].func )
2383 /* Initialize the table. */
2384 int i = 0;
2385 #define ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( type, func ) print_description_table[i++] = (struct print_description_table_tag){ type, func }
2386 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, isom_print_visual_description );
2387 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, isom_print_visual_description );
2388 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, isom_print_visual_description );
2389 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, isom_print_visual_description );
2390 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, isom_print_visual_description );
2391 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, isom_print_visual_description );
2392 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, isom_print_visual_description );
2393 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, isom_print_visual_description );
2394 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, isom_print_visual_description );
2395 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, isom_print_visual_description );
2396 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, isom_print_visual_description );
2397 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, isom_print_visual_description );
2398 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, isom_print_visual_description );
2399 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, isom_print_visual_description );
2400 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, isom_print_visual_description );
2401 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, isom_print_visual_description );
2402 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, isom_print_visual_description );
2403 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, isom_print_visual_description );
2404 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, isom_print_visual_description );
2405 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, isom_print_visual_description );
2406 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, isom_print_visual_description );
2407 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, isom_print_visual_description );
2408 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, isom_print_visual_description );
2409 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, isom_print_visual_description );
2410 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, isom_print_visual_description );
2411 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, isom_print_visual_description );
2412 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, isom_print_visual_description );
2413 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, isom_print_visual_description );
2414 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, isom_print_visual_description );
2415 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, isom_print_visual_description );
2416 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, isom_print_visual_description );
2417 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, isom_print_visual_description );
2418 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, isom_print_visual_description );
2419 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, isom_print_visual_description );
2420 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, isom_print_visual_description );
2421 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, isom_print_visual_description );
2422 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, isom_print_visual_description );
2423 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, isom_print_visual_description );
2424 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, isom_print_visual_description );
2425 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, isom_print_visual_description );
2426 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, isom_print_visual_description );
2427 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, isom_print_visual_description );
2428 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, isom_print_visual_description );
2429 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, isom_print_visual_description );
2430 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, isom_print_visual_description );
2431 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, isom_print_visual_description );
2432 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, isom_print_visual_description );
2433 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, isom_print_visual_description );
2434 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, isom_print_visual_description );
2435 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, isom_print_visual_description );
2436 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, isom_print_visual_description );
2437 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, isom_print_visual_description );
2438 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, isom_print_visual_description );
2439 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, isom_print_visual_description );
2440 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, isom_print_visual_description );
2441 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, isom_print_visual_description );
2442 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, isom_print_visual_description );
2443 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, isom_print_visual_description );
2444 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, isom_print_visual_description );
2445 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, isom_print_visual_description );
2446 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, isom_print_visual_description );
2447 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, isom_print_visual_description );
2448 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, isom_print_visual_description );
2449 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, isom_print_visual_description );
2450 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, isom_print_visual_description );
2451 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, isom_print_visual_description );
2452 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, isom_print_visual_description );
2453 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, isom_print_visual_description );
2454 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, isom_print_visual_description );
2455 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, isom_print_visual_description );
2456 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, isom_print_visual_description );
2457 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, isom_print_visual_description );
2458 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, isom_print_visual_description );
2459 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, isom_print_visual_description );
2460 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, isom_print_visual_description );
2461 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, isom_print_visual_description );
2462 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, isom_print_audio_description );
2463 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, isom_print_audio_description );
2464 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, isom_print_audio_description );
2465 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, isom_print_audio_description );
2466 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, isom_print_audio_description );
2467 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, isom_print_audio_description );
2468 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, isom_print_audio_description );
2469 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, isom_print_audio_description );
2470 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, isom_print_audio_description );
2471 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, isom_print_audio_description );
2472 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, isom_print_audio_description );
2473 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, isom_print_audio_description );
2474 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, isom_print_audio_description );
2475 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, isom_print_audio_description );
2476 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, isom_print_audio_description );
2477 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, isom_print_audio_description );
2478 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, isom_print_audio_description );
2479 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, isom_print_audio_description );
2480 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, isom_print_audio_description );
2481 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, isom_print_audio_description );
2482 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, isom_print_audio_description );
2483 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, isom_print_audio_description );
2484 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_MP4A_AUDIO, isom_print_audio_description );
2485 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, isom_print_audio_description );
2486 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, isom_print_audio_description );
2487 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, isom_print_audio_description );
2488 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, isom_print_audio_description );
2489 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, isom_print_audio_description );
2490 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, isom_print_audio_description );
2491 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, isom_print_audio_description );
2492 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, isom_print_audio_description );
2493 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, isom_print_audio_description );
2494 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, isom_print_audio_description );
2495 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, isom_print_audio_description );
2496 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, isom_print_audio_description );
2497 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, isom_print_audio_description );
2498 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, isom_print_audio_description );
2499 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, isom_print_audio_description );
2500 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, isom_print_audio_description );
2501 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, isom_print_audio_description );
2502 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, isom_print_audio_description );
2503 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, isom_print_audio_description );
2504 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, isom_print_audio_description );
2505 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, isom_print_audio_description );
2506 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, isom_print_audio_description );
2507 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, isom_print_audio_description );
2508 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, isom_print_audio_description );
2509 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, isom_print_audio_description );
2510 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, isom_print_audio_description );
2511 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, isom_print_audio_description );
2512 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, isom_print_audio_description );
2513 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, isom_print_audio_description );
2514 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, isom_print_text_description );
2515 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, isom_print_tx3g_description );
2516 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, isom_print_mp4s_description );
2517 ADD_PRINT_DESCRIPTION_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL );
2518 #undef ADD_PRINT_DESCRIPTION_TABLE_ELEMENT
2520 for( int i = 0; print_description_table[i].func; i++ )
2521 if( lsmash_check_codec_type_identical( sample_type, print_description_table[i].type ) )
2522 return print_description_table[i].func;
2523 return isom_print_unknown;
2525 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2527 if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_FRMA ) )
2528 return isom_print_frma;
2529 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ENDA ) )
2530 return isom_print_enda;
2531 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_TERMINATOR ) )
2532 return isom_print_terminator;
2533 else
2534 return isom_print_sample_description_extesion;
2536 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2537 return isom_print_track_reference_type;
2538 if( parent->parent )
2540 if( lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2541 return isom_print_sample_description_extesion;
2542 else if( lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_ILST )
2543 || lsmash_check_box_type_identical( parent->parent->type, QT_BOX_TYPE_ILST ) )
2545 if( parent->type.fourcc == LSMASH_4CC( '-', '-', '-', '-' ) )
2547 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_MEAN ) )
2548 return isom_print_mean;
2549 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_NAME ) )
2550 return isom_print_name;
2552 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_DATA ) )
2553 return isom_print_data;
2556 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2557 || lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2558 return isom_print_metaitem;
2560 static struct print_box_table_tag
2562 lsmash_box_type_t type;
2563 isom_print_box_t func;
2564 } print_box_table[128] = { { LSMASH_BOX_TYPE_INITIALIZER, NULL } };
2565 if( !print_box_table[0].func )
2567 /* Initialize the table. */
2568 int i = 0;
2569 #define ADD_PRINT_BOX_TABLE_ELEMENT( type, func ) print_box_table[i++] = (struct print_box_table_tag){ type, func }
2570 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, isom_print_ftyp );
2571 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, isom_print_styp );
2572 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, isom_print_sidx );
2573 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, isom_print_moov );
2574 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, isom_print_mvhd );
2575 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, isom_print_iods );
2576 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, isom_print_ctab );
2577 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, isom_print_trak );
2578 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, isom_print_tkhd );
2579 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, isom_print_tapt );
2580 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, isom_print_clef );
2581 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_PROF, isom_print_prof );
2582 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, isom_print_enof );
2583 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, isom_print_edts );
2584 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, isom_print_elst );
2585 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, isom_print_tref );
2586 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, isom_print_mdia );
2587 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, isom_print_mdhd );
2588 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, isom_print_hdlr );
2589 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, isom_print_minf );
2590 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, isom_print_vmhd );
2591 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, isom_print_smhd );
2592 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, isom_print_hmhd );
2593 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, isom_print_nmhd );
2594 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, isom_print_gmhd );
2595 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, isom_print_gmin );
2596 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, isom_print_text );
2597 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, isom_print_dinf );
2598 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, isom_print_dref );
2599 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_URL, isom_print_url );
2600 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, isom_print_stbl );
2601 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, isom_print_stsd );
2602 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, isom_print_clap );
2603 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, isom_print_pasp );
2604 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, isom_print_colr );
2605 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_COLR, isom_print_colr );
2606 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, isom_print_glbl );
2607 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, isom_print_gama );
2608 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, isom_print_fiel );
2609 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, isom_print_cspc );
2610 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, isom_print_sgbt );
2611 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, isom_print_stsl );
2612 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, isom_print_wave );
2613 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, isom_print_chan );
2614 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, isom_print_srat );
2615 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, isom_print_ftab );
2616 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, isom_print_stts );
2617 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, isom_print_ctts );
2618 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, isom_print_cslg );
2619 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, isom_print_stss );
2620 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_STPS, isom_print_stps );
2621 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, isom_print_sdtp );
2622 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, isom_print_stsc );
2623 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, isom_print_stsz );
2624 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, isom_print_stco );
2625 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, isom_print_stco );
2626 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, isom_print_sgpd );
2627 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, isom_print_sbgp );
2628 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, isom_print_udta );
2629 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, isom_print_chpl );
2630 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, isom_print_WLOC );
2631 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, isom_print_LOOP );
2632 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_SELO, isom_print_SelO );
2633 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, isom_print_AllF );
2634 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CPRT, isom_print_cprt );
2635 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, isom_print_mvex );
2636 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, isom_print_mehd );
2637 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, isom_print_trex );
2638 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, isom_print_moof );
2639 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, isom_print_mfhd );
2640 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, isom_print_traf );
2641 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, isom_print_tfhd );
2642 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, isom_print_tfdt );
2643 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, isom_print_trun );
2644 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, isom_print_free );
2645 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, isom_print_free );
2646 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, isom_print_mdat );
2647 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, isom_print_keys );
2648 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_META, isom_print_meta );
2649 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_ILST, isom_print_ilst );
2650 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_ILST, isom_print_ilst );
2651 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, isom_print_mfra );
2652 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, isom_print_tfra );
2653 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, isom_print_mfro );
2654 ADD_PRINT_BOX_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
2655 #undef ADD_PRINT_BOX_TABLE_ELEMENT
2657 for( int i = 0; print_box_table[i].func; i++ )
2658 if( lsmash_check_box_type_identical( box->type, print_box_table[i].type ) )
2659 return print_box_table[i].func;
2660 return isom_print_unknown;
2663 static inline void isom_print_remove_plastic_box( isom_box_t *box )
2665 if( box->manager & LSMASH_ABSENT_IN_FILE )
2666 /* free flagged box */
2667 isom_remove_box_by_itself( box );
2670 int isom_add_print_func( lsmash_file_t *file, void *box, int level )
2672 if( !(file->flags & LSMASH_FILE_MODE_DUMP) )
2674 isom_print_remove_plastic_box( box );
2675 return 0;
2677 isom_print_entry_t *data = lsmash_malloc( sizeof(isom_print_entry_t) );
2678 if( !data )
2680 isom_print_remove_plastic_box( box );
2681 return LSMASH_ERR_MEMORY_ALLOC;
2683 data->level = level;
2684 data->box = (isom_box_t *)box;
2685 data->func = isom_select_print_func( (isom_box_t *)box );
2686 assert( data->func );
2687 if( lsmash_add_entry( file->print, data ) < 0 )
2689 isom_print_remove_plastic_box( data->box );
2690 lsmash_free( data );
2691 return LSMASH_ERR_MEMORY_ALLOC;
2693 return 0;
2696 static void isom_remove_print_func( isom_print_entry_t *data )
2698 if( !data || !data->box )
2699 return;
2700 isom_print_remove_plastic_box( data->box );
2701 lsmash_free( data );
2704 void isom_remove_print_funcs( lsmash_file_t *file )
2706 lsmash_remove_list( file->print, isom_remove_print_func );
2707 file->print = NULL;
2710 #endif /* LSMASH_DEMUXER_ENABLED */