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