2 /* Dump MJ2, JP2 metadata (partial so far) to xml file */
3 /* Callable from mj2_to_metadata */
4 /* Contributed to Open JPEG by Glenn Pearson, contract software developer, U.S. National Library of Medicine.
6 The base code in this file was developed by the author as part of a video archiving
7 project for the U.S. National Library of Medicine, Bethesda, MD.
8 It is the policy of NLM (and U.S. government) to not assert copyright.
10 A non-exclusive copy of this code has been contributed to the Open JPEG project.
11 Except for copyright, inclusion of the code within Open JPEG for distribution and use
12 can be bound by the Open JPEG open-source license and disclaimer, expressed elsewhere.
15 #include <windows.h> /* for time functions */
17 #include "opj_includes.h"
23 static BOOL notes = TRUE;
24 static BOOL sampletables = FALSE;
25 static BOOL raw = TRUE;
26 static BOOL derived = TRUE;
28 opj_tcp_t *j2k_default_tcp;
31 int xml_write_overall_header(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr);
32 int xml_write_moov(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr);
34 void uint_to_chars(unsigned int value, char* buf);
36 void xml_write_trak(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum, unsigned int sampleframe, opj_event_mgr_t *event_mgr);
37 void xml_write_tkhd(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
38 void xml_write_udta(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
39 void xml_write_mdia(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
40 void xml_write_stbl(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
42 void UnixTimeToFileTime(time_t t, LPFILETIME pft);
43 void UnixTimeToSystemTime(time_t t, LPSYSTEMTIME pst);
44 void xml_time_out(FILE* xmlout, time_t t);
46 void int16_to_3packedchars(short int value, char* buf);
48 void xml_write_moov_udta(FILE* xmlout, opj_mj2_t * movie);
49 void xml_write_free_and_skip(FILE* xmlout, opj_mj2_t * movie);
50 void xml_write_uuid(FILE* xmlout, opj_mj2_t * movie);
52 int xml_out_frame(FILE* file, FILE* xmlout, mj2_sample_t *sample, unsigned int snum, opj_event_mgr_t *event_mgr);
54 void xml_out_frame_siz(FILE* xmlout, opj_image_t *img, opj_cp_t *cp);
55 void xml_out_frame_cod(FILE* xmlout, opj_tcp_t *tcp);
56 void xml_out_frame_coc(FILE* xmlout, opj_tcp_t *tcp, int numcomps); /* opj_image_t *img); */
57 BOOL same_component_style(opj_tccp_t *tccp1, opj_tccp_t *tccp2);
58 void xml_out_frame_qcd(FILE* xmlout, opj_tcp_t *tcp);
59 void xml_out_frame_qcc(FILE* xmlout, opj_tcp_t *tcp, int numcomps); /* opj_image_t *img); */
60 BOOL same_component_quantization(opj_tccp_t *tccp1, opj_tccp_t *tccp2);
61 void xml_out_frame_rgn(FILE* xmlout, opj_tcp_t *tcp, int numcomps);/* opj_image_t *img);*/
62 void xml_out_frame_poc(FILE* xmlout, opj_tcp_t *tcp);
63 void xml_out_frame_ppm(FILE* xmlout, opj_cp_t *cp);
64 void xml_out_frame_ppt(FILE* xmlout, opj_tcp_t *tcp);
65 void xml_out_frame_tlm(FILE* xmlout); /* j2k_default_tcp is passed globally */ /* NO-OP. TLM NOT SAVED IN DATA STRUCTURE */
66 void xml_out_frame_plm(FILE* xmlout); /* j2k_default_tcp is passed globally */ /* NO-OP. PLM NOT SAVED IN DATA STRUCTURE. opt in main; can be used in conjunction with PLT */
67 void xml_out_frame_plt(FILE* xmlout, opj_tcp_t *tcp); /* NO-OP. PLM NOT SAVED IN DATA STRUCTURE. opt in main; can be used in conjunction with PLT */
68 void xml_out_frame_crg(FILE* xmlout); /* j2k_default_tcp is passed globally */ /* opt in main; */
69 void xml_out_frame_com(FILE* xmlout, opj_tcp_t *tcp); /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */ /* opt in main; */
70 void xml_out_dump_hex(FILE* xmlout, char *data, int data_len, char* s);
71 void xml_out_dump_hex_and_ascii(FILE* xmlout, char *data, int data_len, char* s);
72 void xml_out_frame_jp2h(FILE* xmlout, opj_jp2_t *jp2_struct);
74 /* Shown with cp, extended, as data structure... but it could be a new different one */
75 void xml_out_frame_jp2i(FILE* xmlout, opj_cp_t *cp);/* IntellectualProperty 'jp2i' (no restrictions on location) */
76 void xml_out_frame_xml(FILE* xmlout, opj_cp_t *cp); /* XML 'xml\040' (0x786d6c20). Can appear multiply */
77 void xml_out_frame_uuid(FILE* xmlout, opj_cp_t *cp); /* UUID 'uuid' (top level only) */
78 void xml_out_frame_uinf(FILE* xmlout, opj_cp_t *cp); /* UUIDInfo 'uinf', includes UUIDList 'ulst' and URL 'url\40' */
79 void xml_out_frame_unknown_type(FILE* xmlout, opj_cp_t *cp);
83 void xml_write_init(BOOL n, BOOL t, BOOL r, BOOL d)
85 /* Init file globals */
92 int xml_write_struct(FILE* file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, char* stringDTD, opj_event_mgr_t *event_mgr) {
96 fprintf(xmlout,"<?xml version=\"1.0\" standalone=\"no\"?>\n");
97 /* stringDTD is known to start with "SYSTEM " or "PUBLIC " */
98 /* typical: SYSTEM mj2_to_metadata.dtd */
99 stringDTD[6] = '\0'; /* Break into two strings at space, so quotes can be inserted. */
100 fprintf(xmlout,"<!DOCTYPE MJ2_File %s \"%s\">\n", stringDTD, stringDTD+7);
101 stringDTD[6] = ' '; /* restore for sake of debugger or memory allocator */
103 fprintf(xmlout,"<?xml version=\"1.0\" standalone=\"yes\"?>\n");
105 fprintf(xmlout, "<MJ2_File>\n");
106 xml_write_overall_header(file, xmlout, movie, sampleframe, event_mgr);
107 fprintf(xmlout, "</MJ2_File>");
113 int xml_write_overall_header(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr)
119 fprintf(xmlout, " <JP2 BoxType=\"jP[space][space]\" Signature=\"0x0d0a870a\" />\n");
120 // Called after structure initialized by mj2_read_ftyp
121 fprintf(xmlout, " <FileType BoxType=\"ftyp\">\n");
122 uint_to_chars(movie->brand, buf);
123 fprintf(xmlout, " <Brand>%s</Brand>\n", buf); /* 4 character; BR */
124 fprintf(xmlout, " <MinorVersion>%u</MinorVersion>\n", movie->minversion); /* 4 char; MinV */
125 fprintf(xmlout, " <CompatibilityList Count=\"%d\">\n",movie->num_cl);
126 for (i = movie->num_cl - 1; i > -1; i--) /* read routine stored in reverse order, so let's undo damage */
128 uint_to_chars(movie->cl[i], buf);
129 fprintf(xmlout, " <CompatibleBrand>%s</CompatibleBrand>\n", buf); /*4 characters, each CLi */
131 fprintf(xmlout, " </CompatibilityList>\n");
132 fprintf(xmlout, " </FileType>\n");
133 xml_write_moov(file, xmlout, movie, sampleframe, event_mgr);
134 // To come? <mdat> // This is the container for media data that can also be accessed through track structures,
135 // so is redundant, and simply not of interest as metadata
136 // <moof> // Allows incremental build up of movie. Probably not in Simple Profile
137 xml_write_free_and_skip(xmlout, movie); /* NO OP so far */ /* May be a place where user squirrels metadata */
138 xml_write_uuid(xmlout, movie); /* NO OP so far */ /* May be a place where user squirrels metadata */
144 int xml_write_moov(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr)
149 fprintf(xmlout, " <MovieBox BoxType=\"moov\">\n");
150 fprintf(xmlout, " <MovieHeader BoxType=\"mvhd\">\n");
151 fprintf(xmlout, " <CreationTime>\n");
153 fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", movie->creation_time);
155 fprintf(xmlout, " <!-- Seconds since start of Jan. 1, 1904 UTC (Greenwich) -->\n");
156 /* 2082844800 = seconds between 1/1/04 and 1/1/70 */
157 /* There's still a time zone offset problem not solved... but spec is ambigous as to whether stored time
158 should be local or UTC */
160 fprintf(xmlout, " <AsLocalTime>");
161 xml_time_out(xmlout, movie->creation_time - 2082844800);
162 fprintf(xmlout,"</AsLocalTime>\n");
164 fprintf(xmlout, " </CreationTime>\n");
165 fprintf(xmlout, " <ModificationTime>\n");
167 fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", movie->modification_time);
169 fprintf(xmlout, " <AsLocalTime>");
170 xml_time_out(xmlout, movie->modification_time - 2082844800);
171 fprintf(xmlout,"</AsLocalTime>\n");
173 fprintf(xmlout, " </ModificationTime>\n");
174 fprintf(xmlout, " <Timescale>%d</Timescale>\n", movie->timescale);
176 fprintf(xmlout, " <!-- Timescale defines time units in one second -->\n");
177 fprintf(xmlout, " <Rate>\n"); /* Rate to play presentation (default = 0x00010000) */
179 fprintf(xmlout, " <!-- Rate to play presentation is stored as fixed-point binary 16.16 value. Decimal value is approximation. -->\n");
180 fprintf(xmlout, " <!-- Rate is expressed relative to normal (default) value of 0x00010000 (1.0) -->\n");
183 fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", movie->rate);
185 fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)movie->rate/(double)0x00010000);
186 fprintf(xmlout, " </Rate>\n");
187 fprintf(xmlout, " <Duration>\n");
189 fprintf(xmlout, " <InTimeUnits>%u</InTimeUnits>\n", movie->duration);
191 fprintf(xmlout, " <InSeconds>%12.3f</InSeconds>\n", (double)movie->duration/(double)movie->timescale); // Make this double later to get fractional seconds
192 fprintf(xmlout, " </Duration>\n");
194 movie->volume = movie->volume << 8;
196 fprintf(xmlout, " <Volume>\n");
198 fprintf(xmlout, " <!-- Audio volume stored as fixed-point binary 8.8 value. Decimal value is approximation. -->\n");
199 fprintf(xmlout, " <!-- Full, normal (default) value is 0x0100 (1.0) -->\n");
202 fprintf(xmlout, " <AsHex>0x%04x</AsHex>\n", movie->volume);
204 fprintf(xmlout, " <AsDecimal>%6.3f</AsDecimal>\n", (double)movie->volume/(double)0x0100);
205 fprintf(xmlout, " </Volume>\n");
208 fprintf(xmlout, " <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
209 movie->volume = movie->volume >> 8;
211 /* Transformation matrix for video */
212 fprintf(xmlout, " <TransformationMatrix>\n");
214 fprintf(xmlout, " <!-- 3 x 3 Video Transformation Matrix {a,b,u,c,d,v,x,y,w}. Required: u=0, v=0, w=1 -->\n");
215 fprintf(xmlout, " <!-- Maps decompressed point (p,q) to rendered point (ap + cq + x, bp + dq + y) -->\n");
216 fprintf(xmlout, " <!-- Stored as Fixed Point Hex: all are binary 16.16, except u,v,w are 2.30 -->\n");
217 fprintf(xmlout, " <!-- Unity = 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 -->\n");
219 fprintf(xmlout, " <TMa>0x%08x</TMa>\n", movie->trans_matrix[0]);
220 fprintf(xmlout, " <TMb>0x%08x</TMb>\n", movie->trans_matrix[1]);
221 fprintf(xmlout, " <TMu>0x%08x</TMu>\n", movie->trans_matrix[2]);
222 fprintf(xmlout, " <TMc>0x%08x</TMc>\n", movie->trans_matrix[3]);
223 fprintf(xmlout, " <TMd>0x%08x</TMd>\n", movie->trans_matrix[4]);
224 fprintf(xmlout, " <TMv>0x%08x</TMv>\n", movie->trans_matrix[5]);
225 fprintf(xmlout, " <TMx>0x%08x</TMx>\n", movie->trans_matrix[6]);
226 fprintf(xmlout, " <TMy>0x%08x</TMy>\n", movie->trans_matrix[7]);
227 fprintf(xmlout, " <TMw>0x%08x</TMw>\n", movie->trans_matrix[8]);
228 fprintf(xmlout, " </TransformationMatrix>\n");
229 fprintf(xmlout, " </MovieHeader>\n");
231 fprintf(xmlout, " <Statistics>\n");
232 fprintf(xmlout, " <TracksFound>\n");
233 fprintf(xmlout, " <Video>%d</Video>\n", movie->num_vtk);
234 fprintf(xmlout, " <Audio>%d</Audio>\n", movie->num_stk);
235 fprintf(xmlout, " <Hint>%d</Hint>\n", movie->num_htk);
237 fprintf(xmlout, " <!-- Hint tracks for streaming video are not part of MJ2, but are a defined extension. -->\n");
238 /* See Part 3 Amend 2 Section 4.2 for relation of MJ2 to Part 12 Sections 7 and 10 hints */
239 fprintf(xmlout, " </TracksFound>\n");
240 fprintf(xmlout, " </Statistics>\n");
241 /* Idea for the future: It would be possible to add code to verify that the file values:
242 1) are legal and self-consistent
243 2) comply with particular JP2 and/or MJ2 profiles.
244 This could be reported here as additional XML elements */
246 // Find first video track
248 while (movie->tk[tnum].track_type != 0)
251 track = &(movie->tk[tnum]);
252 // For now, output info on first video track
253 xml_write_trak(file, xmlout, track, tnum, sampleframe, event_mgr);
255 // to come: <MovieExtends mvek> // possibly not in Simple Profile
256 xml_write_moov_udta(xmlout, movie); /* NO OP so far */ /* <UserDataBox udta> contains <CopyrightBox cprt> */
257 fprintf(xmlout, " </MovieBox>\n");
261 /* --------------- */
263 void uint_to_chars(unsigned int value, char* buf)
265 /* buf is at least char[5] */
267 for (i = 3; i >= 0; i--)
269 buf[i] = (value & 0x000000ff);
270 value = (value >> 8);
272 buf[4] = '\0'; /* Precautionary */
277 /* WINDOWS SPECIFIC */
279 void UnixTimeToFileTime(time_t t, LPFILETIME pft)
281 /* Windows specific. From MS Q167296 */
282 /* 'time_t' represents seconds since midnight January 1, 1970 UTC (coordinated universal time). */
283 /* 64-bit FILETIME structure represents the number of 100-nanosecond intervals since January 1, 1601 UTC (coordinate universal time). */
284 LONGLONG ll; /* LONGLONG is a 64-bit value. */
285 ll = Int32x32To64(t, 10000000) + 116444736000000000;
286 pft->dwLowDateTime = (DWORD)ll;
287 /* pft->dwLowDateTime = (DWORD)(0x00000000ffffffff & ll); */
288 pft->dwHighDateTime = (DWORD)(ll >> 32);
290 // Once the UNIX time is converted to a FILETIME structure,
291 // other Win32 time formats can be easily obtained by using Win32 functions such
292 // as FileTimeToSystemTime() and FileTimeToDosDateTime().
296 void UnixTimeToSystemTime(time_t t, LPSYSTEMTIME pst)
298 /* Windows specific */
300 UnixTimeToFileTime(t, &ft);
301 FileTimeToLocalFileTime( &ft, &ft ); /* Adjust from UTC to local time zone */
302 FileTimeToSystemTime(&ft, pst);
307 void xml_time_out(FILE* xmlout, time_t t)
309 /* Windows specific */
311 char szLocalDate[255], szLocalTime[255];
312 UnixTimeToSystemTime( t, &st );
313 GetDateFormat( LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szLocalDate, 255 );
314 GetTimeFormat( LOCALE_USER_DEFAULT, 0, &st, NULL, szLocalTime, 255 );
315 fprintf(xmlout, "%s %s", szLocalDate, szLocalTime );
318 /* END WINDOWS SPECIFIC */
322 void xml_write_moov_udta(FILE* xmlout, opj_mj2_t * movie) {
323 /* Compare with xml_write_udta */
325 /* NO-OP so far. Optional UserData 'udta' (zero or one in moov or each trak)
326 can contain multiple Copyright 'cprt' with different language codes */
327 /* There may be nested non-standard boxes within udta */
328 IMAGINE movie->udta, movie->copyright_count, movie->copyright_language[i] (array of 16bit ints), movie->copyright_notice[i] (array of buffers)
329 PROBABLY ALSO NEED movie->udta_len or special handler for non-standard boxes
334 return; /* Not present */
336 fprintf(xmlout, " <UserData BoxType=\"udta\">\n");
337 for(i = 0; i < movie->copyright_count; i++) {
338 fprintf(xmlout, " <Copyright BoxType=\"cprt\"> Instance=\"%d\">\n", i+1);
339 int16_to_3packedchars((short int)movie->copyright_languages[i], buf);
340 fprintf(xmlout, " <Language>%s</Language>\n", buf); /* 3 chars */
341 fprintf(xmlout, " <Notice>%s</Notice>\n",movie->copyright_notices[i]);
342 fprintf(xmlout, " </Copyright>\n", i+1);
344 /* TO DO: Non-standard boxes */
345 fprintf(xmlout, " </UserData>\n");
349 void xml_write_free_and_skip(FILE* xmlout, opj_mj2_t * movie) {
351 /* NO-OP so far. There can be zero or more instances of free and/or skip
352 at the top level of the file. This may be a place where the user squirrel's metadata.
353 Let's assume unstructured, and do a dump */
354 IMAGINE movie->free_and_skip, movie->free_and_skip_count, movie->free_and_skip_content[i] (array of buffers),
355 movie->free_and_skip_len[i] (array of ints), movie->is_skip[i] (array of BOOL)
358 if(movie->free_and_skip != 1)
359 return; /* Not present */
361 for(i = 0; i < movie->free_and_skip_count; i++) {
362 if(movie->is_skip[i])
363 fprintf(xmlout, " <Skip BoxType=\"skip\">\n");
365 fprintf(xmlout, " <Free BoxType=\"free\">\n");
367 xml_out_dump_hex_and_ascii(xmlout, movie->free_and_skip_contents[i], movie->free_and_skip_len[i]);
369 if(movie->is_skip[i])
370 fprintf(xmlout, " </Skip>\n");
372 fprintf(xmlout, " </Free>\n");
377 void xml_write_uuid(FILE* xmlout, opj_mj2_t * movie) {
378 /* Univeral Unique IDs of 16 bytes. */
380 /* NO-OP so far. There can be zero or more instances of private uuid boxes in a file.
381 This function supports the top level of the file, but uuid may be elsewhere [not yet supported].
382 This may be a place where the user squirrel's metadata. Let's assume unstructured, and do a dump */
383 IMAGINE movie->uuid, movie->uuid_count, movie->uuid_content[i] (array of buffers),
384 movie->uuid_len[i] (array of ints), movie->uuid_type[i] (array of 17-byte (16+null termination) buffers)
388 return; /* Not present */
390 for(i = 0; i < movie->uuid_count; i++) {
391 fprintf(xmlout, " <PrivateExtension BoxType=\"uuid\" UUID=\"%s\">\n", movie->uuid_type[i]);
392 // See Part III section 5.2.1, 6.1, 6.2
393 xml_out_dump_hex_and_ascii(xmlout, movie->uuid_contents[i], movie->uuid_len[i]);
394 fprintf(xmlout, " </PrivateExtension>\n");
401 void xml_write_trak(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum, unsigned int sampleframe, opj_event_mgr_t *event_mgr)
403 fprintf(xmlout, " <Track BoxType=\"trak\" Instance=\"%d\">\n", tnum);
404 xml_write_tkhd(file, xmlout, track, tnum);
405 // TO DO: TrackReferenceContainer 'tref' just used in hint track
406 // TO DO: EditListContainer 'edts', contains EditList 'elst' with media-time, segment-duration, media-rate
407 xml_write_mdia(file, xmlout, track, tnum);
408 xml_write_udta(file, xmlout, track, tnum); // NO-OP so far. Optional UserData 'udta', can contain multiple Copyright 'cprt'
410 if(track->track_type==0) { /* Only do for visual track */
411 /* sampleframe is from user option -f. 1 = first frame */
412 /* sampleframe of 0 is a user requests: no jp2 header */
413 /* Treat out-of-bounds values in the same way */
414 if(sampleframe > 0 && sampleframe <= track->num_samples)
416 mj2_sample_t *sample;
419 snum = sampleframe-1;
420 // Someday maybe do a smart range scan... for (snum=0; snum < track->num_samples; snum++){
421 // fprintf(stdout,"Frame %d: ",snum+1);
422 sample = &track->sample[snum];
423 if(xml_out_frame(file, xmlout, sample, snum, event_mgr))
424 return; /* Not great error handling here */
427 fprintf(xmlout, " </Track>\n");
432 void xml_write_tkhd(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum)
434 fprintf(xmlout, " <TrackHeader BoxType=\"tkhd\">\n");
436 fprintf(xmlout, " <!-- Not shown here: CreationTime, ModificationTime, Duration. -->\n");
437 fprintf(xmlout, " <!-- These 3 fields are reported under MediaHeader below. When reading these 3, -->\n");
438 fprintf(xmlout, " <!-- m2j_to_metadata currently doesn't distinguish between TrackHeader and MediaHeader source. -->\n");
439 fprintf(xmlout, " <!-- If both found, value read from MediaHeader is used. -->\n");
441 fprintf(xmlout, " <TrackID>%u</TrackID>\n", track->track_ID);
442 if(track->track_type==0) /* For visual track */
444 fprintf(xmlout, " <TrackLayer>%d</TrackLayer>\n", track->layer);
446 fprintf(xmlout," <!-- front-to-back ordering of video tracks. 0 = normal, -1 is closer, etc. -->\n");
448 if(track->track_type!=0) /* volume irrelevant for visual track */
451 track->volume = track->volume << 8;
453 fprintf(xmlout, " <Volume>\n");
455 fprintf(xmlout," <!-- Track audio volume stored as fixed-point binary 8.8 value. Decimal value is approximation. -->\n");
456 fprintf(xmlout," <!-- Full, normal (default) value is 0x0100 (1.0) -->\n");
459 fprintf(xmlout," <AsHex>0x%04x</AsHex>\n", track->volume);
461 fprintf(xmlout," <AsDecimal>%6.3f</AsDecimal>\n", (double)track->volume/(double)0x0100);
462 fprintf(xmlout, " </Volume>\n");
465 fprintf(xmlout, " <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
466 track->volume = track->volume >> 8;
469 if(track->track_type==0)
471 /* Transformation matrix for video */
472 fprintf(xmlout, " <TransformationMatrix>\n");
474 fprintf(xmlout," <!-- Comments about matrix in MovieHeader apply here as well. -->\n");
475 fprintf(xmlout," <!-- This matrix is applied before MovieHeader one. -->\n");
477 fprintf(xmlout, " <TMa>0x%08x</TMa>\n", track->trans_matrix[0]);
478 fprintf(xmlout, " <TMb>0x%08x</TMb>\n", track->trans_matrix[1]);
479 fprintf(xmlout, " <TMu>0x%08x</TMu>\n", track->trans_matrix[2]);
480 fprintf(xmlout, " <TMc>0x%08x</TMc>\n", track->trans_matrix[3]);
481 fprintf(xmlout, " <TMd>0x%08x</TMd>\n", track->trans_matrix[4]);
482 fprintf(xmlout, " <TMv>0x%08x</TMv>\n", track->trans_matrix[5]);
483 fprintf(xmlout, " <TMx>0x%08x</TMx>\n", track->trans_matrix[6]);
484 fprintf(xmlout, " <TMy>0x%08x</TMy>\n", track->trans_matrix[7]);
485 fprintf(xmlout, " <TMw>0x%08x</TMw>\n", track->trans_matrix[8]);
486 fprintf(xmlout, " </TransformationMatrix>\n");
489 track->w = track->w << 16;
490 track->h = track->h << 16;
493 fprintf(xmlout, " <!-- Width and Height in pixels are for the presentation; frames will be scaled to this. -->\n");
494 fprintf(xmlout, " <!-- Both stored as fixed-point binary 16.16 values. Decimal values are approximations. -->\n");
496 fprintf(xmlout, " <Width>\n");
498 fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->w);
500 fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->w/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
501 fprintf(xmlout, " </Width>\n");
502 fprintf(xmlout, " <Height>\n");
504 fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->h);
506 fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->h/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
507 fprintf(xmlout, " </Height>\n");
510 fprintf(xmlout, " <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
511 fprintf(xmlout, " <!-- Also, width and height values shown here will actually be those read from track's <VisualSampleEntry> if given. -->\n");
513 track->w = track->w >> 16;
514 track->h = track->h >> 16;
516 fprintf(xmlout, " </TrackHeader>\n");
521 void xml_write_udta(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum) {
522 /* NO-OP so far. Optional UserData 'udta' (zero or one in moov or each trak)
523 can contain multiple Copyright 'cprt' with different language codes */
524 /* There may be nested non-standard boxes within udta */
526 IMAGINE track->udta, track->copyright_count, track->copyright_language[i] (array of 16bit ints), track->copyright_notice[i] (array of buffers)
527 PROBABLY ALSO NEED track->udta_len or special handler for non-standard boxes
532 return; /* Not present */
534 fprintf(xmlout, " <UserData BoxType=\"udta\">\n");
535 for(i = 0; i < track->copyright_count; i++) {
536 fprintf(xmlout, " <Copyright BoxType=\"cprt\"> Instance=\"%d\">\n", i+1);
537 int16_to_3packedchars((short int)track->copyright_languages[i], buf);
538 fprintf(xmlout, " <Language>%s</Language>\n", buf); /* 3 chars */
539 fprintf(xmlout, " <Notice>%s</Notice>\n",track->copyright_notices[i]);
540 fprintf(xmlout, " </Copyright>\n", i+1);
542 /* TO DO: Non-standard boxes */
543 fprintf(xmlout, " </UserData>\n");
549 void xml_write_mdia(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum)
555 fprintf(xmlout, " <Media BoxType=\"mdia\">\n");
556 fprintf(xmlout, " <MediaHeader BoxType=\"mdhd\">\n");
557 fprintf(xmlout, " <CreationTime>\n");
559 fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", track->creation_time);
561 fprintf(xmlout, " <!-- Seconds since start of Jan. 1, 1904 UTC (Greenwich) -->\n");
562 /* 2082844800 = seconds between 1/1/04 and 1/1/70 */
563 /* There's still a time zone offset problem not solved... but spec is ambigous as to whether stored time
564 should be local or UTC */
566 fprintf(xmlout, " <AsLocalTime>");
567 xml_time_out(xmlout, track->creation_time - 2082844800);
568 fprintf(xmlout,"</AsLocalTime>\n");
570 fprintf(xmlout, " </CreationTime>\n");
571 fprintf(xmlout, " <ModificationTime>\n");
573 fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", track->modification_time);
575 fprintf(xmlout, " <AsLocalTime>");
576 xml_time_out(xmlout, track->modification_time - 2082844800);
577 fprintf(xmlout,"</AsLocalTime>\n");
579 fprintf(xmlout, " </ModificationTime>\n");
580 fprintf(xmlout, " <Timescale>%d</Timescale>\n", track->timescale);
582 fprintf(xmlout, " <!-- Timescale defines time units in one second -->\n");
583 fprintf(xmlout, " <Duration>\n");
585 fprintf(xmlout, " <InTimeUnits>%u</InTimeUnits>\n", track->duration);
587 fprintf(xmlout, " <InSeconds>%12.3f</InSeconds>\n", (double)track->duration/(double)track->timescale); // Make this double later to get fractional seconds
588 fprintf(xmlout, " </Duration>\n");
589 int16_to_3packedchars((short int)track->language, buf);
590 fprintf(xmlout, " <Language>%s</Language>\n", buf); /* 3 chars */
591 fprintf(xmlout, " </MediaHeader>\n");
592 fprintf(xmlout, " <HandlerReference BoxType=\"hdlr\">\n");
593 switch(track->track_type)
596 fprintf(xmlout, " <HandlerType Code=\"vide\">video media track</HandlerType>\n"); break;
598 fprintf(xmlout, " <HandlerType Code=\"soun\">Sound</HandlerType>\n"); break;
600 fprintf(xmlout, " <HandlerType Code=\"hint\">Hint</HandlerType>\n"); break;
603 fprintf(xmlout, " <!-- String value shown is not actually read from file. -->\n");
604 fprintf(xmlout, " <!-- Shown value is one used for our encode. -->\n");
606 fprintf(xmlout, " </HandlerReference>\n");
607 fprintf(xmlout, " <MediaInfoContainer BoxType=\"minf\">\n");
608 switch(track->track_type)
611 fprintf(xmlout, " <VideoMediaHeader BoxType=\"vmhd\">\n");
612 fprintf(xmlout, " <GraphicsMode>0x%02x</GraphicsMode>\n", track->graphicsmode);
614 fprintf(xmlout," <!-- Enumerated values of graphics mode: -->\n");
615 fprintf(xmlout," <!-- 0x00 = copy (over existing image); -->\n");
616 fprintf(xmlout," <!-- 0x24 = transparent; 'blue-screen' this image using opcolor; -->\n");
617 fprintf(xmlout," <!-- 0x100 = alpha; alpha-blend this image -->\n");
618 /* fprintf(xmlout," <!-- 0x101 = whitealpha; alpha-blend this image, which has been blended with white; -->\n"); This was evidently dropped upon amendment */
619 fprintf(xmlout," <!-- 0x102 = pre-multiplied black alpha; image has been already been alpha-blended with black. -->\n");
620 fprintf(xmlout," <!-- 0x110 = component alpha; blend alpha channel(s) and color channels individually. -->\n");
622 fprintf(xmlout, " <Opcolor>\n");
623 fprintf(xmlout, " <Red>0x%02x</Red>\n", track->opcolor[0]);
624 fprintf(xmlout, " <Green>0x%02x</Green>\n",track->opcolor[1]);
625 fprintf(xmlout, " <Blue>0x%02x</Blue>\n",track->opcolor[2]);
626 fprintf(xmlout, " </Opcolor>\n");
627 fprintf(xmlout, " </VideoMediaHeader>\n");
630 fprintf(xmlout, " <SoundMediaHeader BoxType=\"smhd\">\n");
632 track->balance = track->balance << 8;
634 fprintf(xmlout, " <Balance>\n");
636 fprintf(xmlout," <!-- Track audio balance fixes mono track in stereo space. -->\n");
637 fprintf(xmlout," <!-- Stored as fixed-point binary 8.8 value. Decimal value is approximation. -->\n");
638 fprintf(xmlout," <!-- 0.0 = center, -1.0 = full left, 1.0 = full right -->\n");
641 fprintf(xmlout," <AsHex>0x%04x</AsHex>\n", track->balance);
643 fprintf(xmlout," <AsDecimal>%6.3f</AsDecimal>\n", (double)track->balance/(double)0x0100);
644 fprintf(xmlout, " </Balance>\n");
647 fprintf(xmlout," <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
648 track->balance = track->balance >> 8;
650 fprintf(xmlout, " </SoundMediaHeader>\n");
653 fprintf(xmlout, " <HintMediaHeader BoxType=\"hmhd\">\n");
654 fprintf(xmlout, " <MaxPDU_Size>%d</MaxPDU_Size>\n", track->maxPDUsize);
656 fprintf(xmlout," <!-- Size in bytes of largest PDU in this hint stream. -->\n");
657 fprintf(xmlout, " <AvgPDU_Size>%d</AvgPDU_Size>\n", track->avgPDUsize);
659 fprintf(xmlout," <!-- Average size in bytes of a PDU over the entire presentation. -->\n");
660 fprintf(xmlout, " <MaxBitRate>%d</MaxBitRate>\n", track->maxbitrate);
662 fprintf(xmlout," <!-- Maximum rate in bits per second over any window of 1 second. -->\n");
663 fprintf(xmlout, " <AvgBitRate>%d</AvgBitRate>\n", track->avgbitrate);
665 fprintf(xmlout," <!-- Averate rate in bits per second over the entire presentation. -->\n");
666 fprintf(xmlout, " <SlidingAvgBit>%d</SlidingAvgBitRate>\n", track->slidingavgbitrate);
668 fprintf(xmlout," <!-- Maximum rate in bits per second over any window of one minute. -->\n");
669 fprintf(xmlout, " </HintMediaHeader>\n");
672 fprintf(xmlout, " <DataInfo BoxType=\"dinf\">\n");
673 fprintf(xmlout, " <DataReference BoxType=\"dref\" URL_Count=\"%d\" URN_Count=\"%d\">\n", track->num_url, track->num_urn); // table w. flags, URLs, URNs
674 // Data structure does not distinguish between single URL, single URN, or DREF table or URLs & URNs.
675 // We could infer those, but for now just present everything as a DREF table.
677 fprintf(xmlout, " <!-- No entries here mean that file is self-contained, as required by Simple Profile. -->\n");
678 for(k = 0; k < track->num_url; k++) {
679 fprintf(xmlout, " <DataEntryUrlBox BoxType=\"url[space]\">\n"); // table w. flags, URLs, URNs
681 fprintf(xmlout," <!-- Only the first 16 bytes of URL location are recorded in mj2_to_metadata data structure. -->\n");
682 for(i = 0; i < 4; i++) {
683 uint_to_chars(track->url[track->num_url].location[i], buf);
684 fprintf(xmlout, " <Location>%s</Location>\n");
686 fprintf(xmlout, " </DataEntryUrlBox>\n"); // table w. flags, URLs, URNs
688 for(k = 0; k < track->num_urn; k++) {
689 fprintf(xmlout," <DataEntryUrnBox BoxType=\"urn[space]\">\n"); // table w. flags, URLs, URNs
690 // Only the first 16 bytes are recorded in the data structure currently.
692 fprintf(xmlout," <!-- Only the first 16 bytes each of URN name and optional location are recorded in mj2_to_metadata data structure. -->\n");
693 fprintf(xmlout, " <Name>");
694 for(i = 0; i < 4; i++) {
695 uint_to_chars(track->urn[track->num_urn].name[i], buf);
696 fprintf(xmlout,"%s", buf);
698 fprintf(xmlout, "</Name>\n");
699 fprintf(xmlout, " <Location>");
700 for(i = 0; i < 4; i++) {
701 uint_to_chars(track->urn[track->num_urn].location[i], buf);
702 fprintf(xmlout,"%s");
704 fprintf(xmlout, "</Location>\n");
705 fprintf(xmlout, " </DataEntryUrnBox>\n");
707 fprintf(xmlout, " </DataReference>\n");
708 fprintf(xmlout, " </DataInfo>\n");
710 xml_write_stbl(file, xmlout, track, tnum); /* SampleTable */
712 fprintf(xmlout, " </MediaInfoContainer>\n");
713 fprintf(xmlout, " </Media>\n");
718 void xml_write_stbl(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum)
720 char buf[5], buf33[33];
724 fprintf(xmlout, " <SampleTable BoxType=\"stbl\">\n");
726 fprintf(xmlout, " <!-- What follows are specific instances of generic SampleDescription BoxType=\"stsd\" -->\n");
727 switch(track->track_type)
730 // There could be multiple instances of this, but "entry_count" is just a local at read-time.
731 // And it's used wrong, too, as count of just visual type, when it's really all 3 types.
732 // This is referred to as "smj2" within mj2.c
733 fprintf(xmlout, " <VisualSampleEntry BoxType=\"mjp2\">\n");
735 fprintf(xmlout, " <!-- If multiple instances of this box, only first is shown here. -->\n");
736 fprintf(xmlout, " <!-- Width and Height are in pixels. Unlike the Track Header, there is no fractional part. -->\n");
737 fprintf(xmlout, " <!-- In mj2_to_metadata implementation, the values are not represented separately from Track Header's values. -->\n");
739 /* No shifting required. If CURRENTSTRUCT gets changed, then may need to revisit treatment of these */
740 fprintf(xmlout, " <WidthAsInteger>%d</WidthAsInteger>\n", track->w);
741 fprintf(xmlout, " <HeightAsInteger>%d</HeightAsInteger>\n", track->h);
742 // Horizresolution and vertresolution don't require shifting, already stored right in CURRENTSTRUCT
744 fprintf(xmlout, " <!-- Resolutions are in pixels per inch, for the highest-resolution component (typically luminance). -->\n");
745 fprintf(xmlout, " <!-- Both stored as fixed-point binary 16.16 values. Decimal values are approximations. -->\n");
746 fprintf(xmlout, " <!-- Typical value for both resolutions is 0x00480000 (72.0) -->\n");
748 fprintf(xmlout, " <HorizontalRes>\n");
750 fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->horizresolution);
752 fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->horizresolution/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
753 fprintf(xmlout, " </HorizontalRes>\n");
754 fprintf(xmlout, " <VerticalRes>\n");
756 fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->vertresolution);
758 fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->vertresolution/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
759 fprintf(xmlout, " </VerticalRes>\n");
762 for(i = 0; i < 8; i++) {
763 uint_to_chars((unsigned int)track->compressorname[i], buf);
764 strcat(buf33, buf); /* This loads up (4 * 8) + 1 chars, but trailing ones are usually junk */
766 len = (int)buf33[0]; /* First byte has string length in bytes. There may be garbage beyond it. */
767 buf33[len+1] = '\0'; /* Suppress it */
768 fprintf(xmlout, " <CompressorName>%s</CompressorName>\n", buf33+1); /* Start beyond first byte */
770 fprintf(xmlout, " <!-- Compressor name for debugging. Standard restricts max length to 31 bytes. -->\n");
771 fprintf(xmlout, " <!-- Usually blank or \"Motion JPEG2000\" -->\n");
773 fprintf(xmlout, " <Depth>0x%02x</Depth>\n",track->depth);
775 fprintf(xmlout, " <!-- Depth is: -->\n");
776 fprintf(xmlout, " <!-- 0x20: alpha channels present (color or grayscale) -->\n");
777 fprintf(xmlout, " <!-- 0x28: grayscale without alpha -->\n");
778 fprintf(xmlout, " <!-- 0x18: color without alpha -->\n");
781 xml_out_frame_jp2h(xmlout, &(track->jp2_struct)); /* JP2 Header */
783 /* Following subboxes are optional */
784 fprintf(xmlout, " <FieldCoding BoxType=\"fiel\">\n");
785 fprintf(xmlout, " <FieldCount>%d</FieldCount>\n", (unsigned int)track->fieldcount); /* uchar as 1 byte uint */
787 fprintf(xmlout, " <!-- Must be either 1 or 2 -->\n");
788 fprintf(xmlout, " <FieldOrder>%d</FieldOrder>\n", (unsigned int)track->fieldorder); /* uchar as 1 byte uint */
790 fprintf(xmlout, " <!-- When FieldCount=2, FieldOrder means: -->\n");
791 fprintf(xmlout, " <!-- 0: Field coding unknown -->\n");
792 fprintf(xmlout, " <!-- 1: Field with topmost line is stored first in sample; fields are in temporal order -->\n");
793 fprintf(xmlout, " <!-- 6: Field with topmost line is stored second in sample; fields are in temporal order -->\n");
794 fprintf(xmlout, " <!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->\n");
795 fprintf(xmlout, " <!-- Current implementation doesn't retain whether box was actually present. -->\n");
797 fprintf(xmlout, " </FieldCoding>\n");
799 fprintf(xmlout, " <MJP2_Profile BoxType=\"jp2p\" Count=\"%d\">\n",track->num_br);
800 for (i = 0; i < track->num_br; i++) /* read routine stored in reverse order, so let's undo damage */
802 uint_to_chars(track->br[i], buf);
803 fprintf(xmlout, " <CompatibleBrand>%s</CompatibleBrand>\n", buf); /*4 characters, each CLi */
805 fprintf(xmlout, " </MJP2_Profile>\n");
807 fprintf(xmlout, " <MJP2_Prefix BoxType=\"jp2x\" Count=\"%d\">\n",track->num_jp2x);
808 for (i = 0; i < track->num_jp2x; i++)
809 { // We'll probably need better formatting than this
810 fprintf(xmlout, " <Data>0x%02x</Data>\n", track->jp2xdata[i]); /* Each entry is single byte */
812 fprintf(xmlout, " </MJP2_Prefix>\n");
814 fprintf(xmlout, " <MJP2_SubSampling BoxType=\"jsub\">\n"); /* These values are all 1 byte */
816 fprintf(xmlout, " <!-- Typical subsample value is 2 for 4:2:0 -->\n");
817 fprintf(xmlout, " <HorizontalSub>%d</HorizontalSub>\n", track->hsub);
818 fprintf(xmlout, " <VerticalSub>%d</VerticalSub>\n", track->vsub);
819 fprintf(xmlout, " <HorizontalOffset>%d</HorizontalOffset>\n", track->hoff);
820 fprintf(xmlout, " <VerticalOffset>%d</VerticalOffset>\n", track->voff);
822 fprintf(xmlout, " <!-- Typical {horizontal, vertical} chroma offset values: -->\n");
823 fprintf(xmlout, " <!-- 4:2:2 format (CCIR601, H.262, MPEG2, MPEG4, recom. Exif): {0, 0} -->\n");
824 fprintf(xmlout, " <!-- 4:2:2 format (JFIF): {1, 0} -->\n");
825 fprintf(xmlout, " <!-- 4:2:0 format (H.262, MPEG2, MPEG4): {0, 1} -->\n");
826 fprintf(xmlout, " <!-- 4:2:0 format (MPEG1, H.261, JFIF, recom. Exif): {1, 1} -->\n");
828 fprintf(xmlout, " </MJP2_SubSampling>\n"); /* These values are all 1 byte */
830 fprintf(xmlout, " <MJP2_OriginalFormat BoxType=\"orfo\">\n"); /* Part III Appx. 2 */
831 fprintf(xmlout, " <OriginalFieldCount>%u</OriginalFieldCount>\n", (unsigned int)track->or_fieldcount); /* uchar as 1-byte uint */
833 fprintf(xmlout, " <!-- In original material before encoding. Must be either 1 or 2 -->\n");
834 fprintf(xmlout, " <OriginalFieldOrder>%u</OriginalFieldOrder>\n", (unsigned int)track->or_fieldorder); /* uchar as 1-byte uint */
836 fprintf(xmlout, " <!-- When FieldCount=2, FieldOrder means: -->\n");
837 fprintf(xmlout, " <!-- 0: Field coding unknown -->\n");
838 fprintf(xmlout, " <!-- 11: Topmost line came from the earlier field; -->\n");
839 fprintf(xmlout, " <!-- 16: Topmost line came form the later field. -->\n");
840 fprintf(xmlout, " <!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->\n");
841 fprintf(xmlout, " <!-- Current implementation doesn't retain whether box was actually present. -->\n");
843 fprintf(xmlout, " </MJP2_OriginalFormat>\n");
844 fprintf(xmlout, " </VisualSampleEntry>\n");
848 fprintf(xmlout, " <!-- mj2_to_metadata's data structure doesn't record this currently. -->\n"); break;
850 fprintf(xmlout, " <TimeToSample BoxType=\"stts\">\n");
851 fprintf(xmlout, " <SampleStatistics>\n");
852 fprintf(xmlout, " <TotalSamples>%d</TotalSamples>\n", track->num_samples);
854 fprintf(xmlout, " <!-- For video, gives the total frames in the track, by summing all entries in the Sample Table -->\n");
855 fprintf(xmlout, " </SampleStatistics>\n");
856 fprintf(xmlout, " <SampleEntries EntryCount=\"%d\">\n", track->num_tts);
857 for (i = 0; i < track->num_tts; i++) {
858 fprintf(xmlout, " <Table Entry=\"%u\" SampleCount=\"%d\" SampleDelta=\"%u\" />\n",
859 i+1, track->tts[i].sample_count, track->tts[i].sample_delta);
861 fprintf(xmlout, " </SampleEntries>\n");
862 fprintf(xmlout, " </TimeToSample>\n");
864 fprintf(xmlout, " <SampleToChunk BoxType=\"stsc\" Count=\"%d\">\n", track->num_samplestochunk);
865 for (i = 0; i < track->num_samplestochunk; i++) {
866 fprintf(xmlout, " <FirstChunk>%u</FirstChunk>\n",track->sampletochunk[i].first_chunk); /* 4 bytes */
867 fprintf(xmlout, " <SamplesPerChunk>%u</SamplesPerChunk>\n",track->sampletochunk[i].samples_per_chunk); /* 4 bytes */
868 fprintf(xmlout, " <SampleDescrIndex>%u</SampleDescrIndex>\n",track->sampletochunk[i].sample_descr_idx); /* 4 bytes */
870 fprintf(xmlout, " </SampleToChunk>\n");
871 // After reading this info in, track->num_chunks is calculated and a decompressed table established internally.
873 fprintf(xmlout, " <SampleSize BoxType=\"stsz\">\n");
874 if(track->same_sample_size) {
875 // all values in track->sample[i].sample_size are equal. Grab the first one.
876 fprintf(xmlout, " <Sample_Size>%u</Sample_Size>\n", track->sample[0].sample_size);
878 fprintf(xmlout, " <!-- Non-zero value means all samples have that size. -->\n");
879 fprintf(xmlout, " <!-- So <Sample_Count> (aka Entry_Count in std.) has no meaning, is suppressed from this output, and no table follows. -->\n");
882 fprintf(xmlout, " <Sample_Size>0</Sample_Size>\n");
885 fprintf(xmlout," <!-- Zero value means samples have different sizes, given in table next of length Sample_Count (aka Entry_Count in std). -->\n");
887 fprintf(xmlout," <!-- Zero value means samples have different sizes, given in table (not shown) of length Sample_Count (aka Entry_Count in std). -->\n");
888 fprintf(xmlout, " <Sample_Count>%u</Sample_Count>\n", track->num_samples);
890 for (i = 0; i < (int)track->num_samples; i++) {
891 fprintf(xmlout, " <EntrySize Num=\"%u\">%u</EntrySize>\n", i+1, track->sample[i].sample_size);
894 fprintf(xmlout, " </SampleSize>\n");
896 fprintf(xmlout, " <ChunkOffset BoxType=\"stco\">\n");
897 // Structure not yet - Variant ChunkLargeOffset 'co64'
898 fprintf(xmlout, " <EntryCount>%u</EntryCount>\n", track->num_chunks);
900 fprintf(xmlout, " <!-- For this implementation, EntryCount shown is one calculated during file read of <SampleToChunk> data. -->\n");
901 fprintf(xmlout, " <!-- Implementation will report failure during file read of <ChunkOffset> data if read entry-count disagrees. -->\n");
904 for (i = 0; i < (int)track->num_chunks; i++)
905 fprintf(xmlout, " <Chunk_Offset Num=\"%d\">%u</Chunk_Offset>\n", i+1, track->chunk[i].offset);
906 fprintf(xmlout, " </ChunkOffset>\n");
908 fprintf(xmlout, " </SampleTable>\n");
913 int xml_out_frame(FILE* file, FILE* xmlout, mj2_sample_t *sample, unsigned int snum, opj_event_mgr_t *event_mgr)
915 opj_dparameters_t parameters; /* decompression parameters */
920 unsigned char* frame_codestream;
921 opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
922 opj_cio_t *cio = NULL;
925 /* JPEG 2000 compressed image data */
927 /* get a decoder handle */
928 dinfo = opj_create_decompress(CODEC_J2K);
930 /* catch events using our callbacks and give a local context */
931 opj_set_event_mgr((opj_common_ptr)dinfo, event_mgr, stderr);
933 /* setup the decoder decoding parameters using the current image and user parameters */
934 parameters.cp_limit_decoding = DECODE_ALL_BUT_PACKETS;
935 opj_setup_decoder(dinfo, ¶meters);
937 frame_codestream = (unsigned char*) malloc (sample->sample_size-8); /* Skipping JP2C marker */
938 if(frame_codestream == NULL)
941 fseek(file,sample->offset+8,SEEK_SET);
942 fread(frame_codestream,sample->sample_size-8,1, file); /* Assuming that jp and ftyp markers size do */
944 /* open a byte stream */
945 cio = opj_cio_open((opj_common_ptr)dinfo, frame_codestream, sample->sample_size-8);
947 /* Decode J2K to image: */
948 img = opj_decode(dinfo, cio);
950 fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
951 opj_destroy_decompress(dinfo);
956 j2k = (opj_j2k_t*)dinfo->j2k_handle;
957 j2k_default_tcp = j2k->default_tcp;
960 numcomps = img->numcomps;
961 /* Alignments: " < To help maintain xml pretty-printing */
962 fprintf(xmlout, " <JP2_Frame Num=\"%d\">\n", snum+1);
963 fprintf(xmlout, " <MainHeader>\n");
964 /* There can be multiple codestreams; a particular image is entirely within a single codestream */
965 /* TO DO: A frame can be represented by two I-guess-contigious codestreams if its interleaved. */
966 fprintf(xmlout, " <StartOfCodestream Marker=\"SOC\" />\n");
967 /* "cp" stands for "coding parameter"; "tcp" is tile coding parameters, "tccp" is tile-component coding parameters */
968 xml_out_frame_siz(xmlout, img, cp); /* reqd in main */
969 xml_out_frame_cod(xmlout, j2k_default_tcp); /* reqd in main */
970 xml_out_frame_coc(xmlout, j2k_default_tcp, numcomps); /* opt in main, at most 1 per component */
971 xml_out_frame_qcd(xmlout, j2k_default_tcp); /* reqd in main */
972 xml_out_frame_qcc(xmlout, j2k_default_tcp, numcomps); /* opt in main, at most 1 per component */
973 xml_out_frame_rgn(xmlout, j2k_default_tcp, numcomps); /* opt, at most 1 per component */
974 xml_out_frame_poc(xmlout, j2k_default_tcp); /* opt (but reqd in main or tile for any progression order changes) */
975 /* Next four get j2k_default_tcp passed globally: */
976 #ifdef SUPPRESS_FOR_NOW
977 xml_out_frame_ppm(xmlout, cp); /* opt (but either PPM or PPT [distributed in tile headers] or codestream packet header reqd) */
979 xml_out_frame_tlm(xmlout); /* NO-OP. TLM NOT SAVED IN DATA STRUCTURE */ /* opt */
980 xml_out_frame_plm(xmlout); /* NO-OP. PLM NOT SAVED IN DATA STRUCTURE */ /* opt in main; can be used in conjunction with PLT */
981 xml_out_frame_crg(xmlout); /* NO-OP. CRG NOT SAVED IN DATA STRUCTURE */ /* opt in main; */
982 xml_out_frame_com(xmlout, j2k_default_tcp); /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */ /* opt in main; */
984 fprintf(xmlout, " </MainHeader>\n");
986 /* TO DO: all the tile headers (sigh) */
987 fprintf(xmlout, " <TilePartHeaders Count=\"%d\">\n", cp->tileno_size); /* size of the vector tileno */
988 for(i = 0; i < cp->tileno_size; i++) { /* I think cp->tileno_size will be same number as (cp->tw * cp->th) or as global j2k_curtileno */
989 // Standard seems to use zero-based # for tile-part.
990 fprintf(xmlout, " <TilePartHeader Num=\"%d\" ID=\"%d\">\n", i, cp->tileno[i]); /* ID number of the tiles present in the codestream */
991 fprintf(xmlout, " <StartOfTilePart Marker=\"SOT\" />\n");
992 /* All markers in tile-part headers (between SOT and SOD) are optional, unless structure requires. */
994 xml_out_frame_cod(xmlout, &(cp->tcps[i])); /* No more than 1 per tile */
995 xml_out_frame_coc(xmlout, &(cp->tcps[i]), numcomps); /* No more than 1 per component */
996 xml_out_frame_qcd(xmlout, &(cp->tcps[i])); /* No more than 1 per tile */
997 xml_out_frame_qcc(xmlout, &(cp->tcps[i]), numcomps); /* No more than 1 per component */
998 xml_out_frame_rgn(xmlout, &(cp->tcps[i]), numcomps); /* No more than 1 per component */
1000 xml_out_frame_poc(xmlout, &(cp->tcps[i])); /* Reqd only if any progression order changes different from main POC */
1001 #ifdef SUPPRESS_FOR_NOW
1002 xml_out_frame_ppt(xmlout, &(cp->tcps[i])); /* Either PPT [distributed in tile headers] or PPM or codestream packet header reqd. */
1004 xml_out_frame_plt(xmlout, &(cp->tcps[i])); /* NO-OP. PLT NOT SAVED IN DATA STRUCTURE */ /* Can be used in conjunction with main's PLM */
1005 xml_out_frame_com(xmlout, &(cp->tcps[i])); /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */
1006 /* opj_tcp_t * cp->tcps; "tile coding parameters" */
1007 /* Maybe not: fprintf(xmlout, " <>%d</>, cp->matrice[i]; */ /* Fixed layer */
1008 fprintf(xmlout, " <StartOfData Marker=\"SOD\" />\n");
1010 fprintf(xmlout, " <!-- Tile-part bitstream, not shown, follows tile-part header and SOD marker. -->\n");
1011 fprintf(xmlout, " </TilePartHeader>\n");
1013 fprintf(xmlout, " </TilePartHeaders>\n"); /* size of the vector tileno */
1016 IMAGINE the cp object has data to support the following... but we could use an new different data structure instead
1017 /* I'm unclear if the span of the original fread(frame_codestream...) included the following items if they're trailing. */
1018 /* ALSO TO DO, BUT DATA STRUCTURE DOESN'T HANDLE YET: boxes (anywhere in file except before the Filetype box): */
1019 xml_out_frame_jp2i(xmlout, &cp); /* IntellectualProperty 'jp2i' (no restrictions on location) */
1020 xml_out_frame_xml(xmlout, &cp); /* XML 'xml\040' (0x786d6c20). Can appear multiply */
1021 xml_out_frame_uuid(xmlout, &cp); /* UUID 'uuid' (top level only) */
1022 xml_out_frame_uinf(xmlout, &cp); /* UUIDInfo 'uinf', includes UUIDList 'ulst' and URL 'url\40' */
1025 fprintf(xmlout, " </JP2_Frame>\n");
1027 /* Extra commentary: */
1029 fprintf(xmlout, " <!-- Given the number and size of components, mj2_to_frame would try to convert this -->\n");
1030 if (((img->numcomps == 3) && (img->comps[0].dx == img->comps[1].dx / 2)
1031 && (img->comps[0].dx == img->comps[2].dx / 2 ) && (img->comps[0].dx == 1))
1032 || (img->numcomps == 1)) {
1033 fprintf(xmlout, " <!-- file to a YUV movie in the normal manner. -->\n");
1035 else if ((img->numcomps == 3) &&
1036 (img->comps[0].dx == 1) && (img->comps[1].dx == 1)&&
1037 (img->comps[2].dx == 1)) {// If YUV 4:4:4 input --> to bmp
1038 fprintf(xmlout, " <!-- YUV 4:4:4 file to a series of .bmp files. -->\n");
1041 fprintf(xmlout, " <!-- file whose image component dimension are unknown, to a series of .j2k files. -->\n");
1045 opj_destroy_decompress(dinfo);
1047 free(frame_codestream);
1054 void int16_to_3packedchars(short int value, char* buf)
1056 /* This is to retrieve the 3-letter ASCII language code */
1057 /* Each char is packed into 5 bits, as difference from 0x60 */
1059 for (i = 2; i >= 0; i--)
1061 buf[i] = (value & 0x001f) + 0x60;
1062 value = (value >>5);
1069 void xml_out_frame_siz(FILE* xmlout, opj_image_t *img, opj_cp_t *cp)
1071 opj_image_comp_t *comp;
1074 fprintf(xmlout, " <ImageAndFileSize Marker=\"SIZ\">\n");
1075 // This is similar to j2k.c's j2k_dump_image.
1076 // Not of interest: Lsiz, Rsiz
1077 fprintf(xmlout, " <Xsiz>%d</Xsiz>\n", img->x1);
1078 fprintf(xmlout, " <Ysiz>%d</Ysiz>\n", img->y1);
1080 fprintf(xmlout, " <!-- Xsiz, Ysiz is the size of the reference grid. -->\n");
1081 fprintf(xmlout, " <XOsiz>%d</XOsiz>\n", img->x0);
1082 fprintf(xmlout, " <YOsiz>%d</YOsiz>\n", img->y0);
1084 fprintf(xmlout, " <!-- XOsiz, YOsiz are offsets from grid origin to image origin. -->\n");
1085 fprintf(xmlout, " <XTsiz>%d</XTsiz>\n", cp->tdx);
1086 fprintf(xmlout, " <YTsiz>%d</YTsiz>\n", cp->tdy);
1088 fprintf(xmlout, " <!-- XTsiz, YTsiz is the size of one tile with respect to the grid. -->\n");
1089 fprintf(xmlout, " <XTOsiz>%d</XTOsiz>\n", cp->tx0);
1090 fprintf(xmlout, " <YTOsiz>%d</YTOsiz>\n", cp->ty0);
1092 fprintf(xmlout, " <!-- XTOsiz, YTOsiz are offsets from grid origin to first tile origin. -->\n");
1093 fprintf(xmlout, " <Csiz>%d</Csiz>\n", img->numcomps);
1095 fprintf(xmlout, " <!-- Csiz is the number of components in the image. -->\n");
1096 fprintf(xmlout, " <!-- For image components next: -->\n");
1097 fprintf(xmlout, " <!-- XRsiz, YRsiz denote pixel-sample-spacing on the grid, per Part I Annex B. -->\n");
1098 //fprintf(xmlout," <!-- XO, YO is offset of the component compared to the whole image. -->\n");
1099 fprintf(xmlout, " <!-- Bits per pixel (bpp) is the pixel depth. -->\n");
1100 fprintf(xmlout, " <!-- WidthOfData and HeightOfData are calculated values, e.g.: w = roundup((Xsiz - XOsiz)/ XRsiz) -->\n");
1103 for (i = 0; i < img->numcomps; i++) {/* image-components */
1104 comp = &(img->comps[i]);
1105 fprintf(xmlout, " <Component Num=\"%d\">\n", i+1);
1106 fprintf(xmlout, " <Ssiz>\n");
1108 fprintf(xmlout," <AsHex>0x%02x</AsHex>\n", (comp->sgnd << 7) & (comp->prec - 1));
1110 fprintf(xmlout," <Signed>%d</Signed>\n", comp->sgnd);
1111 fprintf(xmlout," <PrecisionInBits>%d</PrecisionInBits>\n", comp->prec);
1113 fprintf(xmlout, " </Ssiz>\n");
1114 fprintf(xmlout, " <XRsiz>%d</XRsiz>\n", comp->dx);
1115 fprintf(xmlout, " <YRsiz>%d</YRsiz>\n", comp->dy);
1116 fprintf(xmlout, " <WidthOfData>%d</WidthOfData>\n", comp->w);
1117 fprintf(xmlout, " <HeightOfData>%d</HeightOfData>\n", comp->h);
1118 /* Rest of these aren't calculated when SIZ is read:
1119 fprintf(xmlout, " <XO>%d</XO>\n", comp->x0);
1120 fprintf(xmlout, " <YO>%d</YO>\n", comp->y0);
1122 fprintf(xmlout," <!-- XO, YO is offset of the component compared to the whole image. -->\n");
1123 fprintf(xmlout, " <BitsPerPixel>%d</BitsPerPixel>\n", comp->bpp);
1124 fprintf(xmlout, " <NumberOfDecodedResolution>%d</NumberOfDecodedResolution>\n", comp->resno_decoded); */
1125 // SUPPRESS: n/a to mj2_to_metadata. fprintf(xmlout," <Factor>%d</Factor\n", comp->factor);
1126 /* factor = number of division by 2 of the out image compare to the original size of image */
1127 // TO DO comp->data: int *data; /* image-component data */
1129 fprintf(xmlout, " </Component>\n");
1131 fprintf(xmlout, " </ImageAndFileSize>\n");
1136 void xml_out_frame_cod(FILE* xmlout, opj_tcp_t *tcp)
1138 /* Could be called with tcp = &j2k_default_tcp;
1139 /* Or, for tile-part header, with &j2k_cp->tcps[j2k_curtileno]
1140 /* Alignment for main:" < < < < To help maintain xml pretty-printing */
1141 /* Alignment for tile:" < < < To help maintain xml pretty-printing */
1144 char spaces[13] = " "; /* 12 spaces if tilepart*/
1146 if(tcp == j2k_default_tcp) {
1147 s++;s++; /* shorten s to 10 spaces if main */
1149 tccp = &(tcp->tccps[0]);
1151 fprintf(xmlout, "%s<CodingStyleDefault Marker=\"COD\">\n",s); /* Required in main header */
1152 /* Not retained or of interest: Lcod */
1153 fprintf(xmlout, "%s <Scod>0x%02x</Scod>\n", s, tcp->csty); /* 1 byte */
1155 fprintf(xmlout, "%s <!-- For Scod, specific bits mean (where bit 0 is lowest or rightmost): -->\n",s);
1156 fprintf(xmlout, "%s <!-- bit 0: Defines entropy coder precincts -->\n",s);
1157 fprintf(xmlout, "%s <!-- 0 = (PPx=15, PPy=15); 1 = precincts defined below. -->\n",s);
1158 fprintf(xmlout, "%s <!-- bit 1: 1 = SOP marker may be used; 0 = not. -->\n",s);
1159 fprintf(xmlout, "%s <!-- bit 2: 1 = EPH marker may be used; 0 = not. -->\n",s);
1161 fprintf(xmlout, "%s <SGcod>\n",s);
1162 fprintf(xmlout, "%s <ProgressionOrder>%d</ProgressionOrder>\n", s, tcp->prg); /* 1 byte, SGcod (A) */
1164 fprintf(xmlout, "%s <!-- Defined Progression Order Values are: -->\n",s);
1165 fprintf(xmlout, "%s <!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->\n",s);
1166 fprintf(xmlout, "%s <!-- where L = \"layer\", R = \"resolution level\", C = \"component\", P = \"position\". -->\n",s);
1168 fprintf(xmlout, "%s <NumberOfLayers>%d</NumberOfLayers>\n", s, tcp->numlayers); /* 2 bytes, SGcod (B) */
1169 fprintf(xmlout, "%s <MultipleComponentTransformation>%d</MultipleComponentTransformation>\n", s, tcp->mct); /* 1 byte, SGcod (C). More or less boolean */
1171 fprintf(xmlout, "%s <!-- For MCT, 0 = none, 1 = transform first 3 components for efficiency, per Part I Annex G -->\n",s);
1172 fprintf(xmlout, "%s </SGcod>\n",s);
1173 /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
1174 fprintf(xmlout, "%s <SPcod>\n",s);
1175 /* Internal data structure tccp defines separate defaults for each component, but they all get the same values */
1176 /* So we only have to report the first component's values here. */
1177 /* Compare j2k_read_cox(...) */
1178 fprintf(xmlout, "%s <NumberOfDecompositionLevels>%d</NumberOfDecompositionLevels>\n", s, tccp->numresolutions - 1); /* 1 byte, SPcox (D) */
1179 fprintf(xmlout, "%s <CodeblockWidth>%d</CodeblockWidth>\n", s, tccp->cblkw - 2); /* 1 byte, SPcox (E) */
1180 fprintf(xmlout, "%s <CodeblockHeight>%d</CodeblockHeight>\n", s, tccp->cblkh - 2); /* 1 byte, SPcox (F) */
1182 fprintf(xmlout, "%s <!-- CBW and CBH are non-negative, and summed cannot exceed 8 -->\n",s);
1183 fprintf(xmlout, "%s <!-- Codeblock dimension is 2^(value + 2) -->\n", s);
1185 fprintf(xmlout, "%s <CodeblockStyle>0x%02x</CodeblockStyle>\n", s, tccp->cblksty); /* 1 byte, SPcox (G) */
1187 fprintf(xmlout, "%s <!-- For CodeblockStyle, bits mean (with value 1=feature on, 0=off): -->\n",s);
1188 fprintf(xmlout, "%s <!-- bit 0: Selective arithmetic coding bypass. -->\n",s);
1189 fprintf(xmlout, "%s <!-- bit 1: Reset context probabilities on coding pass boundaries. -->\n",s);
1190 fprintf(xmlout, "%s <!-- bit 2: Termination on each coding pass. -->\n",s);
1191 fprintf(xmlout, "%s <!-- bit 3: Vertically causal context. -->\n",s);
1192 fprintf(xmlout, "%s <!-- bit 4: Predictable termination. -->\n",s);
1193 fprintf(xmlout, "%s <!-- bit 5: Segmentation symbols are used. -->\n",s);
1195 fprintf(xmlout, "%s <Transformation>%d</Transformation>\n", s, tccp->qmfbid); /* 1 byte, SPcox (H) */
1197 fprintf(xmlout, "%s <!-- For Transformation, 0=\"9-7 irreversible filter\", 1=\"5-3 reversible filter\" -->\n",s);
1198 if (tccp->csty & J2K_CP_CSTY_PRT) {
1199 fprintf(xmlout, "%s <PrecinctSize>\n",s); /* 1 byte, SPcox (I_i) */
1201 fprintf(xmlout, "%s <!-- These are size exponents PPx and PPy. May be zero only for first level (aka N(L)LL subband)-->\n",s);
1202 for (i = 0; i < tccp->numresolutions; i++) {
1203 fprintf(xmlout, "%s <PrecinctHeightAndWidth ResolutionLevel=\"%d\">\n", s, i);
1205 fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->prch[i] << 4) | tccp->prcw[i]); /* packed into 1 byte, SPcox (G) */
1207 fprintf(xmlout,"%s <WidthAsDecimal>%d</WidthAsDecimal>\n", s, tccp->prcw[i]);
1208 fprintf(xmlout,"%s <HeightAsDecimal>%d</HeightAsDecimal>\n", s, tccp->prch[i]);
1210 fprintf(xmlout, "%s </PrecinctHeightAndWidth>\n", s, i);
1212 fprintf(xmlout, "%s </PrecinctSize>\n",s); /* 1 byte, SPcox (I_i) */
1214 fprintf(xmlout, "%s </SPcod>\n",s);
1215 fprintf(xmlout, "%s</CodingStyleDefault>\n",s);
1220 void xml_out_frame_coc(FILE* xmlout, opj_tcp_t *tcp, int numcomps) /* Optional in main & tile-part headers */
1222 /* Uses global j2k_default_tcp */
1223 opj_tccp_t *tccp, *firstcomp_tccp;
1225 char spaces[13] = " "; /* 12 spaces if tilepart*/
1227 if(tcp == j2k_default_tcp) {
1228 s++;s++; /* shorten s to 10 spaces if main */
1231 firstcomp_tccp = &(tcp->tccps[0]);
1232 /* Internal data structure tccp defines separate defaults for each component, set from main */
1233 /* default, then selectively overwritten. */
1234 /* Compare j2k_read_cox(...) */
1235 /* We don't really know which was the default, and which were not */
1236 /* Let's pretend that [0] is the default and all others are not */
1238 fprintf(xmlout, "%s<!-- mj2_to_metadata implementation always reports component[0] as using default COD, -->\n", s);
1239 if(tcp == j2k_default_tcp)
1240 fprintf(xmlout, "%s<!-- and any other component, with main-header style values different from [0], as COC. -->\n", s);
1242 fprintf(xmlout, "%s<!-- and any other component, with tile-part-header style values different from [0], as COC. -->\n", s);
1244 for (compno = 1; compno < numcomps; compno++) /* spec says components are zero-based */
1246 tccp = &tcp->tccps[compno];
1247 if(same_component_style(firstcomp_tccp, tccp))
1250 /* Alignments: " < < < < < To help maintain xml pretty-printing */
1251 fprintf(xmlout, "%s<CodingStyleComponent Marker=\"COC\">\n", s); /* Optional in main header, at most 1 per component */
1253 fprintf(xmlout, "%s <!-- See Ccoc below for zero-based component number. -->\n", s);
1254 /* Overrides the main COD for the specific component */
1255 /* Not retained or of interest: Lcod */
1256 fprintf(xmlout, "%s <Scoc>0x%02x</Scoc>\n", s, tccp->csty); /* 1 byte */
1258 fprintf(xmlout, "%s <!-- Scoc defines entropy coder precincts: -->\n", s);
1259 fprintf(xmlout, "%s <!-- 0 = maximum, namely (PPx=15, PPy=15); 1 = precincts defined below. -->\n", s);
1261 fprintf(xmlout, "%s <Ccoc>%d</Ccoc>\n", s, compno); /* 1 or 2 bytes */
1262 /* Unfortunately compo isn't retained in j2k_read_coc: compno = cio_read(j2k_img->numcomps <= 256 ? 1 : 2); /* Ccoc */
1263 /*if(j2k_img_numcomps <=256)
1268 /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
1269 fprintf(xmlout, "%s <SPcoc>\n", s);
1270 fprintf(xmlout, "%s <NumberOfDecompositionLevels>%d</NumberOfDecompositionLevels>\n", s, tccp->numresolutions - 1); /* 1 byte, SPcox (D) */
1271 fprintf(xmlout, "%s <CodeblockWidth>%d</CodeblockWidth>\n", s, tccp->cblkw - 2); /* 1 byte, SPcox (E) */
1272 fprintf(xmlout, "%s <CodeblockHeight>%d</CodeblockHeight>\n", s, tccp->cblkh - 2); /* 1 byte, SPcox (F) */
1274 fprintf(xmlout, "%s <!-- CBW and CBH are non-negative, and summed cannot exceed 8 -->\n", s);
1275 fprintf(xmlout, "%s <!-- Codeblock dimension is 2^(value + 2) -->\n", s);
1277 fprintf(xmlout, "%s <CodeblockStyle>0x%02x</CodeblockStyle>\n", s, tccp->cblksty); /* 1 byte, SPcox (G) */
1279 fprintf(xmlout, "%s <!-- For CodeblockStyle, bits mean (with value 1=feature on, 0=off): -->\n", s);
1280 fprintf(xmlout, "%s <!-- bit 0: Selective arithmetic coding bypass. -->\n", s);
1281 fprintf(xmlout, "%s <!-- bit 1: Reset context probabilities on coding pass boundaries. -->\n", s);
1282 fprintf(xmlout, "%s <!-- bit 2: Termination on each coding pass. -->\n", s);
1283 fprintf(xmlout, "%s <!-- bit 3: Vertically causal context. -->\n", s);
1284 fprintf(xmlout, "%s <!-- bit 4: Predictable termination. -->\n", s);
1285 fprintf(xmlout, "%s <!-- bit 5: Segmentation symbols are used. -->\n", s);
1287 fprintf(xmlout, "%s <Transformation>%d</Transformation>\n", s, tccp->qmfbid); /* 1 byte, SPcox (H) */
1289 fprintf(xmlout, "%s <!-- For Transformation, 0=\"9-7 irreversible filter\", 1=\"5-3 reversible filter\" -->\n", s);
1290 if (tccp->csty & J2K_CP_CSTY_PRT) {
1291 fprintf(xmlout, "%s <PrecinctSize>\n", s); /* 1 byte, SPcox (I_i) */
1293 fprintf(xmlout, "%s <!-- These are size exponents PPx and PPy. May be zero only for first level (aka N(L)LL subband)-->\n", s);
1294 for (i = 0; i < tccp->numresolutions-1; i++) { /* subtract 1 to get # of decomposition levels */
1295 fprintf(xmlout, "%s <PrecinctHeightAndWidth ResolutionLevel=\"%d\">\n", s, i);
1297 fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->prch[i] << 4) | tccp->prcw[i]); /* packed into 1 byte, SPcox (G) */
1299 fprintf(xmlout,"%s <WidthAsDecimal>%d</WidthAsDecimal>\n", s, tccp->prcw[i]);
1300 fprintf(xmlout,"%s <HeightAsDecimal>%d</HeightAsDecimal>\n", s, tccp->prch[i]);
1302 fprintf(xmlout, "%s </PrecinctHeightAndWidth>\n", s, i);
1304 fprintf(xmlout, "%s </PrecinctSize>\n", s); /* 1 byte, SPcox (I_i) */
1306 fprintf(xmlout, "%s </SPcoc>\n", s);
1307 fprintf(xmlout, "%s</CodingStyleComponent>\n", s);
1313 BOOL same_component_style(opj_tccp_t *tccp1, opj_tccp_t *tccp2)
1317 if(tccp1->numresolutions != tccp2->numresolutions)
1319 if(tccp1->cblkw != tccp2->cblkw)
1321 if(tccp1->cblkh != tccp2->cblkh)
1323 if(tccp1->cblksty != tccp2->cblksty)
1325 if(tccp1->csty != tccp2->csty)
1328 if (tccp1->csty & J2K_CP_CSTY_PRT) {
1329 for (i = 0; i < tccp1->numresolutions; i++) {
1330 if(tccp1->prcw[i] != tccp2->prcw[i] || tccp1->prch[i] != tccp2->prch[i])
1339 void xml_out_frame_qcd(FILE* xmlout, opj_tcp_t *tcp)
1341 /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
1343 int bandno, numbands;
1344 char spaces[13] = " "; /* 12 spaces if tilepart*/
1346 if(tcp == j2k_default_tcp) {
1347 s++;s++; /* shorten s to 10 spaces if main */
1350 /* Compare j2k_read_qcx */
1351 fprintf(xmlout, "%s<QuantizationDefault Marker=\"QCD\">\n", s); /* Required in main header, single occurrence */
1352 tccp = &(tcp->tccps[0]);
1353 /* Not retained or of interest: Lqcd */
1354 fprintf(xmlout, "%s <Sqcd>\n", s); /* 1 byte */
1356 fprintf(xmlout, "%s <!-- Default quantization style for all components. -->\n", s);
1358 fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->numgbits) << 5 | tccp->qntsty);
1360 fprintf(xmlout, "%s <QuantizationStyle>%d</QuantizationStyle>\n", s, tccp->qntsty);
1362 fprintf(xmlout, "%s <!-- Quantization style (in Sqcd's low 5 bits) may be: -->\n", s);
1363 fprintf(xmlout, "%s <!-- 0 = No quantization. SPqcd size = 8 bits-->\n", s);
1364 fprintf(xmlout, "%s <!-- 1 = Scalar derived (values signaled for N(L)LL subband only). Use Eq. E.5. SPqcd size = 16. -->\n", s);
1365 fprintf(xmlout, "%s <!-- 2 = Scalar expounded (values signaled for each subband). SPqcd size = 16. -->\n", s);
1368 fprintf(xmlout, "%s <NumberOfGuardBits>%d</NumberOfGuardBits>\n", s, tccp->numgbits);
1370 fprintf(xmlout, "%s <!-- 0-7 guard bits allowed (stored in Sqcd's high 3 bits) -->\n", s);
1371 fprintf(xmlout, "%s </Sqcd>\n", s);
1373 /* Problem: numbands in some cases is calculated from len, which is not retained or available here at this time */
1374 /* So we'll just dump all internal values */
1375 /* We could calculate it, but I'm having trouble believing the length equations in the standard */
1377 fprintf(xmlout, "%s <SPqcd>\n", s);
1378 switch(tccp->qntsty) {
1379 case J2K_CCP_QNTSTY_NOQNT: /* no quantization */
1380 /* This is what standard says, but I don't believe it: len = 4 + (3*decomp); */
1381 numbands = J2K_MAXBANDS; /* should be: numbands = len - 1; */
1382 /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
1383 /* Instead look for first zero exponent, quit there. Adequate? */
1384 fprintf(xmlout, "%s <ReversibleStepSizeValue>\n", s);
1386 fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
1387 fprintf(xmlout, "%s <!-- until an exponent with zero value is reached. -->\n", s);
1388 fprintf(xmlout, "%s <!-- Exponent epsilon(b) of reversible dynamic range. -->\n", s);
1389 fprintf(xmlout, "%s <!-- Hex value is as stored, in high-order 5 bits. -->\n", s);
1391 for (bandno = 0; bandno < numbands; bandno++) {
1392 if(tccp->stepsizes[bandno].expn == 0)
1393 break; /* Remove when we have real numbands */
1394 fprintf(xmlout, "%s <DynamicRangeExponent Subband=\"%d\">\n", s, bandno);
1396 fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, tccp->stepsizes[bandno].expn << 3);
1398 fprintf(xmlout,"%s <AsDecimal>%d</AsDecimal>\n", s, tccp->stepsizes[bandno].expn);
1399 fprintf(xmlout, "%s </DynamicRangeExponent>\n", s);
1401 fprintf(xmlout, "%s </ReversibleStepSizeValue>\n", s);
1403 case J2K_CCP_QNTSTY_SIQNT: /* scalar quantization derived */
1404 /* This is what standard says. Should I believe it:: len = 5;
1406 fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
1408 fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
1409 fprintf(xmlout, "%s <QuantizationValues Subband=\"0\">\n", s);
1411 fprintf(xmlout, "%s <!-- For N(L)LL subband: >\n", s);
1413 fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[0].expn << 11) | tccp->stepsizes[0].mant);
1415 fprintf(xmlout, "%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[0].expn);
1416 fprintf(xmlout, "%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[0].mant);
1418 fprintf(xmlout, "%s </QuantizationValues>\n", s);
1420 fprintf(xmlout, "%s <!-- Exponents for subbands beyond 0 are not from header, but calculated per Eq. E.5 -->\n", s);
1421 fprintf(xmlout, "%s <!-- The mantissa for all subbands is the same, given by the value above. -->\n", s);
1422 fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
1423 fprintf(xmlout, "%s <!-- until a subband with exponent of zero value is reached. -->\n", s);
1426 for (bandno = 1; bandno < J2K_MAXBANDS; bandno++) {
1427 if(tccp->stepsizes[bandno].expn == 0)
1430 fprintf(xmlout, "%s <CalculatedExponent Subband=\"%d\">%d</CalculatedExponent>\n", s, bandno, tccp->stepsizes[bandno].expn);
1433 fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
1436 default: /* J2K_CCP_QNTSTY_SEQNT */ /* scalar quantization expounded */
1437 /* This is what standard says, but should I believe it: len = 5 + 6*decomp; */
1438 numbands = J2K_MAXBANDS; /* should be: (len - 1) / 2;*/
1439 /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
1440 fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
1442 fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
1443 fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
1444 fprintf(xmlout, "%s <!-- until a subband with mantissa and exponent of zero values is reached. -->\n", s);
1446 for (bandno = 0; bandno < numbands; bandno++) {
1447 if(tccp->stepsizes[bandno].expn == 0 && tccp->stepsizes[bandno].mant == 0)
1448 break; /* Remove when we have real numbands */
1450 fprintf(xmlout, "%s <QuantizationValues Subband=\"%d\">\n", s, bandno);
1452 fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[bandno].expn << 11) | tccp->stepsizes[bandno].mant);
1454 fprintf(xmlout,"%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[bandno].expn);
1455 fprintf(xmlout,"%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[bandno].mant);
1457 fprintf(xmlout, "%s </QuantizationValues>\n", s);
1459 fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
1462 fprintf(xmlout, "%s </SPqcd>\n", s);
1463 fprintf(xmlout, "%s</QuantizationDefault>\n", s);
1465 /* Alignments: " < < < < < To help maintain xml pretty-printing */
1470 void xml_out_frame_qcc(FILE* xmlout, opj_tcp_t *tcp, int numcomps)
1472 /* Uses global j2k_default_tcp */
1473 /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
1474 opj_tccp_t *tccp, *firstcomp_tccp;
1475 int bandno, numbands;
1477 char spaces[13] = " "; /* 12 spaces if tilepart*/
1479 if(tcp == j2k_default_tcp) {
1480 s++;s++; /* shorten s to 10 spaces if main */
1483 firstcomp_tccp = &(tcp->tccps[0]);
1484 /* Internal data structure tccp defines separate defaults for each component, set from main */
1485 /* default, then selectively overwritten. */
1486 /* Compare j2k_read_qcx(...) */
1487 /* We don't really know which was the default, and which were not */
1488 /* Let's pretend that [0] is the default and all others are not */
1490 fprintf(xmlout, "%s<!-- mj2_to_metadata implementation always reports component[0] as using default QCD, -->\n", s);
1491 if(tcp == j2k_default_tcp)
1492 fprintf(xmlout, "%s<!-- and any other component, with main-header quantization values different from [0], as QCC. -->\n", s);
1494 fprintf(xmlout, "%s<!-- and any other component, with tile-part-header quantization values different from [0], as QCC. -->\n", s);
1496 for (compno = 1; compno < numcomps; compno++) /* spec says components are zero-based */
1498 tccp = &(tcp->tccps[compno]);
1499 if(same_component_quantization(firstcomp_tccp, tccp))
1502 /* Compare j2k_read_qcx */
1503 fprintf(xmlout, "%s<QuantizationComponent Marker=\"QCC\" Component=\"%d\">\n", s, compno); /* Required in main header, single occurrence */
1504 tccp = &j2k_default_tcp->tccps[0];
1505 /* Not retained or perhaps of interest: Lqcd It maybe can be calculated. */
1506 fprintf(xmlout, "%s <Sqcc>\n", s); /* 1 byte */
1508 fprintf(xmlout, "%s <!-- Quantization style for this component. -->\n", s);
1510 fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->numgbits) << 5 | tccp->qntsty);
1512 fprintf(xmlout, "%s <QuantizationStyle>%d</QuantizationStyle>\n", s, tccp->qntsty);
1514 fprintf(xmlout, "%s <!-- Quantization style (in Sqcc's low 5 bits) may be: -->\n", s);
1515 fprintf(xmlout, "%s <!-- 0 = No quantization. SPqcc size = 8 bits-->\n", s);
1516 fprintf(xmlout, "%s <!-- 1 = Scalar derived (values signaled for N(L)LL subband only). Use Eq. E.5. SPqcc size = 16. -->\n", s);
1517 fprintf(xmlout, "%s <!-- 2 = Scalar expounded (values signaled for each subband). SPqcc size = 16. -->\n", s);
1520 fprintf(xmlout, "%s <NumberOfGuardBits>%d</NumberOfGuardBits>\n", s, tccp->numgbits);
1522 fprintf(xmlout, "%s <!-- 0-7 guard bits allowed (stored in Sqcc's high 3 bits) -->\n", s);
1523 fprintf(xmlout, "%s </Sqcc>\n", s);
1525 /* Problem: numbands in some cases is calculated from len, which is not retained or available here at this time */
1526 /* So we'll just dump all internal values */
1527 fprintf(xmlout, "%s <SPqcc>\n", s);
1528 switch(tccp->qntsty) {
1529 case J2K_CCP_QNTSTY_NOQNT:
1530 numbands = J2K_MAXBANDS; /* should be: numbands = len - 1; */
1531 /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
1533 /* Instead look for first zero exponent, quit there. Adequate? */
1534 fprintf(xmlout, "%s <ReversibleStepSizeValue>\n", s);
1536 fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
1537 fprintf(xmlout, "%s <!-- until an exponent with zero value is reached. -->\n", s);
1538 fprintf(xmlout, "%s <!-- Exponent epsilon(b) of reversible dynamic range. -->\n", s);
1539 fprintf(xmlout, "%s <!-- Hex value is as stored, in high-order 5 bits. -->\n", s);
1541 for (bandno = 0; bandno < numbands; bandno++) {
1542 if(tccp->stepsizes[bandno].expn == 0)
1543 break; /* Remove this once we have real numbands */
1544 fprintf(xmlout, "%s <Exponent Subband=\"%d\">\n", s, bandno);
1546 fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, tccp->stepsizes[bandno].expn << 3);
1548 fprintf(xmlout,"%s <AsDecimal>%d</AsDecimal>\n", s, tccp->stepsizes[bandno].expn);
1549 fprintf(xmlout, "%s </Exponent>\n", s);
1551 fprintf(xmlout, "%s </ReversibleStepSizeValue>\n", s);
1553 case J2K_CCP_QNTSTY_SIQNT:
1555 fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
1557 fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
1558 fprintf(xmlout, "%s <QuantizationValuesForSubband0>\n", s);
1560 fprintf(xmlout, "%s <!-- For N(L)LL subband: >\n", s);
1562 fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[0].expn << 11) | tccp->stepsizes[0].mant);
1564 fprintf(xmlout, "%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[0].expn);
1565 fprintf(xmlout, "%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[0].mant);
1567 fprintf(xmlout, "%s </QuantizationValuesForSubband0>\n", s);
1569 fprintf(xmlout, "%s <!-- Exponents for subbands beyond 0 are not from header, but calculated per Eq. E.5 -->\n", s);
1570 fprintf(xmlout, "%s <!-- The mantissa for all subbands is the same, given by the value above. -->\n", s);
1571 fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
1572 fprintf(xmlout, "%s <!-- until a subband with exponent of zero value is reached. -->\n", s);
1575 for (bandno = 1; bandno < J2K_MAXBANDS; bandno++) {
1576 if(tccp->stepsizes[bandno].expn == 0)
1579 fprintf(xmlout, "%s <CalculatedExponent Subband=\"%d\">%d</CalculatedExponent>\n", s, bandno, tccp->stepsizes[bandno].expn);
1581 fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
1584 default: /* J2K_CCP_QNTSTY_SEQNT */
1585 numbands = J2K_MAXBANDS; /* should be: (len - 1) / 2;*/
1586 /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
1587 fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
1589 fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
1590 fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
1591 fprintf(xmlout, "%s <!-- until a subband with mantissa and exponent of zero values is reached. -->\n", s);
1593 for (bandno = 0; bandno < numbands; bandno++) {
1594 if(tccp->stepsizes[bandno].expn == 0 && tccp->stepsizes[bandno].mant == 0)
1595 break; /* Remove this once we have real numbands count */
1596 fprintf(xmlout, "%s <QuantizationValues Subband=\"%d\">\n", s, bandno);
1598 fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[bandno].expn << 11) | tccp->stepsizes[bandno].mant);
1600 fprintf(xmlout,"%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[bandno].expn);
1601 fprintf(xmlout,"%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[bandno].mant);
1603 fprintf(xmlout, "%s </QuantizationValues>\n", s);
1605 fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
1608 fprintf(xmlout, "%s </SPqcc>\n", s);
1609 fprintf(xmlout, "%s</QuantizationComponent>\n", s);
1611 /* Alignments: " < < < < < To help maintain xml pretty-printing */
1616 BOOL same_component_quantization(opj_tccp_t *tccp1, opj_tccp_t *tccp2)
1618 int bandno, numbands;
1620 if(tccp1->qntsty != tccp2->qntsty)
1622 if(tccp1->numgbits != tccp2->numgbits)
1625 switch(tccp1->qntsty) {
1626 case J2K_CCP_QNTSTY_NOQNT:
1627 numbands = J2K_MAXBANDS; /* should be: numbands = len - 1; */
1628 /* Instead look for first zero exponent, quit there. Adequate? */
1629 for (bandno = 0; bandno < numbands; bandno++) {
1630 if(tccp1->stepsizes[bandno].expn == 0)
1632 if(tccp1->stepsizes[bandno].expn != tccp2->stepsizes[bandno].expn)
1636 case J2K_CCP_QNTSTY_SIQNT:
1638 if(tccp1->stepsizes[0].expn != tccp2->stepsizes[0].expn || tccp1->stepsizes[0].mant != tccp2->stepsizes[0].mant)
1640 /* Don't need to check remainder, since they are calculated from [0] */
1643 default: /* J2K_CCP_QNTSTY_SEQNT */
1644 numbands = J2K_MAXBANDS; /* should be: (len - 1) / 2;*/
1645 /* This comparison may cause us problems with trailing junk values. */
1646 for (bandno = 0; bandno < numbands; bandno++) {
1647 if(tccp1->stepsizes[bandno].expn != tccp2->stepsizes[bandno].expn || tccp1->stepsizes[bandno].mant != tccp2->stepsizes[bandno].mant);
1657 void xml_out_frame_rgn(FILE* xmlout, opj_tcp_t *tcp, int numcomps)
1660 /* MJ2 files can have regions of interest if hybridized with JPX Part II */
1661 char spaces[13] = " "; /* 12 spaces if tilepart*/
1663 if(tcp == j2k_default_tcp) {
1664 s++;s++; /* shorten s to 10 spaces if main */
1667 for(compno = 0; compno < numcomps; compno++) {
1668 SPrgn = tcp->tccps[compno].roishift; /* 1 byte; SPrgn */
1670 continue; /* Yet another kludge */
1672 fprintf(xmlout, "%s<RegionOfInterest Marker=\"RGN\">\n", s); /* Optional in main header, at most 1 per component */
1674 fprintf(xmlout, "%s<!-- See Crgn below for zero-based component number. -->\n", s);
1675 /* Not retained or of interest: Lrgd */
1676 fprintf(xmlout, "%s <Srgn>0</Srgn>\n", s); /* 1 byte */
1678 fprintf(xmlout, "%s <!-- Srgn is ROI style. Only style=0 defined: Implicit ROI (max. shift) -->\n", s);
1679 fprintf(xmlout, "%s <Crgn>%d</Crgn>\n", s, compno); /* 1 or 2 bytes */
1680 fprintf(xmlout, "%s <SPrgn>%d</SPrgn>\n", s, SPrgn); /* 1 byte */
1682 fprintf(xmlout, "%s <!-- SPrgn is implicit ROI shift, i.e., binary shifting of ROI coefficients above background. -->\n", s);
1683 fprintf(xmlout, "</RegionOfInterest\n", s); /* Optional in main header, at most 1 per component */
1689 void xml_out_frame_poc(FILE* xmlout, opj_tcp_t *tcp) { /* Progression Order Change */
1690 /* Compare j2k_read_poc() */
1693 char spaces[13] = " "; /* 12 spaces if tilepart*/
1695 if(tcp == j2k_default_tcp) {
1696 s++;s++; /* shorten s to 10 spaces if main */
1700 return; /* Not present */
1702 fprintf(xmlout, "%s<ProgressionOrderChange Marker=\"POC\">\n", s); /* Optional in main header, at most 1 per component */
1703 /* j2k_read_poc seems to allow accumulation of default pocs from multiple POC segments, but does
1704 the spec really allow that? */
1705 /* 2 bytes, not retained; Lpoc */
1706 /* I probably didn't get this dump precisely right. */
1707 for (i = 0; i < tcp->numpocs; i++) {
1708 poc = &tcp->pocs[i];
1709 fprintf(xmlout, "%s <Progression Num=\"%d\">\n", s, i+1);
1710 fprintf(xmlout, "%S <RSpoc>%d</RSpoc>\n", s, poc->resno0); /* 1 byte, RSpoc_i */
1712 fprintf(xmlout,"%s <!-- Resolution level index (inclusive) for progression start. Range: 0 to 33 -->\n", s);
1713 fprintf(xmlout, "%s <CSpoc>%d</CSpoc>\n", s, poc->compno0);/* j2k_img->numcomps <= 256 ? 1 byte : 2 bytes; CSpoc_i */
1715 fprintf(xmlout,"%s <!-- Component index (inclusive) for progression start. -->\n", s);
1716 fprintf(xmlout, "%s <LYEpoc>%d</LYEpoc>\n", s, poc->layno1); /* int_min(cio_read(2), tcp->numlayers); /* 2 bytes; LYEpoc_i */
1718 fprintf(xmlout,"%s <!-- Layer index (exclusive) for progression end. -->\n", s);
1719 fprintf(xmlout, "%s <REpoc>%d</REpoc>\n", s, poc->resno1); /*int_min(cio_read(1), tccp->numresolutions); /* REpoc_i */
1721 fprintf(xmlout,"%s <!-- Resolution level index (exclusive) for progression end. Range: RSpoc to 33 -->\n", s);
1722 fprintf(xmlout, "%s <CEpoc>%d</CEpoc>\n", s, poc->compno1); /* int_min(cio_read(j2k_img->numcomps <= 256 ? 1 : 2), j2k_img->numcomps); /* CEpoc_i */
1724 fprintf(xmlout,"%s <!-- Component index (exclusive) for progression end. Minimum: CSpoc -->\n", s);
1725 fprintf(xmlout, "%s <Ppoc>%d</Ppoc>\n", s, poc->prg); /* 1 byte Ppoc_i */
1727 fprintf(xmlout,"%s <!-- Defined Progression Order Values are: -->\n", s);
1728 fprintf(xmlout,"%s <!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->\n", s);
1729 fprintf(xmlout,"%s <!-- where L = \"layer\", R = \"resolution level\", C = \"component\", P = \"position\". -->\n", s);
1731 fprintf(xmlout, "%s </Progression>\n", s);
1733 fprintf(xmlout, "%s</ProgressionOrderChange\n", s);
1738 #ifdef SUPPRESS_FOR_NOW
1739 /* Suppress PPM and PPT since we're not showing data from the third option, namely within the codestream, and
1740 that's evidently what frames_to_mj2 uses. And a hex dump isn't so useful anyway */
1742 void xml_out_frame_ppm(FILE *xmlout, opj_cp_t *cp) { /* For main header, not tile-part (which uses PPT instead). */
1743 /* Either the PPM or PPT is required if the packet headers are not distributed in the bit stream */
1744 /* Use of PPM and PPT are mutually exclusive. */
1745 /* Compare j2k_read_ppm() */
1749 return; /* Not present */
1750 /* Main header uses indent of 10 spaces */
1751 fprintf(xmlout, " <PackedPacketHeadersMainHeader Marker=\"PPM\">\n"); /* Optional in main header, but if not, must be in PPT or codestream */
1752 /* 2 bytes Lppm not saved */
1754 fprintf(xmlout, " <!-- If there are multiple PPM marker segments in the main header, -->\n");
1755 fprintf(xmlout, " <!-- this mj2_to_metadata implementation will report them as a single consolidated PPM header. -->\n");
1756 fprintf(xmlout, " <!-- The implementation can't currently segregate by tile-part. -->\n");
1757 fprintf(xmlout, " <!-- TO DO? further map the packet headers to xml. -->\n");
1760 /* 1 byte, not retained ; Zppm is sequence # of this PPM header */
1761 /* 4 bytes, possibly overwritten multiple times in j2k_cp->ppm_previous: Nppm */
1762 /* Use j symbol for index instead of i, to make comparable with j2k_read_ppm */
1763 /* Not real clear whether to use ppm->store or ppm_len as upper bound */
1764 fprintf(xmlout, " <PackedData>\n");
1765 xml_out_dump_hex(xmlout, cp->ppm_data, cp->ppm_len);
1766 /* Dump packet headers 1 byte at a time: lppm[i][j] */
1767 fprintf(xmlout, " </PackedData>\n");
1768 fprintf(xmlout, " </PackedPacketHeadersMainHeader>\n"); /* Optional in main header, but if not, must be in PPT or codestream */
1773 void xml_out_frame_ppt(FILE *xmlout, opj_tcp_t *tcp) { /* For tile-part header, not main (which uses PPM instead). */
1774 /* Either the PPM or PPT is required if the packet headers are not distributed in the bit stream */
1775 /* Use of PPM and PPT are mutually exclusive. */
1776 /* Compare j2k_read_ppt() */
1780 return; /* Not present */
1782 /* Tile-part indents are 12 spaces */
1783 fprintf(xmlout, " <PackedPacketHeadersTilePartHeader Marker=\"PPT\">\n"); /* Optional in main header, but if not, must be in PPT or codestream */
1784 /* 2 bytes Lppm not saved */
1786 fprintf(xmlout, " <!-- If there are multiple PPT marker segments in the tile-part header, -->\n");
1787 fprintf(xmlout, " <!-- this mj2_to_metadata implementation will report them as a single consolidated PPT header. -->\n");
1788 fprintf(xmlout, " <!-- The implementation can't currently segregate by tile-part. -->\n");
1789 fprintf(xmlout, " <!-- TO DO? further map the packet headers to xml. -->\n");
1792 /* 1 byte, not retained ; Zppt is sequence # of this PPT header */
1793 /* 4 bytes, possibly overwritten multiple times in j2k_cp->ppt_previous: Nppt */
1794 /* Use j symbol for index instead of i, to make comparable with j2k_read_ppt */
1795 /* Not real clear whether to use ppt->store or ppt_len as upper bound */
1796 fprintf(xmlout, " <PackedData>\n");
1797 xml_out_dump_hex(xmlout, tcp->ppt_data, tcp->ppt_len);
1798 /* Dump packet headers 1 byte at a time: lppt[i][j] */
1799 fprintf(xmlout, " </PackedData>\n");
1800 fprintf(xmlout, " </PackedPacketHeadersTileHeader>\n"); /* Optional in tile-part header, but if not, must be in PPM or codestream */
1802 #endif SUPPRESS_FOR_NOW
1806 void xml_out_frame_tlm(FILE* xmlout) { /* opt, main header only. May be multiple. */
1807 /* Compare j2k_read_tlm()... which doesn't retain anything! */
1808 /* Plan: Since this is only called from main header, not tilepart, use global j2k_default_tcp rather than parameter */
1809 /* Main header indents are 10 spaces */
1814 void xml_out_frame_plm(FILE* xmlout) { /* opt, main header only; can be used in conjunction with tile-part's PLT */
1815 /* NO-OP. PLM NOT SAVED IN DATA STRUCTURE */
1816 /* Compare j2k_read_plm()... which doesn't retain anything! */
1817 /* Plan: Since this is only called from main header, not tilepart, use global j2k_default_tcp rather than parameter */
1818 /* Main header indents are 10 spaces */
1823 void xml_out_frame_plt(FILE* xmlout, opj_tcp_t *tcp) { /* opt, tile-part headers only; can be used in conjunction with main header's PLM */
1824 /* NO-OP. PLT NOT SAVED IN DATA STRUCTURE */
1825 /* Compare j2k_read_plt()... which doesn't retain anything! */
1826 /* Tile-part header indents are 12 spaces */
1831 void xml_out_frame_crg(FILE* xmlout) { /* NO-OP. CRG NOT SAVED IN DATA STRUCTURE */ /* opt, main header only; */
1832 /* Compare j2k_read_crg()... which doesn't retain anything! */
1833 /* Plan: Since this is only called from main header, not tilepart, use global j2k_default_tcp rather than parameter */
1835 THIS PSEUDOCODE IMAGINES THESE EXIST: j2k_default_tcp->crg, j2k_default_tcp->crg_i, j2k_default_tcp->crg_xcrg*, j2k_default_tcp->crg_ycrg*
1836 (POSSIBLY DON'T NEED crg_i, CAN GET NUMBER OR COMPONENTS FROM ELSEWHERE)
1837 if(j2k_default_tcp->crg != 1 || j2k_default_tcp->crg_i == 0)
1838 return; /* Not present */
1840 /* Main header indents are 10 spaces */
1841 fprintf(xmlout, " <ComponentRegistration Marker=\"RG\" Count=\"%d\">\n", j2k_default_tcp->crg_i);
1843 fprintf(xmlout, " <!-- Fine tuning of registration of components with respect to each other, -->\n");
1844 fprintf(xmlout, " <!-- not required but potentially helpful for decoder. -->\n");
1845 fprintf(xmlout, " <!-- These supplementary fractional offsets are in units of 1/65536 of the horizontal -->\n");
1846 fprintf(xmlout, " <!-- or vertical separation (e.g., XRsiz[i] or YRsiz[i] for component i). -->\n");
1848 /* This isn't the most compact form of table, but is OK when number of components is small, as is likely. */
1849 for (i = 0; i < j2k_default_tcp->crg_i; i++) {
1850 fprintf(xmlout, " <Component Num=\"%d\">\n", i+1);
1851 fprintf(xmlout, " <Xcrg>\n");
1853 fprintf(xmlout," <AsNumerator>%d</AsNumerator>\n", j2k_default_tcp->crg_xcrg[i]);
1855 /* Calculate n * 100%/65536; 4 digits after decimal point is sufficiently accurate */
1856 fprintf(xmlout," <AsPercentage>%.4f</AsPercentage>\n", ((double)j2k_default_tcp->crg_xcrg[i])/655.36);
1857 /* We could do another calculation that include XRsiz[i]; maybe later. */
1859 fprintf(xmlout, " </Xcrg>\n");
1860 fprintf(xmlout, " <Ycrg>\n");
1862 fprintf(xmlout," <AsNumerator>%d</AsNumerator>\n", j2k_default_tcp->crg_ycrg[i]);
1864 fprintf(xmlout," <AsPercentage>%f</AsPercentage>\n", ((double)j2k_default_tcp->crg_ycrg[i])/655.36);
1866 fprintf(xmlout, " </Ycrg>\n");
1867 fprintf(xmlout, " </Component>\n");
1870 fprintf(xmlout, " </ComponentRegistration>\n");
1877 /* Regrettably from a metadata point of view, j2k_read_com() skips over any comments in main header or tile-part-header */
1878 void xml_out_frame_com(FILE* xmlout, opj_tcp_t *tcp) { /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */ /* opt in main or tile-part headers; */
1879 /* Compare j2k_read_com()... which doesn't retain anything! */
1881 char spaces[13] = " "; /* 12 spaces if tilepart*/
1883 if(tcp == &j2k_default_tcp) {
1884 s++;s++; /* shorten s to 10 spaces if main */
1886 THIS PSEUDOCODE IMAGINES THESE EXIST: tcp->com, tcp->com_len, tcp->com_data array
1888 return; /* Not present */
1890 fprintf(xmlout, "%s<Comment Marker=\"COM\">\n", s); /* Optional in main or tile-part header */
1891 xml_out_dump_hex_and_ascii(tcp->com_data, tcp->com_len, s);
1892 fprintf(xmlout, "%s</Comment>\n", s);
1896 void xml_out_dump_hex(FILE* xmlout, char *data, int data_len, char* s) {
1897 /* s is a string of spaces for indent */
1900 /* This is called when raw is true, or there is no appropriate derived form */
1901 fprintf(xmlout, "%s<AsHex>\n", s);
1902 fprintf(xmlout, "%s ", s); /* Inadequate for pretty printing */
1903 for (i = 0; i < data_len; i++) { /* Dump packet headers */
1904 fprintf(xmlout, "%02x", data[i]);
1906 fprintf(xmlout, "%s</AsHex>\n", s);
1909 /* Define this as an even number: */
1910 #define BYTES_PER_DUMP_LINE 40
1911 /* Current total width for Hex and ASCII is : 11 spaces lead + (3 * BPDL) + 2 spaces + BPDL */
1912 void xml_out_dump_hex_and_ascii(FILE* xmlout, char *data, int data_len, char* s) {
1913 /* s is a string of spaces for indent */
1917 xml_out_dump_hex(xmlout, data, data_len, s);
1920 fprintf(xmlout, "%s<AsHexAndASCII>\n", s);
1921 for (i = 0; i < data_len; ) {
1922 fprintf(xmlout,"%s ", s); /* Additional leading space added in loop */
1923 /* First column: hex */
1924 for (j = 0; j < BYTES_PER_DUMP_LINE; j++) /* Dump bytes */
1925 fprintf(xmlout," %02x", data[i+j]);
1926 /* Space between columns... */ fprintf(xmlout, " ");
1927 /* Second column: ASCII */
1928 for (j = 0; j < BYTES_PER_DUMP_LINE; j++, i++) {
1929 if(isprint((int)data[i]) && i < data_len)
1930 fprintf(xmlout,"%c", data[i]);
1932 fprintf(xmlout," ");
1934 /* If we also wanted to output UCS-2 Unicode as a third column, then entire document
1935 must use fwprintf. Forget about it for now. As it stands, if data is UCS-2 format but still
1936 the ASCII set, then we'll be able to read every other byte as ASCII in column 2. If
1937 data is UTF-8 format but still ASCII, then we'll be able to read every byte as ASCII
1940 fprintf(xmlout, "%s</AsHexAndASCII>\n", s);
1947 void xml_out_frame_jp2h(FILE* xmlout, opj_jp2_t *jp2_struct) { /* JP2 Header */
1948 /* Compare jp2_read_jp2h(opj_jp2_t * jp2_struct) */
1951 fprintf(xmlout, " <JP2Header BoxType=\"jp2h\">\n");
1953 /* Compare jp2_read_ihdr(jp2_struct)) */
1954 fprintf(xmlout, " <ImageHeader BoxType=\"ihdr\">\n");
1955 fprintf(xmlout, " <HEIGHT>%d</HEIGHT>\n", jp2_struct->h); /* 4 bytes */
1956 fprintf(xmlout, " <WIDTH>%d</WIDTH>\n", jp2_struct->w); /* 4 bytes */
1958 fprintf(xmlout, " <!-- HEIGHT here, if 2 fields per image, is of total deinterlaced height. -->\n");
1959 fprintf(xmlout, " <NC>%d</NC>\n", jp2_struct->numcomps); /* 2 bytes */
1961 fprintf(xmlout, " <!-- NC is number of components -->\n"); /* 2 bytes */
1962 fprintf(xmlout, " <BPC>\n"); /* 1 byte */
1963 if(jp2_struct->bpc == 255) {
1964 fprintf(xmlout, " <AsHex>0x%02x</AsHex>\n", jp2_struct->bpc); /* 1 byte */
1966 fprintf(xmlout, " <!-- BPC = 0xff means bits per pixel varies with component; see table below. -->\n");
1967 } else { /* Not 0xff */
1969 fprintf(xmlout, " <AsHex>0x%02x</AsHex>\n", jp2_struct->bpc); /* 1 byte */
1971 fprintf(xmlout," <!-- BPC = 0xff means bits per pixel varies with component; see table below. -->\n");
1974 fprintf(xmlout, " <BitsPerPixel>%d</BitsPerPixel>\n", jp2_struct->bpc & 0x7f);
1975 fprintf(xmlout, " <Signed>%d</Signed>\n", jp2_struct->bpc >> 7);
1978 fprintf(xmlout, " </BPC>\n");
1979 fprintf(xmlout, " <C>%d</C>\n", jp2_struct->C); /* 1 byte */
1981 fprintf(xmlout, " <!-- C is compression type. Only \"7\" is allowed to date. -->\n"); /* 2 bytes */
1982 fprintf(xmlout, " <UnkC>%d</UnkC>\n", jp2_struct->UnkC); /* 1 byte */
1984 fprintf(xmlout, " <!-- Colourspace Unknown. 1 = unknown, 0 = known (e.g., colourspace spec is accurate) -->\n"); /* 1 byte */
1985 fprintf(xmlout, " <IPR>%d</IPR>\n", jp2_struct->IPR); /* 1 byte */
1987 fprintf(xmlout, " <!-- IPR is 1 if frame contains an Intellectual Property box; 0 otherwise. -->\n"); /* 2 bytes */
1988 fprintf(xmlout, " </ImageHeader>\n");
1990 if (jp2_struct->bpc == 255)
1992 fprintf(xmlout, " <BitsPerComponent BoxType=\"bpcc\">\n");
1994 fprintf(xmlout, " <!-- Pixel depth (range 1 to 38) is low 7 bits of hex value + 1 -->\n");
1995 /* Bits per pixel varies with components */
1996 /* Compare jp2_read_bpcc(jp2_struct) */
1997 for (i = 0; i < (int)jp2_struct->numcomps; i++) {
1999 fprintf(xmlout," <AsHex>0x%02x</AsHex>\n", jp2_struct->comps[i].bpcc); /* 1 byte */
2001 fprintf(xmlout," <BitsPerPixel>%d</BitsPerPixel>\n", (jp2_struct->comps[i].bpcc & 0x7f)+1);
2002 fprintf(xmlout," <Signed>%d</Signed>\n", jp2_struct->comps[i].bpcc >> 7);
2005 fprintf(xmlout, " </BitsPerComponent>\n");
2008 /* Compare jp2_read_colr(jp2_struct) */
2009 fprintf(xmlout, " <ColourSpecification BoxType=\"colr\">\n");
2010 fprintf(xmlout, " <METH>%d</METH>\n", jp2_struct->meth); /* 1 byte */
2012 fprintf(xmlout, " <!-- Valid values of specification method so far: -->\n");
2013 fprintf(xmlout, " <!-- 1 = Enumerated colourspace, in EnumCS field -->\n");
2014 fprintf(xmlout, " <!-- 2 = Restricted ICC Profile, in PROFILE field -->\n");
2016 fprintf(xmlout, " <PREC>%d</PREC>\n", jp2_struct->precedence); /* 1 byte */
2018 fprintf(xmlout, " <!-- 0 is only valid value of precedence so far. -->\n");
2019 fprintf(xmlout, " <APPROX>%d</APPROX>\n", jp2_struct->approx); /* 1 byte */
2021 fprintf(xmlout, " <!-- 0 is only valid value of colourspace approximation so far. -->\n");
2023 if (jp2_struct->meth == 1) {
2024 fprintf(xmlout, " <EnumCS>%d</EnumCS>\n", jp2_struct->enumcs); /* 4 bytes */
2026 fprintf(xmlout, " <!-- Valid values of enumerated MJ2 colourspace so far: -->\n");
2027 fprintf(xmlout, " <!-- 16: sRGB as defined by IEC 61966-2-1. -->\n");
2028 fprintf(xmlout, " <!-- 17: greyscale (related to sRGB). -->\n");
2029 fprintf(xmlout, " <!-- 18: sRGB YCC (from JPEG 2000 Part II). -->\n");
2030 fprintf(xmlout, " <!-- (Additional JPX values are defined in Part II). -->\n");
2035 fprintf(xmlout, " <!-- PROFILE is not handled by current OpenJPEG implementation. -->\n");
2036 /* only 1 byte is read and nothing stored */
2037 fprintf(xmlout, " </ColourSpecification>\n");
2039 /* TO DO? No OpenJPEG support.
2041 ComponentMapping 'cmap'
2042 ChannelDefinition 'cdef'
2045 fprintf(xmlout, " </JP2Header>\n");
2050 IMAGE these use cp structure, extended... but we could use a new data structure instead
2051 void xml_out_frame_jp2i(FILE* xmlout, opj_cp_t *cp) {
2052 /* IntellectualProperty 'jp2i' (no restrictions on location) */
2054 IMAGE cp->jp2i, cp->jp2i_count, cp->jp2i_data (array of chars), cp->cp2i_len (array of ints)
2056 return; /* Not present */
2058 for(i = 0; i < cp->jp2i_count; i++)
2060 fprintf(xmlout, " <IntellectualProperty BoxType=\"jp2i\">\n");
2061 /* I think this can be anything, including binary, so do a dump */
2062 /* Is it better to indent or not indent this content? Indent is better for reading, but
2063 worse for cut/paste. */
2064 xml_out_dump_hex_and_ascii(xmlout, cp->jp2i_data[i], cp->jp2i_len[i]);
2065 fprintf(xmlout, " </IntellectualProperty>\n");
2069 void xml_out_frame_xml(FILE* xmlout, opj_cp_t *cp) {
2070 /* XML 'xml\040' (0x786d6c20). Can appear multiply, before or after jp2c codestreams */
2071 IMAGE cp->xml, cp->xml_count, cp->xml_data (array of chars)
2072 MAYBE WE DON'T NEED cp->xml_len (array of ints) IF WE ASSUME xml_data IS NULL-TERMINATED.
2073 ASSUME ASSUME EACH LINE IS ENDED BY \n.
2076 return; /* Not present */
2078 for(i = 0; i < cp->xml_count; i++)
2080 fprintf(xmlout, " <TextFormXML BoxType=\"xml[space]" Instance=\"%d\">\n", i+1);
2081 /* Is it better to indent or not indent this content? Indent is better for reading, but
2082 worse for cut/paste. Being lazy, didn't indent here. */
2083 fprintf(xmlout,cp->xml_data[i]); /* May be multiple lines */ /* Could check if this is well-formed */
2084 fprintf(xmlout, " </TextFormXML>\n");
2088 void xml_out_frame_uuid(FILE* xmlout, opj_cp_t *cp) {
2089 /* UUID 'uuid' (top level only) */
2090 /* Part I 1.7.2 says: may appear multiply in JP2 file, anywhere except before File Type box */
2091 /* Part III 5.2.1 says: Private extensions shall be achieved through the 'uuid' type. */
2092 /* A UUID is a 16-byte value. There is a conventional string representation for it:
2093 "0x12345678-9ABC-DEF0-1234-567890ABCDEF". Let's assume that is what is stored in uuid_value */
2095 /* Part III 6.1 Any other MJ2 box type could be alternatively written as a 'uuid' box, with value given
2096 as : 0xXXXXXXXX-0011-0010-8000-00AA00389B71, where the Xs are the boxtype in hex. However,
2097 such a file is "not compliant; systems may choose to read [such] objects ... as equivalent to the box of
2098 the same type, or not." Here, we choose not to. */
2100 IMAGE cp->uuid, cp->uuid_count, cp->uuid_value (array of uuids... let's say fixed-length strings) cp->uuid_data (array of char buffers), cp->uuid_len (array of ints)
2102 return; /* Not present */
2104 for(i = 0; i < cp->uuid_count; i++)
2106 fprintf(xmlout, " <UniversalUniqueID BoxType=\"uuid\">
2107 fprintf(xmlout, " <UUID>%s</UUDI>\n", cp->uuid_value[i]);
2108 fprintf(xmlout, " <Data>\n");
2109 /* I think this can be anything, including binary, so do a dump */
2110 /* Is it better to indent or not indent this content? Indent is better for reading, but
2111 worse for cut/paste. */
2112 xml_out_dump_hex_and_ascii(xmlout, cp->uuid_data[i], cp->uuid_len[i]);
2113 fprintf(xmlout, " </Data>\n");
2114 fprintf(xmlout, " </UniversalUniqueID>\n");
2118 void xml_out_frame_uinf(FILE* xmlout, opj_cp_t *cp) {
2119 /* UUIDInfo 'uinf', includes UUIDList 'ulst' and URL 'url\40' */
2120 /* Part I 1.7.3 says: may appear multiply in JP2 file, anywhere at the top level except before File Type box */
2121 /* So there may be multiple ulst's, and each can have multiple UUIDs listed (with a single URL) */
2122 /* This is not quite as vendor-specific as UUIDs, or at least is meant to be generally readable */
2123 /* Assume UUIDs stored in canonical string format */
2125 IMAGE cp->uinf, cp->uinf_count, cp->uinf_ulst_nu (array of ints)
2126 cp->uinf_uuid (2 dimensional array of uuids... let's say fixed-length strings),
2127 cp->uinf_url (array of char buffers)
2130 return; /* Not present */
2132 for(i = 0; i < cp->uuid_count; i++)
2134 fprintf(xmlout, " <UUIDInfo BoxType=\"uinf\">\n");
2135 fprintf(xmlout, " <UUIDList BoxType=\"ulst\" Count=\"%d\">\n",cp->cp->uinf_ulst_nu[i]);
2136 for(j = 0; j < cp->uinf_ulst_nu[i]; j++)
2137 fprintf(xmlout, " <ID Instance=\"%s\">%s</ID>\n", cp->uuif_uuid[i][j], j+1);
2138 fprintf(xmlout, " </UUIDList>\n");
2139 fprintf(xmlout, " <DataEntryURL>\n");
2140 /* Could add VERS and FLAG here */
2141 fprintf(xmlout, " <LOC>\n");
2142 fprintf(xmlout, " %s",cp->uinf_url[i]); /* Probably single line, so indent works */ /* In theory, could check if this is well-formed, or good live link */
2143 fprintf(xmlout, " </LOC>\n");
2144 fprintf(xmlout, " </DataEntryURL>\n");
2145 fprintf(xmlout, " </UUIDInfo>\n");
2149 IMAGE these use cp structure, extended... but we could use a new data structure instead
2150 void xml_out_frame_unknown_type(FILE* xmlout, opj_cp_t *cp) {
2151 /* Part III 5.2.1 says "Type fields not defined here are reserved. Private extensions
2152 shall be acieved through the 'uuid' type." [This implies an unknown
2153 type would be an error, but then...] "Boxes not explicitly defined in this standard,
2154 or otherwise unrecognized by a reader, may be ignored."
2155 Also, it says "the following types are not and will not be used, or used only in
2156 their existing sense, in future versions of this specification, to avoid conflict
2157 with existing content using earlier pre-standard versions of this format:
2158 clip, crgn, matt, kmat, pnot, ctab, load, imap;
2159 track reference types tmcd, chap, sync,scpt, ssrc"
2160 [But good luck figuring out the mapping.]
2161 Part III Amend. 2 4.1 is stronger: "All these specifications [of this family, e.g.,
2162 JP2 Part I, ISO Base format (Part 12) leading to MP4, Quicktime, and possibly including
2163 MJ2] require that readers ignore objects that are unrecognizable to them".
2166 IMAGE cp->unknown_type, cp->unknown_type_count, cp->unknown_type_boxtype (array of buf[5]s), cp->unknown_type_data (array of chars), cp->unknown_type_len (array of ints)
2167 if(cp->unknown_type != 1)
2168 return; /* Not present */
2170 for(i = 0; i < cp->unknown_type_count; i++)
2172 fprintf(xmlout, " <UnknownType BoxType=\"%s\">\n", cp->unknown_type_boxtype[i]);
2173 /* Can be anything, including binary, so do a dump */
2174 /* Is it better to indent or not indent this content? Indent is better for reading, but
2175 worse for cut/paste. */
2176 xml_out_dump_hex_and_ascii(xmlout, cp->unknown_type_data[i], cp->unknown_type_len[i]);
2177 fprintf(xmlout, " </UnknownType>\n");