Update copyright dates.
[L-SMASH.git] / core / print.c
blob0f66145ebd8c725f51efa6d1e3f95368e5052c95
1 /*****************************************************************************
2 * print.c
3 *****************************************************************************
4 * Copyright (C) 2010-2017 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
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_stz2( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1536 isom_stz2_t *stz2 = (isom_stz2_t *)box;
1537 int indent = level;
1538 uint32_t i = 0;
1539 isom_print_box_common( fp, indent++, box, "Compact Sample Size Box" );
1540 lsmash_ifprintf( fp, indent, "reserved = 0x%06"PRIx32"\n", stz2->reserved );
1541 lsmash_ifprintf( fp, indent, "field_size = %"PRIu8"\n", stz2->field_size );
1542 lsmash_ifprintf( fp, indent, "sample_count = %"PRIu32"\n", stz2->sample_count );
1543 for( lsmash_entry_t *entry = stz2->list->head; entry; entry = entry->next )
1545 isom_stsz_entry_t *data = (isom_stsz_entry_t *)entry->data;
1546 lsmash_ifprintf( fp, indent, "entry_size[%"PRIu32"] = %"PRIu32"\n", i++, data->entry_size );
1548 return 0;
1551 static int isom_print_stco( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1553 if( !((isom_stco_t *)box)->list )
1554 return LSMASH_ERR_INVALID_DATA;
1555 isom_stco_t *stco = (isom_stco_t *)box;
1556 int indent = level;
1557 uint32_t i = 0;
1558 isom_print_box_common( fp, indent++, box, "Chunk Offset Box" );
1559 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", stco->list->entry_count );
1560 if( lsmash_check_box_type_identical( stco->type, ISOM_BOX_TYPE_STCO ) )
1562 for( lsmash_entry_t *entry = stco->list->head; entry; entry = entry->next )
1563 lsmash_ifprintf( fp, indent, "chunk_offset[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_stco_entry_t *)entry->data)->chunk_offset );
1565 else
1567 for( lsmash_entry_t *entry = stco->list->head; entry; entry = entry->next )
1568 lsmash_ifprintf( fp, indent, "chunk_offset[%"PRIu32"] = %"PRIu64"\n", i++, ((isom_co64_entry_t *)entry->data)->chunk_offset );
1570 return 0;
1573 static int isom_print_sgpd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1575 if( !((isom_sgpd_t *)box)->list )
1576 return LSMASH_ERR_INVALID_DATA;
1577 isom_sgpd_t *sgpd = (isom_sgpd_t *)box;
1578 int indent = level;
1579 uint32_t i = 0;
1580 isom_print_box_common( fp, indent++, box, "Sample Group Description Box" );
1581 lsmash_ifprintf( fp, indent, "grouping_type = %s\n", isom_4cc2str( sgpd->grouping_type ) );
1582 if( sgpd->version == 1 )
1584 lsmash_ifprintf( fp, indent, "default_length = %"PRIu32, sgpd->default_length );
1585 fprintf( fp, " %s\n", sgpd->default_length ? "(constant)" : "(variable)" );
1587 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", sgpd->list->entry_count );
1588 switch( sgpd->grouping_type )
1590 case ISOM_GROUP_TYPE_RAP :
1591 for( lsmash_entry_t *entry = sgpd->list->head; entry; entry = entry->next )
1593 if( sgpd->version == 1 && !sgpd->default_length )
1594 lsmash_ifprintf( fp, indent, "description_length[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_rap_entry_t *)entry->data)->description_length );
1595 else
1597 isom_rap_entry_t *rap = (isom_rap_entry_t *)entry->data;
1598 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1599 lsmash_ifprintf( fp, indent, "num_leading_samples_known = %"PRIu8"\n", rap->num_leading_samples_known );
1600 lsmash_ifprintf( fp, indent--, "num_leading_samples = %"PRIu8"\n", rap->num_leading_samples );
1603 break;
1604 case ISOM_GROUP_TYPE_ROLL :
1605 case ISOM_GROUP_TYPE_PROL :
1606 for( lsmash_entry_t *entry = sgpd->list->head; entry; entry = entry->next )
1608 if( sgpd->version == 1 && !sgpd->default_length )
1609 lsmash_ifprintf( fp, indent, "description_length[%"PRIu32"] = %"PRIu32"\n", i++, ((isom_roll_entry_t *)entry->data)->description_length );
1610 else
1611 lsmash_ifprintf( fp, indent, "roll_distance[%"PRIu32"] = %"PRId16"\n", i++, ((isom_roll_entry_t *)entry->data)->roll_distance );
1613 break;
1614 default :
1615 break;
1617 return 0;
1620 static int isom_print_sbgp( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1622 if( !((isom_sbgp_t *)box)->list )
1623 return LSMASH_ERR_INVALID_DATA;
1624 isom_sbgp_t *sbgp = (isom_sbgp_t *)box;
1625 int indent = level;
1626 int is_fragment = sbgp->parent && lsmash_check_box_type_identical( sbgp->parent->type, ISOM_BOX_TYPE_TRAF );
1627 uint32_t i = 0;
1628 isom_print_box_common( fp, indent++, box, "Sample to Group Box" );
1629 lsmash_ifprintf( fp, indent, "grouping_type = %s\n", isom_4cc2str( sbgp->grouping_type ) );
1630 if( sbgp->version == 1 )
1631 lsmash_ifprintf( fp, indent, "grouping_type_parameter = %s\n", isom_4cc2str( sbgp->grouping_type_parameter ) );
1632 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", sbgp->list->entry_count );
1633 for( lsmash_entry_t *entry = sbgp->list->head; entry; entry = entry->next )
1635 isom_group_assignment_entry_t *data = (isom_group_assignment_entry_t *)entry->data;
1636 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
1637 lsmash_ifprintf( fp, indent, "sample_count = %"PRIu32"\n", data->sample_count );
1638 lsmash_ifprintf( fp, indent--, "group_description_index = %"PRIu32, data->group_description_index );
1639 if( is_fragment && data->group_description_index >= 0x10000 )
1640 fprintf( fp, " (i.e. %"PRIu32" for this fragment-local group)", data->group_description_index - 0x10000 );
1641 if( !data->group_description_index )
1642 fprintf( fp, " (not in this grouping type)\n" );
1643 else
1644 fprintf( fp, "\n" );
1646 return 0;
1649 static int isom_print_udta( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1651 return isom_print_simple( fp, box, level, "User Data Box" );
1654 static int isom_print_chpl( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1656 isom_chpl_t *chpl = (isom_chpl_t *)box;
1657 uint32_t timescale;
1658 if( !chpl->version )
1660 if( !file->moov || !file->moov->mvhd )
1661 return LSMASH_ERR_INVALID_DATA;
1662 timescale = file->moov->mvhd->timescale;
1664 else
1665 timescale = 10000000;
1666 int indent = level;
1667 uint32_t i = 0;
1668 isom_print_box_common( fp, indent++, box, "Chapter List Box" );
1669 if( chpl->version == 1 )
1671 lsmash_ifprintf( fp, indent, "unknown = 0x%02"PRIx8"\n", chpl->unknown );
1672 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", chpl->list->entry_count );
1674 else
1675 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu8"\n", (uint8_t)chpl->list->entry_count );
1676 for( lsmash_entry_t *entry = chpl->list->head; entry; entry = entry->next )
1678 isom_chpl_entry_t *data = (isom_chpl_entry_t *)entry->data;
1679 int64_t start_time = data->start_time / timescale;
1680 int hh = start_time / 3600;
1681 int mm = (start_time / 60) % 60;
1682 int ss = start_time % 60;
1683 int ms = ((data->start_time / (double)timescale) - hh * 3600 - mm * 60 - ss) * 1e3 + 0.5;
1684 int with_bom = 0;
1685 if( !memcmp( data->chapter_name, "\xEF\xBB\xBF", 3 ) ) /* detect BOM */
1687 data->chapter_name += 3;
1688 with_bom = 1;
1690 lsmash_ifprintf( fp, indent++, "chapter[%"PRIu32"]\n", i++ );
1691 lsmash_ifprintf( fp, indent, "start_time = %02d:%02d:%02d.%03d\n", hh, mm, ss, ms );
1692 lsmash_ifprintf( fp, indent--, with_bom ? "chapter_name = %s ( it has BOM in it )\n" : "chapter_name = %s\n", data->chapter_name );
1694 return 0;
1697 static int isom_print_meta( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1699 int indent = level;
1700 if( !(box->manager & LSMASH_QTFF_BASE) )
1702 isom_print_basebox_common( fp, indent++, box, "Meta Box" );
1703 lsmash_ifprintf( fp, indent, "version = %"PRIu8"\n", box->version );
1704 lsmash_ifprintf( fp, indent, "flags = 0x%06"PRIx32"\n", box->flags & 0x00ffffff );
1706 else
1707 isom_print_basebox_common( fp, indent, box, "Metadata Box" );
1708 return 0;
1711 static int isom_print_keys( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1713 if( !((isom_keys_t *)box)->list )
1714 return LSMASH_ERR_INVALID_DATA;
1715 isom_keys_t *keys = (isom_keys_t *)box;
1716 int indent = level;
1717 uint32_t i = 1;
1718 isom_print_box_common( fp, indent++, box, "Metadata Item Keys Box" );
1719 lsmash_ifprintf( fp, indent, "entry_count = %"PRIu32"\n", keys->list->entry_count );
1720 for( lsmash_entry_t *entry = keys->list->head; entry; entry = entry->next )
1722 isom_keys_entry_t *data = (isom_keys_entry_t *)entry->data;
1723 lsmash_ifprintf( fp, indent++, "[key %"PRIu32"]\n", i++ );
1724 lsmash_ifprintf( fp, indent, "key_size = %"PRIu32"\n", data->key_size );
1725 lsmash_ifprintf( fp, indent, "key_namespace = %s\n", isom_4cc2str( data->key_namespace ) );
1726 uint32_t value_length = data->key_size - 8;
1727 char *str = lsmash_malloc( value_length + 1 );
1728 if( !str )
1729 return LSMASH_ERR_MEMORY_ALLOC;
1730 memcpy( str, data->key_value, value_length );
1731 str[value_length] = 0;
1732 lsmash_ifprintf( fp, indent--, "key_value = %s\n", str );
1733 lsmash_free( str );
1735 return 0;
1738 static int isom_print_ilst( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1740 return isom_print_simple( fp, box, level, "Metadata Item List Box" );
1743 static int isom_print_metaitem( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1745 isom_metaitem_t *metaitem = (isom_metaitem_t *)box;
1746 if( box->parent && box->parent->parent && (box->parent->parent->manager & LSMASH_QTFF_BASE) )
1748 int indent = level;
1749 lsmash_ifprintf( fp, indent++, "[key_index %"PRIu32": Metadata Item Box]\n", box->type.fourcc );
1750 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
1751 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
1752 return 0;
1754 static const struct
1756 lsmash_itunes_metadata_item item;
1757 char *name;
1758 } metaitem_table[] =
1760 { ITUNES_METADATA_ITEM_ALBUM_NAME, "Album Name" },
1761 { ITUNES_METADATA_ITEM_ARTIST, "Artist" },
1762 { ITUNES_METADATA_ITEM_USER_COMMENT, "User Comment" },
1763 { ITUNES_METADATA_ITEM_RELEASE_DATE, "Release Date" },
1764 { ITUNES_METADATA_ITEM_ENCODED_BY, "Encoded By" },
1765 { ITUNES_METADATA_ITEM_USER_GENRE, "User Genre" },
1766 { ITUNES_METADATA_ITEM_GROUPING, "Grouping" },
1767 { ITUNES_METADATA_ITEM_LYRICS, "Lyrics" },
1768 { ITUNES_METADATA_ITEM_TITLE, "Title" },
1769 { ITUNES_METADATA_ITEM_ENCODING_TOOL, "Encoding Tool" },
1770 { ITUNES_METADATA_ITEM_COMPOSER, "Composer" },
1771 { ITUNES_METADATA_ITEM_ALBUM_ARTIST, "Album Artist" },
1772 { ITUNES_METADATA_ITEM_PODCAST_CATEGORY, "Podcast Category" },
1773 { ITUNES_METADATA_ITEM_COVER_ART, "Cover Art" },
1774 { ITUNES_METADATA_ITEM_DISC_COMPILATION, "Disc Compilation" },
1775 { ITUNES_METADATA_ITEM_COPYRIGHT, "Copyright" },
1776 { ITUNES_METADATA_ITEM_DESCRIPTION, "Description" },
1777 { ITUNES_METADATA_ITEM_DISC_NUMBER, "Disc Number" },
1778 { ITUNES_METADATA_ITEM_EPISODE_GLOBAL_ID, "Episode Global Unique ID" },
1779 { ITUNES_METADATA_ITEM_PREDEFINED_GENRE, "Pre-defined Genre" },
1780 { ITUNES_METADATA_ITEM_GROUPING_DRAFT, "Grouping (Overall work like TIT1 in ID3)" },
1781 { ITUNES_METADATA_ITEM_HIGH_DEFINITION_VIDEO, "High Definition Video" },
1782 { ITUNES_METADATA_ITEM_PODCAST_KEYWORD, "Podcast Keyword" },
1783 { ITUNES_METADATA_ITEM_LONG_DESCRIPTION, "Long Description" },
1784 { ITUNES_METADATA_ITEM_PODCAST, "Podcast" },
1785 { ITUNES_METADATA_ITEM_GAPLESS_PLAYBACK, "Gapless Playback" },
1786 { ITUNES_METADATA_ITEM_PURCHASE_DATE, "Purchase Date" },
1787 { ITUNES_METADATA_ITEM_PODCAST_URL, "Podcast URL" },
1788 { ITUNES_METADATA_ITEM_CONTENT_RATING, "Content Rating" },
1789 { ITUNES_METADATA_ITEM_MEDIA_TYPE, "Media Type" },
1790 { ITUNES_METADATA_ITEM_BEATS_PER_MINUTE, "Beats Per Minute" },
1791 { ITUNES_METADATA_ITEM_TRACK_NUMBER, "Track Number" },
1792 { ITUNES_METADATA_ITEM_TV_EPISODE_ID, "TV Episode ID" },
1793 { ITUNES_METADATA_ITEM_TV_EPISODE, "TV Episode" },
1794 { ITUNES_METADATA_ITEM_TV_NETWORK, "TV Network" },
1795 { ITUNES_METADATA_ITEM_TV_SHOW_NAME, "TV Show Name" },
1796 { ITUNES_METADATA_ITEM_TV_SEASON, "TV Season" },
1797 { ITUNES_METADATA_ITEM_ITUNES_PURCHASE_ACCOUNT_ID, "iTunes Account Used for Purchase" },
1798 { ITUNES_METADATA_ITEM_ITUNES_ACCOUNT_TYPE, "iTunes Account Type" },
1799 { ITUNES_METADATA_ITEM_ITUNES_ARTIST_ID, "iTunes Artist ID" },
1800 { ITUNES_METADATA_ITEM_ITUNES_COMPOSER_ID, "iTunes Composer ID" },
1801 { ITUNES_METADATA_ITEM_ITUNES_CATALOG_ID, "iTunes Catalog ID" },
1802 { ITUNES_METADATA_ITEM_ITUNES_TV_GENRE_ID, "iTunes TV Genre ID" },
1803 { ITUNES_METADATA_ITEM_ITUNES_PLAYLIST_ID, "iTunes Playlist ID" },
1804 { ITUNES_METADATA_ITEM_ITUNES_COUNTRY_CODE, "iTunes Country Code" },
1805 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM, "Sort Album" },
1806 { ITUNES_METADATA_ITEM_ITUNES_SORT_ARTIST, "Sort Artist" },
1807 { ITUNES_METADATA_ITEM_ITUNES_SORT_ALBUM_ARTIST, "Sort Album Artist" },
1808 { ITUNES_METADATA_ITEM_ITUNES_SORT_COMPOSER, "Sort Composer" },
1809 { ITUNES_METADATA_ITEM_ITUNES_SORT_NAME, "Sort Name" },
1810 { ITUNES_METADATA_ITEM_ITUNES_SORT_SHOW, "Sort Show" },
1811 { ITUNES_METADATA_ITEM_CUSTOM, "Custom Metadata Item" },
1812 { 0, NULL }
1814 char *name = NULL;
1815 int i;
1816 for( i = 0; metaitem_table[i].name; i++ )
1817 if( metaitem->type.fourcc == metaitem_table[i].item )
1819 name = metaitem_table[i].name;
1820 break;
1822 if( !name )
1823 name = "Unknown";
1824 uint32_t name_length = strlen( name );
1825 uint32_t display_name_length = name_length + 20;
1826 char *display_name = lsmash_malloc( display_name_length + 1 );
1827 if( !display_name )
1828 return LSMASH_ERR_MEMORY_ALLOC;
1829 memcpy( display_name, "Metadata Item Box (", 19 );
1830 memcpy( display_name + 19, name, name_length );
1831 display_name[display_name_length - 1] = ')';
1832 display_name[display_name_length] = 0;
1833 int ret = isom_print_simple( fp, box, level, display_name );
1834 lsmash_free( display_name );
1835 return ret;
1838 static int isom_print_name( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1840 isom_name_t *name = (isom_name_t *)box;
1841 int indent = level;
1842 isom_print_box_common( fp, indent++, box, "Name Box" );
1843 char *str = lsmash_malloc( name->name_length + 1 );
1844 if( !str )
1845 return LSMASH_ERR_MEMORY_ALLOC;
1846 memcpy( str, name->name, name->name_length );
1847 str[name->name_length] = 0;
1848 lsmash_ifprintf( fp, indent, "name = %s\n", str );
1849 lsmash_free( str );
1850 return 0;
1853 static int isom_print_mean( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1855 isom_mean_t *mean = (isom_mean_t *)box;
1856 int indent = level;
1857 isom_print_box_common( fp, indent++, box, "Mean Box" );
1858 char *str = lsmash_malloc( mean->meaning_string_length + 1 );
1859 if( !str )
1860 return LSMASH_ERR_MEMORY_ALLOC;
1861 memcpy( str, mean->meaning_string, mean->meaning_string_length );
1862 str[mean->meaning_string_length] = 0;
1863 lsmash_ifprintf( fp, indent, "meaning_string = %s\n", str );
1864 lsmash_free( str );
1865 return 0;
1868 static int isom_print_data( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1870 isom_data_t *data = (isom_data_t *)box;
1871 int indent = level;
1872 isom_print_box_common( fp, indent++, box, "Data Box" );
1873 if( box->parent && box->parent->parent && box->parent->parent->parent
1874 && (box->parent->parent->parent->manager & LSMASH_QTFF_BASE) )
1876 uint32_t type_set_indicator = data->reserved >> 8;
1877 uint32_t well_known_type = ((data->reserved << 16) | (data->type_set_identifier << 8) | data->type_code) & 0xffffff;
1878 char *well_known_type_name = "Unknown";
1879 static const struct
1881 uint32_t type;
1882 char *name;
1883 } well_known_type_table[] =
1885 { 0, "reserved" },
1886 { 1, "UTF-8" },
1887 { 2, "UTF-16 BE" },
1888 { 3, "S/JIS" },
1889 { 4, "UTF-8 sort" },
1890 { 5, "UTF-16 sort" },
1891 { 13, "JPEG in a JFIF wrapper" },
1892 { 14, "PNG in a PNG wrapper" },
1893 { 21, "BE Signed Integer" },
1894 { 22, "BE Unsigned Integer" },
1895 { 23, "BE Float32" },
1896 { 24, "BE Float64" },
1897 { 27, "BMP (Windows bitmap format graphics)" },
1898 { 28, "QuickTime Metadata box" },
1899 { UINT32_MAX }
1901 int table_index;
1902 for( table_index = 0; well_known_type_table[table_index].type != UINT32_MAX; table_index++ )
1903 if( well_known_type == well_known_type_table[table_index].type )
1905 well_known_type_name = well_known_type_table[table_index].name;
1906 break;
1908 lsmash_ifprintf( fp, indent, "type_set_indicator = %"PRIu8"\n", type_set_indicator );
1909 lsmash_ifprintf( fp, indent, "well_known_type = %"PRIu32" (%s)\n", well_known_type, well_known_type_name );
1910 lsmash_ifprintf( fp, indent, "locale_indicator = %"PRIu32"\n", data->the_locale );
1911 if( data->value_length == 0 )
1913 lsmash_ifprintf( fp, indent, "value = (null)\n" );
1914 return 0;
1916 if( well_known_type == 1 )
1918 /* UTF-8 without any count or null terminator */
1919 char *str = lsmash_malloc( data->value_length + 1 );
1920 if( !str )
1921 return LSMASH_ERR_MEMORY_ALLOC;
1922 memcpy( str, data->value, data->value_length );
1923 str[data->value_length] = 0;
1924 lsmash_ifprintf( fp, indent, "value = %s\n", str );
1925 lsmash_free( str );
1927 else if( well_known_type == 13 || well_known_type == 14 || well_known_type == 27 )
1928 lsmash_ifprintf( fp, indent, "value = (binary data)\n" );
1929 else if( well_known_type == 21 && data->value_length <= 4 )
1930 /* a big-endian signed integer in 1,2,3 or 4 bytes */
1931 goto show_in_signed_integer;
1932 else if( well_known_type == 22 && data->value_length <= 4 )
1934 /* a big-endian unsigned integer in 1,2,3 or 4 bytes */
1935 uint32_t integer = data->value[0];
1936 for( uint32_t i = 1; i < data->value_length; i++ )
1937 integer = (integer << 8) | data->value[i];
1938 lsmash_ifprintf( fp, indent, "value = %"PRIu32"\n", integer );
1940 else if( well_known_type == 23 && data->value_length == 4 )
1942 /* a big-endian 32-bit floating point value (IEEE754) */
1943 uint32_t float32 = LSMASH_GET_BE32( data->value );
1944 lsmash_ifprintf( fp, indent, "value = %f\n", lsmash_int2float32( float32 ) );
1946 else if( well_known_type == 24 && data->value_length == 8 )
1948 /* a big-endian 64-bit floating point value (IEEE754) */
1949 uint64_t float64 = LSMASH_GET_BE64( data->value );
1950 lsmash_ifprintf( fp, indent, "value = %lf\n", lsmash_int2float64( float64 ) );
1952 else
1953 goto show_in_binary;
1955 else
1957 char *basic_data_type_name = "Unknown";
1958 static const struct
1960 uint32_t type;
1961 char *name;
1962 } basic_data_type_table[] =
1964 { 0, "Implicit" },
1965 { 1, "UTF-8" },
1966 { 2, "UTF-16 BE" },
1967 { 3, "S/JIS" },
1968 { 6, "HTML" },
1969 { 7, "XML" },
1970 { 8, "UUID" },
1971 { 9, "ISRC" },
1972 { 10, "MI3P" },
1973 { 12, "GIF" },
1974 { 13, "JPEG in a JFIF wrapper" },
1975 { 14, "PNG in a PNG wrapper" },
1976 { 15, "URL" },
1977 { 16, "duration" },
1978 { 17, "date/time" },
1979 { 18, "Genres" },
1980 { 21, "BE Signed Integer" },
1981 { 24, "RIAA-PA (RIAA Parental advisory)" },
1982 { 25, "UPC (Universal Product Code)" },
1983 { 27, "BMP (Windows bitmap format graphics)" },
1984 { UINT32_MAX }
1986 int table_index;
1987 for( table_index = 0; basic_data_type_table[table_index].type != UINT32_MAX; table_index++ )
1988 if( data->type_code == basic_data_type_table[table_index].type )
1990 basic_data_type_name = basic_data_type_table[table_index].name;
1991 break;
1993 lsmash_ifprintf( fp, indent, "reserved = %"PRIu16"\n", data->reserved );
1994 lsmash_ifprintf( fp, indent, "type_set_identifier = %"PRIu8"%s\n",
1995 data->type_set_identifier,
1996 data->type_set_identifier ? "" : " (basic type set)" );
1997 lsmash_ifprintf( fp, indent, "type_code = %"PRIu8" (%s)\n", data->type_code, basic_data_type_name );
1998 lsmash_ifprintf( fp, indent, "the_locale = %"PRIu32"\n", data->the_locale );
1999 if( data->value_length == 0 )
2001 lsmash_ifprintf( fp, indent, "value = (null)\n" );
2002 return 0;
2004 if( data->type_code == 6 || data->type_code == 7
2005 || data->type_code == 12 || data->type_code == 13
2006 || data->type_code == 14 || data->type_code == 27 )
2007 lsmash_ifprintf( fp, indent, "value = (binary data)\n" );
2008 else if( data->type_code == 8 && data->value_length == 16 )
2009 /* UUID */
2010 lsmash_ifprintf( fp, indent, "value = 0x%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"-%04"PRIx16"0x%08"PRIx32"\n",
2011 LSMASH_GET_BE32( &data->value[ 0] ),
2012 LSMASH_GET_BE16( &data->value[ 4] ),
2013 LSMASH_GET_BE16( &data->value[ 6] ),
2014 LSMASH_GET_BE16( &data->value[ 8] ),
2015 LSMASH_GET_BE16( &data->value[10] ),
2016 LSMASH_GET_BE32( &data->value[12] ) );
2017 else if( data->type_code == 16 && data->value_length == 4 )
2019 /* duration in milliseconds */
2020 uint32_t duration = LSMASH_GET_BE32( data->value );
2021 lsmash_ifprintf( fp, indent, "value = %"PRIu32" milliseconds\n", duration );
2023 else if( data->type_code == 17 && (data->value_length == 4 || data->value_length == 8) )
2025 /* UTC, counting seconds since midnight on 1 January, 1904 */
2026 uint64_t mp4time = data->value_length == 8
2027 ? LSMASH_GET_BE64( data->value )
2028 : LSMASH_GET_BE32( data->value );
2029 isom_mp4time2utc( mp4time );
2031 else if( data->type_code == 21 && data->value_length <= 8 )
2032 /* a big-endian signed integer in 1,2,3,4 or 8 bytes */
2033 goto show_in_signed_integer;
2034 else if( data->type_code == 24 )
2036 /* RIAA-PA (RIAA Parental advisory) 8-bit integer */
2037 lsmash_ifprintf( fp, indent, "value = %"PRIu8, data->value[0] );
2038 if( data->value[0] == (uint8_t)-1 )
2039 fprintf( fp, " (no)" );
2040 else if( data->value[0] == 1 )
2041 fprintf( fp, " (yes)" );
2042 else if( data->value[0] == 0 )
2043 fprintf( fp, " (unspecified)" );
2044 fprintf( fp, "\n" );
2046 else if( data->type_code == 1 || data->type_code == 2 || data->type_code == 3
2047 || data->type_code == 9 || data->type_code == 10 || data->type_code == 15
2048 || data->type_code == 25 )
2050 /* String */
2051 char *str = lsmash_malloc( data->value_length + 1 );
2052 if( !str )
2053 return LSMASH_ERR_MEMORY_ALLOC;
2054 memcpy( str, data->value, data->value_length );
2055 str[data->value_length] = 0;
2056 lsmash_ifprintf( fp, indent, "value = %s\n", str );
2057 lsmash_free( str );
2059 else
2060 goto show_in_binary;
2062 return 0;
2063 show_in_signed_integer:;
2064 uint64_t integer = data->value[0];
2065 uint64_t max_value = 0xff;
2066 for( uint32_t i = 1; i < data->value_length; i++ )
2068 integer = (integer << 8) | data->value[i];
2069 max_value = (max_value << 8) | 0xff;
2071 lsmash_ifprintf( fp, indent, "value = %"PRId64"\n", (int64_t)(integer | (integer > (max_value >> 1) ? ~max_value : 0)) );
2072 return 0;
2073 show_in_binary:
2074 lsmash_ifprintf( fp, indent, "value = " );
2075 if( data->value_length )
2077 fprintf( fp, "0x" );
2078 for( uint32_t i = 0; i < data->value_length; i++ )
2079 fprintf( fp, "%02"PRIx8, data->value[i] );
2081 fprintf( fp, "\n" );
2082 return 0;
2085 static int isom_print_WLOC( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2087 isom_WLOC_t *WLOC = (isom_WLOC_t *)box;
2088 int indent = level;
2089 isom_print_box_common( fp, indent++, box, "Window Location Box" );
2090 lsmash_ifprintf( fp, indent, "x = %"PRIu16"\n", WLOC->x );
2091 lsmash_ifprintf( fp, indent, "y = %"PRIu16"\n", WLOC->y );
2092 return 0;
2095 static int isom_print_LOOP( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2097 isom_LOOP_t *LOOP = (isom_LOOP_t *)box;
2098 int indent = level;
2099 isom_print_box_common( fp, indent++, box, "Looping Box" );
2100 lsmash_ifprintf( fp, indent, "looping_mode = %"PRIu32, LOOP->looping_mode );
2101 switch( LOOP->looping_mode )
2103 case 0 :
2104 fprintf( fp, " (none)\n" );
2105 break;
2106 case 1 :
2107 fprintf( fp, " (looping)\n" );
2108 break;
2109 case 2 :
2110 fprintf( fp, " (palindromic looping)\n" );
2111 break;
2112 default :
2113 fprintf( fp, "\n" );
2114 break;
2116 return 0;
2119 static int isom_print_SelO( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2121 isom_SelO_t *SelO = (isom_SelO_t *)box;
2122 int indent = level;
2123 isom_print_box_common( fp, indent++, box, "Play Selection Only Box" );
2124 lsmash_ifprintf( fp, indent, "selection_only = %"PRIu8"\n", SelO->selection_only );
2125 return 0;
2128 static int isom_print_AllF( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2130 isom_AllF_t *AllF = (isom_AllF_t *)box;
2131 int indent = level;
2132 isom_print_box_common( fp, indent++, box, "Play All Frames Box" );
2133 lsmash_ifprintf( fp, indent, "play_all_frames = %"PRIu8"\n", AllF->play_all_frames );
2134 return 0;
2137 static int isom_print_cprt( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2139 isom_cprt_t *cprt = (isom_cprt_t *)box;
2140 int indent = level;
2141 char *str = lsmash_malloc( cprt->notice_length + 1 );
2142 if( !str )
2143 return LSMASH_ERR_MEMORY_ALLOC;
2144 memcpy( str, cprt->notice, cprt->notice_length );
2145 str[cprt->notice_length] = 0;
2146 isom_print_box_common( fp, indent++, box, "Copyright Box" );
2147 lsmash_ifprintf( fp, indent, "language = %s\n", isom_unpack_iso_language( cprt->language ) );
2148 lsmash_ifprintf( fp, indent, "notice = %s\n", str );
2149 lsmash_free( str );
2150 return 0;
2153 static int isom_print_mvex( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2155 return isom_print_simple( fp, box, level, "Movie Extends Box" );
2158 static int isom_print_mehd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2160 isom_mehd_t *mehd = (isom_mehd_t *)box;
2161 int indent = level;
2162 isom_print_box_common( fp, indent++, box, "Movie Extends Header Box" );
2163 if( file->moov && file->moov->mvhd )
2164 isom_ifprintf_duration( fp, indent, "fragment_duration", mehd->fragment_duration, file->moov->mvhd->timescale );
2165 else
2166 isom_ifprintf_duration( fp, indent, "fragment_duration", mehd->fragment_duration, 0 );
2167 return 0;
2170 static int isom_print_trex( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2172 isom_trex_t *trex = (isom_trex_t *)box;
2173 int indent = level;
2174 isom_print_box_common( fp, indent++, box, "Track Extends Box" );
2175 lsmash_ifprintf( fp, indent, "track_ID = %"PRIu32"\n", trex->track_ID );
2176 lsmash_ifprintf( fp, indent, "default_sample_description_index = %"PRIu32"\n", trex->default_sample_description_index );
2177 lsmash_ifprintf( fp, indent, "default_sample_duration = %"PRIu32"\n", trex->default_sample_duration );
2178 lsmash_ifprintf( fp, indent, "default_sample_size = %"PRIu32"\n", trex->default_sample_size );
2179 isom_ifprintf_sample_flags( fp, indent, "default_sample_flags", &trex->default_sample_flags );
2180 return 0;
2183 static int isom_print_moof( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2185 return isom_print_simple( fp, box, level, "Movie Fragment Box" );
2188 static int isom_print_mfhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2190 isom_mfhd_t *mfhd = (isom_mfhd_t *)box;
2191 int indent = level;
2192 isom_print_box_common( fp, indent++, box, "Movie Fragment Header Box" );
2193 lsmash_ifprintf( fp, indent, "sequence_number = %"PRIu32"\n", mfhd->sequence_number );
2194 return 0;
2197 static int isom_print_traf( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2199 return isom_print_simple( fp, box, level, "Track Fragment Box" );
2202 static int isom_print_tfhd( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2204 isom_tfhd_t *tfhd = (isom_tfhd_t *)box;
2205 int indent = level;
2206 isom_print_box_common( fp, indent++, box, "Track Fragment Header Box" );
2207 ++indent;
2208 if( tfhd->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) lsmash_ifprintf( fp, indent, "base-data-offset-present\n" );
2209 if( tfhd->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) lsmash_ifprintf( fp, indent, "sample-description-index-present\n" );
2210 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) lsmash_ifprintf( fp, indent, "default-sample-duration-present\n" );
2211 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) lsmash_ifprintf( fp, indent, "default-sample-size-present\n" );
2212 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) lsmash_ifprintf( fp, indent, "default-sample-flags-present\n" );
2213 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_BASE_IS_MOOF ) lsmash_ifprintf( fp, indent, "default-base-is-moof\n" );
2214 lsmash_ifprintf( fp, --indent, "track_ID = %"PRIu32"\n", tfhd->track_ID );
2215 if( tfhd->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT )
2216 lsmash_ifprintf( fp, indent, "base_data_offset = %"PRIu64"\n", tfhd->base_data_offset );
2217 if( tfhd->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT )
2218 lsmash_ifprintf( fp, indent, "sample_description_index = %"PRIu32"\n", tfhd->sample_description_index );
2219 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT )
2220 lsmash_ifprintf( fp, indent, "default_sample_duration = %"PRIu32"\n", tfhd->default_sample_duration );
2221 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT )
2222 lsmash_ifprintf( fp, indent, "default_sample_size = %"PRIu32"\n", tfhd->default_sample_size );
2223 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT )
2224 isom_ifprintf_sample_flags( fp, indent, "default_sample_flags", &tfhd->default_sample_flags );
2225 return 0;
2228 static int isom_print_tfdt( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2230 isom_tfdt_t *tfdt = (isom_tfdt_t *)box;
2231 int indent = level;
2232 isom_print_box_common( fp, indent++, box, "Track Fragment Base Media Decode Time Box" );
2233 lsmash_ifprintf( fp, indent, "baseMediaDecodeTime = %"PRIu64"\n", tfdt->baseMediaDecodeTime );
2234 return 0;
2237 static int isom_print_trun( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2239 isom_trun_t *trun = (isom_trun_t *)box;
2240 int indent = level;
2241 isom_print_box_common( fp, indent++, box, "Track Fragment Run Box" );
2242 ++indent;
2243 if( trun->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) lsmash_ifprintf( fp, indent, "data-offset-present\n" );
2244 if( trun->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) lsmash_ifprintf( fp, indent, "first-sample-flags-present\n" );
2245 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) lsmash_ifprintf( fp, indent, "sample-duration-present\n" );
2246 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) lsmash_ifprintf( fp, indent, "sample-size-present\n" );
2247 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) lsmash_ifprintf( fp, indent, "sample-flags-present\n" );
2248 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) lsmash_ifprintf( fp, indent, "sample-composition-time-offsets-present\n" );
2249 lsmash_ifprintf( fp, --indent, "sample_count = %"PRIu32"\n", trun->sample_count );
2250 if( trun->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT )
2251 lsmash_ifprintf( fp, indent, "data_offset = %"PRId32"\n", trun->data_offset );
2252 if( trun->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT )
2253 isom_ifprintf_sample_flags( fp, indent, "first_sample_flags", &trun->first_sample_flags );
2254 if( trun->optional )
2256 uint32_t i = 0;
2257 for( lsmash_entry_t *entry = trun->optional->head; entry; entry = entry->next )
2259 isom_trun_optional_row_t *row = (isom_trun_optional_row_t *)entry->data;
2260 lsmash_ifprintf( fp, indent++, "sample[%"PRIu32"]\n", i++ );
2261 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT )
2262 lsmash_ifprintf( fp, indent, "sample_duration = %"PRIu32"\n", row->sample_duration );
2263 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT )
2264 lsmash_ifprintf( fp, indent, "sample_size = %"PRIu32"\n", row->sample_size );
2265 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT )
2266 isom_ifprintf_sample_flags( fp, indent, "sample_flags", &row->sample_flags );
2267 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT )
2269 if( trun->version == 0 )
2270 lsmash_ifprintf( fp, indent, "sample_composition_time_offset = %"PRIu32"\n",
2271 row->sample_composition_time_offset );
2272 else
2273 lsmash_ifprintf( fp, indent, "sample_composition_time_offset = %"PRId32"\n",
2274 (union {uint32_t ui; int32_t si;}){ row->sample_composition_time_offset }.si );
2276 --indent;
2279 return 0;
2282 static int isom_print_free( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2284 return isom_print_simple( fp, box, level, "Free Space Box" );
2287 static int isom_print_mdat( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2289 return isom_print_simple( fp, box, level, "Media Data Box" );
2292 static int isom_print_mfra( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2294 return isom_print_simple( fp, box, level, "Movie Fragment Random Access Box" );
2297 static int isom_print_tfra( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2299 isom_tfra_t *tfra = (isom_tfra_t *)box;
2300 int indent = level;
2301 isom_print_box_common( fp, indent++, box, "Track Fragment Random Access Box" );
2302 lsmash_ifprintf( fp, indent, "track_ID = %"PRIu32"\n", tfra->track_ID );
2303 lsmash_ifprintf( fp, indent, "reserved = 0x%08"PRIx32"\n", tfra->reserved );
2304 lsmash_ifprintf( fp, indent, "length_size_of_traf_num = %"PRIu8"\n", tfra->length_size_of_traf_num );
2305 lsmash_ifprintf( fp, indent, "length_size_of_trun_num = %"PRIu8"\n", tfra->length_size_of_trun_num );
2306 lsmash_ifprintf( fp, indent, "length_size_of_sample_num = %"PRIu8"\n", tfra->length_size_of_sample_num );
2307 lsmash_ifprintf( fp, indent, "number_of_entry = %"PRIu32"\n", tfra->number_of_entry );
2308 if( tfra->list )
2310 uint32_t i = 0;
2311 for( lsmash_entry_t *entry = tfra->list->head; entry; entry = entry->next )
2313 isom_tfra_location_time_entry_t *data = (isom_tfra_location_time_entry_t *)entry->data;
2314 lsmash_ifprintf( fp, indent++, "entry[%"PRIu32"]\n", i++ );
2315 lsmash_ifprintf( fp, indent, "time = %"PRIu64"\n", data->time );
2316 lsmash_ifprintf( fp, indent, "moof_offset = %"PRIu64"\n", data->moof_offset );
2317 lsmash_ifprintf( fp, indent, "traf_number = %"PRIu32"\n", data->traf_number );
2318 lsmash_ifprintf( fp, indent, "trun_number = %"PRIu32"\n", data->trun_number );
2319 lsmash_ifprintf( fp, indent, "sample_number = %"PRIu32"\n", data->sample_number );
2320 --indent;
2323 return 0;
2326 static int isom_print_mfro( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
2328 isom_mfro_t *mfro = (isom_mfro_t *)box;
2329 int indent = level;
2330 isom_print_box_common( fp, indent++, box, "Movie Fragment Random Access Offset Box" );
2331 lsmash_ifprintf( fp, indent, "size = %"PRIu32"\n", mfro->length );
2332 return 0;
2335 int lsmash_print_movie( lsmash_root_t *root, const char *filename )
2337 if( !root )
2338 return LSMASH_ERR_FUNCTION_PARAM;
2339 lsmash_file_t *file = root->file;
2340 if( !file
2341 || !file->print
2342 || !(file->flags & LSMASH_FILE_MODE_DUMP) )
2343 return LSMASH_ERR_FUNCTION_PARAM;
2344 FILE *destination;
2345 if( !strcmp( filename, "-" ) )
2346 destination = stdout;
2347 else
2349 destination = lsmash_fopen( filename, "wb" );
2350 if( !destination )
2351 return LSMASH_ERR_NAMELESS;
2353 fprintf( destination, "[File]\n" );
2354 fprintf( destination, " size = %"PRIu64"\n", file->size );
2355 for( lsmash_entry_t *entry = file->print->head; entry; entry = entry->next )
2357 isom_print_entry_t *data = (isom_print_entry_t *)entry->data;
2358 if( !data || !data->box )
2360 fclose( destination );
2361 return LSMASH_ERR_NAMELESS;
2363 int ret = data->func( destination, file, data->box, data->level );
2364 if( ret < 0 )
2366 fclose( destination );
2367 return ret;
2370 fclose( destination );
2371 return 0;
2374 static isom_print_box_t isom_select_print_func( isom_box_t *box )
2376 if( box->manager & LSMASH_UNKNOWN_BOX )
2377 return isom_print_unknown;
2378 if( box->parent )
2380 isom_box_t *parent = box->parent;
2381 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2383 /* OK, this box is a sample entry.
2384 * Here, determine the suitable sample entry printer by media type if possible. */
2385 if( isom_check_media_hdlr_from_stsd( (isom_stsd_t *)parent ) )
2387 lsmash_media_type media_type = isom_get_media_type_from_stsd( (isom_stsd_t *)parent );
2388 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
2389 return isom_print_visual_description;
2390 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
2391 return isom_print_audio_description;
2392 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
2394 if( lsmash_check_box_type_identical( box->type, QT_CODEC_TYPE_TEXT_TEXT ) )
2395 return isom_print_text_description;
2396 else if( lsmash_check_box_type_identical( box->type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
2397 return isom_print_tx3g_description;
2399 else if( lsmash_check_box_type_identical( box->type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
2400 return isom_print_mp4s_description;
2402 return isom_print_unknown;
2404 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2406 if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_FRMA ) )
2407 return isom_print_frma;
2408 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ENDA ) )
2409 return isom_print_enda;
2410 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_TERMINATOR ) )
2411 return isom_print_terminator;
2412 else
2413 return isom_print_sample_description_extesion;
2415 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2416 return isom_print_track_reference_type;
2417 if( parent->parent )
2419 if( lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2420 return isom_print_sample_description_extesion;
2421 else if( lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_ILST )
2422 || lsmash_check_box_type_identical( parent->parent->type, QT_BOX_TYPE_ILST ) )
2424 if( parent->type.fourcc == LSMASH_4CC( '-', '-', '-', '-' ) )
2426 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_MEAN ) )
2427 return isom_print_mean;
2428 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_NAME ) )
2429 return isom_print_name;
2431 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_DATA ) )
2432 return isom_print_data;
2435 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2436 || lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2437 return isom_print_metaitem;
2439 static struct print_box_table_tag
2441 lsmash_box_type_t type;
2442 isom_print_box_t func;
2443 } print_box_table[128] = { { LSMASH_BOX_TYPE_INITIALIZER, NULL } };
2444 if( !print_box_table[0].func )
2446 /* Initialize the table. */
2447 int i = 0;
2448 #define ADD_PRINT_BOX_TABLE_ELEMENT( type, func ) print_box_table[i++] = (struct print_box_table_tag){ type, func }
2449 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, isom_print_ftyp );
2450 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, isom_print_styp );
2451 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, isom_print_sidx );
2452 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, isom_print_moov );
2453 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, isom_print_mvhd );
2454 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, isom_print_iods );
2455 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, isom_print_ctab );
2456 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, isom_print_trak );
2457 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, isom_print_tkhd );
2458 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, isom_print_tapt );
2459 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, isom_print_clef );
2460 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_PROF, isom_print_prof );
2461 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, isom_print_enof );
2462 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, isom_print_edts );
2463 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, isom_print_elst );
2464 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, isom_print_tref );
2465 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, isom_print_mdia );
2466 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, isom_print_mdhd );
2467 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, isom_print_hdlr );
2468 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, isom_print_minf );
2469 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, isom_print_vmhd );
2470 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, isom_print_smhd );
2471 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, isom_print_hmhd );
2472 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, isom_print_nmhd );
2473 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, isom_print_gmhd );
2474 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, isom_print_gmin );
2475 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, isom_print_text );
2476 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, isom_print_dinf );
2477 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, isom_print_dref );
2478 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_URL, isom_print_url );
2479 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, isom_print_stbl );
2480 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, isom_print_stsd );
2481 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, isom_print_clap );
2482 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, isom_print_pasp );
2483 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, isom_print_colr );
2484 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_COLR, isom_print_colr );
2485 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, isom_print_glbl );
2486 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, isom_print_gama );
2487 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, isom_print_fiel );
2488 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, isom_print_cspc );
2489 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, isom_print_sgbt );
2490 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, isom_print_stsl );
2491 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, isom_print_wave );
2492 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, isom_print_chan );
2493 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, isom_print_srat );
2494 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, isom_print_ftab );
2495 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, isom_print_stts );
2496 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, isom_print_ctts );
2497 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, isom_print_cslg );
2498 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, isom_print_stss );
2499 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_STPS, isom_print_stps );
2500 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, isom_print_sdtp );
2501 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, isom_print_stsc );
2502 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, isom_print_stsz );
2503 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2, isom_print_stz2 );
2504 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, isom_print_stco );
2505 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, isom_print_stco );
2506 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, isom_print_sgpd );
2507 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, isom_print_sbgp );
2508 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, isom_print_udta );
2509 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, isom_print_chpl );
2510 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, isom_print_WLOC );
2511 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, isom_print_LOOP );
2512 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_SELO, isom_print_SelO );
2513 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, isom_print_AllF );
2514 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_CPRT, isom_print_cprt );
2515 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, isom_print_mvex );
2516 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, isom_print_mehd );
2517 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, isom_print_trex );
2518 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, isom_print_moof );
2519 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, isom_print_mfhd );
2520 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, isom_print_traf );
2521 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, isom_print_tfhd );
2522 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, isom_print_tfdt );
2523 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, isom_print_trun );
2524 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, isom_print_free );
2525 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, isom_print_free );
2526 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, isom_print_mdat );
2527 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, isom_print_keys );
2528 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_META, isom_print_meta );
2529 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_ILST, isom_print_ilst );
2530 ADD_PRINT_BOX_TABLE_ELEMENT( QT_BOX_TYPE_ILST, isom_print_ilst );
2531 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, isom_print_mfra );
2532 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, isom_print_tfra );
2533 ADD_PRINT_BOX_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, isom_print_mfro );
2534 ADD_PRINT_BOX_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
2535 #undef ADD_PRINT_BOX_TABLE_ELEMENT
2537 for( int i = 0; print_box_table[i].func; i++ )
2538 if( lsmash_check_box_type_identical( box->type, print_box_table[i].type ) )
2539 return print_box_table[i].func;
2540 return isom_print_unknown;
2543 static inline void isom_print_remove_plastic_box( isom_box_t *box )
2545 if( box->manager & LSMASH_ABSENT_IN_FILE )
2546 /* free flagged box */
2547 isom_remove_box_by_itself( box );
2550 int isom_add_print_func( lsmash_file_t *file, void *box, int level )
2552 if( !(file->flags & LSMASH_FILE_MODE_DUMP) )
2554 isom_print_remove_plastic_box( box );
2555 return 0;
2557 isom_print_entry_t *data = lsmash_malloc( sizeof(isom_print_entry_t) );
2558 if( !data )
2560 isom_print_remove_plastic_box( box );
2561 return LSMASH_ERR_MEMORY_ALLOC;
2563 data->level = level;
2564 data->box = (isom_box_t *)box;
2565 data->func = isom_select_print_func( (isom_box_t *)box );
2566 assert( data->func );
2567 if( lsmash_add_entry( file->print, data ) < 0 )
2569 isom_print_remove_plastic_box( data->box );
2570 lsmash_free( data );
2571 return LSMASH_ERR_MEMORY_ALLOC;
2573 return 0;
2576 static void isom_remove_print_func( isom_print_entry_t *data )
2578 if( !data || !data->box )
2579 return;
2580 isom_print_remove_plastic_box( data->box );
2581 lsmash_free( data );
2584 void isom_remove_print_funcs( lsmash_file_t *file )
2586 lsmash_remove_list( file->print, isom_remove_print_func );
2587 file->print = NULL;