Coverage Report

Created: 2023-11-19 07:02

/src/libraw/src/metadata/cr3_parser.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- C++ -*-
2
 * Copyright 2019-2021 LibRaw LLC (info@libraw.org)
3
 *
4
5
 LibRaw is free software; you can redistribute it and/or modify
6
 it under the terms of the one of two licenses as you choose:
7
8
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
9
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
10
11
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
12
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
13
14
 */
15
16
#include "../../internal/dcraw_defs.h"
17
18
19
0
static libraw_area_t sget_CanonArea(uchar *s) {
20
0
  libraw_area_t la = {};
21
0
  la.l = s[0] << 8 | s[1];
22
0
  la.t = s[2] << 8 | s[3];
23
0
  la.r = s[4] << 8 | s[5];
24
0
  la.b = s[6] << 8 | s[7];
25
0
  return la;
26
0
}
27
28
int LibRaw::selectCRXFrame(short trackNum, unsigned frameIndex)
29
0
{
30
0
  uint32_t sample_size;
31
0
  uint32_t stsc_index = 0;
32
0
  uint32_t current_sample = 0;
33
0
  crx_data_header_t *hdr = &libraw_internal_data.unpacker_data.crx_header[trackNum];
34
35
0
  if (frameIndex >= hdr->sample_count)
36
0
    return -1;
37
38
0
  for (int i = 0; i < hdr->chunk_count; i++)
39
0
  {
40
0
    int64_t current_offset = hdr->chunk_offsets[i];
41
42
0
    while((stsc_index < hdr->stsc_count) && (i+1 == hdr->stsc_data[stsc_index+1].first))
43
0
      stsc_index++;
44
45
0
    for (int j = 0; j < hdr->stsc_data[stsc_index].count; j++)
46
0
    {
47
0
      if (current_sample > hdr->sample_count)
48
0
        return -1;
49
50
0
      sample_size = hdr->sample_size > 0 ? hdr->sample_size : hdr->sample_sizes[current_sample];
51
0
      if(current_sample == frameIndex)
52
0
      {
53
0
        hdr->MediaOffset = current_offset;
54
0
        hdr->MediaSize = sample_size;
55
0
        return 0;
56
0
      }
57
0
      current_offset += sample_size;
58
0
      current_sample++;
59
0
    }
60
0
  }
61
0
  return -1;
62
0
}
63
64
void LibRaw::selectCRXTrack()
65
20
{
66
20
  short maxTrack = libraw_internal_data.unpacker_data.crx_track_count;
67
20
  if (maxTrack < 0)
68
0
    return;
69
70
20
  INT64 bitcounts[LIBRAW_CRXTRACKS_MAXCOUNT], maxbitcount = 0;
71
20
  int framecounts[LIBRAW_CRXTRACKS_MAXCOUNT], maxframecount = 0;
72
20
  uint32_t maxjpegbytes = 0;
73
20
  int framecnt = 0;
74
20
  int media_tracks = 0;
75
20
  int track_select = 0;
76
20
  int frame_select = 0;
77
20
  int err;
78
20
  memset(bitcounts, 0, sizeof(bitcounts));
79
20
  memset(framecounts, 0, sizeof(framecounts));
80
81
  // Calc max frame bitcount for max-sized RAW track(s) selection
82
153
  for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
83
133
  {
84
133
    crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i];
85
133
    if (d->MediaType == 1) // RAW
86
0
    {
87
0
      bitcounts[i] = INT64(d->nBits) * INT64(d->f_width) * INT64(d->f_height);
88
0
      maxbitcount = MAX(bitcounts[i], maxbitcount);
89
0
    if (d->sample_count > 1)
90
0
      framecounts[i] = d->sample_count;
91
0
    }
92
133
  }
93
94
20
  if (maxbitcount < 8) // no raw tracks
95
20
    return;
96
97
  // Calc  RAW tracks and frames
98
0
  for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
99
0
  {
100
0
    if (bitcounts[i] == maxbitcount)
101
0
    {
102
0
      media_tracks++;
103
0
      if (framecounts[i] > 1)
104
0
        framecnt = MAX(framecnt, framecounts[i]);
105
0
    }
106
0
  }
107
  
108
  // If the file has only 1 media track shot_select represents frames select.
109
  // If the file has multiple media tracks shot_select represents track select.
110
  // If the file has multiple media tracks and multiple frames it is currently unsupported.
111
112
0
  if (framecnt && media_tracks > 1)
113
0
    return;
114
0
  else if (framecnt)
115
0
    frame_select = shot_select;
116
0
  else
117
0
    track_select = shot_select;
118
119
0
  int tracki = -1;
120
0
  for (int i = 0, trackcnt = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
121
0
  {
122
0
    if (bitcounts[i] == maxbitcount)
123
0
    {
124
0
      if (trackcnt <= (int)track_select)
125
0
        tracki = i;
126
0
    trackcnt++;
127
0
    }
128
0
  }
129
130
0
  if (tracki >= 0 && tracki < LIBRAW_CRXTRACKS_MAXCOUNT /* && frame_select > 0 */)
131
0
  {
132
0
    framecnt = framecounts[tracki]; // Update to selected track
133
0
    frame_select = LIM(frame_select, 0, framecnt);
134
0
    if(frame_select > 0)
135
0
    if (selectCRXFrame(tracki, frame_select))
136
0
        return;
137
0
  }
138
0
  else
139
0
    return; // No RAW track index
140
141
  // Frame selected: parse CTMD metadata
142
0
  for (int i = 0, trackcnt = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
143
0
  {
144
0
    crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i];
145
0
    int fsel = LIM(frame_select, 0, d->sample_count);
146
0
    if (d->MediaType == 3) // CTMD metadata
147
0
    {
148
      /* ignore errors !*/
149
0
      if (fsel)
150
0
        selectCRXFrame(i, fsel);
151
0
      parseCR3_CTMD(i);
152
0
    }
153
0
    else if (d->MediaType == 2) // JPEG
154
0
    {
155
0
      if (fsel)
156
0
        selectCRXFrame(i, fsel);
157
0
      if (d->MediaSize > maxjpegbytes)
158
0
      {
159
0
        maxjpegbytes = d->MediaSize;
160
0
        thumb_offset = d->MediaOffset;
161
0
        thumb_length = d->MediaSize;
162
0
              if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
163
0
              {
164
0
                bool do_add = true;
165
0
                for (int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++)
166
0
                  if (imgdata.thumbs_list.thumblist[idx].toffset == thumb_offset)
167
0
                  {
168
0
                    do_add = false;
169
0
                    break;
170
0
                  }
171
0
                if (do_add)
172
0
                {
173
0
                  int idx = imgdata.thumbs_list.thumbcount;
174
0
                  imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG;
175
0
                  imgdata.thumbs_list.thumblist[idx].toffset = thumb_offset;
176
0
                  imgdata.thumbs_list.thumblist[idx].tlength = thumb_length;
177
0
                  imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
178
0
                  imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps
179
0
                  imgdata.thumbs_list.thumblist[idx].twidth = 0;
180
0
                  imgdata.thumbs_list.thumblist[idx].theight = 0;
181
0
                  imgdata.thumbs_list.thumbcount++;
182
0
                }
183
0
              }
184
0
      }
185
0
    }
186
0
  }
187
188
0
  if (framecnt)
189
0
    is_raw = framecnt;
190
0
  else
191
0
    is_raw = media_tracks;
192
193
0
  if (tracki >= 0 && tracki < LIBRAW_CRXTRACKS_MAXCOUNT)
194
0
  {
195
0
    crx_data_header_t *d =
196
0
        &libraw_internal_data.unpacker_data.crx_header[tracki];
197
0
    data_offset = d->MediaOffset;
198
0
    data_size = d->MediaSize;
199
0
    raw_width = d->f_width;
200
0
    raw_height = d->f_height;
201
0
    load_raw = &LibRaw::crxLoadRaw;
202
0
    tiff_bps = d->encType == 3? d->medianBits : d->nBits;
203
0
    switch (d->cfaLayout)
204
0
    {
205
0
    case 0:
206
0
      filters = 0x94949494;
207
0
      break;
208
0
    case 1:
209
0
      filters = 0x61616161;
210
0
      break;
211
0
    case 2:
212
0
      filters = 0x49494949;
213
0
      break;
214
0
    case 3:
215
0
      filters = 0x16161616;
216
0
      break;
217
0
    }
218
219
0
    libraw_internal_data.unpacker_data.crx_track_selected = tracki;
220
221
0
    int tiff_idx = -1;
222
0
    INT64 tpixels = 0;
223
0
    for (unsigned i = 0; i < tiff_nifds && i < LIBRAW_IFD_MAXCOUNT; i++)
224
0
      if (INT64(tiff_ifd[i].t_height) * INT64(tiff_ifd[i].t_height) > tpixels)
225
0
      {
226
0
        tpixels = INT64(tiff_ifd[i].t_height) * INT64(tiff_ifd[i].t_height);
227
0
        tiff_idx = i;
228
0
      }
229
0
    if (tiff_idx >= 0)
230
0
      flip = tiff_ifd[tiff_idx].t_flip;
231
0
  }
232
0
}
233
234
#define bad_hdr()                                                              \
235
0
  (((order != 0x4d4d) && (order != 0x4949)) || (get2() != 0x002a) ||           \
236
0
   (get4() != 0x00000008))
237
238
int LibRaw::parseCR3_CTMD(short trackNum)
239
0
{
240
0
  int err = 0;
241
0
  short s_order = order;
242
0
  order = 0x4949;
243
0
  uint32_t relpos_inDir = 0;
244
0
  uint32_t relpos_inBox = 0;
245
0
  unsigned szItem, Tag, lTag;
246
0
  ushort tItem;
247
248
0
#define track libraw_internal_data.unpacker_data.crx_header[trackNum]
249
250
0
  if (track.MediaType != 3)
251
0
  {
252
0
    err = -10;
253
0
    goto ctmd_fin;
254
0
  }
255
256
0
  while (relpos_inDir + 6 < track.MediaSize)
257
0
  {
258
0
    if (track.MediaOffset + relpos_inDir > ifp->size() - 6) // need at least 6 bytes
259
0
    {
260
0
        err = -11;
261
0
        goto ctmd_fin;
262
0
    }
263
0
    fseek(ifp, track.MediaOffset + relpos_inDir, SEEK_SET);
264
0
    szItem = get4();
265
0
    tItem = get2();
266
0
    if (szItem < 1 || (  (relpos_inDir + szItem) > track.MediaSize))
267
0
    {
268
0
      err = -11;
269
0
      goto ctmd_fin;
270
0
    }
271
0
    if ((tItem == 7) || (tItem == 8) || (tItem == 9))
272
0
    {
273
0
      relpos_inBox = relpos_inDir + 12L;
274
0
      while (relpos_inBox + 8 < relpos_inDir + szItem)
275
0
      {
276
0
        if (track.MediaOffset + relpos_inBox > ifp->size() - 8) // need at least 8 bytes
277
0
        {
278
0
            err = -11;
279
0
            goto ctmd_fin;
280
0
        }
281
0
        fseek(ifp, track.MediaOffset + relpos_inBox, SEEK_SET);
282
0
        lTag = get4();
283
0
        Tag = get4();
284
0
        if (lTag < 8)
285
0
        {
286
0
          err = -12;
287
0
          goto ctmd_fin;
288
0
        }
289
0
        else if ((relpos_inBox + lTag) > (relpos_inDir + szItem))
290
0
        {
291
0
          err = -11;
292
0
          goto ctmd_fin;
293
0
        }
294
0
        if ((Tag == 0x927c) && ((tItem == 7) || (tItem == 8)))
295
0
        {
296
0
          fseek(ifp, track.MediaOffset + relpos_inBox + 8L,
297
0
                SEEK_SET);
298
0
          short q_order = order;
299
0
          order = get2();
300
0
          if (bad_hdr())
301
0
          {
302
0
            err = -13;
303
0
            goto ctmd_fin;
304
0
          }
305
0
          fseek(ifp, -8L, SEEK_CUR);
306
0
          libraw_internal_data.unpacker_data.CR3_CTMDtag = 1;
307
0
          parse_makernote(track.MediaOffset + relpos_inBox + 8,
308
0
                          0);
309
0
          libraw_internal_data.unpacker_data.CR3_CTMDtag = 0;
310
0
          order = q_order;
311
0
        }
312
0
        relpos_inBox += lTag;
313
0
      }
314
0
    }
315
0
    relpos_inDir += szItem;
316
0
  }
317
318
0
ctmd_fin:
319
0
  order = s_order;
320
0
  return err;
321
0
}
322
#undef track
323
324
int LibRaw::parseCR3(INT64 oAtomList,
325
                     INT64 szAtomList, short &nesting,
326
                     char *AtomNameStack, short &nTrack, short &TrackType)
327
2.16k
{
328
  /*
329
  Atom starts with 4 bytes for Atom size and 4 bytes containing Atom name
330
  Atom size includes the length of the header and the size of all "contained"
331
  Atoms if Atom size == 1, Atom has the extended size stored in 8 bytes located
332
  after the Atom name if Atom size == 0, it is the last top-level Atom extending
333
  to the end of the file Atom name is often a 4 symbol mnemonic, but can be a
334
  4-byte integer
335
  */
336
2.16k
  const char UIID_Canon[17] =
337
2.16k
      "\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48";
338
2.16k
  const unsigned char UIID_CanonPreview[17] = "\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16";
339
2.16k
  const unsigned char UUID_XMP[17] = "\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac";
340
  
341
  /*
342
  AtomType = 0 - unknown: "unk."
343
  AtomType = 1 - container atom: "cont"
344
  AtomType = 2 - leaf atom: "leaf"
345
  AtomType = 3 - can be container, can be leaf: "both"
346
  */
347
2.16k
  short AtomType;
348
2.16k
  static const struct
349
2.16k
  {
350
2.16k
    char AtomName[5];
351
2.16k
    short AtomType;
352
2.16k
  } AtomNamesList[] = {
353
2.16k
      {"dinf", 1},
354
2.16k
      {"edts", 1},
355
2.16k
      {"fiin", 1},
356
2.16k
      {"ipro", 1},
357
2.16k
      {"iprp", 1},
358
2.16k
      {"mdia", 1},
359
2.16k
      {"meco", 1},
360
2.16k
      {"mere", 1},
361
2.16k
      {"mfra", 1},
362
2.16k
      {"minf", 1},
363
2.16k
      {"moof", 1},
364
2.16k
      {"moov", 1},
365
2.16k
      {"mvex", 1},
366
2.16k
      {"paen", 1},
367
2.16k
      {"schi", 1},
368
2.16k
      {"sinf", 1},
369
2.16k
      {"skip", 1},
370
2.16k
      {"stbl", 1},
371
2.16k
      {"stsd", 1},
372
2.16k
      {"strk", 1},
373
2.16k
      {"tapt", 1},
374
2.16k
      {"traf", 1},
375
2.16k
      {"trak", 1},
376
377
2.16k
      {"cdsc", 2},
378
2.16k
      {"colr", 2},
379
2.16k
      {"dimg", 2},
380
      // {"dref", 2},
381
2.16k
      {"free", 2},
382
2.16k
      {"frma", 2},
383
2.16k
      {"ftyp", 2},
384
2.16k
      {"hdlr", 2},
385
2.16k
      {"hvcC", 2},
386
2.16k
      {"iinf", 2},
387
2.16k
      {"iloc", 2},
388
2.16k
      {"infe", 2},
389
2.16k
      {"ipco", 2},
390
2.16k
      {"ipma", 2},
391
2.16k
      {"iref", 2},
392
2.16k
      {"irot", 2},
393
2.16k
      {"ispe", 2},
394
2.16k
      {"meta", 2},
395
2.16k
      {"mvhd", 2},
396
2.16k
      {"pitm", 2},
397
2.16k
      {"pixi", 2},
398
2.16k
      {"schm", 2},
399
2.16k
      {"thmb", 2},
400
2.16k
      {"tkhd", 2},
401
2.16k
      {"url ", 2},
402
2.16k
      {"urn ", 2},
403
404
2.16k
      {"CCTP", 1},
405
2.16k
      {"CRAW", 1},
406
407
2.16k
      {"JPEG", 2},
408
2.16k
      {"CDI1", 2},
409
2.16k
      {"CMP1", 2},
410
411
2.16k
      {"CNCV", 2},
412
2.16k
      {"CCDT", 2},
413
2.16k
      {"CTBO", 2},
414
2.16k
      {"CMT1", 2},
415
2.16k
      {"CMT2", 2},
416
2.16k
      {"CMT3", 2},
417
2.16k
      {"CMT4", 2},
418
2.16k
      {"CNOP", 2},
419
2.16k
      {"THMB", 2},
420
2.16k
      {"co64", 2},
421
2.16k
      {"mdat", 2},
422
2.16k
      {"mdhd", 2},
423
2.16k
      {"nmhd", 2},
424
2.16k
      {"stsc", 2},
425
2.16k
      {"stsz", 2},
426
2.16k
      {"stts", 2},
427
2.16k
      {"vmhd", 2},
428
429
2.16k
      {"dref", 3},
430
2.16k
      {"uuid", 3},
431
2.16k
  };
432
433
2.16k
  const char sHandlerType[5][5] = {"unk.", "soun", "vide", "hint", "meta"};
434
435
2.16k
  int c, err=0;
436
437
2.16k
  ushort tL;                        // Atom length represented in 4 or 8 bytes
438
2.16k
  char nmAtom[5];                   // Atom name
439
2.16k
  INT64 oAtom, szAtom; // Atom offset and Atom size
440
2.16k
  INT64 oAtomContent,
441
2.16k
      szAtomContent; // offset and size of Atom content
442
2.16k
  INT64 lHdr;
443
444
2.16k
  char UIID[16];
445
2.16k
  uchar CMP1[85];
446
2.16k
  uchar CDI1[60];
447
2.16k
  char HandlerType[5], MediaFormatID[5];
448
2.16k
  uint32_t relpos_inDir, relpos_inBox;
449
2.16k
  unsigned szItem, Tag, lTag;
450
2.16k
  ushort tItem;
451
452
2.16k
  nmAtom[0] = MediaFormatID[0] = nmAtom[4] = MediaFormatID[4] = '\0';
453
2.16k
  strcpy(HandlerType, sHandlerType[0]);
454
2.16k
  oAtom = oAtomList;
455
2.16k
  nesting++;
456
2.16k
  if (nesting > 31)
457
0
    return -14; // too deep nesting
458
2.16k
  short s_order = order;
459
460
1.53M
  while ((oAtom + 8LL) <= (oAtomList + szAtomList))
461
1.53M
  {
462
1.53M
    lHdr = 0ULL;
463
1.53M
    err = 0;
464
1.53M
    order = 0x4d4d;
465
1.53M
    fseek(ifp, oAtom, SEEK_SET);
466
1.53M
    szAtom = get4();
467
6.14M
    FORC4 nmAtom[c] = AtomNameStack[nesting * 4 + c] = fgetc(ifp);
468
1.53M
    AtomNameStack[(nesting + 1) * 4] = '\0';
469
1.53M
    tL = 4;
470
1.53M
    AtomType = 0;
471
472
55.4M
    for (c = 0; c < int(sizeof AtomNamesList / sizeof *AtomNamesList); c++)
473
55.1M
      if (!strcmp(nmAtom, AtomNamesList[c].AtomName))
474
1.28M
      {
475
1.28M
        AtomType = AtomNamesList[c].AtomType;
476
1.28M
        break;
477
1.28M
      }
478
479
1.53M
    if (!AtomType)
480
247k
    {
481
247k
      err = 1;
482
247k
    }
483
484
1.53M
    if (szAtom == 0ULL)
485
23
    {
486
23
      if (nesting != 0)
487
11
      {
488
11
        err = -2;
489
11
        goto fin;
490
11
      }
491
12
      szAtom = szAtomList - oAtom;
492
12
      oAtomContent = oAtom + 8ULL;
493
12
      szAtomContent = szAtom - 8ULL;
494
12
    }
495
1.53M
    else if (szAtom == 1LL)
496
196
    {
497
196
      if ((oAtom + 16LL) > (oAtomList + szAtomList))
498
3
      {
499
3
        err = -3;
500
3
        goto fin;
501
3
      }
502
193
      tL = 8;
503
193
      szAtom = (((unsigned long long)get4()) << 32) | get4();
504
193
      oAtomContent = oAtom + 16ULL;
505
193
      szAtomContent = szAtom - 16ULL;
506
193
    }
507
1.53M
    else
508
1.53M
    {
509
1.53M
      oAtomContent = oAtom + 8ULL;
510
1.53M
      szAtomContent = szAtom - 8ULL;
511
1.53M
    }
512
513
1.53M
  if (!strcmp(AtomNameStack, "uuid")) // Top level uuid
514
29
  {
515
29
    INT64 tt = ftell(ifp);
516
29
    lHdr = 16ULL;
517
29
    fread(UIID, 1, lHdr, ifp);
518
29
    if (!memcmp(UIID, UUID_XMP, 16) && szAtom > 24LL && szAtom < 1024000LL)
519
2
    {
520
2
      xmpdata = (char *)malloc(xmplen = unsigned(szAtom - 23));
521
2
      fread(xmpdata, szAtom - 24, 1, ifp);
522
2
      xmpdata[szAtom - 24] = 0;
523
2
    }
524
27
    else if (!memcmp(UIID, UIID_CanonPreview, 16) && szAtom > 48LL && szAtom < 100LL * 1024000LL)
525
0
    {
526
      // read next 48 bytes, check for 'PRVW'
527
0
      unsigned char xdata[32];
528
0
      fread(xdata, 32, 1, ifp);  
529
0
      if (!memcmp(xdata + 12, "PRVW", 4))
530
0
      {
531
0
        thumb_length = unsigned(szAtom - 56);
532
0
        thumb_offset = ftell(ifp);
533
0
        if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
534
0
        {
535
0
          bool do_add = true;
536
0
          for(int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++)
537
0
            if (imgdata.thumbs_list.thumblist[idx].toffset == thumb_offset)
538
0
            {
539
0
              do_add = false;
540
0
              break;
541
0
            }
542
0
          if (do_add)
543
0
          {
544
0
            int idx = imgdata.thumbs_list.thumbcount;
545
0
            imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG;
546
0
            imgdata.thumbs_list.thumblist[idx].toffset = thumb_offset;
547
0
            imgdata.thumbs_list.thumblist[idx].tlength = thumb_length;
548
0
            imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
549
0
            imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps
550
0
            imgdata.thumbs_list.thumblist[idx].twidth = (xdata[22] << 8) + xdata[23];
551
0
                        imgdata.thumbs_list.thumblist[idx].theight = (xdata[24] << 8) + xdata[25];
552
0
            imgdata.thumbs_list.thumbcount++;
553
0
          }
554
0
        }
555
556
0
      }
557
0
    }
558
29
    fseek(ifp, tt, SEEK_SET);
559
29
  }
560
561
1.53M
    if (!strcmp(nmAtom, "trak"))
562
497
    {
563
497
      nTrack++;
564
497
      TrackType = 0;
565
497
      if (nTrack >= LIBRAW_CRXTRACKS_MAXCOUNT)
566
14
        break;
567
497
    }
568
1.53M
    if (!strcmp(AtomNameStack, "moovuuid"))
569
4
    {
570
4
      lHdr = 16ULL;
571
4
      fread(UIID, 1, lHdr, ifp);
572
4
      if (!strncmp(UIID, UIID_Canon, lHdr))
573
0
      {
574
0
        AtomType = 1;
575
0
      }
576
4
      else
577
4
        fseek(ifp, -lHdr, SEEK_CUR);
578
4
    }
579
1.53M
    else if (!strcmp(AtomNameStack, "moovuuidCCTP"))
580
0
    {
581
0
      lHdr = 12ULL;
582
0
    }
583
1.53M
    else if (!strcmp(AtomNameStack, "moovuuidCMT1"))
584
0
    {
585
0
      short q_order = order;
586
0
      order = get2();
587
0
      if ((tL != 4) || bad_hdr())
588
0
      {
589
0
        err = -4;
590
0
        goto fin;
591
0
      }
592
0
      if (!libraw_internal_data.unpacker_data.cr3_ifd0_length)
593
0
        libraw_internal_data.unpacker_data.cr3_ifd0_length = unsigned(szAtomContent);
594
0
      parse_tiff_ifd(oAtomContent);
595
0
      order = q_order;
596
0
    }
597
1.53M
  else if (!strcmp(AtomNameStack, "moovuuidTHMB") && szAtom > 24)
598
0
  {
599
0
    unsigned char xdata[16];
600
0
    fread(xdata, 16, 1, ifp);
601
0
    INT64 xoffset = ftell(ifp);
602
0
    if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
603
0
    {
604
0
      bool do_add = true;
605
0
      for (int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++)
606
0
        if (imgdata.thumbs_list.thumblist[idx].toffset == xoffset)
607
0
        {
608
0
          do_add = false;
609
0
          break;
610
0
        }
611
0
            if (do_add)
612
0
            {
613
0
              int idx = imgdata.thumbs_list.thumbcount;
614
0
              imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG;
615
0
        imgdata.thumbs_list.thumblist[idx].toffset = xoffset;
616
0
              imgdata.thumbs_list.thumblist[idx].tlength = szAtom-24;
617
0
        imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
618
0
              imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps
619
0
              imgdata.thumbs_list.thumblist[idx].twidth = (xdata[4] << 8) + xdata[5];
620
0
              imgdata.thumbs_list.thumblist[idx].theight = (xdata[6] << 8) + xdata[7];
621
0
              imgdata.thumbs_list.thumbcount++;
622
0
            }
623
0
    }
624
0
  }
625
1.53M
  else if (!strcmp(AtomNameStack, "moovuuidCMT2"))
626
0
  {
627
0
    short q_order = order;
628
0
    order = get2();
629
0
    if ((tL != 4) || bad_hdr())
630
0
    {
631
0
      err = -5;
632
0
      goto fin;
633
0
    }
634
0
    if (!libraw_internal_data.unpacker_data.cr3_exif_length)
635
0
      libraw_internal_data.unpacker_data.cr3_exif_length = unsigned(szAtomContent); 
636
0
      parse_exif(oAtomContent);
637
0
      order = q_order;
638
0
    }
639
1.53M
    else if (!strcmp(AtomNameStack, "moovuuidCMT3"))
640
0
    {
641
0
      short q_order = order;
642
0
      order = get2();
643
0
      if ((tL != 4) || bad_hdr())
644
0
      {
645
0
        err = -6;
646
0
        goto fin;
647
0
      }
648
0
      fseek(ifp, -12L, SEEK_CUR);
649
0
      parse_makernote(oAtomContent, 0);
650
0
      order = q_order;
651
0
    }
652
1.53M
    else if (!strcmp(AtomNameStack, "moovuuidCMT4"))
653
0
    {
654
0
      short q_order = order;
655
0
      order = get2();
656
0
      if ((tL != 4) || bad_hdr())
657
0
      {
658
0
        err = -6;
659
0
        goto fin;
660
0
      }
661
0
      INT64 off = ftell(ifp);
662
0
      parse_gps(oAtomContent);
663
0
      fseek(ifp, off, SEEK_SET);
664
0
      parse_gps_libraw(oAtomContent);
665
0
      order = q_order;
666
0
    }
667
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiahdlr"))
668
0
    {
669
0
      fseek(ifp, 8L, SEEK_CUR);
670
0
      FORC4 HandlerType[c] = fgetc(ifp);
671
0
      for (c = 1; c < int(sizeof sHandlerType / sizeof *sHandlerType); c++)
672
0
        if (!strcmp(HandlerType, sHandlerType[c]))
673
0
        {
674
0
          TrackType = c;
675
0
          break;
676
0
        }
677
0
    }
678
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsd"))
679
76
    {
680
76
      if (szAtomContent >= 16)
681
74
      {
682
74
        fseek(ifp, 12L, SEEK_CUR);
683
74
        lHdr = 8;
684
74
      }
685
2
      else
686
2
      {
687
2
        err = -7;
688
2
        goto fin;
689
2
      }
690
296
      FORC4 MediaFormatID[c] = fgetc(ifp);
691
74
      if ((TrackType == 2) && (!strcmp(MediaFormatID, "CRAW")))
692
0
      {
693
0
        if (szAtomContent >= 44)
694
0
          fseek(ifp, 24L, SEEK_CUR);
695
0
        else
696
0
        {
697
0
          err = -8;
698
0
          goto fin;
699
0
        }
700
0
      }
701
74
      else
702
74
      {
703
74
        AtomType = 2; // only continue for CRAW
704
74
        lHdr = 0;
705
74
      }
706
11.7M
#define current_track libraw_internal_data.unpacker_data.crx_header[nTrack]
707
708
74
      /*ImageWidth =*/ get2();
709
74
      /*ImageHeight =*/ get2();
710
74
    }
711
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAW"))
712
0
    {
713
0
      lHdr = 82;
714
0
    }
715
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWCMP1"))
716
0
    {
717
0
      int read_size = szAtomContent > 85 ? 85 : szAtomContent;
718
0
      if (szAtomContent >= 40)
719
0
        fread(CMP1, 1, read_size, ifp);
720
0
      else
721
0
      {
722
0
        err = -7;
723
0
        goto fin;
724
0
      }
725
0
      if (!crxParseImageHeader(CMP1, nTrack, read_size))
726
0
        current_track.MediaType = 1;
727
0
    }
728
729
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWCDI1")) {
730
0
      if (szAtomContent >= 60) {
731
0
        fread(CDI1, 1, 60, ifp);
732
0
        if (!strncmp((char *)CDI1+8, "IAD1", 4) && (sgetn(8, CDI1) == 0x38)) {
733
          // sensor area at CDI1+12, 4 16-bit values
734
          // Bayer pattern? - next 4 16-bit values
735
0
          imCanon.RecommendedImageArea = sget_CanonArea(CDI1+12 + 2*4*2);
736
0
          imCanon.LeftOpticalBlack     = sget_CanonArea(CDI1+12 + 3*4*2);
737
0
          imCanon.UpperOpticalBlack    = sget_CanonArea(CDI1+12 + 4*4*2);
738
0
          imCanon.ActiveArea           = sget_CanonArea(CDI1+12 + 5*4*2);
739
0
        }
740
0
      }
741
0
    }
742
743
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWJPEG"))
744
0
    {
745
0
      current_track.MediaType = 2;
746
0
    }
747
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsc"))
748
37
    {
749
37
      if (szAtomContent >= 12) {
750
25
        fseek(ifp, 4L, SEEK_CUR);
751
25
        int entries = get4();
752
25
        if (entries < 1 || entries > 1000000)
753
4
        {
754
4
          err =  -9;
755
4
          goto fin;
756
4
        }
757
758
21
        current_track.stsc_data = (crx_sample_to_chunk_t*) malloc(entries * sizeof(crx_sample_to_chunk_t));
759
21
        if(!current_track.stsc_data)
760
0
        {
761
0
          err =  -9;
762
0
          goto fin;
763
0
        }
764
21
        current_track.stsc_count = entries;
765
1.71M
        for(int i = 0; i < entries; i++)
766
1.71M
        {
767
1.71M
          current_track.stsc_data[i].first = get4();
768
1.71M
          current_track.stsc_data[i].count = get4();
769
1.71M
          current_track.stsc_data[i].id = get4();
770
1.71M
        }
771
21
      }
772
37
    }
773
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsz"))
774
179
    {
775
179
      if (szAtomContent >= 12)
776
170
      {
777
170
        fseek(ifp, 4L, SEEK_CUR);
778
170
        int sample_size = get4();
779
170
        int entries = get4();
780
170
        current_track.sample_count = entries;
781
782
        // if sample size is zero sample size is fixed
783
170
        if (sample_size)
784
108
        {
785
108
           current_track.MediaSize = sample_size;
786
108
           current_track.sample_size = sample_size;
787
108
        }
788
62
        else
789
62
        {
790
62
          current_track.sample_size = 0;
791
62
          if (entries < 1 || entries > 1000000) {
792
5
            err = -10;
793
5
            goto fin;
794
5
          }
795
57
          current_track.sample_sizes = (int32_t*)malloc(entries * sizeof(int32_t));
796
57
          if (!current_track.sample_sizes)
797
0
          {
798
0
            err = -10;
799
0
            goto fin;
800
0
          }
801
2.66M
          for (int i = 0; i < entries; i++)
802
2.66M
            current_track.sample_sizes[i] = get4();
803
804
57
          current_track.MediaSize = current_track.sample_sizes[0];
805
57
        }
806
170
      }
807
179
    }
808
1.53M
    else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblco64"))
809
55
    {
810
55
      if (szAtomContent >= 16) {
811
55
        fseek(ifp, 4L, SEEK_CUR);
812
55
        uint32_t entries = get4();
813
55
        int i;
814
55
        if (entries < 1 || entries > 1000000)
815
7
        {
816
7
          err = -11;
817
7
          goto fin;
818
7
        }
819
48
        current_track.chunk_offsets = (INT64*)malloc(entries * sizeof(int64_t));
820
48
        if(!current_track.chunk_offsets)
821
0
        {
822
0
          err = -11;
823
0
          goto fin;
824
0
        }
825
826
48
        current_track.chunk_count = entries;
827
3.66M
        for (i = 0; i < entries; i++)
828
3.66M
          current_track.chunk_offsets[i] = (((int64_t)get4()) << 32) | get4();
829
830
48
        current_track.chunk_count = i;
831
48
        current_track.MediaOffset =  current_track.chunk_offsets[0];
832
48
      }
833
55
    }
834
835
1.53M
    if (nTrack >= 0 && nTrack < LIBRAW_CRXTRACKS_MAXCOUNT &&
836
1.53M
        current_track.MediaSize && current_track.MediaOffset &&
837
1.53M
        ((oAtom + szAtom) >= (oAtomList + szAtomList)) &&
838
1.53M
        !strncmp(AtomNameStack, "moovtrakmdiaminfstbl", 20))
839
44
    {
840
44
      if ((TrackType == 4) && (!strcmp(MediaFormatID, "CTMD")))
841
0
      {
842
0
        current_track.MediaType = 3;
843
0
      }
844
44
    }
845
1.53M
#undef current_track
846
1.53M
    if (AtomType == 1)
847
1.71k
    {
848
1.71k
      err = parseCR3(oAtomContent + lHdr, szAtomContent - lHdr, nesting,
849
1.71k
                     AtomNameStack, nTrack, TrackType);
850
1.71k
      if (err)
851
1.08k
        goto fin;
852
1.71k
    }
853
1.53M
    oAtom += szAtom;
854
1.53M
  }
855
856
2.16k
fin:
857
2.16k
  nesting--;
858
2.16k
  if (nesting >= 0)
859
1.71k
    AtomNameStack[nesting * 4] = '\0';
860
2.16k
  order = s_order;
861
2.16k
  return err;
862
2.16k
}
863
#undef bad_hdr
864
865
void LibRaw::parseCR3_Free()
866
144k
{
867
144k
  short maxTrack = libraw_internal_data.unpacker_data.crx_track_count;
868
144k
  if (maxTrack < 0)
869
58.6k
    return;
870
871
171k
  for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++)
872
85.8k
  {
873
85.8k
    crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i];
874
85.8k
    if (d->stsc_data)
875
21
    {
876
21
      free(d->stsc_data);
877
21
      d->stsc_data = NULL;
878
21
    }
879
85.8k
    if (d->chunk_offsets)
880
47
    {
881
47
      free(d->chunk_offsets);
882
47
      d->chunk_offsets = NULL;
883
47
    }
884
885
85.8k
    if (d->sample_sizes)
886
35
    {
887
35
      free(d->sample_sizes);
888
35
      d->sample_sizes = NULL;
889
35
    }
890
85.8k
    d->stsc_count   = 0;
891
85.8k
    d->sample_count = 0;
892
85.8k
    d->sample_size  = 0;
893
85.8k
    d->chunk_count  = 0;
894
85.8k
  }
895
85.6k
  libraw_internal_data.unpacker_data.crx_track_count = -1;
896
85.6k
}