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>
11 // TODO: Rethink how to subdivide these formats into modules.
12 DE_DECLARE_MODULE(de_module_bmff
);
13 DE_DECLARE_MODULE(de_module_jpeg2000
);
15 typedef struct localctx_struct
{
18 u8 is_jp2_jpx_jpm
, is_jpx
, is_jpm
;
22 i64 max_entries_to_print
;
24 u8 exif_item_id_known
;
25 unsigned int exif_item_id
;
30 typedef void (*handler_fn_type
)(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
);
32 struct box_type_info
{
34 // flags1 is intended to be used to indicate which formats/brands use this box.
35 // 0x00000001 = Generic BMFF (isom brand, etc.)
37 // 0x00010000 = JP2/JPX/JPM
38 // 0x00040000 = JPEG XT
40 // 0x01000000 = Used in ilst boxes
42 // flags2: 0x1 = is_superbox
43 // flags2: 0x2 = critical top-level box (used for format identification)
49 #define BRAND_heic 0x68656963U
50 #define BRAND_isom 0x69736f6dU
51 #define BRAND_mif1 0x6d696631U
52 #define BRAND_mp41 0x6d703431U
53 #define BRAND_mp42 0x6d703432U
54 #define BRAND_M4A 0x4d344120U
55 #define BRAND_jp2 0x6a703220U
56 #define BRAND_jpm 0x6a706d20U
57 #define BRAND_jpx 0x6a707820U
58 #define BRAND_mjp2 0x6d6a7032U
59 #define BRAND_mj2s 0x6d6a3273U
60 #define BRAND_qt 0x71742020U
62 #define BOX_alis 0x616c6973U
63 #define BOX_auxC 0x61757843U
64 #define BOX_co64 0x636f3634U
65 #define BOX_ctts 0x63747473U
66 #define BOX_data 0x64617461U
67 #define BOX_elst 0x656c7374U
68 #define BOX_ftyp 0x66747970U
69 #define BOX_grpl 0x6772706cU
70 #define BOX_hvcC 0x68766343U
71 #define BOX_idat 0x69646174U
72 #define BOX_iinf 0x69696e66U
73 #define BOX_iloc 0x696c6f63U
74 #define BOX_ilst 0x696c7374U
75 #define BOX_infe 0x696e6665U
76 #define BOX_iods 0x696f6473U
77 #define BOX_ipco 0x6970636fU
78 #define BOX_ipma 0x69706d61U
79 #define BOX_ipro 0x6970726fU
80 #define BOX_iprp 0x69707270U
81 #define BOX_iref 0x69726566U
82 #define BOX_ispe 0x69737065U
83 #define BOX_jP 0x6a502020U
84 #define BOX_jp2c 0x6a703263U
85 #define BOX_load 0x6c6f6164U
86 #define BOX_mdat 0x6d646174U
87 #define BOX_mdhd 0x6d646864U
88 #define BOX_mvhd 0x6d766864U
89 #define BOX_name 0x6e616d65U
90 #define BOX_pitm 0x7069746dU
91 #define BOX_pnot 0x706e6f74U
92 #define BOX_rsrc 0x72737263U
93 #define BOX_sbgp 0x73626770U
94 #define BOX_sdtp 0x73647470U
95 #define BOX_sgpd 0x73677064U
96 #define BOX_stsd 0x73747364U
97 #define BOX_tkhd 0x746b6864U
98 #define BOX_uuid 0x75756964U
99 #define BOX_wide 0x77696465U
100 #define BOX_xml 0x786d6c20U
101 #define BOX_PICT 0x50494354U
102 #define BOX_THMB 0x54484d42U
103 #define BOX_PRVW 0x50525657U
105 #define BOX_blank 0x2d2d2d2dU // "----"
106 #define BOX_cpil 0x6370696cU
107 #define BOX_gnre 0x676e7265U
108 #define BOX_tmpo 0x746d706fU
109 #define BOX_a9ART 0xa9415254U
110 #define BOX_a9cmt 0xa9636d74U
111 #define BOX_a9nam 0xa96e616dU
112 #define BOX_a9too 0xa9746f6fU
115 #define BOX_cdef 0x63646566U
116 #define BOX_colr 0x636f6c72U
117 #define BOX_jp2h 0x6a703268U
118 #define BOX_ihdr 0x69686472U
119 #define BOX_res 0x72657320U
120 #define BOX_resc 0x72657363U
121 #define BOX_resd 0x72657364U
122 #define BOX_uinf 0x75696e66U
123 #define BOX_ulst 0x756c7374U
124 #define BOX_url 0x75726c20U
126 #define BOX_jpch 0x6a706368U
127 #define BOX_jplh 0x6a706c68U
128 #define BOX_cgrp 0x63677270U
129 #define BOX_ftbl 0x6674626cU
130 #define BOX_comp 0x636f6d70U
131 #define BOX_asoc 0x61736f63U
132 #define BOX_drep 0x64726570U
133 #define BOX_dtbl 0x6474626cU
134 #define BOX_flst 0x666c7374U
135 #define BOX_lbl 0x6c626c20U
136 #define BOX_nlst 0x6e6c7374U
137 #define BOX_rreq 0x72726571U
139 #define BOX_page 0x70616765U
140 #define BOX_lobj 0x6c6f626aU
141 #define BOX_objc 0x6f626a63U
142 #define BOX_sdat 0x73646174U
143 #define BOX_mhdr 0x6d686472U
144 #define BOX_lhdr 0x6c686472U
145 #define BOX_ohdr 0x6f686472U
146 #define BOX_pagt 0x70616774U
147 #define BOX_pcol 0x70636f6cU
148 #define BOX_phdr 0x70686472U
149 #define BOX_scal 0x7363616cU
150 // BMFF, QuickTime, MP4, ...:
151 #define BOX_cinf 0x63696e66U
152 #define BOX_clip 0x636c6970U
153 #define BOX_dinf 0x64696e66U
154 #define BOX_dref 0x64726566U
155 #define BOX_edts 0x65647473U
156 //#define BOX_extr 0x65787472U // Irregular format?
157 #define BOX_fdsa 0x66647361U
158 #define BOX_fiin 0x6669696eU
159 #define BOX_free 0x66726565U
160 #define BOX_hdlr 0x68646c72U
161 #define BOX_hinf 0x68696e66U
162 #define BOX_hmhd 0x686d6864U
163 #define BOX_hnti 0x686e7469U
164 #define BOX_matt 0x6d617474U
165 #define BOX_mdia 0x6d646961U
166 #define BOX_meco 0x6d65636fU
167 #define BOX_meta 0x6d657461U
168 #define BOX_minf 0x6d696e66U
169 #define BOX_mfra 0x6d667261U
170 #define BOX_moof 0x6d6f6f66U
171 #define BOX_moov 0x6d6f6f76U
172 #define BOX_mvex 0x6d766578U
173 #define BOX_nmhd 0x6e6d6864U
174 #define BOX_paen 0x7061656eU
175 #define BOX_rinf 0x72696e66U
176 #define BOX_schi 0x73636869U
177 #define BOX_sinf 0x73696e66U
178 #define BOX_skip 0x736b6970U
179 #define BOX_smhd 0x736d6864U
180 #define BOX_stbl 0x7374626cU
181 #define BOX_stco 0x7374636fU
182 #define BOX_strd 0x73747264U
183 #define BOX_strk 0x7374726bU
184 #define BOX_stsc 0x73747363U
185 #define BOX_stss 0x73747373U
186 #define BOX_stsz 0x7374737aU
187 #define BOX_stts 0x73747473U
188 #define BOX_stz2 0x73747a32U
189 #define BOX_traf 0x74726166U
190 #define BOX_trak 0x7472616bU
191 #define BOX_tref 0x74726566U
192 #define BOX_udta 0x75647461U
193 #define BOX_vmhd 0x766d6864U
195 #define BOX_LCHK 0x4c43484bU
196 #define BOX_RESI 0x52455349U
197 #define BOX_SPEC 0x53504543U
199 #define CODE_Exif 0x45786966U
200 #define CODE_rICC 0x72494343U
201 #define CODE_prof 0x70726f66U
203 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";
204 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";
206 // Called for each primary or compatible brand.
207 // Brand-specific setup can be done here.
208 static void apply_brand(deark
*c
, lctx
*d
, u32 brand_id
)
212 d
->is_jp2_jpx_jpm
= 1;
216 d
->is_jp2_jpx_jpm
= 1;
220 d
->is_jp2_jpx_jpm
= 1;
239 if((brand_id
>>16) == 0x3367) { // "3g??"
245 // JPEG 2000 signature box (presumably)
246 static void do_box_jP(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
249 struct de_boxdata
*curbox
= bctx
->curbox
;
251 if(curbox
->level
!=0) return;
252 if(curbox
->payload_len
<4) return;
253 n
= (u32
)dbuf_getu32be(bctx
->f
, curbox
->payload_pos
);
255 de_dbg(c
, "found JPEG 2000 signature");
259 static void do_box_ftyp(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
263 i64 num_compat_brands
;
264 struct de_fourcc brand4cc
;
265 struct de_boxdata
*curbox
= bctx
->curbox
;
267 if(curbox
->payload_len
<4) goto done
;
268 dbuf_read_fourcc(bctx
->f
, curbox
->payload_pos
, &brand4cc
, 4, 0x0);
269 d
->major_brand
= brand4cc
.id
;
270 de_dbg(c
, "major brand: '%s'", brand4cc
.id_dbgstr
);
272 apply_brand(c
, d
, d
->major_brand
);
274 if(curbox
->payload_len
<8) goto done
;
275 mver
= dbuf_getu32be(bctx
->f
, curbox
->payload_pos
+4);
276 de_dbg(c
, "minor version: %u", (unsigned int)mver
);
278 if(curbox
->payload_len
<12) goto done
;
279 num_compat_brands
= (curbox
->payload_len
- 8)/4;
281 for(i
=0; i
<num_compat_brands
; i
++) {
282 dbuf_read_fourcc(bctx
->f
, curbox
->payload_pos
+ 8 + i
*4, &brand4cc
, 4, 0x0);
283 if(brand4cc
.id
==0) continue; // Placeholder. Ignore.
284 de_dbg(c
, "compatible brand: '%s'", brand4cc
.id_dbgstr
);
286 apply_brand(c
, d
, brand4cc
.id
);
293 static void do_read_version_and_flags(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
,
294 u8
*version
, u32
*flags
, int dbgflag
)
299 struct de_boxdata
*curbox
= bctx
->curbox
;
301 n
= (u32
)dbuf_getu32be(bctx
->f
, curbox
->payload_pos
);
302 version1
= (u8
)(n
>>24);
303 flags1
= n
&0x00ffffff;
305 de_dbg(c
, "version=%d, flags=0x%06x", (int)version1
, (unsigned int)flags1
);
307 if(version
) *version
= version1
;
308 if(flags
) *flags
= flags1
;
311 // For any box whose entire contents are a UTF-8 text string.
312 static void do_box_justtext(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
314 struct de_boxdata
*curbox
= bctx
->curbox
;
315 de_ucstring
*s
= NULL
;
318 name
= curbox
->box_name
? curbox
->box_name
: "value";
319 s
= ucstring_create(c
);
320 dbuf_read_to_ucstring_n(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
,
321 DE_DBG_MAX_STRLEN
, s
, 0, DE_ENCODING_UTF8
);
322 de_dbg(c
, "%s: \"%s\"", name
, ucstring_getpsz_d(s
));
326 static const char *get_ilst_type_name(unsigned int ns
, unsigned int wkt
)
328 const char *name
= NULL
;
333 case 0: name
="binary"; break;
334 case 1: name
="UTF-8"; break;
335 case 2: name
="UTF-16"; break;
336 case 3: name
="S/JIS"; break;
337 case 4: name
="UTF-8 sort key"; break;
338 case 5: name
="UTF-16 sort key"; break;
339 case 13: name
="JPEG"; break;
340 case 14: name
="PNG"; break;
341 case 21: name
="signed int"; break;
342 case 22: name
="unsigned int"; break;
343 case 23: name
="float32"; break;
344 case 24: name
="float64"; break;
345 case 27: name
="BMP"; break;
346 case 28: name
="metadata atom"; break;
353 static void do_box_data(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
355 unsigned int type_field
, type_namespace
, wkt
;
356 unsigned int cntry
, lang
;
358 struct de_boxdata
*curbox
= bctx
->curbox
;
359 struct de_boxdata
*par
;
360 struct de_boxdata
*gpar
;
361 i64 pos
= curbox
->payload_pos
;
362 de_ucstring
*s
= NULL
;
364 par
= curbox
->parent
;
368 if(gpar
->boxtype
!= BOX_ilst
) goto done
;
370 if(curbox
->payload_len
<8) goto done
;
371 type_field
= (unsigned int)dbuf_getu32be_p(bctx
->f
, &pos
);
372 type_namespace
= type_field
>>24;
373 wkt
= (type_field
& 0x00ffffff); // well-known type (if namespace==0)
374 de_dbg(c
, "type: %u, %u (%s)", type_namespace
, wkt
,
375 get_ilst_type_name(type_namespace
, wkt
));
377 cntry
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
378 lang
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
379 de_dbg(c
, "locale: %u, %u", cntry
, lang
);
381 if(type_namespace
!=0) goto done
;
382 vlen
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
384 if(wkt
==1 || wkt
==4) { // UTF-8
385 s
= ucstring_create(c
);
386 dbuf_read_to_ucstring_n(bctx
->f
, pos
, vlen
,
387 DE_DBG_MAX_STRLEN
, s
, 0, DE_ENCODING_UTF8
);
388 de_dbg(c
, "value: \"%s\"", ucstring_getpsz_d(s
));
390 else if(wkt
==21 && vlen
==1) { // 1-byte signed int
392 n
= (int)(signed char)dbuf_getbyte(bctx
->f
, pos
);
393 de_dbg(c
, "value: %d", n
);
395 else if(wkt
==21 && vlen
==2) { // 2-byte BE signed int
397 n
= (int)dbuf_geti16be(bctx
->f
, pos
);
398 de_dbg(c
, "value: %d", n
);
401 de_dbg_hexdump(c
, bctx
->f
, pos
, vlen
, 256, "value", 0x1);
403 // TODO: There are lots more types
409 static void do_box_hdlr(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
411 de_ucstring
*s
= NULL
;
412 struct de_boxdata
*curbox
= bctx
->curbox
;
413 i64 pos
= curbox
->payload_pos
;
414 struct de_fourcc tmp4cc
;
416 if(curbox
->payload_len
<4) goto done
;
417 do_read_version_and_flags(c
, d
, bctx
, NULL
, NULL
, 1);
419 if(curbox
->payload_len
<24) goto done
;
420 pos
+= 4; // "Predefined"
422 dbuf_read_fourcc(bctx
->f
, pos
, &tmp4cc
, 4, 0x0);
423 de_dbg(c
, "handler type: '%s'", tmp4cc
.id_dbgstr
);
426 pos
+= 12; // reserved
427 if(curbox
->payload_len
<25) goto done
;
428 if(dbuf_getbyte(bctx
->f
, pos
) == 0x00) goto done
;
430 s
= ucstring_create(c
);
431 dbuf_read_to_ucstring_n(bctx
->f
, pos
, curbox
->payload_pos
+ curbox
->payload_len
- pos
,
432 DE_DBG_MAX_STRLEN
, s
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_UTF8
);
433 de_dbg(c
, "metadata type name: \"%s\"", ucstring_getpsz_d(s
));
439 static void do_box_tkhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
446 struct de_boxdata
*curbox
= bctx
->curbox
;
448 if(curbox
->payload_len
<4) return;
450 pos
= curbox
->payload_pos
;
451 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
455 if(curbox
->payload_len
<96) return;
458 if(curbox
->payload_len
<84) return;
461 // creation time, mod time
467 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
468 de_dbg(c
, "track id: %d", (int)n
);
470 pos
+= 4; // reserved
478 pos
+= 4*2; // reserved
480 pos
+= 2; // alternate group
482 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
483 de_dbg(c
, "volume: %.3f", ((double)n
)/256.0);
485 pos
+= 2; // reserved
486 pos
+= 4*9; // matrix
488 w
= dbuf_fmtutil_read_fixed_16_16(bctx
->f
, pos
);
490 h
= dbuf_fmtutil_read_fixed_16_16(bctx
->f
, pos
);
492 de_dbg(c
, "dimensions: %.1f"DE_CHAR_TIMES
"%.1f", w
, h
);
495 static void do_box_vmhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
501 unsigned int graphicsmode
;
502 struct de_boxdata
*curbox
= bctx
->curbox
;
503 i64 pos
= curbox
->payload_pos
;
505 if(curbox
->payload_len
<12) return;
506 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
508 if(version
!=0 || flags
!=0x1) return;
510 graphicsmode
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
511 de_dbg(c
, "graphicsmode: %u", graphicsmode
);
514 clr
[k
] = (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
516 de_dbg(c
, "opcolor: (%d,%d,%d)", (int)clr
[0], (int)clr
[1], (int)clr
[2]);
519 static void do_box_PICT(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
521 struct de_boxdata
*curbox
= bctx
->curbox
;
524 outf
= dbuf_create_output_file(c
, "pict", NULL
, DE_CREATEFLAG_IS_AUX
);
525 dbuf_write_zeroes(outf
, 512);
526 dbuf_copy(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
, outf
);
530 static void do_box_smhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
535 struct de_boxdata
*curbox
= bctx
->curbox
;
536 i64 pos
= curbox
->payload_pos
;
538 if(curbox
->payload_len
<8) return;
539 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
541 if(version
!=0 || flags
!=0x0) return;
543 n
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
544 de_dbg(c
, "balance: %u", n
);
547 static void do_box_mvhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
555 struct de_boxdata
*curbox
= bctx
->curbox
;
557 if(curbox
->payload_len
<4) return;
559 pos
= curbox
->payload_pos
;
560 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
564 if(curbox
->payload_len
<112) return;
567 if(curbox
->payload_len
<100) return;
570 // creation time, mod time
576 timescale
= dbuf_getu32be_p(bctx
->f
, &pos
);
577 de_dbg(c
, "timescale: %d time units per second", (int)timescale
);
581 n
= dbuf_geti64be(bctx
->f
, pos
);
585 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
588 nd
= (double)n
/ (double)timescale
;
591 de_dbg(c
, "duration: %d time units (%.2f seconds)", (int)n
, nd
);
593 nd
= dbuf_fmtutil_read_fixed_16_16(bctx
->f
, pos
);
595 de_dbg(c
, "rate: %.3f", nd
);
597 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
598 de_dbg(c
, "volume: %.3f", ((double)n
)/256.0);
600 pos
+= 2; // reserved
601 pos
+= 4*2; // reserved
602 pos
+= 4*9; // matrix
603 pos
+= 4*6; // pre_defined
605 n
= dbuf_getu32be(bctx
->f
, pos
);
606 de_dbg(c
, "next track id: %d", (int)n
);
609 static void do_box_mdhd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
617 struct de_boxdata
*curbox
= bctx
->curbox
;
619 // TODO: Share code with do_box_mvhd()?
620 if(curbox
->payload_len
<4) return;
622 pos
= curbox
->payload_pos
;
623 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
627 if(curbox
->payload_len
<36) return;
630 if(curbox
->payload_len
<24) return;
633 // creation time, mod time
639 timescale
= dbuf_getu32be_p(bctx
->f
, &pos
);
640 de_dbg(c
, "timescale: %d time units per second", (int)timescale
);
644 n
= dbuf_geti64be(bctx
->f
, pos
);
648 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
651 nd
= (double)n
/ (double)timescale
;
654 de_dbg(c
, "duration: %d time units (%.2f seconds)", (int)n
, nd
);
657 static void do_box_stsc(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
661 struct de_boxdata
*curbox
= bctx
->curbox
;
662 i64 pos
= curbox
->payload_pos
;
663 i64 e_count
, e_to_print
;
667 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
669 if(version
!=0 || flags
!=0) return;
671 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
672 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
674 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
675 if(bytesleft
/12 < e_count
) return;
677 e_to_print
= de_min_int(e_count
, d
->max_entries_to_print
);
679 for(k
=0; k
<e_to_print
; k
++) {
680 i64 first_chunk
, spc
, sdi
;
681 first_chunk
= dbuf_getu32be_p(bctx
->f
, &pos
);
682 spc
= dbuf_getu32be_p(bctx
->f
, &pos
);
683 sdi
= dbuf_getu32be_p(bctx
->f
, &pos
);
684 de_dbg(c
, "entry[%d]: first chunk=%d, samples/chunk=%d, descr. index=%d",
685 (int)k
, (int)first_chunk
, (int)spc
, (int)sdi
);
687 if(e_to_print
< e_count
) {
688 de_dbg(c
, "[%d more entry(s) omitted, starting at %"I64_FMT
"]",
689 (int)(e_count
-e_to_print
), pos
);
693 static void do_box_stsd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
700 struct de_fourcc fmt4cc
;
701 struct de_boxdata
*curbox
= bctx
->curbox
;
703 if(curbox
->payload_len
<8) return;
705 pos
= curbox
->payload_pos
;
706 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
708 if(version
!=0) return;
710 num_entries
= dbuf_getu32be_p(bctx
->f
, &pos
);
711 de_dbg(c
, "number of sample description entries: %d", (int)num_entries
);
714 if(pos
+ 16 >= curbox
->payload_pos
+ curbox
->payload_len
) break;
715 entry_size
= dbuf_getu32be(bctx
->f
, pos
);
716 de_dbg(c
, "sample description entry at %d, len=%d", (int)pos
, (int)entry_size
);
717 if(entry_size
<16) break;
720 dbuf_read_fourcc(bctx
->f
, pos
+4, &fmt4cc
, 4, 0x0);
721 de_dbg(c
, "data format: '%s'", fmt4cc
.id_dbgstr
);
722 de_dbg_indent(c
, -1);
728 // Decode a table of (4- or 8-byte) integers.
729 // Limit to d->max_entries_to_print.
730 static void do_simple_int_table(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
,
731 i64 pos1
, i64 e_count
, i64 e_size
,
732 const char *s1
, const char *s2
)
737 struct de_boxdata
*curbox
= bctx
->curbox
;
740 if(e_count
<=0) return;
741 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
742 if(bytesleft
< e_size
*e_count
) return;
744 e_to_print
= de_min_int(e_count
, d
->max_entries_to_print
);
746 for(k
=0; k
<e_to_print
; k
++) {
750 n
= dbuf_geti64be(bctx
->f
, pos
); pos
+= 8;
753 n
= dbuf_getu32be_p(bctx
->f
, &pos
);
756 de_dbg(c
, "%s[%"I64_FMT
"]: %s=%"I64_FMT
, s1
, k
, s2
, n
);
758 if(e_to_print
< e_count
) {
759 de_dbg(c
, "[%"I64_FMT
" more %s(s) omitted, starting at %"I64_FMT
"]",
760 e_count
-e_to_print
, s1
, pos
);
764 static void do_box_stsz(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
768 struct de_boxdata
*curbox
= bctx
->curbox
;
769 i64 pos
= curbox
->payload_pos
;
772 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
774 if(version
!=0 || flags
!=0) return;
776 s_size
= dbuf_getu32be_p(bctx
->f
, &pos
);
777 de_dbg(c
, "sample size: %u", (unsigned int)s_size
);
778 s_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
779 de_dbg(c
, "sample count: %u", (unsigned int)s_count
);
781 if(s_size
!=0) goto done
;
783 do_simple_int_table(c
, d
, bctx
, pos
, s_count
, 4, "sample", "entry size");
790 static void do_box_stco(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
794 struct de_boxdata
*curbox
= bctx
->curbox
;
795 i64 pos
= curbox
->payload_pos
;
799 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
801 if(version
!=0 || flags
!=0) return;
803 e_size
= (bctx
->curbox
->boxtype
== BOX_co64
) ? 8 : 4;
804 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
805 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
807 do_simple_int_table(c
, d
, bctx
, pos
, e_count
, e_size
, "entry", "chunk offset");
810 static void do_box_stss(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
814 struct de_boxdata
*curbox
= bctx
->curbox
;
815 i64 pos
= curbox
->payload_pos
;
818 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
820 if(version
!=0 || flags
!=0) return;
822 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
823 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
825 do_simple_int_table(c
, d
, bctx
, pos
, e_count
, 4, "entry", "sample number");
828 static void do_box_stts(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
832 struct de_boxdata
*curbox
= bctx
->curbox
;
833 i64 pos
= curbox
->payload_pos
;
834 i64 e_count
, e_to_print
;
838 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
840 if(version
!=0 || flags
!=0) return;
842 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
843 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
845 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
846 if(bytesleft
/8 < e_count
) return;
848 e_to_print
= de_min_int(e_count
, d
->max_entries_to_print
);
850 for(k
=0; k
<e_to_print
; k
++) {
851 i64 s_count
, s_delta
;
852 s_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
853 s_delta
= dbuf_getu32be_p(bctx
->f
, &pos
);
854 de_dbg(c
, "entry[%d]: sample count=%d, delta=%d", (int)k
,
855 (int)s_count
, (int)s_delta
);
857 if(e_to_print
< e_count
) {
858 de_dbg(c
, "[%d more entry(s) omitted, starting at %"I64_FMT
"]",
859 (int)(e_count
-e_to_print
), pos
);
863 static void do_box_ctts(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
867 struct de_boxdata
*curbox
= bctx
->curbox
;
868 i64 pos
= curbox
->payload_pos
;
869 i64 e_count
, e_to_print
;
873 do_read_version_and_flags(c
, d
, bctx
, &version
, &flags
, 1);
875 if(version
>1 || flags
!=0) return;
877 e_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
878 de_dbg(c
, "entry count: %u", (unsigned int)e_count
);
880 bytesleft
= curbox
->payload_pos
+ curbox
->payload_len
- pos
;
881 if(bytesleft
< e_count
*8) return;
883 e_to_print
= e_count
;
884 if(e_to_print
> d
->max_entries_to_print
) {
885 e_to_print
= d
->max_entries_to_print
;
888 for(k
=0; k
<e_to_print
; k
++) {
889 i64 s_count
, s_offset
;
890 s_count
= dbuf_getu32be_p(bctx
->f
, &pos
);
892 s_offset
= dbuf_getu32be_p(bctx
->f
, &pos
);
895 s_offset
= dbuf_geti32be(bctx
->f
, pos
); pos
+= 4;
897 de_dbg(c
, "entry[%d]: sample count=%"I64_FMT
", offset=%"I64_FMT
,
898 (int)k
, s_count
, s_offset
);
900 if(e_to_print
< e_count
) {
901 de_dbg(c
, "[%d more entry(s) omitted, starting at %"I64_FMT
"]",
902 (int)(e_count
-e_to_print
), pos
);
906 static void do_box_full_superbox(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
908 struct de_boxdata
*curbox
= bctx
->curbox
;
910 do_read_version_and_flags(c
, d
, bctx
, NULL
, NULL
, 1);
911 curbox
->extra_bytes_before_children
= 4;
914 static void do_box_meta(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
916 if(bctx
->curbox
->payload_len
>=8) {
917 // The QuickTime spec says 'meta' is not a full box, but in newer files
918 // it is. I don't know how you're supposed to know, but sniffing for
919 // "hdlr" should be good enough.
920 u32 n
= (u32
)dbuf_getu32be(bctx
->f
, bctx
->curbox
->payload_pos
+4);
926 do_box_full_superbox(c
, d
, bctx
);
929 static void do_box_jp2c(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
931 struct de_boxdata
*curbox
= bctx
->curbox
;
933 de_dbg(c
, "JPEG 2000 codestream at %d, len=%d",
934 (int)curbox
->payload_pos
, (int)curbox
->payload_len
);
936 // I think this box is used regardless of the compression format, so make
937 // sure it seems to be in "JPEG 2000" format.
938 // This is a hack -- we could track the compression method instead.
939 if((u32
)dbuf_getu32be(bctx
->f
, curbox
->payload_pos
) != 0xff4fff51U
) {
940 de_dbg(c
, "[non-J2C]");
944 dbuf_create_file_from_slice(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
,
948 static void format_jp2_res(char *buf
, size_t buflen
,
949 i64 num
, i64 denom
, int exponent
)
951 // TODO: Format this better
952 de_snprintf(buf
, buflen
, "(%d/%d)"DE_CHAR_TIMES
"10^%d points/meter",
953 (int)num
, (int)denom
, exponent
);
956 static void do_box_resc_resd(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
960 struct de_boxdata
*curbox
= bctx
->curbox
;
962 i64 pos
= curbox
->payload_pos
;
965 if(curbox
->boxtype
==BOX_resc
)
970 if(curbox
->payload_len
<10) return;
971 vn
= dbuf_getu16be_p(bctx
->f
, &pos
);
972 vd
= dbuf_getu16be_p(bctx
->f
, &pos
);
973 hn
= dbuf_getu16be_p(bctx
->f
, &pos
);
974 hd
= dbuf_getu16be_p(bctx
->f
, &pos
);
975 ve
= (int)(signed char)dbuf_getbyte_p(bctx
->f
, &pos
);
976 he
= (int)(signed char)dbuf_getbyte_p(bctx
->f
, &pos
);
977 format_jp2_res(res_buf
, sizeof(res_buf
), vn
, vd
, ve
);
978 de_dbg(c
, "vert. %s grid res.: %s", name
, res_buf
);
979 format_jp2_res(res_buf
, sizeof(res_buf
), hn
, hd
, he
);
980 de_dbg(c
, "horz. %s grid res.: %s", name
, res_buf
);
983 static const char *get_rreq_sf_name(UI n
)
985 static const u8 ids
[11] = {1, 2, 5, 8, 12, 18, 19, 20, 31, 45, 46};
986 static const char *names
[11] = { "no extensions", "has layers",
987 "cmpr=JPEG 2000/15444-1", "no opacity", "contiguous",
988 "layers not req'd", "discrete layers", "1 codestream per layer",
989 "scaling not req'd", "sRGB", "sRGB-gray" };
992 for(i
=0; i
<DE_ARRAYCOUNT(ids
); i
++) {
993 if((UI
)ids
[i
]==n
) return names
[i
];
998 static void do_box_rreq(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1000 i64 pos
= bctx
->curbox
->payload_pos
;
1001 i64 endpos
= pos
+ bctx
->curbox
->payload_len
;
1007 if(pos
>=endpos
) goto done
;
1008 ml
= (UI
)dbuf_getbyte_p(bctx
->f
, &pos
);
1009 de_dbg(c
, "ml: %u bytes", ml
);
1010 if(ml
<1 || ml
>8) goto done
;
1012 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1014 de_dbg(c
, "fuam: 0x%"U64_FMTx
, msk
);
1016 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1018 de_dbg(c
, "dcm: 0x%"U64_FMTx
, msk
);
1020 nsf
= dbuf_getu16be_p(bctx
->f
, &pos
);
1021 de_dbg(c
, "nsf: %d", (int)nsf
);
1023 for(i
=0; i
<nsf
; i
++) {
1026 if(pos
>=endpos
) goto done
;
1027 sf
= (UI
)dbuf_getu16be_p(bctx
->f
, &pos
);
1028 de_dbg(c
, "sf[%d]: %u (%s)", (int)i
, sf
, get_rreq_sf_name(sf
));
1030 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1032 de_dbg(c
, "sm[%d]: 0x%"U64_FMTx
, (int)i
, msk
);
1035 if(pos
>=endpos
) goto done
;
1036 nvf
= dbuf_getu16be_p(bctx
->f
, &pos
);
1037 de_dbg(c
, "nvf: %d", (int)nvf
);
1039 for(i
=0; i
<nvf
; i
++) {
1041 char uuid_string
[50];
1043 if(pos
>=endpos
) goto done
;
1044 dbuf_read(bctx
->f
, ubuf
, pos
, 16);
1045 fmtutil_render_uuid(c
, ubuf
, uuid_string
, sizeof(uuid_string
));
1046 de_dbg(c
, "vf[%d]: {%s}", (int)i
, uuid_string
);
1049 msk
= (u64
)dbuf_getint_ext(bctx
->f
, pos
, ml
, 0, 0);
1051 de_dbg(c
, "vm[%d]: 0x%"U64_FMTx
, (int)i
, msk
);
1058 static const char *get_jpeg2000_cmpr_name(deark
*c
, lctx
*d
, u8 ct
)
1060 const char *name
= NULL
;
1062 if(ct
==7) { name
="JPEG 2000"; goto done
; }
1065 case 0: name
="uncompressed"; break;
1066 case 1: name
="MH"; break;
1067 case 2: name
="MR"; break;
1068 case 3: name
="MMR"; break;
1069 case 4: name
="JBIG bi-level"; break;
1070 case 5: name
="JPEG"; break;
1071 case 6: name
="JPEG-LS"; break;
1072 case 8: name
="JBIG2"; break;
1073 case 9: name
="JBIG"; break;
1082 static void do_box_ihdr(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1086 struct de_boxdata
*curbox
= bctx
->curbox
;
1087 i64 pos
= curbox
->payload_pos
;
1090 if(curbox
->payload_len
<14) return;
1091 h
= dbuf_getu32be_p(bctx
->f
, &pos
);
1092 w
= dbuf_getu32be_p(bctx
->f
, &pos
);
1093 de_dbg_dimensions(c
, w
, h
);
1095 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
1096 de_dbg(c
, "number of components: %d", (int)n
);
1098 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1100 de_strlcpy(tmps
, "various", sizeof(tmps
));
1103 de_snprintf(tmps
, sizeof(tmps
), "%u bits/comp., %ssigned",
1104 (unsigned int)(1+(b
&0x7f)), (b
&0x80)?"":"un");
1106 de_dbg(c
, "bits-per-component code: %u (%s)", (unsigned int)b
, tmps
);
1108 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1109 de_dbg(c
, "compression type: %u (%s)", (unsigned int)b
,
1110 get_jpeg2000_cmpr_name(c
, d
, b
));
1112 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1113 de_dbg(c
, "colorspace-is-unknown flag: %d", (int)b
);
1114 b
= dbuf_getbyte_p(bctx
->f
, &pos
);
1115 de_dbg(c
, "has-IPR: %d", (int)b
);
1118 static const char *get_channel_type_name(i64 t
)
1122 case 0: name
= "colour image data for associated color"; break;
1123 case 1: name
= "opacity"; break;
1124 case 2: name
= "premultiplied opacity"; break;
1125 case 65535: name
= "not specified"; break;
1126 default: name
= "?";
1131 static void do_box_cdef(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1134 struct de_boxdata
*curbox
= bctx
->curbox
;
1135 i64 pos
= curbox
->payload_pos
;
1138 ndescs
= dbuf_getu16be_p(bctx
->f
, &pos
);
1139 de_dbg(c
, "number of channel descriptions: %d", (int)ndescs
);
1141 for(k
=0; k
<ndescs
; k
++) {
1144 if(pos
+6 > curbox
->payload_pos
+ curbox
->payload_len
) break;
1145 de_dbg(c
, "channel description[%d] at %"I64_FMT
, (int)k
, pos
);
1146 de_dbg_indent(c
, 1);
1147 idx
= dbuf_getu16be_p(bctx
->f
, &pos
);
1148 de_dbg(c
, "channel index: %d", (int)idx
);
1149 typ
= dbuf_getu16be_p(bctx
->f
, &pos
);
1150 de_dbg(c
, "channel type: %d (%s)", (int)typ
, get_channel_type_name(typ
));
1151 asoc
= dbuf_getu16be_p(bctx
->f
, &pos
);
1152 de_dbg(c
, "index of associated color: %d", (int)asoc
);
1153 de_dbg_indent(c
, -1);
1157 // BMFF-style 'colr' box
1158 static void do_box_colr_bmff(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1160 struct de_boxdata
*curbox
= bctx
->curbox
;
1161 i64 pos
= curbox
->payload_pos
;
1162 struct de_fourcc ct4cc
; // colour_type
1164 if(curbox
->payload_len
<4) goto done
;
1166 dbuf_read_fourcc(bctx
->f
, pos
, &ct4cc
, 4, 0x0);
1167 de_dbg(c
, "colour type: '%s'", ct4cc
.id_dbgstr
);
1170 if(ct4cc
.id
==CODE_rICC
|| ct4cc
.id
==CODE_prof
) {
1171 dbuf_create_file_from_slice(bctx
->f
, pos
,
1172 curbox
->payload_pos
+curbox
->payload_len
-pos
,
1173 "icc", NULL
, DE_CREATEFLAG_IS_AUX
);
1180 // JP2/JPX-style 'colr' box
1181 static void do_box_colr_jp2(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1184 struct de_boxdata
*curbox
= bctx
->curbox
;
1185 i64 pos
= curbox
->payload_pos
;
1188 if(curbox
->payload_len
<3) goto done
;
1189 meth
= dbuf_getbyte_p(bctx
->f
, &pos
);
1191 case 1: s
="enumerated"; break;
1192 case 2: s
="ICC profile (restricted)"; break;
1193 case 3: s
="ICC profile (any)"; break; // JPX only
1194 case 4: s
="vendor"; break; // JPX only
1197 de_dbg(c
, "specification method: %d (%s)", (int)meth
, s
);
1203 unsigned int enumcs
;
1204 if(curbox
->payload_len
<7) goto done
;
1205 enumcs
= (unsigned int)dbuf_getu32be_p(bctx
->f
, &pos
);
1207 // TODO: There are lots more valid values for JPX.
1208 case 16: s
="sRGB"; break;
1209 case 17: s
="sRGB-like grayscale"; break;
1210 case 18: s
="sYCC"; break;
1213 de_dbg(c
, "enumerated colourspace: %u (%s)", enumcs
, s
);
1215 else if(meth
==2 || meth
==3) {
1216 dbuf_create_file_from_slice(bctx
->f
,
1217 curbox
->payload_pos
+3, curbox
->payload_len
-3,
1218 "icc", NULL
, DE_CREATEFLAG_IS_AUX
);
1225 static void do_box_ulst(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1227 struct de_boxdata
*curbox
= bctx
->curbox
;
1228 i64 pos
= curbox
->payload_pos
;
1232 char uuid_string
[50];
1234 nuuids
= dbuf_getu16be_p(bctx
->f
, &pos
);
1235 de_dbg(c
, "number of UUIDs: %d", (int)nuuids
);
1237 for(k
=0; k
<nuuids
; k
++) {
1238 if(pos
+16 > curbox
->payload_pos
+ curbox
->payload_len
) break;
1239 dbuf_read(bctx
->f
, ubuf
, pos
, 16);
1240 fmtutil_render_uuid(c
, ubuf
, uuid_string
, sizeof(uuid_string
));
1241 de_dbg(c
, "UUID[%d]: {%s}", (int)k
, uuid_string
);
1246 static void do_box_url(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1248 de_ucstring
*s
= NULL
;
1249 struct de_boxdata
*curbox
= bctx
->curbox
;
1250 i64 pos
= curbox
->payload_pos
;
1253 do_read_version_and_flags(c
, d
, bctx
, NULL
, &flags
, 1);
1256 // "If the self-contained flag is set, [...] no string is present".
1257 // But there is no flag named "self-contained".
1258 // I assume it is flag 0x1.
1259 if(flags
&0x000001) goto done
;
1261 s
= ucstring_create(c
);
1262 dbuf_read_to_ucstring_n(bctx
->f
,
1263 pos
, curbox
->payload_pos
+ curbox
->payload_len
- pos
, DE_DBG_MAX_STRLEN
,
1264 s
, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_UTF8
);
1265 de_dbg(c
, "URL: \"%s\"", ucstring_getpsz_d(s
));
1267 ucstring_destroy(s
);
1270 static void do_box_dtbl(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1273 struct de_boxdata
*curbox
= bctx
->curbox
;
1275 ndr
= dbuf_getu16be(bctx
->f
, curbox
->payload_pos
);
1276 de_dbg(c
, "number of data references: %d", (int)ndr
);
1278 curbox
->num_children_is_known
= 1;
1279 curbox
->num_children
= ndr
;
1280 curbox
->extra_bytes_before_children
= 2;
1283 static void do_box_dref(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1287 struct de_boxdata
*curbox
= bctx
->curbox
;
1288 i64 pos
= curbox
->payload_pos
;
1290 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1293 nitems
= dbuf_getu32be_p(bctx
->f
, &pos
);
1294 de_dbg(c
, "number of items: %u", (unsigned int)nitems
);
1296 curbox
->num_children_is_known
= 1;
1297 curbox
->num_children
= nitems
;
1298 curbox
->extra_bytes_before_children
= pos
- curbox
->payload_pos
;
1301 static void do_box_iinf(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1305 struct de_boxdata
*curbox
= bctx
->curbox
;
1306 i64 pos
= curbox
->payload_pos
;
1308 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1312 nitems
= dbuf_getu16be_p(bctx
->f
, &pos
);
1315 nitems
= dbuf_getu32be_p(bctx
->f
, &pos
);
1317 de_dbg(c
, "number of items: %d", (int)nitems
);
1319 curbox
->num_children_is_known
= 1;
1320 curbox
->num_children
= nitems
;
1321 curbox
->extra_bytes_before_children
= pos
- curbox
->payload_pos
;
1324 static void extract_exif_item(deark
*c
, lctx
*d
, dbuf
*f
)
1329 if(!d
->exif_item_id_known
) return;
1330 if(d
->exif_item_offs
<=0) return;
1331 if(d
->exif_item_len
<24) return;
1332 // I'm just guessing the format of this item. It seems to start with 10
1333 // bytes of header info.
1334 dpos
= d
->exif_item_offs
+10;
1335 dlen
= d
->exif_item_len
-10;
1336 b0
= dbuf_getbyte(f
, dpos
);
1337 b1
= dbuf_getbyte(f
, dpos
+1);
1338 if(!((b0
=='M' && b1
=='M') || (b0
=='I' && b1
=='I'))) {
1341 de_dbg(c
, "Exif item segment at %"I64_FMT
", size=%"I64_FMT
, dpos
, dlen
);
1342 de_dbg_indent(c
, 1);
1343 fmtutil_handle_exif(c
, dpos
, dlen
);
1344 de_dbg_indent(c
, -1);
1347 static void do_box_iloc(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1350 struct de_boxdata
*curbox
= bctx
->curbox
;
1351 i64 pos
= curbox
->payload_pos
;
1353 unsigned int offset_size
, length_size
, base_offset_size
, index_size
;
1356 int saved_indent_level
;
1358 de_dbg_indent_save(c
, &saved_indent_level
);
1359 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1362 // TODO: Support more versions
1363 if(version
!=1) goto done
;
1365 u
= (unsigned int)dbuf_getbyte_p(bctx
->f
, &pos
);
1367 de_dbg(c
, "offset size: %u", offset_size
);
1368 if(offset_size
!=0 && offset_size
!=4 && offset_size
!=8) goto done
;
1369 length_size
= u
&0xf;
1370 de_dbg(c
, "length size: %u", length_size
);
1371 if(length_size
!=0 && length_size
!=4 && length_size
!=8) goto done
;
1373 u
= (unsigned int)dbuf_getbyte_p(bctx
->f
, &pos
);
1374 base_offset_size
= u
>>4;
1375 de_dbg(c
, "base offset size: %u", base_offset_size
);
1376 if(base_offset_size
!=0 && base_offset_size
!=4 && base_offset_size
!=8) goto done
;
1378 de_dbg(c
, "index size: %u", index_size
);
1379 if(index_size
!=0 && index_size
!=4 && index_size
!=8) goto done
;
1381 item_count
= dbuf_getu16be_p(bctx
->f
, &pos
);
1382 de_dbg(c
, "item count: %d", (int)item_count
);
1384 for(k
=0; k
<item_count
; k
++) {
1385 unsigned int item_id
;
1388 unsigned int cnstr_meth
;
1390 if(pos
>= curbox
->payload_pos
+curbox
->payload_len
) goto done
;
1391 de_dbg(c
, "item[%d] at %"I64_FMT
, (int)k
, pos
);
1392 de_dbg_indent(c
, 1);
1393 item_id
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
1394 de_dbg(c
, "item id: %u", item_id
);
1396 u
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
1398 de_dbg(c
, "construction method: %u", cnstr_meth
);
1400 pos
+= 2; // data reference index
1401 pos
+= base_offset_size
;
1403 extent_count
= dbuf_getu16be_p(bctx
->f
, &pos
);
1404 de_dbg(c
, "extent count: %d", (int)extent_count
);
1406 for(e
=0; e
<extent_count
; e
++) {
1410 if(pos
>= curbox
->payload_pos
+curbox
->payload_len
) goto done
;
1411 de_dbg(c
, "extent[%d]", (int)e
);
1412 de_dbg_indent(c
, 1);
1416 xoffs
= dbuf_getint_ext(bctx
->f
, pos
, offset_size
, 0, 0);
1417 de_dbg(c
, "offset: %"I64_FMT
, xoffs
);
1422 xlen
= dbuf_getint_ext(bctx
->f
, pos
, length_size
, 0, 0);
1423 de_dbg(c
, "length: %"I64_FMT
, xlen
);
1427 if(d
->exif_item_id_known
&& item_id
==d
->exif_item_id
&& extent_count
==1) {
1428 de_dbg(c
, "[Exif item]");
1429 d
->exif_item_offs
= xoffs
;
1430 d
->exif_item_len
= xlen
;
1433 de_dbg_indent(c
, -1);
1436 de_dbg_indent(c
, -1);
1440 if(d
->exif_item_id_known
) {
1441 extract_exif_item(c
, d
, bctx
->f
);
1443 de_dbg_indent_restore(c
, saved_indent_level
);
1446 static void do_box_infe(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1449 struct de_boxdata
*curbox
= bctx
->curbox
;
1450 i64 pos
= curbox
->payload_pos
;
1452 unsigned int item_id
;
1454 do_read_version_and_flags(c
, d
, bctx
, &version
, NULL
, 1);
1457 if(version
==2 || version
==3) {
1458 struct de_fourcc itemtype4cc
;
1461 item_id
= (unsigned int)dbuf_getu16be_p(bctx
->f
, &pos
);
1464 item_id
= (unsigned int)dbuf_getu32be_p(bctx
->f
, &pos
);
1466 de_dbg(c
, "item id: %u", item_id
);
1468 n
= dbuf_getu16be_p(bctx
->f
, &pos
);
1469 de_dbg(c
, "item protection: %u", (unsigned int)n
);
1471 dbuf_read_fourcc(bctx
->f
, pos
, &itemtype4cc
, 4, 0x0);
1473 de_dbg(c
, "item type: '%s'", itemtype4cc
.id_dbgstr
);
1475 if(itemtype4cc
.id
==CODE_Exif
) {
1476 d
->exif_item_id_known
= 1;
1477 d
->exif_item_id
= item_id
;
1480 // TODO: string item_name
1481 // TODO: sometimes there are additional strings after item_name
1485 static void do_box_ispe(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1487 struct de_boxdata
*curbox
= bctx
->curbox
;
1488 i64 pos
= curbox
->payload_pos
;
1491 if(curbox
->payload_len
<12) return;
1492 do_read_version_and_flags(c
, d
, bctx
, NULL
, NULL
, 1);
1494 w
= dbuf_getu32be_p(bctx
->f
, &pos
);
1495 h
= dbuf_getu32be_p(bctx
->f
, &pos
);
1496 de_dbg_dimensions(c
, w
, h
);
1499 static void do_box_xml(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1501 struct de_boxdata
*curbox
= bctx
->curbox
;
1503 // TODO: Detect the specific XML format, and use it to choose a better
1505 de_dbg(c
, "XML data at %d, len=%d", (int)curbox
->payload_pos
, (int)curbox
->payload_len
);
1506 dbuf_create_file_from_slice(bctx
->f
, curbox
->payload_pos
, curbox
->payload_len
,
1507 "xml", NULL
, DE_CREATEFLAG_IS_AUX
);
1510 static void do_box_THMB(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1512 struct de_boxdata
*curbox
= bctx
->curbox
;
1516 if(!curbox
->parent
) return;
1517 if(!curbox
->parent
->is_uuid
) return;
1518 if(de_memcmp(curbox
->parent
->uuid
, g_uuid_cr3_85c0
, 16)) return;
1519 if(curbox
->payload_len
<20) return;
1520 img_pos
= curbox
->payload_pos
+16;
1521 if(dbuf_memcmp(bctx
->f
, img_pos
, "\xff\xd8\xff", 3)) return;
1522 img_len
= dbuf_getu32be(bctx
->f
, curbox
->payload_pos
+8);
1523 de_dbg(c
, "image at %"I64_FMT
", len=%"I64_FMT
, img_pos
, img_len
);
1524 if(img_pos
+img_len
> curbox
->payload_pos
+curbox
->payload_len
) return;
1525 dbuf_create_file_from_slice(bctx
->f
, img_pos
, img_len
, "thumb.jpg", NULL
,
1526 DE_CREATEFLAG_IS_AUX
);
1529 static void do_box_PRVW(deark
*c
, lctx
*d
, struct de_boxesctx
*bctx
)
1531 struct de_boxdata
*curbox
= bctx
->curbox
;
1535 if(!curbox
->parent
) return;
1536 if(!curbox
->parent
->is_uuid
) return;
1537 if(de_memcmp(curbox
->parent
->uuid
, g_uuid_cr3_eaf4
, 16)) return;
1538 if(curbox
->payload_len
<20) return;
1539 img_pos
= curbox
->payload_pos
+16;
1540 if(dbuf_memcmp(bctx
->f
, img_pos
, "\xff\xd8\xff", 3)) return;
1541 img_len
= dbuf_getu32be(bctx
->f
, curbox
->payload_pos
+12);
1542 de_dbg(c
, "image at %"I64_FMT
", len=%"I64_FMT
, img_pos
, img_len
);
1543 if(img_pos
+img_len
> curbox
->payload_pos
+curbox
->payload_len
) return;
1544 dbuf_create_file_from_slice(bctx
->f
, img_pos
, img_len
, "preview.jpg", NULL
,
1545 DE_CREATEFLAG_IS_AUX
);
1548 // The first line that matches will be used, so items related to more-specific
1549 // formats/brands should be listed first.
1550 static const struct box_type_info box_type_info_arr
[] = {
1551 {BOX_ftyp
, 0x00000000, 0x00000002, "file type", do_box_ftyp
},
1552 {BOX_jP
, 0x00010008, 0x00000002, "JPEG 2000 signature", do_box_jP
},
1553 {BOX_mdat
, 0x00000008, 0x00000001, "media data", NULL
},
1554 {BOX_mdat
, 0x00080001, 0x00000000, "media data", NULL
},
1555 {BOX_alis
, 0x00000001, 0x00000000, "Macintosh file alias", NULL
},
1556 {BOX_cinf
, 0x00000001, 0x00000001, "complete track information", NULL
},
1557 {BOX_clip
, 0x00000001, 0x00000001, NULL
, NULL
},
1558 {BOX_co64
, 0x00000001, 0x00000000, "chunk offset", do_box_stco
},
1559 {BOX_colr
, 0x00080001, 0x00000000, "colour information", do_box_colr_bmff
},
1560 {BOX_dinf
, 0x00080001, 0x00000001, "data information", NULL
},
1561 {BOX_dref
, 0x00080001, 0x00000001, "data reference", do_box_dref
},
1562 {BOX_edts
, 0x00000001, 0x00000001, "edit", NULL
},
1563 {BOX_elst
, 0x00000001, 0x00000000, "edit list", NULL
},
1564 {BOX_fdsa
, 0x00000001, 0x00000001, NULL
, NULL
},
1565 {BOX_fiin
, 0x00000001, 0x00000001, "FD item information", NULL
},
1566 {BOX_free
, 0x00090001, 0x00000000, "free space", NULL
},
1567 {BOX_hdlr
, 0x00080001, 0x00000000, "handler reference", do_box_hdlr
},
1568 {BOX_hinf
, 0x00000001, 0x00000001, NULL
, NULL
},
1569 {BOX_hmhd
, 0x00000001, 0x00000000, "hint media header", NULL
},
1570 {BOX_hnti
, 0x00000001, 0x00000001, NULL
, NULL
},
1571 {BOX_iinf
, 0x00080001, 0x00000001, "item info", do_box_iinf
},
1572 {BOX_iloc
, 0x00080001, 0x00000000, "item location", do_box_iloc
},
1573 {BOX_ilst
, 0x00000001, 0x00000001, "metadata item list", NULL
},
1574 {BOX_infe
, 0x00080001, 0x00000000, "item info entry", do_box_infe
},
1575 {BOX_iods
, 0x00000001, 0x00000000, "object descriptor", NULL
},
1576 {BOX_iref
, 0x00080001, 0x00000001, "item reference", do_box_full_superbox
},
1577 {BOX_load
, 0x00000001, 0x00000000, "track load settings", NULL
},
1578 {BOX_matt
, 0x00000001, 0x00000001, NULL
, NULL
},
1579 {BOX_mdhd
, 0x00000001, 0x00000000, "media header", do_box_mdhd
},
1580 {BOX_mdia
, 0x00000001, 0x00000001, "media", NULL
},
1581 {BOX_meco
, 0x00000001, 0x00000001, "additional metadata container", NULL
},
1582 {BOX_meta
, 0x00080001, 0x00000001, "metadata", do_box_meta
},
1583 {BOX_minf
, 0x00000001, 0x00000001, "media information", NULL
},
1584 {BOX_mfra
, 0x00000001, 0x00000001, "movie fragment random access", NULL
},
1585 {BOX_moof
, 0x00000001, 0x00000001, "movie fragment", NULL
},
1586 {BOX_moov
, 0x00000001, 0x00000001, "movie (metadata container)", NULL
},
1587 {BOX_mvex
, 0x00000001, 0x00000001, "movie extends", NULL
},
1588 {BOX_mvhd
, 0x00000001, 0x00000000, "movie header", do_box_mvhd
},
1589 {BOX_nmhd
, 0x00000001, 0x00000000, "null media header", NULL
},
1590 {BOX_paen
, 0x00000001, 0x00000001, NULL
, NULL
},
1591 {BOX_pnot
, 0x00000001, 0x00000000, "reference to movie preview", NULL
},
1592 {BOX_rinf
, 0x00000001, 0x00000001, "restricted scheme information", NULL
},
1593 {BOX_rsrc
, 0x00000001, 0x00000000, "Macintosh resource alias", NULL
},
1594 {BOX_sbgp
, 0x00000001, 0x00000000, "sample-to-group", NULL
},
1595 {BOX_schi
, 0x00000001, 0x00000001, "scheme information", NULL
},
1596 {BOX_sdtp
, 0x00000001, 0x00000000, "independent and disposable samples", NULL
},
1597 {BOX_sgpd
, 0x00000001, 0x00000000, "sample group description", NULL
},
1598 {BOX_sinf
, 0x00000001, 0x00000001, "protection scheme information", NULL
},
1599 {BOX_skip
, 0x00080001, 0x00000000, "user-data", NULL
},
1600 {BOX_smhd
, 0x00000001, 0x00000000, "sound media header", do_box_smhd
},
1601 {BOX_stbl
, 0x00000001, 0x00000001, "sample table", NULL
},
1602 {BOX_stco
, 0x00000001, 0x00000000, "chunk offset", do_box_stco
},
1603 {BOX_strd
, 0x00000001, 0x00000001, "sub track definition", NULL
},
1604 {BOX_strk
, 0x00000001, 0x00000001, "sub track", NULL
},
1605 {BOX_stsc
, 0x00000001, 0x00000000, "sample to chunk", do_box_stsc
},
1606 {BOX_stsd
, 0x00000001, 0x00000000, "sample description", do_box_stsd
},
1607 {BOX_stss
, 0x00000001, 0x00000000, "sync sample", do_box_stss
},
1608 {BOX_stsz
, 0x00000001, 0x00000000, "sample sizes", do_box_stsz
},
1609 {BOX_stts
, 0x00000001, 0x00000000, "decoding time to sample", do_box_stts
},
1610 {BOX_ctts
, 0x00000001, 0x00000000, "composition time to sample", do_box_ctts
},
1611 {BOX_stz2
, 0x00000001, 0x00000000, "compact sample size", NULL
},
1612 {BOX_tkhd
, 0x00000001, 0x00000000, "track header", do_box_tkhd
},
1613 {BOX_traf
, 0x00000001, 0x00000001, "track fragment", NULL
},
1614 {BOX_trak
, 0x00000001, 0x00000001, "track", NULL
},
1615 {BOX_tref
, 0x00000001, 0x00000001, "track reference", NULL
},
1616 {BOX_udta
, 0x00000001, 0x00000001, "user data", NULL
},
1617 {BOX_url
, 0x00090001, 0x00000000, "URL", do_box_url
},
1618 {BOX_vmhd
, 0x00000001, 0x00000000, "video media header", do_box_vmhd
},
1619 {BOX_wide
, 0x00000001, 0x00000000, "reserved space", NULL
},
1620 {BOX_PICT
, 0x00000001, 0x00000000, "QuickDraw picture", do_box_PICT
},
1621 {BOX_PRVW
, 0x00000001, 0x00000000, "preview", do_box_PRVW
},
1622 {BOX_THMB
, 0x00000001, 0x00000000, "thumbnail", do_box_THMB
},
1623 {BOX_asoc
, 0x00010000, 0x00000001, "association", NULL
},
1624 {BOX_cgrp
, 0x00010000, 0x00000001, "colour group", NULL
},
1625 {BOX_cdef
, 0x00010000, 0x00000000, "channel definition", do_box_cdef
},
1626 {BOX_colr
, 0x00010000, 0x00000000, "colour specification", do_box_colr_jp2
},
1627 {BOX_comp
, 0x00010000, 0x00000001, NULL
, NULL
},
1628 {BOX_drep
, 0x00010000, 0x00000001, NULL
, NULL
},
1629 {BOX_dtbl
, 0x00010000, 0x00000001, "data reference", do_box_dtbl
},
1630 {BOX_flst
, 0x00010000, 0x00000000, "fragment list", NULL
},
1631 {BOX_ftbl
, 0x00010000, 0x00000001, "fragment table", NULL
},
1632 {BOX_ihdr
, 0x00010000, 0x00000000, "image header", do_box_ihdr
},
1633 {BOX_jp2c
, 0x00010008, 0x00000000, "contiguous codestream", do_box_jp2c
},
1634 {BOX_jp2h
, 0x00010000, 0x00000001, "JP2 header", NULL
},
1635 {BOX_jpch
, 0x00010000, 0x00000001, "codestream header", NULL
},
1636 {BOX_jplh
, 0x00010000, 0x00000001, "compositing layer header", NULL
},
1637 {BOX_lhdr
, 0x00010000, 0x00000000, "layout object header", NULL
},
1638 {BOX_lbl
, 0x00010000, 0x00000000, "label", do_box_justtext
},
1639 {BOX_lobj
, 0x00010000, 0x00000001, "layout object", NULL
},
1640 {BOX_mhdr
, 0x00010000, 0x00000000, "compound image header", NULL
},
1641 {BOX_nlst
, 0x00010000, 0x00000000, "number list", NULL
},
1642 {BOX_objc
, 0x00010000, 0x00000001, "object", NULL
},
1643 {BOX_ohdr
, 0x00010000, 0x00000000, "object header", NULL
},
1644 {BOX_page
, 0x00010000, 0x00000001, "page", NULL
},
1645 {BOX_pagt
, 0x00010000, 0x00000000, "page table", NULL
},
1646 {BOX_pcol
, 0x00010000, 0x00000001, "page collection", NULL
},
1647 {BOX_phdr
, 0x00010000, 0x00000000, "page header", NULL
},
1648 {BOX_res
, 0x00010000, 0x00000001, "resolution", NULL
},
1649 {BOX_resc
, 0x00010000, 0x00000000, "capture resolution", do_box_resc_resd
},
1650 {BOX_resd
, 0x00010000, 0x00000000, "default display resolution", do_box_resc_resd
},
1651 {BOX_rreq
, 0x00010000, 0x00000000, "reader requirements", do_box_rreq
},
1652 {BOX_scal
, 0x00010000, 0x00000000, "object scale", NULL
},
1653 {BOX_sdat
, 0x00010000, 0x00000001, NULL
, NULL
},
1654 {BOX_uinf
, 0x00010000, 0x00000001, "UUID info", NULL
},
1655 {BOX_ulst
, 0x00010000, 0x00000000, "UUID list", do_box_ulst
},
1656 {BOX_xml
, 0x00010008, 0x00000000, "XML", do_box_xml
},
1657 {BOX_LCHK
, 0x00040000, 0x00000000, "checksum", NULL
},
1658 {BOX_RESI
, 0x00040000, 0x00000000, "residual codestream", NULL
},
1659 {BOX_SPEC
, 0x00040000, 0x00000001, NULL
, NULL
},
1660 {BOX_auxC
, 0x00080000, 0x00000000, "auxiliary type property", NULL
},
1661 {BOX_grpl
, 0x00080000, 0x00000000, "groups list", NULL
},
1662 {BOX_idat
, 0x00080000, 0x00000000, "item data", NULL
},
1663 {BOX_ipco
, 0x00080000, 0x00000001, "item property container", NULL
},
1664 {BOX_ipma
, 0x00080000, 0x00000000, "item property association", NULL
},
1665 {BOX_ipro
, 0x00080000, 0x00000000, "item protection", NULL
},
1666 {BOX_iprp
, 0x00080000, 0x00000001, "item properties", NULL
},
1667 {BOX_ispe
, 0x00080000, 0x00000000, "image spatial extents", do_box_ispe
},
1668 {BOX_hvcC
, 0x00080000, 0x00000000, "HEVC configuration", NULL
},
1669 {BOX_pitm
, 0x00080000, 0x00000000, "primary item", NULL
}
1672 // TODO: These ilst (iTunes metadata?) boxes should probably go in the above
1673 // list, but the logic for finding the right box will be complicated.
1674 // Superboxes are not flagged in this list, because that determination
1675 // is based on their location, not their type.
1676 static const struct box_type_info ilst_box_type_info_arr
[] = {
1677 {BOX_data
, 0x01000000, 0x00000000, "value atom", do_box_data
},
1678 {BOX_name
, 0x01000000, 0x00000000, "name atom", NULL
},
1679 {BOX_blank
, 0x01000000, 0x00000000, "custom metadata item", NULL
},
1680 {BOX_cpil
, 0x01000000, 0x00000000, "compilation", NULL
},
1681 {BOX_gnre
, 0x01000000, 0x00000000, "genre (enumerated)", NULL
},
1682 {BOX_tmpo
, 0x01000000, 0x00000000, "tempo", NULL
},
1683 {BOX_a9ART
, 0x01000000, 0x00000000, "artist", NULL
},
1684 {BOX_a9cmt
, 0x01000000, 0x00000000, "comment", NULL
},
1685 {BOX_a9nam
, 0x01000000, 0x00000000, "name / title", NULL
},
1686 {BOX_a9too
, 0x01000000, 0x00000000, "encoder software", NULL
}
1689 static const struct box_type_info
*find_box_type_info(deark
*c
, lctx
*d
,
1690 u32 boxtype
, int level
)
1695 if(d
->is_bmff
) mask
|= 0x00000001;
1696 if(d
->is_mj2
) mask
|= 0x000000008;
1697 if(d
->is_jp2_jpx_jpm
) mask
|= 0x00010000;
1698 if(d
->is_jpegxt
) mask
|= 0x00040000;
1699 if(d
->is_heif
) mask
|= 0x00080000;
1701 for(k
=0; k
<DE_ARRAYCOUNT(box_type_info_arr
); k
++) {
1702 if(box_type_info_arr
[k
].boxtype
!= boxtype
) continue;
1703 if(level
==0 && (box_type_info_arr
[k
].flags2
& 0x2)) {
1704 // Critical box. Always match.
1705 return &box_type_info_arr
[k
];
1707 if((box_type_info_arr
[k
].flags1
& mask
)==0) continue;
1708 return &box_type_info_arr
[k
];
1713 static const struct box_type_info
*find_ilst_box_type_info(deark
*c
, lctx
*d
,
1718 for(k
=0; k
<DE_ARRAYCOUNT(ilst_box_type_info_arr
); k
++) {
1719 if(ilst_box_type_info_arr
[k
].boxtype
!= boxtype
) continue;
1720 return &ilst_box_type_info_arr
[k
];
1725 static void my_box_identify_fn(deark
*c
, struct de_boxesctx
*bctx
)
1727 const struct box_type_info
*bti
;
1728 lctx
*d
= (lctx
*)bctx
->userdata
;
1729 struct de_boxdata
*curbox
= bctx
->curbox
;
1730 struct de_boxdata
*par
= curbox
->parent
;
1731 struct de_boxdata
*gpar
= NULL
;
1732 int is_ilst_child
= 0;
1734 if(curbox
->boxtype
!= BOX_uuid
) {
1735 curbox
->box_name
= "?";
1742 if((par
&& (par
->boxtype
==BOX_ilst
)) ||
1743 (gpar
&& (gpar
->boxtype
==BOX_ilst
)) )
1749 bti
= find_ilst_box_type_info(c
, d
, curbox
->boxtype
);
1752 bti
= find_box_type_info(c
, d
, curbox
->boxtype
, curbox
->level
);
1756 // So that we don't have to run "find" again in my_box_handler(),
1758 curbox
->box_userdata
= (void*)bti
;
1761 curbox
->box_name
= bti
->name
;
1764 // TODO: Do we need special handling of 'data' boxes?
1767 static int my_box_handler(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
;
1773 if(curbox
->is_uuid
) {
1774 if(!de_memcmp(curbox
->uuid
, g_uuid_cr3_85c0
, 16)) {
1775 curbox
->is_superbox
= 1;
1777 else if(!de_memcmp(curbox
->uuid
, g_uuid_cr3_eaf4
, 16)) {
1778 curbox
->is_superbox
= 1;
1779 curbox
->extra_bytes_before_children
= 8;
1782 return fmtutil_default_box_handler(c
, bctx
);
1787 bti
= (const struct box_type_info
*)curbox
->box_userdata
;
1789 if(bti
&& (bti
->flags2
& 0x1)) {
1790 curbox
->is_superbox
= 1;
1792 else if(d
->is_bmff
&& curbox
->parent
&& (curbox
->parent
->boxtype
==BOX_ilst
)) {
1793 curbox
->is_superbox
= 1;
1796 if(bti
&& bti
->hfn
) {
1797 bti
->hfn(c
, d
, bctx
);
1803 static void de_run_bmff(deark
*c
, de_module_params
*mparams
)
1806 struct de_boxesctx
*bctx
= NULL
;
1807 int skip_autodetect
= 0;
1810 d
= de_malloc(c
, sizeof(lctx
));
1811 bctx
= de_malloc(c
, sizeof(struct de_boxesctx
));
1813 if(de_havemodcode(c
, mparams
, 'T')) {
1815 skip_autodetect
= 1;
1817 if(de_havemodcode(c
, mparams
, 'X')) {
1819 d
->is_jp2_jpx_jpm
= 1;
1820 skip_autodetect
= 1;
1822 if(de_havemodcode(c
, mparams
, 'B')) {
1824 skip_autodetect
= 1;
1827 if(!skip_autodetect
) {
1829 // Try to detect old QuickTime files that don't have an ftyp box.
1830 first_boxtype
= (u32
)de_getu32be(4);
1831 if(first_boxtype
==BOX_mdat
|| first_boxtype
==BOX_moov
||
1832 first_boxtype
==BOX_free
|| first_boxtype
==BOX_wide
||
1833 first_boxtype
==BOX_skip
|| first_boxtype
==BOX_pnot
)
1839 s
= de_get_ext_option(c
, "bmff:maxentries");
1841 d
->max_entries_to_print
= de_atoi64(s
);
1844 d
->max_entries_to_print
= 32;
1846 if(d
->max_entries_to_print
<0) {
1847 d
->max_entries_to_print
= 0;
1850 bctx
->userdata
= (void*)d
;
1851 bctx
->f
= c
->infile
;
1852 bctx
->identify_box_fn
= my_box_identify_fn
;
1853 bctx
->handle_box_fn
= my_box_handler
;
1855 fmtutil_read_boxes_format(c
, bctx
);
1861 static int de_identify_jpeg2000(deark
*c
)
1863 if(!dbuf_memcmp(c
->infile
, 0, "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a", 12))
1868 static void de_help_bmff(deark
*c
)
1870 de_msg(c
, "-opt bmff:maxentries=<n> : Number of sample table entries to print with -d");
1873 void de_module_jpeg2000(deark
*c
, struct deark_module_info
*mi
)
1875 mi
->id
= "jpeg2000";
1876 mi
->desc
= "JPEG 2000 image";
1877 mi
->desc2
= "resources only";
1878 mi
->run_fn
= de_run_bmff
;
1879 mi
->identify_fn
= de_identify_jpeg2000
;
1882 static int de_identify_bmff(deark
*c
)
1886 first_boxtype
= (u32
)de_getu32be(4);
1887 if(first_boxtype
==BOX_ftyp
) return 80;
1888 if(first_boxtype
==BOX_mdat
) return 35;
1889 if(first_boxtype
==BOX_moov
) return 35;
1890 if(first_boxtype
==BOX_skip
) return 10;
1891 if(first_boxtype
==BOX_wide
) return 10;
1892 if(first_boxtype
==BOX_pnot
) return 10;
1893 if(first_boxtype
==BOX_free
) return 9;
1897 void de_module_bmff(deark
*c
, struct deark_module_info
*mi
)
1900 mi
->desc
= "ISO Base Media File Format";
1901 mi
->desc2
= "MP4, QuickTime, etc.";
1902 mi
->id_alias
[0] = "mp4";
1903 mi
->run_fn
= de_run_bmff
;
1904 mi
->identify_fn
= de_identify_bmff
;
1905 mi
->help_fn
= de_help_bmff
;