1 // This file is part of Deark.
2 // Copyright (C) 2016-2018 Jason Summers
3 // See the file COPYING for terms of use.
5 // ISO Base Media File Format, and related formats
6 // (JPEG 2000, MP4, QuickTime, etc.)
8 #include <deark-config.h>
9 #include <deark-private.h>
10 #include <deark-fmtutil.h>
12 // TODO: Rethink how to subdivide these formats into modules.
13 DE_DECLARE_MODULE(de_module_bmff
);
14 DE_DECLARE_MODULE(de_module_jpeg2000
);
16 typedef struct localctx_struct
{
19 u8 is_jp2_jpx_jpm
, is_jpx
, is_jpm
;
23 i64 max_entries_to_print
;
25 u8 exif_item_id_known
;
26 unsigned int exif_item_id
;
31 typedef void (*handler_fn_type
)(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
);
33 struct box_type_info
{
35 // flags1 is intended to be used to indicate which formats/brands use this box.
36 // 0x00000001 = Generic BMFF (isom brand, etc.)
38 // 0x00010000 = JP2/JPX/JPM
39 // 0x00040000 = JPEG XT
41 // 0x01000000 = Used in ilst boxes
43 // flags2: 0x1 = is_superbox
44 // flags2: 0x2 = critical top-level box (used for format identification)
50 #define BRAND_heic 0x68656963U
51 #define BRAND_isom 0x69736f6dU
52 #define BRAND_mif1 0x6d696631U
53 #define BRAND_mp41 0x6d703431U
54 #define BRAND_mp42 0x6d703432U
55 #define BRAND_M4A 0x4d344120U
56 #define BRAND_jp2 0x6a703220U
57 #define BRAND_jpm 0x6a706d20U
58 #define BRAND_jpx 0x6a707820U
59 #define BRAND_mjp2 0x6d6a7032U
60 #define BRAND_mj2s 0x6d6a3273U
61 #define BRAND_qt 0x71742020U
63 #define BOX_alis 0x616c6973U
64 #define BOX_auxC 0x61757843U
65 #define BOX_co64 0x636f3634U
66 #define BOX_ctts 0x63747473U
67 #define BOX_data 0x64617461U
68 #define BOX_elst 0x656c7374U
69 #define BOX_ftyp 0x66747970U
70 #define BOX_grpl 0x6772706cU
71 #define BOX_hvcC 0x68766343U
72 #define BOX_idat 0x69646174U
73 #define BOX_iinf 0x69696e66U
74 #define BOX_iloc 0x696c6f63U
75 #define BOX_ilst 0x696c7374U
76 #define BOX_infe 0x696e6665U
77 #define BOX_iods 0x696f6473U
78 #define BOX_ipco 0x6970636fU
79 #define BOX_ipma 0x69706d61U
80 #define BOX_ipro 0x6970726fU
81 #define BOX_iprp 0x69707270U
82 #define BOX_iref 0x69726566U
83 #define BOX_ispe 0x69737065U
84 #define BOX_jP 0x6a502020U
85 #define BOX_jp2c 0x6a703263U
86 #define BOX_load 0x6c6f6164U
87 #define BOX_mdat 0x6d646174U
88 #define BOX_mdhd 0x6d646864U
89 #define BOX_mvhd 0x6d766864U
90 #define BOX_name 0x6e616d65U
91 #define BOX_pitm 0x7069746dU
92 #define BOX_pnot 0x706e6f74U
93 #define BOX_rsrc 0x72737263U
94 #define BOX_sbgp 0x73626770U
95 #define BOX_sdtp 0x73647470U
96 #define BOX_sgpd 0x73677064U
97 #define BOX_stsd 0x73747364U
98 #define BOX_tkhd 0x746b6864U
99 #define BOX_uuid 0x75756964U
100 #define BOX_wide 0x77696465U
101 #define BOX_xml 0x786d6c20U
102 #define BOX_PICT 0x50494354U
103 #define BOX_THMB 0x54484d42U
104 #define BOX_PRVW 0x50525657U
106 #define BOX_blank 0x2d2d2d2dU // "----"
107 #define BOX_cpil 0x6370696cU
108 #define BOX_gnre 0x676e7265U
109 #define BOX_tmpo 0x746d706fU
110 #define BOX_a9ART 0xa9415254U
111 #define BOX_a9cmt 0xa9636d74U
112 #define BOX_a9nam 0xa96e616dU
113 #define BOX_a9too 0xa9746f6fU
116 #define BOX_cdef 0x63646566U
117 #define BOX_colr 0x636f6c72U
118 #define BOX_jp2h 0x6a703268U
119 #define BOX_ihdr 0x69686472U
120 #define BOX_res 0x72657320U
121 #define BOX_resc 0x72657363U
122 #define BOX_resd 0x72657364U
123 #define BOX_uinf 0x75696e66U
124 #define BOX_ulst 0x756c7374U
125 #define BOX_url 0x75726c20U
127 #define BOX_jpch 0x6a706368U
128 #define BOX_jplh 0x6a706c68U
129 #define BOX_cgrp 0x63677270U
130 #define BOX_ftbl 0x6674626cU
131 #define BOX_comp 0x636f6d70U
132 #define BOX_asoc 0x61736f63U
133 #define BOX_drep 0x64726570U
134 #define BOX_dtbl 0x6474626cU
135 #define BOX_flst 0x666c7374U
136 #define BOX_lbl 0x6c626c20U
137 #define BOX_nlst 0x6e6c7374U
138 #define BOX_rreq 0x72726571U
140 #define BOX_page 0x70616765U
141 #define BOX_lobj 0x6c6f626aU
142 #define BOX_objc 0x6f626a63U
143 #define BOX_sdat 0x73646174U
144 #define BOX_mhdr 0x6d686472U
145 #define BOX_lhdr 0x6c686472U
146 #define BOX_ohdr 0x6f686472U
147 #define BOX_pagt 0x70616774U
148 #define BOX_pcol 0x70636f6cU
149 #define BOX_phdr 0x70686472U
150 #define BOX_scal 0x7363616cU
151 // BMFF, QuickTime, MP4, ...:
152 #define BOX_cinf 0x63696e66U
153 #define BOX_clip 0x636c6970U
154 #define BOX_dinf 0x64696e66U
155 #define BOX_dref 0x64726566U
156 #define BOX_edts 0x65647473U
157 //#define BOX_extr 0x65787472U // Irregular format?
158 #define BOX_fdsa 0x66647361U
159 #define BOX_fiin 0x6669696eU
160 #define BOX_free 0x66726565U
161 #define BOX_hdlr 0x68646c72U
162 #define BOX_hinf 0x68696e66U
163 #define BOX_hmhd 0x686d6864U
164 #define BOX_hnti 0x686e7469U
165 #define BOX_matt 0x6d617474U
166 #define BOX_mdia 0x6d646961U
167 #define BOX_meco 0x6d65636fU
168 #define BOX_meta 0x6d657461U
169 #define BOX_minf 0x6d696e66U
170 #define BOX_mfra 0x6d667261U
171 #define BOX_moof 0x6d6f6f66U
172 #define BOX_moov 0x6d6f6f76U
173 #define BOX_mvex 0x6d766578U
174 #define BOX_nmhd 0x6e6d6864U
175 #define BOX_paen 0x7061656eU
176 #define BOX_rinf 0x72696e66U
177 #define BOX_schi 0x73636869U
178 #define BOX_sinf 0x73696e66U
179 #define BOX_skip 0x736b6970U
180 #define BOX_smhd 0x736d6864U
181 #define BOX_stbl 0x7374626cU
182 #define BOX_stco 0x7374636fU
183 #define BOX_strd 0x73747264U
184 #define BOX_strk 0x7374726bU
185 #define BOX_stsc 0x73747363U
186 #define BOX_stss 0x73747373U
187 #define BOX_stsz 0x7374737aU
188 #define BOX_stts 0x73747473U
189 #define BOX_stz2 0x73747a32U
190 #define BOX_traf 0x74726166U
191 #define BOX_trak 0x7472616bU
192 #define BOX_tref 0x74726566U
193 #define BOX_udta 0x75647461U
194 #define BOX_vmhd 0x766d6864U
196 #define BOX_LCHK 0x4c43484bU
197 #define BOX_RESI 0x52455349U
198 #define BOX_SPEC 0x53504543U
200 #define CODE_Exif 0x45786966U
201 #define CODE_rICC 0x72494343U
202 #define CODE_prof 0x70726f66U
204 static const u8
*g_uuid_cr3_85c0
= (const u8
*)"\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48";
205 static const u8
*g_uuid_cr3_eaf4
= (const u8
*)"\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16";
207 // Called for each primary or compatible brand.
208 // Brand-specific setup can be done here.
209 static void apply_brand(deark
*c
, lctx
*d
, u32 brand_id
)
213 d
->is_jp2_jpx_jpm
= 1;
217 d
->is_jp2_jpx_jpm
= 1;
221 d
->is_jp2_jpx_jpm
= 1;
240 if((brand_id
>>16) == 0x3367) { // "3g??"
246 // JPEG 2000 signature box (presumably)
247 static void do_box_jP(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
250 struct de_boxdata
*curbox
= bctx
->curbox
;
252 if(curbox
->level
!=0) return;
253 if(curbox
->payload_len
<4) return;
254 n
= (u32
)dbuf_getu32be(bctx
->f
, curbox
->payload_pos
);
256 de_dbg(c
, "found JPEG 2000 signature");
260 static void do_box_ftyp(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
264 i64 num_compat_brands
;
265 struct de_fourcc brand4cc
;
266 struct de_boxdata
*curbox
= bctx
->curbox
;
268 if(curbox
->payload_len
<4) goto done
;
269 dbuf_read_fourcc(bctx
->f
, curbox
->payload_pos
, &brand4cc
, 4, 0x0);
270 d
->major_brand
= brand4cc
.id
;
271 de_dbg(c
, "major brand: '%s'", brand4cc
.id_dbgstr
);
273 apply_brand(c
, d
, d
->major_brand
);
275 if(curbox
->payload_len
<8) goto done
;
276 mver
= dbuf_getu32be(bctx
->f
, curbox
->payload_pos
+4);
277 de_dbg(c
, "minor version: %u", (unsigned int)mver
);
279 if(curbox
->payload_len
<12) goto done
;
280 num_compat_brands
= (curbox
->payload_len
- 8)/4;
282 for(i
=0; i
<num_compat_brands
; i
++) {
283 dbuf_read_fourcc(bctx
->f
, curbox
->payload_pos
+ 8 + i
*4, &brand4cc
, 4, 0x0);
284 if(brand4cc
.id
==0) continue; // Placeholder. Ignore.
285 de_dbg(c
, "compatible brand: '%s'", brand4cc
.id_dbgstr
);
287 apply_brand(c
, d
, brand4cc
.id
);
294 static void do_read_version_and_flags(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
,
295 u8
*version
, u32
*flags
, int dbgflag
)
300 struct de_boxdata
*curbox
= bctx
->curbox
;
302 n
= (u32
)dbuf_getu32be(bctx
->f
, curbox
->payload_pos
);
303 version1
= (u8
)(n
>>24);
304 flags1
= n
&0x00ffffff;
306 de_dbg(c
, "version=%d, flags=0x%06x", (int)version1
, (unsigned int)flags1
);
308 if(version
) *version
= version1
;
309 if(flags
) *flags
= flags1
;
312 // For any box whose entire contents are a UTF-8 text string.
313 static void do_box_justtext(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
315 struct de_boxdata
*curbox
= bctx
->curbox
;
316 de_ucstring
*s
= NULL
;
319 name
= curbox
->box_name
? curbox
->box_name
: "value";
320 s
= ucstring_create(c
);
321 dbuf_read_to_ucstring_n(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
,
322 DE_DBG_MAX_STRLEN
, s
, 0, DE_ENCODING_UTF8
);
323 de_dbg(c
, "%s: \"%s\"", name
, ucstring_getpsz_d(s
));
327 static const char *get_ilst_type_name(unsigned int ns
, unsigned int wkt
)
329 const char *name
= NULL
;
334 case 0: name
="binary"; break;
335 case 1: name
="UTF-8"; break;
336 case 2: name
="UTF-16"; break;
337 case 3: name
="S/JIS"; break;
338 case 4: name
="UTF-8 sort key"; break;
339 case 5: name
="UTF-16 sort key"; break;
340 case 13: name
="JPEG"; break;
341 case 14: name
="PNG"; break;
342 case 21: name
="signed int"; break;
343 case 22: name
="unsigned int"; break;
344 case 23: name
="float32"; break;
345 case 24: name
="float64"; break;
346 case 27: name
="BMP"; break;
347 case 28: name
="metadata atom"; break;
354 static void do_box_data(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
356 unsigned int type_field
, type_namespace
, wkt
;
357 unsigned int cntry
, lang
;
359 struct de_boxdata
*curbox
= bctx
->curbox
;
360 struct de_boxdata
*par
;
361 struct de_boxdata
*gpar
;
362 i64 pos
= curbox
->payload_pos
;
363 de_ucstring
*s
= NULL
;
365 par
= curbox
->parent
;
369 if(gpar
->boxtype
!= BOX_ilst
) goto done
;
371 if(curbox
->payload_len
<8) goto done
;
372 type_field
= (unsigned int)dbuf_getu32be_p(bctx
->f
, &pos
);
373 type_namespace
= type_field
>>24;
374 wkt
= (type_field
& 0x00ffffff); // well-known type (if namespace==0)
375 de_dbg(c
, "type: %u, %u (%s)", type_namespace
, wkt
,
376 get_ilst_type_name(type_namespace
, wkt
));
378 cntry
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
379 lang
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
380 de_dbg(c
, "locale: %u, %u", cntry
, lang
);
382 if(type_namespace
!=0) goto done
;
383 vlen
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
385 if(wkt
==1 || wkt
==4) { // UTF-8
386 s
= ucstring_create(c
);
387 dbuf_read_to_ucstring_n(bctx
->f
, pos
, vlen
,
388 DE_DBG_MAX_STRLEN
, s
, 0, DE_ENCODING_UTF8
);
389 de_dbg(c
, "value: \"%s\"", ucstring_getpsz_d(s
));
391 else if(wkt
==21 && vlen
==1) { // 1-byte signed int
393 n
= (int)(signed char)dbuf_getbyte(bctx
->f
, pos
);
394 de_dbg(c
, "value: %d", n
);
396 else if(wkt
==21 && vlen
==2) { // 2-byte BE signed int
398 n
= (int)dbuf_geti16be(bctx
->f
, pos
);
399 de_dbg(c
, "value: %d", n
);
402 de_dbg_hexdump(c
, bctx
->f
, pos
, vlen
, 256, "value", 0x1);
404 // TODO: There are lots more types
410 static void do_box_hdlr(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
412 de_ucstring
*s
= NULL
;
413 struct de_boxdata
*curbox
= bctx
->curbox
;
414 i64 pos
= curbox
->payload_pos
;
415 struct de_fourcc tmp4cc
;
417 if(curbox
->payload_len
<4) goto done
;
418 do_read_version_and_flags(c
, d
, bctx
, NULL
, NULL
, 1);
420 if(curbox
->payload_len
<24) goto done
;
421 pos
+= 4; // "Predefined"
423 dbuf_read_fourcc(bctx
->f
, pos
, &tmp4cc
, 4, 0x0);
424 de_dbg(c
, "handler type: '%s'", tmp4cc
.id_dbgstr
);
427 pos
+= 12; // reserved
428 if(curbox
->payload_len
<25) goto done
;
429 if(dbuf_getbyte(bctx
->f
, pos
) == 0x00) goto done
;
431 s
= ucstring_create(c
);
432 dbuf_read_to_ucstring_n(bctx
->f
, pos
, curbox
->payload_pos
+ curbox
->payload_len
- pos
,
433 DE_DBG_MAX_STRLEN
, s
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_UTF8
);
434 de_dbg(c
, "metadata type name: \"%s\"", ucstring_getpsz_d(s
));
440 static void do_box_tkhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
447 struct de_boxdata
*curbox
= bctx
->curbox
;
449 if(curbox
->payload_len
<4) return;
451 pos
= curbox
->payload_pos
;
452 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
456 if(curbox
->payload_len
<96) return;
459 if(curbox
->payload_len
<84) return;
462 // creation time, mod time
468 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
469 de_dbg(c
, "track id: %d", (int)n
);
471 pos
+= 4; // reserved
479 pos
+= 4*2; // reserved
481 pos
+= 2; // alternate group
483 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
484 de_dbg(c
, "volume: %.3f", ((double)n
)/256.0);
486 pos
+= 2; // reserved
487 pos
+= 4*9; // matrix
489 w
= dbuf_fmtutil_read_fixed_16_16(bctx
->f
, pos
);
491 h
= dbuf_fmtutil_read_fixed_16_16(bctx
->f
, pos
);
493 de_dbg(c
, "dimensions: %.1f"DE_CHAR_TIMES
"%.1f", w
, h
);
496 static void do_box_vmhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
502 unsigned int graphicsmode
;
503 struct de_boxdata
*curbox
= bctx
->curbox
;
504 i64 pos
= curbox
->payload_pos
;
506 if(curbox
->payload_len
<12) return;
507 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
509 if(version
!=0 || flags
!=0x1) return;
511 graphicsmode
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
512 de_dbg(c
, "graphicsmode: %u", graphicsmode
);
515 clr
[k
] = (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
517 de_dbg(c
, "opcolor: (%d,%d,%d)", (int)clr
[0], (int)clr
[1], (int)clr
[2]);
520 static void do_box_PICT(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
522 struct de_boxdata
*curbox
= bctx
->curbox
;
525 outf
= dbuf_create_output_file(c
, "pict", NULL
, DE_CREATEFLAG_IS_AUX
);
526 dbuf_write_zeroes(outf
, 512);
527 dbuf_copy(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
, outf
);
531 static void do_box_smhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
536 struct de_boxdata
*curbox
= bctx
->curbox
;
537 i64 pos
= curbox
->payload_pos
;
539 if(curbox
->payload_len
<8) return;
540 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
542 if(version
!=0 || flags
!=0x0) return;
544 n
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
545 de_dbg(c
, "balance: %u", n
);
548 static void do_box_mvhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
556 struct de_boxdata
*curbox
= bctx
->curbox
;
558 if(curbox
->payload_len
<4) return;
560 pos
= curbox
->payload_pos
;
561 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
565 if(curbox
->payload_len
<112) return;
568 if(curbox
->payload_len
<100) return;
571 // creation time, mod time
577 timescale
= dbuf_getu32be_p(bctx
->f
, &pos
);
578 de_dbg(c
, "timescale: %d time units per second", (int)timescale
);
582 n
= dbuf_geti64be(bctx
->f
, pos
);
586 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
589 nd
= (double)n
/ (double)timescale
;
592 de_dbg(c
, "duration: %d time units (%.2f seconds)", (int)n
, nd
);
594 nd
= dbuf_fmtutil_read_fixed_16_16(bctx
->f
, pos
);
596 de_dbg(c
, "rate: %.3f", nd
);
598 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
599 de_dbg(c
, "volume: %.3f", ((double)n
)/256.0);
601 pos
+= 2; // reserved
602 pos
+= 4*2; // reserved
603 pos
+= 4*9; // matrix
604 pos
+= 4*6; // pre_defined
606 n
= dbuf_getu32be(bctx
->f
, pos
);
607 de_dbg(c
, "next track id: %d", (int)n
);
610 static void do_box_mdhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
618 struct de_boxdata
*curbox
= bctx
->curbox
;
620 // TODO: Share code with do_box_mvhd()?
621 if(curbox
->payload_len
<4) return;
623 pos
= curbox
->payload_pos
;
624 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
628 if(curbox
->payload_len
<36) return;
631 if(curbox
->payload_len
<24) return;
634 // creation time, mod time
640 timescale
= dbuf_getu32be_p(bctx
->f
, &pos
);
641 de_dbg(c
, "timescale: %d time units per second", (int)timescale
);
645 n
= dbuf_geti64be(bctx
->f
, pos
);
649 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
652 nd
= (double)n
/ (double)timescale
;
655 de_dbg(c
, "duration: %d time units (%.2f seconds)", (int)n
, nd
);
658 static void do_box_stsc(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
662 struct de_boxdata
*curbox
= bctx
->curbox
;
663 i64 pos
= curbox
->payload_pos
;
664 i64 e_count
, e_to_print
;
668 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
670 if(version
!=0 || flags
!=0) return;
672 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
673 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
675 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
676 if(bytesleft
/12 < e_count
) return;
678 e_to_print
= de_min_int(e_count
, d
->max_entries_to_print
);
680 for(k
=0; k
<e_to_print
; k
++) {
681 i64 first_chunk
, spc
, sdi
;
682 first_chunk
= dbuf_getu32be_p(bctx
->f
, &pos
);
683 spc
= dbuf_getu32be_p(bctx
->f
, &pos
);
684 sdi
= dbuf_getu32be_p(bctx
->f
, &pos
);
685 de_dbg(c
, "entry[%d]: first chunk=%d, samples/chunk=%d, descr. index=%d",
686 (int)k
, (int)first_chunk
, (int)spc
, (int)sdi
);
688 if(e_to_print
< e_count
) {
689 de_dbg(c
, "[%d more entry(s) omitted, starting at %"I64_FMT
"]",
690 (int)(e_count
-e_to_print
), pos
);
694 static void do_box_stsd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
701 struct de_fourcc fmt4cc
;
702 struct de_boxdata
*curbox
= bctx
->curbox
;
704 if(curbox
->payload_len
<8) return;
706 pos
= curbox
->payload_pos
;
707 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
709 if(version
!=0) return;
711 num_entries
= dbuf_getu32be_p(bctx
->f
, &pos
);
712 de_dbg(c
, "number of sample description entries: %d", (int)num_entries
);
715 if(pos
+ 16 >= curbox
->payload_pos
+ curbox
->payload_len
) break;
716 entry_size
= dbuf_getu32be(bctx
->f
, pos
);
717 de_dbg(c
, "sample description entry at %d, len=%d", (int)pos
, (int)entry_size
);
718 if(entry_size
<16) break;
721 dbuf_read_fourcc(bctx
->f
, pos
+4, &fmt4cc
, 4, 0x0);
722 de_dbg(c
, "data format: '%s'", fmt4cc
.id_dbgstr
);
723 de_dbg_indent(c
, -1);
729 // Decode a table of (4- or 8-byte) integers.
730 // Limit to d->max_entries_to_print.
731 static void do_simple_int_table(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
,
732 i64 pos1
, i64 e_count
, i64 e_size
,
733 const char *s1
, const char *s2
)
738 struct de_boxdata
*curbox
= bctx
->curbox
;
741 if(e_count
<=0) return;
742 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
743 if(bytesleft
< e_size
*e_count
) return;
745 e_to_print
= de_min_int(e_count
, d
->max_entries_to_print
);
747 for(k
=0; k
<e_to_print
; k
++) {
751 n
= dbuf_geti64be(bctx
->f
, pos
); pos
+= 8;
754 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
757 de_dbg(c
, "%s[%"I64_FMT
"]: %s=%"I64_FMT
, s1
, k
, s2
, n
);
759 if(e_to_print
< e_count
) {
760 de_dbg(c
, "[%"I64_FMT
" more %s(s) omitted, starting at %"I64_FMT
"]",
761 e_count
-e_to_print
, s1
, pos
);
765 static void do_box_stsz(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
769 struct de_boxdata
*curbox
= bctx
->curbox
;
770 i64 pos
= curbox
->payload_pos
;
773 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
775 if(version
!=0 || flags
!=0) return;
777 s_size
= dbuf_getu32be_p(bctx
->f
, &pos
);
778 de_dbg(c
, "sample size: %u", (unsigned int)s_size
);
779 s_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
780 de_dbg(c
, "sample count: %u", (unsigned int)s_count
);
782 if(s_size
!=0) goto done
;
784 do_simple_int_table(c
, d
, bctx
, pos
, s_count
, 4, "sample", "entry size");
791 static void do_box_stco(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
795 struct de_boxdata
*curbox
= bctx
->curbox
;
796 i64 pos
= curbox
->payload_pos
;
800 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
802 if(version
!=0 || flags
!=0) return;
804 e_size
= (bctx
->curbox
->boxtype
== BOX_co64
) ? 8 : 4;
805 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
806 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
808 do_simple_int_table(c
, d
, bctx
, pos
, e_count
, e_size
, "entry", "chunk offset");
811 static void do_box_stss(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
815 struct de_boxdata
*curbox
= bctx
->curbox
;
816 i64 pos
= curbox
->payload_pos
;
819 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
821 if(version
!=0 || flags
!=0) return;
823 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
824 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
826 do_simple_int_table(c
, d
, bctx
, pos
, e_count
, 4, "entry", "sample number");
829 static void do_box_stts(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
833 struct de_boxdata
*curbox
= bctx
->curbox
;
834 i64 pos
= curbox
->payload_pos
;
835 i64 e_count
, e_to_print
;
839 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
841 if(version
!=0 || flags
!=0) return;
843 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
844 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
846 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
847 if(bytesleft
/8 < e_count
) return;
849 e_to_print
= de_min_int(e_count
, d
->max_entries_to_print
);
851 for(k
=0; k
<e_to_print
; k
++) {
852 i64 s_count
, s_delta
;
853 s_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
854 s_delta
= dbuf_getu32be_p(bctx
->f
, &pos
);
855 de_dbg(c
, "entry[%d]: sample count=%d, delta=%d", (int)k
,
856 (int)s_count
, (int)s_delta
);
858 if(e_to_print
< e_count
) {
859 de_dbg(c
, "[%d more entry(s) omitted, starting at %"I64_FMT
"]",
860 (int)(e_count
-e_to_print
), pos
);
864 static void do_box_ctts(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
868 struct de_boxdata
*curbox
= bctx
->curbox
;
869 i64 pos
= curbox
->payload_pos
;
870 i64 e_count
, e_to_print
;
874 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
876 if(version
>1 || flags
!=0) return;
878 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
879 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
881 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
882 if(bytesleft
< e_count
*8) return;
884 e_to_print
= e_count
;
885 if(e_to_print
> d
->max_entries_to_print
) {
886 e_to_print
= d
->max_entries_to_print
;
889 for(k
=0; k
<e_to_print
; k
++) {
890 i64 s_count
, s_offset
;
891 s_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
893 s_offset
= dbuf_getu32be_p(bctx
->f
, &pos
);
896 s_offset
= dbuf_geti32be(bctx
->f
, pos
); pos
+= 4;
898 de_dbg(c
, "entry[%d]: sample count=%"I64_FMT
", offset=%"I64_FMT
,
899 (int)k
, s_count
, s_offset
);
901 if(e_to_print
< e_count
) {
902 de_dbg(c
, "[%d more entry(s) omitted, starting at %"I64_FMT
"]",
903 (int)(e_count
-e_to_print
), pos
);
907 static void do_box_full_superbox(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
909 struct de_boxdata
*curbox
= bctx
->curbox
;
911 do_read_version_and_flags(c
, d
, bctx
, NULL
, NULL
, 1);
912 curbox
->extra_bytes_before_children
= 4;
915 static void do_box_meta(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
917 if(bctx
->curbox
->payload_len
>=8) {
918 // The QuickTime spec says 'meta' is not a full box, but in newer files
919 // it is. I don't know how you're supposed to know, but sniffing for
920 // "hdlr" should be good enough.
921 u32 n
= (u32
)dbuf_getu32be(bctx
->f
, bctx
->curbox
->payload_pos
+4);
927 do_box_full_superbox(c
, d
, bctx
);
930 static void do_box_jp2c(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
932 struct de_boxdata
*curbox
= bctx
->curbox
;
934 de_dbg(c
, "JPEG 2000 codestream at %d, len=%d",
935 (int)curbox
->payload_pos
, (int)curbox
->payload_len
);
937 // I think this box is used regardless of the compression format, so make
938 // sure it seems to be in "JPEG 2000" format.
939 // This is a hack -- we could track the compression method instead.
940 if((u32
)dbuf_getu32be(bctx
->f
, curbox
->payload_pos
) != 0xff4fff51U
) {
941 de_dbg(c
, "[non-J2C]");
945 dbuf_create_file_from_slice(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
,
949 #define POW10_MAX_E 12
950 static i64
limited_ipow10(int e
)
954 if(e
< 0 || e
> POW10_MAX_E
) return 1;
962 // TODO: Decide whether to use pow()/libm.
963 static double limited_pow10(int e
)
965 if(e
< -POW10_MAX_E
|| e
> POW10_MAX_E
) return 0.0;
967 return 1.0 / (double)limited_ipow10(e
);
969 return (double)limited_ipow10(e
);
972 static void format_jp2_res(char *buf
, size_t buflen
,
973 i64 num
, i64 denom
, int exponent
)
977 if(denom
!= 0 && exponent
>= -POW10_MAX_E
&& exponent
<= POW10_MAX_E
) {
980 dpm
= ((double)num
/ (double)denom
) * limited_pow10(exponent
);
982 de_snprintf(descr
, sizeof(descr
), " = %f points/meter (%f dpi)", dpm
, dpi
);
987 de_snprintf(buf
, buflen
, "(%"I64_FMT
",%"I64_FMT
",%d)%s",
988 num
, denom
, exponent
, descr
);
991 static void do_box_resc_resd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
995 struct de_boxdata
*curbox
= bctx
->curbox
;
997 i64 pos
= curbox
->payload_pos
;
1000 if(curbox
->boxtype
==BOX_resc
)
1005 if(curbox
->payload_len
<10) return;
1006 vn
= dbuf_getu16be_p(bctx
->f
, &pos
);
1007 vd
= dbuf_getu16be_p(bctx
->f
, &pos
);
1008 hn
= dbuf_getu16be_p(bctx
->f
, &pos
);
1009 hd
= dbuf_getu16be_p(bctx
->f
, &pos
);
1010 ve
= (int)(signed char)dbuf_getbyte_p(bctx
->f
, &pos
);
1011 he
= (int)(signed char)dbuf_getbyte_p(bctx
->f
, &pos
);
1012 format_jp2_res(res_buf
, sizeof(res_buf
), vn
, vd
, ve
);
1013 de_dbg(c
, "vert. %s grid res.: %s", name
, res_buf
);
1014 format_jp2_res(res_buf
, sizeof(res_buf
), hn
, hd
, he
);
1015 de_dbg(c
, "horz. %s grid res.: %s", name
, res_buf
);
1018 static const char *get_rreq_sf_name(UI n
)
1020 static const u8 ids
[11] = {1, 2, 5, 8, 12, 18, 19, 20, 31, 45, 46};
1021 static const char *names
[11] = { "no extensions", "has layers",
1022 "cmpr=JPEG 2000/15444-1", "no opacity", "contiguous",
1023 "layers not req'd", "discrete layers", "1 codestream per layer",
1024 "scaling not req'd", "sRGB", "sRGB-gray" };
1027 for(i
=0; i
<DE_ARRAYCOUNT(ids
); i
++) {
1028 if((UI
)ids
[i
]==n
) return names
[i
];
1033 static void do_box_rreq(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1035 i64 pos
= bctx
->curbox
->payload_pos
;
1036 i64 endpos
= pos
+ bctx
->curbox
->payload_len
;
1042 if(pos
>=endpos
) goto done
;
1043 ml
= (UI
)dbuf_getbyte_p(bctx
->f
, &pos
);
1044 de_dbg(c
, "ml: %u byte(s)", ml
);
1045 if(ml
<1 || ml
>8) goto done
;
1047 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1049 de_dbg(c
, "fuam: 0x%"U64_FMTx
, msk
);
1051 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1053 de_dbg(c
, "dcm: 0x%"U64_FMTx
, msk
);
1055 nsf
= dbuf_getu16be_p(bctx
->f
, &pos
);
1056 de_dbg(c
, "nsf: %d", (int)nsf
);
1058 for(i
=0; i
<nsf
; i
++) {
1061 if(pos
>=endpos
) goto done
;
1062 sf
= (UI
)dbuf_getu16be_p(bctx
->f
, &pos
);
1063 de_dbg(c
, "standard feature[%d]: %u (%s)", (int)i
, sf
, get_rreq_sf_name(sf
));
1065 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1067 de_dbg_indent(c
, 1);
1068 de_dbg(c
, "mask: 0x%"U64_FMTx
, msk
);
1069 de_dbg_indent(c
, -1);
1072 if(pos
>=endpos
) goto done
;
1073 nvf
= dbuf_getu16be_p(bctx
->f
, &pos
);
1074 de_dbg(c
, "num. vendor features: %d", (int)nvf
);
1076 for(i
=0; i
<nvf
; i
++) {
1078 char uuid_string
[50];
1080 if(pos
>=endpos
) goto done
;
1081 dbuf_read(bctx
->f
, ubuf
, pos
, 16);
1082 fmtutil_render_uuid(c
, ubuf
, uuid_string
, sizeof(uuid_string
));
1083 de_dbg(c
, "vendor feature[%d]: {%s}", (int)i
, uuid_string
);
1086 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1088 de_dbg_indent(c
, 1);
1089 de_dbg(c
, "mask: 0x%"U64_FMTx
, msk
);
1090 de_dbg_indent(c
, -1);
1097 static const char *get_jpeg2000_cmpr_name(deark
*c
, lctx
*d
, u8 ct
)
1099 const char *name
= NULL
;
1101 if(ct
==7) { name
="JPEG 2000"; goto done
; }
1104 case 0: name
="uncompressed"; break;
1105 case 1: name
="MH"; break;
1106 case 2: name
="MR"; break;
1107 case 3: name
="MMR"; break;
1108 case 4: name
="JBIG bi-level"; break;
1109 case 5: name
="JPEG"; break;
1110 case 6: name
="JPEG-LS"; break;
1111 case 8: name
="JBIG2"; break;
1112 case 9: name
="JBIG"; break;
1121 static void do_box_ihdr(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1125 struct de_boxdata
*curbox
= bctx
->curbox
;
1126 i64 pos
= curbox
->payload_pos
;
1129 if(curbox
->payload_len
<14) return;
1130 h
= dbuf_getu32be_p(bctx
->f
, &pos
);
1131 w
= dbuf_getu32be_p(bctx
->f
, &pos
);
1132 de_dbg_dimensions(c
, w
, h
);
1134 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
1135 de_dbg(c
, "number of components: %d", (int)n
);
1137 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1139 de_strlcpy(tmps
, "various", sizeof(tmps
));
1142 de_snprintf(tmps
, sizeof(tmps
), "%u bits/comp., %ssigned",
1143 (unsigned int)(1+(b
&0x7f)), (b
&0x80)?"":"un");
1145 de_dbg(c
, "bits-per-component code: %u (%s)", (unsigned int)b
, tmps
);
1147 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1148 de_dbg(c
, "compression type: %u (%s)", (unsigned int)b
,
1149 get_jpeg2000_cmpr_name(c
, d
, b
));
1151 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1152 de_dbg(c
, "colorspace-is-unknown flag: %d", (int)b
);
1153 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1154 de_dbg(c
, "has-IPR: %d", (int)b
);
1157 static const char *get_channel_type_name(i64 t
)
1161 case 0: name
= "colour image data for associated color"; break;
1162 case 1: name
= "opacity"; break;
1163 case 2: name
= "premultiplied opacity"; break;
1164 case 65535: name
= "not specified"; break;
1165 default: name
= "?";
1170 static void do_box_cdef(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1173 struct de_boxdata
*curbox
= bctx
->curbox
;
1174 i64 pos
= curbox
->payload_pos
;
1177 ndescs
= dbuf_getu16be_p(bctx
->f
, &pos
);
1178 de_dbg(c
, "number of channel descriptions: %d", (int)ndescs
);
1180 for(k
=0; k
<ndescs
; k
++) {
1183 if(pos
+6 > curbox
->payload_pos
+ curbox
->payload_len
) break;
1184 de_dbg(c
, "channel description[%d] at %"I64_FMT
, (int)k
, pos
);
1185 de_dbg_indent(c
, 1);
1186 idx
= dbuf_getu16be_p(bctx
->f
, &pos
);
1187 de_dbg(c
, "channel index: %d", (int)idx
);
1188 typ
= dbuf_getu16be_p(bctx
->f
, &pos
);
1189 de_dbg(c
, "channel type: %d (%s)", (int)typ
, get_channel_type_name(typ
));
1190 asoc
= dbuf_getu16be_p(bctx
->f
, &pos
);
1191 de_dbg(c
, "index of associated color: %d", (int)asoc
);
1192 de_dbg_indent(c
, -1);
1196 // BMFF-style 'colr' box
1197 static void do_box_colr_bmff(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1199 struct de_boxdata
*curbox
= bctx
->curbox
;
1200 i64 pos
= curbox
->payload_pos
;
1201 struct de_fourcc ct4cc
; // colour_type
1203 if(curbox
->payload_len
<4) goto done
;
1205 dbuf_read_fourcc(bctx
->f
, pos
, &ct4cc
, 4, 0x0);
1206 de_dbg(c
, "colour type: '%s'", ct4cc
.id_dbgstr
);
1209 if(ct4cc
.id
==CODE_rICC
|| ct4cc
.id
==CODE_prof
) {
1210 dbuf_create_file_from_slice(bctx
->f
, pos
,
1211 curbox
->payload_pos
+curbox
->payload_len
-pos
,
1212 "icc", NULL
, DE_CREATEFLAG_IS_AUX
);
1219 // JP2/JPX-style 'colr' box
1220 static void do_box_colr_jp2(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1224 struct de_boxdata
*curbox
= bctx
->curbox
;
1225 i64 pos
= curbox
->payload_pos
;
1228 if(curbox
->payload_len
<3) goto done
;
1229 meth
= dbuf_getbyte_p(bctx
->f
, &pos
);
1231 case 1: s
="enumerated"; break;
1232 case 2: s
="ICC profile (restricted)"; break;
1233 case 3: s
="ICC profile (any)"; break; // JPX only
1234 case 4: s
="vendor"; break; // JPX only
1237 de_dbg(c
, "specification method: %d (%s)", (int)meth
, s
);
1239 n
= dbuf_getbyte_p(bctx
->f
, &pos
);
1240 de_dbg(c
, "precedence: %u", (UI
)n
);
1241 n
= dbuf_getbyte_p(bctx
->f
, &pos
);
1242 de_dbg(c
, "approximation code: %u", (UI
)n
);
1245 unsigned int enumcs
;
1246 if(curbox
->payload_len
<7) goto done
;
1247 enumcs
= (unsigned int)dbuf_getu32be_p(bctx
->f
, &pos
);
1249 // TODO: There are lots more valid values for JPX.
1250 case 16: s
="sRGB"; break;
1251 case 17: s
="sRGB-like grayscale"; break;
1252 case 18: s
="sYCC"; break;
1255 de_dbg(c
, "enumerated colourspace: %u (%s)", enumcs
, s
);
1257 else if(meth
==2 || meth
==3) {
1258 dbuf_create_file_from_slice(bctx
->f
,
1259 curbox
->payload_pos
+3, curbox
->payload_len
-3,
1260 "icc", NULL
, DE_CREATEFLAG_IS_AUX
);
1267 static void do_box_ulst(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1269 struct de_boxdata
*curbox
= bctx
->curbox
;
1270 i64 pos
= curbox
->payload_pos
;
1274 char uuid_string
[50];
1276 nuuids
= dbuf_getu16be_p(bctx
->f
, &pos
);
1277 de_dbg(c
, "number of UUIDs: %d", (int)nuuids
);
1279 for(k
=0; k
<nuuids
; k
++) {
1280 if(pos
+16 > curbox
->payload_pos
+ curbox
->payload_len
) break;
1281 dbuf_read(bctx
->f
, ubuf
, pos
, 16);
1282 fmtutil_render_uuid(c
, ubuf
, uuid_string
, sizeof(uuid_string
));
1283 de_dbg(c
, "UUID[%d]: {%s}", (int)k
, uuid_string
);
1288 static void do_box_url(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1290 de_ucstring
*s
= NULL
;
1291 struct de_boxdata
*curbox
= bctx
->curbox
;
1292 i64 pos
= curbox
->payload_pos
;
1295 do_read_version_and_flags(c
, d
, bctx
, NULL
, &flags
, 1);
1298 // "If the self-contained flag is set, [...] no string is present".
1299 // But there is no flag named "self-contained".
1300 // I assume it is flag 0x1.
1301 if(flags
&0x000001) goto done
;
1303 s
= ucstring_create(c
);
1304 dbuf_read_to_ucstring_n(bctx
->f
,
1305 pos
, curbox
->payload_pos
+ curbox
->payload_len
- pos
, DE_DBG_MAX_STRLEN
,
1306 s
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_UTF8
);
1307 de_dbg(c
, "URL: \"%s\"", ucstring_getpsz_d(s
));
1309 ucstring_destroy(s
);
1312 static void do_box_dtbl(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1315 struct de_boxdata
*curbox
= bctx
->curbox
;
1317 ndr
= dbuf_getu16be(bctx
->f
, curbox
->payload_pos
);
1318 de_dbg(c
, "number of data references: %d", (int)ndr
);
1320 curbox
->num_children_is_known
= 1;
1321 curbox
->num_children
= ndr
;
1322 curbox
->extra_bytes_before_children
= 2;
1325 static void do_box_dref(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1329 struct de_boxdata
*curbox
= bctx
->curbox
;
1330 i64 pos
= curbox
->payload_pos
;
1332 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1335 nitems
= dbuf_getu32be_p(bctx
->f
, &pos
);
1336 de_dbg(c
, "number of items: %u", (unsigned int)nitems
);
1338 curbox
->num_children_is_known
= 1;
1339 curbox
->num_children
= nitems
;
1340 curbox
->extra_bytes_before_children
= pos
- curbox
->payload_pos
;
1343 static void do_box_iinf(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1347 struct de_boxdata
*curbox
= bctx
->curbox
;
1348 i64 pos
= curbox
->payload_pos
;
1350 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1354 nitems
= dbuf_getu16be_p(bctx
->f
, &pos
);
1357 nitems
= dbuf_getu32be_p(bctx
->f
, &pos
);
1359 de_dbg(c
, "number of items: %d", (int)nitems
);
1361 curbox
->num_children_is_known
= 1;
1362 curbox
->num_children
= nitems
;
1363 curbox
->extra_bytes_before_children
= pos
- curbox
->payload_pos
;
1366 static void extract_exif_item(deark
*c
, lctx
*d
, dbuf
*f
)
1371 if(!d
->exif_item_id_known
) return;
1372 if(d
->exif_item_offs
<=0) return;
1373 if(d
->exif_item_len
<24) return;
1374 // I'm just guessing the format of this item. It seems to start with 10
1375 // bytes of header info.
1376 dpos
= d
->exif_item_offs
+10;
1377 dlen
= d
->exif_item_len
-10;
1378 b0
= dbuf_getbyte(f
, dpos
);
1379 b1
= dbuf_getbyte(f
, dpos
+1);
1380 if(!((b0
=='M' && b1
=='M') || (b0
=='I' && b1
=='I'))) {
1383 de_dbg(c
, "Exif item segment at %"I64_FMT
", size=%"I64_FMT
, dpos
, dlen
);
1384 de_dbg_indent(c
, 1);
1385 fmtutil_handle_exif(c
, dpos
, dlen
);
1386 de_dbg_indent(c
, -1);
1389 static void do_box_iloc(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1392 struct de_boxdata
*curbox
= bctx
->curbox
;
1393 i64 pos
= curbox
->payload_pos
;
1395 unsigned int offset_size
, length_size
, base_offset_size
, index_size
;
1398 int saved_indent_level
;
1400 de_dbg_indent_save(c
, &saved_indent_level
);
1401 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1404 // TODO: Support more versions
1405 if(version
!=1) goto done
;
1407 u
= (unsigned int)dbuf_getbyte_p(bctx
->f
, &pos
);
1409 de_dbg(c
, "offset size: %u", offset_size
);
1410 if(offset_size
!=0 && offset_size
!=4 && offset_size
!=8) goto done
;
1411 length_size
= u
&0xf;
1412 de_dbg(c
, "length size: %u", length_size
);
1413 if(length_size
!=0 && length_size
!=4 && length_size
!=8) goto done
;
1415 u
= (unsigned int)dbuf_getbyte_p(bctx
->f
, &pos
);
1416 base_offset_size
= u
>>4;
1417 de_dbg(c
, "base offset size: %u", base_offset_size
);
1418 if(base_offset_size
!=0 && base_offset_size
!=4 && base_offset_size
!=8) goto done
;
1420 de_dbg(c
, "index size: %u", index_size
);
1421 if(index_size
!=0 && index_size
!=4 && index_size
!=8) goto done
;
1423 item_count
= dbuf_getu16be_p(bctx
->f
, &pos
);
1424 de_dbg(c
, "item count: %d", (int)item_count
);
1426 for(k
=0; k
<item_count
; k
++) {
1427 unsigned int item_id
;
1430 unsigned int cnstr_meth
;
1432 if(pos
>= curbox
->payload_pos
+curbox
->payload_len
) goto done
;
1433 de_dbg(c
, "item[%d] at %"I64_FMT
, (int)k
, pos
);
1434 de_dbg_indent(c
, 1);
1435 item_id
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
1436 de_dbg(c
, "item id: %u", item_id
);
1438 u
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
1440 de_dbg(c
, "construction method: %u", cnstr_meth
);
1442 pos
+= 2; // data reference index
1443 pos
+= base_offset_size
;
1445 extent_count
= dbuf_getu16be_p(bctx
->f
, &pos
);
1446 de_dbg(c
, "extent count: %d", (int)extent_count
);
1448 for(e
=0; e
<extent_count
; e
++) {
1452 if(pos
>= curbox
->payload_pos
+curbox
->payload_len
) goto done
;
1453 de_dbg(c
, "extent[%d]", (int)e
);
1454 de_dbg_indent(c
, 1);
1458 xoffs
= dbuf_getint_ext(bctx
->f
, pos
, offset_size
, 0, 0);
1459 de_dbg(c
, "offset: %"I64_FMT
, xoffs
);
1464 xlen
= dbuf_getint_ext(bctx
->f
, pos
, length_size
, 0, 0);
1465 de_dbg(c
, "length: %"I64_FMT
, xlen
);
1469 if(d
->exif_item_id_known
&& item_id
==d
->exif_item_id
&& extent_count
==1) {
1470 de_dbg(c
, "[Exif item]");
1471 d
->exif_item_offs
= xoffs
;
1472 d
->exif_item_len
= xlen
;
1475 de_dbg_indent(c
, -1);
1478 de_dbg_indent(c
, -1);
1482 if(d
->exif_item_id_known
) {
1483 extract_exif_item(c
, d
, bctx
->f
);
1485 de_dbg_indent_restore(c
, saved_indent_level
);
1488 static void do_box_infe(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1491 struct de_boxdata
*curbox
= bctx
->curbox
;
1492 i64 pos
= curbox
->payload_pos
;
1494 unsigned int item_id
;
1496 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1499 if(version
==2 || version
==3) {
1500 struct de_fourcc itemtype4cc
;
1503 item_id
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
1506 item_id
= (unsigned int)dbuf_getu32be_p(bctx
->f
, &pos
);
1508 de_dbg(c
, "item id: %u", item_id
);
1510 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
1511 de_dbg(c
, "item protection: %u", (unsigned int)n
);
1513 dbuf_read_fourcc(bctx
->f
, pos
, &itemtype4cc
, 4, 0x0);
1515 de_dbg(c
, "item type: '%s'", itemtype4cc
.id_dbgstr
);
1517 if(itemtype4cc
.id
==CODE_Exif
) {
1518 d
->exif_item_id_known
= 1;
1519 d
->exif_item_id
= item_id
;
1522 // TODO: string item_name
1523 // TODO: sometimes there are additional strings after item_name
1527 static void do_box_ispe(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1529 struct de_boxdata
*curbox
= bctx
->curbox
;
1530 i64 pos
= curbox
->payload_pos
;
1533 if(curbox
->payload_len
<12) return;
1534 do_read_version_and_flags(c
, d
, bctx
, NULL
, NULL
, 1);
1536 w
= dbuf_getu32be_p(bctx
->f
, &pos
);
1537 h
= dbuf_getu32be_p(bctx
->f
, &pos
);
1538 de_dbg_dimensions(c
, w
, h
);
1541 static void do_box_xml(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1543 struct de_boxdata
*curbox
= bctx
->curbox
;
1545 // TODO: Detect the specific XML format, and use it to choose a better
1547 de_dbg(c
, "XML data at %d, len=%d", (int)curbox
->payload_pos
, (int)curbox
->payload_len
);
1548 dbuf_create_file_from_slice(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
,
1549 "xml", NULL
, DE_CREATEFLAG_IS_AUX
);
1552 static void do_box_THMB(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1554 struct de_boxdata
*curbox
= bctx
->curbox
;
1558 if(!curbox
->parent
) return;
1559 if(!curbox
->parent
->is_uuid
) return;
1560 if(de_memcmp(curbox
->parent
->uuid
, g_uuid_cr3_85c0
, 16)) return;
1561 if(curbox
->payload_len
<20) return;
1562 img_pos
= curbox
->payload_pos
+16;
1563 if(dbuf_memcmp(bctx
->f
, img_pos
, "\xff\xd8\xff", 3)) return;
1564 img_len
= dbuf_getu32be(bctx
->f
, curbox
->payload_pos
+8);
1565 de_dbg(c
, "image at %"I64_FMT
", len=%"I64_FMT
, img_pos
, img_len
);
1566 if(img_pos
+img_len
> curbox
->payload_pos
+curbox
->payload_len
) return;
1567 dbuf_create_file_from_slice(bctx
->f
, img_pos
, img_len
, "thumb.jpg", NULL
,
1568 DE_CREATEFLAG_IS_AUX
);
1571 static void do_box_PRVW(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1573 struct de_boxdata
*curbox
= bctx
->curbox
;
1577 if(!curbox
->parent
) return;
1578 if(!curbox
->parent
->is_uuid
) return;
1579 if(de_memcmp(curbox
->parent
->uuid
, g_uuid_cr3_eaf4
, 16)) return;
1580 if(curbox
->payload_len
<20) return;
1581 img_pos
= curbox
->payload_pos
+16;
1582 if(dbuf_memcmp(bctx
->f
, img_pos
, "\xff\xd8\xff", 3)) return;
1583 img_len
= dbuf_getu32be(bctx
->f
, curbox
->payload_pos
+12);
1584 de_dbg(c
, "image at %"I64_FMT
", len=%"I64_FMT
, img_pos
, img_len
);
1585 if(img_pos
+img_len
> curbox
->payload_pos
+curbox
->payload_len
) return;
1586 dbuf_create_file_from_slice(bctx
->f
, img_pos
, img_len
, "preview.jpg", NULL
,
1587 DE_CREATEFLAG_IS_AUX
);
1590 // The first line that matches will be used, so items related to more-specific
1591 // formats/brands should be listed first.
1592 static const struct box_type_info box_type_info_arr
[] = {
1593 {BOX_ftyp
, 0x00000000, 0x00000002, "file type", do_box_ftyp
},
1594 {BOX_jP
, 0x00010008, 0x00000002, "JPEG 2000 signature", do_box_jP
},
1595 {BOX_mdat
, 0x00000008, 0x00000001, "media data", NULL
},
1596 {BOX_mdat
, 0x00080001, 0x00000000, "media data", NULL
},
1597 {BOX_alis
, 0x00000001, 0x00000000, "Macintosh file alias", NULL
},
1598 {BOX_cinf
, 0x00000001, 0x00000001, "complete track information", NULL
},
1599 {BOX_clip
, 0x00000001, 0x00000001, NULL
, NULL
},
1600 {BOX_co64
, 0x00000001, 0x00000000, "chunk offset", do_box_stco
},
1601 {BOX_colr
, 0x00080001, 0x00000000, "colour information", do_box_colr_bmff
},
1602 {BOX_dinf
, 0x00080001, 0x00000001, "data information", NULL
},
1603 {BOX_dref
, 0x00080001, 0x00000001, "data reference", do_box_dref
},
1604 {BOX_edts
, 0x00000001, 0x00000001, "edit", NULL
},
1605 {BOX_elst
, 0x00000001, 0x00000000, "edit list", NULL
},
1606 {BOX_fdsa
, 0x00000001, 0x00000001, NULL
, NULL
},
1607 {BOX_fiin
, 0x00000001, 0x00000001, "FD item information", NULL
},
1608 {BOX_free
, 0x00090001, 0x00000000, "free space", NULL
},
1609 {BOX_hdlr
, 0x00080001, 0x00000000, "handler reference", do_box_hdlr
},
1610 {BOX_hinf
, 0x00000001, 0x00000001, NULL
, NULL
},
1611 {BOX_hmhd
, 0x00000001, 0x00000000, "hint media header", NULL
},
1612 {BOX_hnti
, 0x00000001, 0x00000001, NULL
, NULL
},
1613 {BOX_iinf
, 0x00080001, 0x00000001, "item info", do_box_iinf
},
1614 {BOX_iloc
, 0x00080001, 0x00000000, "item location", do_box_iloc
},
1615 {BOX_ilst
, 0x00000001, 0x00000001, "metadata item list", NULL
},
1616 {BOX_infe
, 0x00080001, 0x00000000, "item info entry", do_box_infe
},
1617 {BOX_iods
, 0x00000001, 0x00000000, "object descriptor", NULL
},
1618 {BOX_iref
, 0x00080001, 0x00000001, "item reference", do_box_full_superbox
},
1619 {BOX_load
, 0x00000001, 0x00000000, "track load settings", NULL
},
1620 {BOX_matt
, 0x00000001, 0x00000001, NULL
, NULL
},
1621 {BOX_mdhd
, 0x00000001, 0x00000000, "media header", do_box_mdhd
},
1622 {BOX_mdia
, 0x00000001, 0x00000001, "media", NULL
},
1623 {BOX_meco
, 0x00000001, 0x00000001, "additional metadata container", NULL
},
1624 {BOX_meta
, 0x00080001, 0x00000001, "metadata", do_box_meta
},
1625 {BOX_minf
, 0x00000001, 0x00000001, "media information", NULL
},
1626 {BOX_mfra
, 0x00000001, 0x00000001, "movie fragment random access", NULL
},
1627 {BOX_moof
, 0x00000001, 0x00000001, "movie fragment", NULL
},
1628 {BOX_moov
, 0x00000001, 0x00000001, "movie (metadata container)", NULL
},
1629 {BOX_mvex
, 0x00000001, 0x00000001, "movie extends", NULL
},
1630 {BOX_mvhd
, 0x00000001, 0x00000000, "movie header", do_box_mvhd
},
1631 {BOX_nmhd
, 0x00000001, 0x00000000, "null media header", NULL
},
1632 {BOX_paen
, 0x00000001, 0x00000001, NULL
, NULL
},
1633 {BOX_pnot
, 0x00000001, 0x00000000, "reference to movie preview", NULL
},
1634 {BOX_rinf
, 0x00000001, 0x00000001, "restricted scheme information", NULL
},
1635 {BOX_rsrc
, 0x00000001, 0x00000000, "Macintosh resource alias", NULL
},
1636 {BOX_sbgp
, 0x00000001, 0x00000000, "sample-to-group", NULL
},
1637 {BOX_schi
, 0x00000001, 0x00000001, "scheme information", NULL
},
1638 {BOX_sdtp
, 0x00000001, 0x00000000, "independent and disposable samples", NULL
},
1639 {BOX_sgpd
, 0x00000001, 0x00000000, "sample group description", NULL
},
1640 {BOX_sinf
, 0x00000001, 0x00000001, "protection scheme information", NULL
},
1641 {BOX_skip
, 0x00080001, 0x00000000, "user-data", NULL
},
1642 {BOX_smhd
, 0x00000001, 0x00000000, "sound media header", do_box_smhd
},
1643 {BOX_stbl
, 0x00000001, 0x00000001, "sample table", NULL
},
1644 {BOX_stco
, 0x00000001, 0x00000000, "chunk offset", do_box_stco
},
1645 {BOX_strd
, 0x00000001, 0x00000001, "sub track definition", NULL
},
1646 {BOX_strk
, 0x00000001, 0x00000001, "sub track", NULL
},
1647 {BOX_stsc
, 0x00000001, 0x00000000, "sample to chunk", do_box_stsc
},
1648 {BOX_stsd
, 0x00000001, 0x00000000, "sample description", do_box_stsd
},
1649 {BOX_stss
, 0x00000001, 0x00000000, "sync sample", do_box_stss
},
1650 {BOX_stsz
, 0x00000001, 0x00000000, "sample sizes", do_box_stsz
},
1651 {BOX_stts
, 0x00000001, 0x00000000, "decoding time to sample", do_box_stts
},
1652 {BOX_ctts
, 0x00000001, 0x00000000, "composition time to sample", do_box_ctts
},
1653 {BOX_stz2
, 0x00000001, 0x00000000, "compact sample size", NULL
},
1654 {BOX_tkhd
, 0x00000001, 0x00000000, "track header", do_box_tkhd
},
1655 {BOX_traf
, 0x00000001, 0x00000001, "track fragment", NULL
},
1656 {BOX_trak
, 0x00000001, 0x00000001, "track", NULL
},
1657 {BOX_tref
, 0x00000001, 0x00000001, "track reference", NULL
},
1658 {BOX_udta
, 0x00000001, 0x00000001, "user data", NULL
},
1659 {BOX_url
, 0x00090001, 0x00000000, "URL", do_box_url
},
1660 {BOX_vmhd
, 0x00000001, 0x00000000, "video media header", do_box_vmhd
},
1661 {BOX_wide
, 0x00000001, 0x00000000, "reserved space", NULL
},
1662 {BOX_PICT
, 0x00000001, 0x00000000, "QuickDraw picture", do_box_PICT
},
1663 {BOX_PRVW
, 0x00000001, 0x00000000, "preview", do_box_PRVW
},
1664 {BOX_THMB
, 0x00000001, 0x00000000, "thumbnail", do_box_THMB
},
1665 {BOX_asoc
, 0x00010000, 0x00000001, "association", NULL
},
1666 {BOX_cgrp
, 0x00010000, 0x00000001, "colour group", NULL
},
1667 {BOX_cdef
, 0x00010000, 0x00000000, "channel definition", do_box_cdef
},
1668 {BOX_colr
, 0x00010000, 0x00000000, "colour specification", do_box_colr_jp2
},
1669 {BOX_comp
, 0x00010000, 0x00000001, NULL
, NULL
},
1670 {BOX_drep
, 0x00010000, 0x00000001, NULL
, NULL
},
1671 {BOX_dtbl
, 0x00010000, 0x00000001, "data reference", do_box_dtbl
},
1672 {BOX_flst
, 0x00010000, 0x00000000, "fragment list", NULL
},
1673 {BOX_ftbl
, 0x00010000, 0x00000001, "fragment table", NULL
},
1674 {BOX_ihdr
, 0x00010000, 0x00000000, "image header", do_box_ihdr
},
1675 {BOX_jp2c
, 0x00010008, 0x00000000, "contiguous codestream", do_box_jp2c
},
1676 {BOX_jp2h
, 0x00010000, 0x00000001, "JP2 header", NULL
},
1677 {BOX_jpch
, 0x00010000, 0x00000001, "codestream header", NULL
},
1678 {BOX_jplh
, 0x00010000, 0x00000001, "compositing layer header", NULL
},
1679 {BOX_lhdr
, 0x00010000, 0x00000000, "layout object header", NULL
},
1680 {BOX_lbl
, 0x00010000, 0x00000000, "label", do_box_justtext
},
1681 {BOX_lobj
, 0x00010000, 0x00000001, "layout object", NULL
},
1682 {BOX_mhdr
, 0x00010000, 0x00000000, "compound image header", NULL
},
1683 {BOX_nlst
, 0x00010000, 0x00000000, "number list", NULL
},
1684 {BOX_objc
, 0x00010000, 0x00000001, "object", NULL
},
1685 {BOX_ohdr
, 0x00010000, 0x00000000, "object header", NULL
},
1686 {BOX_page
, 0x00010000, 0x00000001, "page", NULL
},
1687 {BOX_pagt
, 0x00010000, 0x00000000, "page table", NULL
},
1688 {BOX_pcol
, 0x00010000, 0x00000001, "page collection", NULL
},
1689 {BOX_phdr
, 0x00010000, 0x00000000, "page header", NULL
},
1690 {BOX_res
, 0x00010000, 0x00000001, "resolution", NULL
},
1691 {BOX_resc
, 0x00010000, 0x00000000, "capture resolution", do_box_resc_resd
},
1692 {BOX_resd
, 0x00010000, 0x00000000, "default display resolution", do_box_resc_resd
},
1693 {BOX_rreq
, 0x00010000, 0x00000000, "reader requirements", do_box_rreq
},
1694 {BOX_scal
, 0x00010000, 0x00000000, "object scale", NULL
},
1695 {BOX_sdat
, 0x00010000, 0x00000001, NULL
, NULL
},
1696 {BOX_uinf
, 0x00010000, 0x00000001, "UUID info", NULL
},
1697 {BOX_ulst
, 0x00010000, 0x00000000, "UUID list", do_box_ulst
},
1698 {BOX_xml
, 0x00010008, 0x00000000, "XML", do_box_xml
},
1699 {BOX_LCHK
, 0x00040000, 0x00000000, "checksum", NULL
},
1700 {BOX_RESI
, 0x00040000, 0x00000000, "residual codestream", NULL
},
1701 {BOX_SPEC
, 0x00040000, 0x00000001, NULL
, NULL
},
1702 {BOX_auxC
, 0x00080000, 0x00000000, "auxiliary type property", NULL
},
1703 {BOX_grpl
, 0x00080000, 0x00000000, "groups list", NULL
},
1704 {BOX_idat
, 0x00080000, 0x00000000, "item data", NULL
},
1705 {BOX_ipco
, 0x00080000, 0x00000001, "item property container", NULL
},
1706 {BOX_ipma
, 0x00080000, 0x00000000, "item property association", NULL
},
1707 {BOX_ipro
, 0x00080000, 0x00000000, "item protection", NULL
},
1708 {BOX_iprp
, 0x00080000, 0x00000001, "item properties", NULL
},
1709 {BOX_ispe
, 0x00080000, 0x00000000, "image spatial extents", do_box_ispe
},
1710 {BOX_hvcC
, 0x00080000, 0x00000000, "HEVC configuration", NULL
},
1711 {BOX_pitm
, 0x00080000, 0x00000000, "primary item", NULL
}
1714 // TODO: These ilst (iTunes metadata?) boxes should probably go in the above
1715 // list, but the logic for finding the right box will be complicated.
1716 // Superboxes are not flagged in this list, because that determination
1717 // is based on their location, not their type.
1718 static const struct box_type_info ilst_box_type_info_arr
[] = {
1719 {BOX_data
, 0x01000000, 0x00000000, "value atom", do_box_data
},
1720 {BOX_name
, 0x01000000, 0x00000000, "name atom", NULL
},
1721 {BOX_blank
, 0x01000000, 0x00000000, "custom metadata item", NULL
},
1722 {BOX_cpil
, 0x01000000, 0x00000000, "compilation", NULL
},
1723 {BOX_gnre
, 0x01000000, 0x00000000, "genre (enumerated)", NULL
},
1724 {BOX_tmpo
, 0x01000000, 0x00000000, "tempo", NULL
},
1725 {BOX_a9ART
, 0x01000000, 0x00000000, "artist", NULL
},
1726 {BOX_a9cmt
, 0x01000000, 0x00000000, "comment", NULL
},
1727 {BOX_a9nam
, 0x01000000, 0x00000000, "name / title", NULL
},
1728 {BOX_a9too
, 0x01000000, 0x00000000, "encoder software", NULL
}
1731 static const struct box_type_info
*find_box_type_info(deark
*c
, lctx
*d
,
1732 u32 boxtype
, int level
)
1737 if(d
->is_bmff
) mask
|= 0x00000001;
1738 if(d
->is_mj2
) mask
|= 0x000000008;
1739 if(d
->is_jp2_jpx_jpm
) mask
|= 0x00010000;
1740 if(d
->is_jpegxt
) mask
|= 0x00040000;
1741 if(d
->is_heif
) mask
|= 0x00080000;
1743 for(k
=0; k
<DE_ARRAYCOUNT(box_type_info_arr
); k
++) {
1744 if(box_type_info_arr
[k
].boxtype
!= boxtype
) continue;
1745 if(level
==0 && (box_type_info_arr
[k
].flags2
& 0x2)) {
1746 // Critical box. Always match.
1747 return &box_type_info_arr
[k
];
1749 if((box_type_info_arr
[k
].flags1
& mask
)==0) continue;
1750 return &box_type_info_arr
[k
];
1755 static const struct box_type_info
*find_ilst_box_type_info(deark
*c
, lctx
*d
,
1760 for(k
=0; k
<DE_ARRAYCOUNT(ilst_box_type_info_arr
); k
++) {
1761 if(ilst_box_type_info_arr
[k
].boxtype
!= boxtype
) continue;
1762 return &ilst_box_type_info_arr
[k
];
1767 static void my_box_identify_fn(deark
*c
, struct de_boxesctx
*bctx
)
1769 const struct box_type_info
*bti
;
1770 lctx
*d
= (lctx
*)bctx
->userdata
;
1771 struct de_boxdata
*curbox
= bctx
->curbox
;
1772 struct de_boxdata
*par
= curbox
->parent
;
1773 struct de_boxdata
*gpar
= NULL
;
1774 int is_ilst_child
= 0;
1776 if(curbox
->boxtype
!= BOX_uuid
) {
1777 curbox
->box_name
= "?";
1784 if((par
&& (par
->boxtype
==BOX_ilst
)) ||
1785 (gpar
&& (gpar
->boxtype
==BOX_ilst
)) )
1791 bti
= find_ilst_box_type_info(c
, d
, curbox
->boxtype
);
1794 bti
= find_box_type_info(c
, d
, curbox
->boxtype
, curbox
->level
);
1798 // So that we don't have to run "find" again in my_box_handler(),
1800 curbox
->box_userdata
= (void*)bti
;
1803 curbox
->box_name
= bti
->name
;
1806 // TODO: Do we need special handling of 'data' boxes?
1809 static int my_box_handler(deark
*c
, struct de_boxesctx
*bctx
)
1811 const struct box_type_info
*bti
;
1812 lctx
*d
= (lctx
*)bctx
->userdata
;
1813 struct de_boxdata
*curbox
= bctx
->curbox
;
1815 if(curbox
->is_uuid
) {
1816 if(!de_memcmp(curbox
->uuid
, g_uuid_cr3_85c0
, 16)) {
1817 curbox
->is_superbox
= 1;
1819 else if(!de_memcmp(curbox
->uuid
, g_uuid_cr3_eaf4
, 16)) {
1820 curbox
->is_superbox
= 1;
1821 curbox
->extra_bytes_before_children
= 8;
1824 return fmtutil_default_box_handler(c
, bctx
);
1829 bti
= (const struct box_type_info
*)curbox
->box_userdata
;
1831 if(bti
&& (bti
->flags2
& 0x1)) {
1832 curbox
->is_superbox
= 1;
1834 else if(d
->is_bmff
&& curbox
->parent
&& (curbox
->parent
->boxtype
==BOX_ilst
)) {
1835 curbox
->is_superbox
= 1;
1838 if(bti
&& bti
->hfn
) {
1839 bti
->hfn(c
, d
, bctx
);
1845 static void de_run_bmff(deark
*c
, de_module_params
*mparams
)
1848 struct de_boxesctx
*bctx
= NULL
;
1849 int skip_autodetect
= 0;
1852 d
= de_malloc(c
, sizeof(lctx
));
1853 bctx
= de_malloc(c
, sizeof(struct de_boxesctx
));
1855 if(de_havemodcode(c
, mparams
, 'T')) {
1857 skip_autodetect
= 1;
1859 if(de_havemodcode(c
, mparams
, 'X')) {
1861 d
->is_jp2_jpx_jpm
= 1;
1862 skip_autodetect
= 1;
1864 if(de_havemodcode(c
, mparams
, 'B')) {
1866 skip_autodetect
= 1;
1869 if(!skip_autodetect
) {
1871 // Try to detect old QuickTime files that don't have an ftyp box.
1872 first_boxtype
= (u32
)de_getu32be(4);
1873 if(first_boxtype
==BOX_mdat
|| first_boxtype
==BOX_moov
||
1874 first_boxtype
==BOX_free
|| first_boxtype
==BOX_wide
||
1875 first_boxtype
==BOX_skip
|| first_boxtype
==BOX_pnot
)
1881 s
= de_get_ext_option(c
, "bmff:maxentries");
1883 d
->max_entries_to_print
= de_atoi64(s
);
1886 d
->max_entries_to_print
= 32;
1888 if(d
->max_entries_to_print
<0) {
1889 d
->max_entries_to_print
= 0;
1892 bctx
->userdata
= (void*)d
;
1893 bctx
->f
= c
->infile
;
1894 bctx
->identify_box_fn
= my_box_identify_fn
;
1895 bctx
->handle_box_fn
= my_box_handler
;
1897 fmtutil_read_boxes_format(c
, bctx
);
1903 static int de_identify_jpeg2000(deark
*c
)
1905 if(!dbuf_memcmp(c
->infile
, 0, "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a", 12))
1910 static void de_help_bmff(deark
*c
)
1912 de_msg(c
, "-opt bmff:maxentries=<n> : Number of sample table entries to print with -d");
1915 void de_module_jpeg2000(deark
*c
, struct deark_module_info
*mi
)
1917 mi
->id
= "jpeg2000";
1918 mi
->desc
= "JPEG 2000 image";
1919 mi
->desc2
= "resources only";
1920 mi
->run_fn
= de_run_bmff
;
1921 mi
->identify_fn
= de_identify_jpeg2000
;
1924 static int de_identify_bmff(deark
*c
)
1928 first_boxtype
= (u32
)de_getu32be(4);
1929 if(first_boxtype
==BOX_ftyp
) return 80;
1930 if(first_boxtype
==BOX_mdat
) return 35;
1931 if(first_boxtype
==BOX_moov
) return 35;
1932 if(first_boxtype
==BOX_skip
) return 10;
1933 if(first_boxtype
==BOX_wide
) return 10;
1934 if(first_boxtype
==BOX_pnot
) return 10;
1935 if(first_boxtype
==BOX_free
) return 9;
1939 void de_module_bmff(deark
*c
, struct deark_module_info
*mi
)
1942 mi
->desc
= "ISO Base Media File Format";
1943 mi
->desc2
= "MP4, QuickTime, etc.";
1944 mi
->id_alias
[0] = "mp4";
1945 mi
->run_fn
= de_run_bmff
;
1946 mi
->identify_fn
= de_identify_bmff
;
1947 mi
->help_fn
= de_help_bmff
;