exiftool-vendored.pl 13.25.1 → 13.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +10 -2
  2. package/bin/Changes +56 -3
  3. package/bin/META.json +3 -2
  4. package/bin/META.yml +3 -2
  5. package/bin/README +3 -3
  6. package/bin/arg_files/exif2xmp.args +2 -1
  7. package/bin/arg_files/xmp2exif.args +2 -1
  8. package/bin/build_geolocation +1 -1
  9. package/bin/exiftool +17 -15
  10. package/bin/lib/Image/ExifTool/Canon.pm +5 -4
  11. package/bin/lib/Image/ExifTool/GIMP.pm +1 -1
  12. package/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -0
  13. package/bin/lib/Image/ExifTool/JPEG.pm +20 -8
  14. package/bin/lib/Image/ExifTool/LigoGPS.pm +16 -2
  15. package/bin/lib/Image/ExifTool/MPF.pm +5 -1
  16. package/bin/lib/Image/ExifTool/Nikon.pm +2 -1
  17. package/bin/lib/Image/ExifTool/Olympus.pm +3 -2
  18. package/bin/lib/Image/ExifTool/PCAP.pm +5 -5
  19. package/bin/lib/Image/ExifTool/Panasonic.pm +9 -1
  20. package/bin/lib/Image/ExifTool/Parrot.pm +54 -7
  21. package/bin/lib/Image/ExifTool/Pentax.pm +102 -1
  22. package/bin/lib/Image/ExifTool/Plot.pm +36 -15
  23. package/bin/lib/Image/ExifTool/QuickTime.pm +78 -12
  24. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +70 -14
  25. package/bin/lib/Image/ExifTool/README +12 -2
  26. package/bin/lib/Image/ExifTool/RIFF.pm +15 -6
  27. package/bin/lib/Image/ExifTool/Sony.pm +5 -0
  28. package/bin/lib/Image/ExifTool/TagLookup.pm +23 -2
  29. package/bin/lib/Image/ExifTool/TagNames.pod +149 -92
  30. package/bin/lib/Image/ExifTool/WriteExif.pl +2 -0
  31. package/bin/lib/Image/ExifTool/WriteQuickTime.pl +3 -0
  32. package/bin/lib/Image/ExifTool/Writer.pl +17 -6
  33. package/bin/lib/Image/ExifTool/XMP.pm +23 -16
  34. package/bin/lib/Image/ExifTool/XMP2.pl +5 -1
  35. package/bin/lib/Image/ExifTool.pm +7 -3
  36. package/bin/lib/Image/ExifTool.pod +13 -12
  37. package/bin/perl-Image-ExifTool.spec +1 -1
  38. package/bin/windows_exiftool.txt +6 -5
  39. package/package.json +12 -9
@@ -15,7 +15,7 @@ use strict;
15
15
  use vars qw($VERSION);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
 
18
- $VERSION = '1.02';
18
+ $VERSION = '1.03';
19
19
 
20
20
  sub Process_mett($$$);
21
21
 
@@ -61,10 +61,18 @@ sub Process_mett($$$);
61
61
  Name => 'ARCoreAccel',
62
62
  SubDirectory => { TagTable => 'Image::ExifTool::Parrot::ARCoreAccel', ByteOrder => 'II' },
63
63
  },
64
+ 'application/arcore-accel-0' => {
65
+ Name => 'ARCoreAccel0',
66
+ SubDirectory => { TagTable => 'Image::ExifTool::Parrot::ARCoreAccel0', ByteOrder => 'II' },
67
+ },
64
68
  'application/arcore-gyro' => {
65
69
  Name => 'ARCoreGyro',
66
70
  SubDirectory => { TagTable => 'Image::ExifTool::Parrot::ARCoreGyro', ByteOrder => 'II' },
67
71
  },
72
+ 'application/arcore-gyro-0' => {
73
+ Name => 'ARCoreGyro0',
74
+ SubDirectory => { TagTable => 'Image::ExifTool::Parrot::ARCoreGyro0', ByteOrder => 'II' },
75
+ },
68
76
  'application/arcore-video-0' => {
69
77
  Name => 'ARCoreVideo',
70
78
  SubDirectory => { TagTable => 'Image::ExifTool::Parrot::ARCoreVideo', ByteOrder => 'II' },
@@ -684,11 +692,24 @@ sub Process_mett($$$);
684
692
  # 33: increments slowly (about once every 56 samples or so)
685
693
  );
686
694
 
695
+ # ARCore Accel data (ref PH)
696
+ %Image::ExifTool::Parrot::ARCoreAccel0 = (
697
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
698
+ GROUPS => { 2 => 'Location' },
699
+ NOTES => 'ARCore accelerometer data.',
700
+ FIRST_ENTRY => 0,
701
+ 9 => { # (NC)
702
+ Name => 'Accelerometer',
703
+ Format => 'undef[14]',
704
+ RawConv => 'GetFloat(\$val,0) . " " . GetFloat(\$val,5) . " " . GetFloat(\$val,10)',
705
+ },
706
+ );
707
+
687
708
  # ARCore Gyro data (ref PH)
688
709
  %Image::ExifTool::Parrot::ARCoreGyro = (
689
710
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
690
711
  GROUPS => { 2 => 'Location' },
691
- NOTES => 'ARCore accelerometer data.',
712
+ NOTES => 'ARCore gyro data.',
692
713
  FIRST_ENTRY => 0,
693
714
  # 00-04: always 10 34 16 3 29
694
715
  4 => {
@@ -704,6 +725,19 @@ sub Process_mett($$$);
704
725
  },
705
726
  );
706
727
 
728
+ # ARCore Gyro data (ref PH)
729
+ %Image::ExifTool::Parrot::ARCoreGyro0 = (
730
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
731
+ GROUPS => { 2 => 'Location' },
732
+ NOTES => 'ARCore gyro data.',
733
+ FIRST_ENTRY => 0,
734
+ 9 => { # (NC)
735
+ Name => 'Gyroscope',
736
+ Format => 'undef[14]',
737
+ RawConv => 'GetFloat(\$val,0) . " " . GetFloat(\$val,5) . " " . GetFloat(\$val,10)',
738
+ },
739
+ );
740
+
707
741
  %Image::ExifTool::Parrot::ARCoreVideo = (
708
742
  PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
709
743
  FIRST_ENTRY => 0,
@@ -766,11 +800,24 @@ sub Process_mett($$$)
766
800
  $et->VerboseDir('Parrot mett', undef, $dirEnd);
767
801
 
768
802
  if ($$tagTbl{$metaType}) {
769
- $et->HandleTag($tagTbl, $metaType, undef,
770
- DataPt => $dataPt,
771
- DataPos => $dataPos,
772
- Base => $$dirInfo{Base},
773
- );
803
+ # loop through ARCore records
804
+ while ($pos < $dirEnd - 2) {
805
+ last unless substr($$dataPt,$pos,1) eq "\x0a";
806
+ my $len = ord(substr($$dataPt, $pos+1, 1));
807
+ if ($pos + $len + 2 > $dirEnd) {
808
+ $et->Warn("Unexpected length for $metaType record", 1);
809
+ last;
810
+ }
811
+ $len or $len = $dirEnd - $pos - 2; # use entire record if length is 0
812
+ $et->HandleTag($tagTbl, $metaType, undef,
813
+ DataPt => $dataPt,
814
+ DataPos => $dataPos,
815
+ DirStart => $pos,
816
+ DirLen => $len,
817
+ Base => $$dirInfo{Base},
818
+ );
819
+ $pos += $len + 2;
820
+ }
774
821
  return 1;
775
822
  }
776
823
  while ($pos + 4 < $dirEnd) {
@@ -58,7 +58,7 @@ use Image::ExifTool::Exif;
58
58
  use Image::ExifTool::GPS;
59
59
  use Image::ExifTool::HP;
60
60
 
61
- $VERSION = '3.47';
61
+ $VERSION = '3.50';
62
62
 
63
63
  sub CryptShutterCount($$);
64
64
  sub PrintFilter($$$);
@@ -558,6 +558,7 @@ my %pentaxModelID = (
558
558
  0x13254 => 'K-3 Mark III', #IB (Ricoh)
559
559
  0x13290 => 'WG-70', # (Ricoh)
560
560
  0x1329a => 'GR IIIx', # (Ricoh)
561
+ 0x132b8 => 'KF', #github322 (Ricoh)
561
562
  0x132d6 => 'K-3 Mark III Monochrome', #github226 (Ricoh)
562
563
  );
563
564
 
@@ -736,6 +737,18 @@ my %filterSettings = (
736
737
  52 => ['Toning2', '%+d'], #31 Extract Color (-3-+3)
737
738
  );
738
739
 
740
+ # order of selectable K-3iii AF points. The array looks like this:
741
+ # B1 C1 E1 G1 I1 K1 L1
742
+ # A3 B3 C3 E3 G3 I3 K3 L3 M3
743
+ # A5 B5 C5 E5 G5 I5 K5 L5 M5
744
+ # A7 B7 C7 E7 G7 I7 K7 L7 M7
745
+ # B9 C9 E9 G9 I9 K9 L9
746
+ my @k3iiiAF = qw(
747
+ C1 E1 G1 I1 K1 C3 E3 G3 I3 K3 C5 E5 G5
748
+ I5 K5 C7 E7 G7 I7 K7 C9 E9 G9 I9 K9 A5 M5 B3
749
+ L3 B5 L5 B7 L7 B1 L1 B9 L9 A3 M3 A7 M7
750
+ );
751
+
739
752
  # decoding for Pentax Firmware ID tags - PH
740
753
  my %pentaxFirmwareID = (
741
754
  # the first 2 numbers are the firmware version, I'm not sure what the second 2 mean
@@ -1943,6 +1956,7 @@ my %binaryDataAttrs = (
1943
1956
  '18 3' => 'Auto Program (MTF)', #PH (NC)
1944
1957
  '18 22' => 'Auto Program (Shallow DOF)', #PH (NC)
1945
1958
  '20 22' => 'Blur Control', #PH (Q)
1959
+ '26 0' => 'Shutter and Aperture Priority (TAv)', #PH (K-3III)
1946
1960
  '249 0' => 'Movie (TAv)', #31
1947
1961
  '250 0' => 'Movie (TAv, Auto Aperture)', #31
1948
1962
  '251 0' => 'Movie (Manual)', #31
@@ -4917,6 +4931,7 @@ my %binaryDataAttrs = (
4917
4931
  # CalFlag, ContrastFlag, PrecalFlag, SelectSensor
4918
4932
  0x00 => { #PH
4919
4933
  Name => 'AFPointsUnknown1',
4934
+ Condition => '$$self{Model} !~ /K-3 Mark III/', # (and maybe others?)
4920
4935
  Unknown => 1,
4921
4936
  Format => 'int16u',
4922
4937
  ValueConv => '$self->Options("Unknown") ? $val : $val & 0x7ff',
@@ -4944,6 +4959,7 @@ my %binaryDataAttrs = (
4944
4959
  },
4945
4960
  0x02 => { #PH
4946
4961
  Name => 'AFPointsUnknown2',
4962
+ Condition => '$$self{Model} !~ /K-3 Mark III/', # (and maybe others?)
4947
4963
  Unknown => 1,
4948
4964
  Format => 'int16u',
4949
4965
  ValueConv => '$self->Options("Unknown") ? $val : $val & 0x7ff',
@@ -5016,6 +5032,41 @@ my %binaryDataAttrs = (
5016
5032
  20 => 'Mid-right',
5017
5033
  },
5018
5034
  },
5035
+ 0x14 => {
5036
+ Name => 'AFPointValues',
5037
+ Condition => '$$self{Model} eq "PENTAX K-3 Mark III"', # any other models?
5038
+ Format => 'int16uRev[69]',
5039
+ Unknown => 1,
5040
+ Notes => 'some unknown values related to each AFPoint',
5041
+ # order is the same as AFPoints below, but there is an additional value for
5042
+ # each AF point starting at offset 28 in the array (yes, the range overlaps
5043
+ # with the 1st values)
5044
+ # (values are int16s stored in reversed byte order)
5045
+ ValueConv => 'my @a=split " ",$val;$_>32767 and $_-=65536 foreach @a;join " ",@a',
5046
+ PrintConv => \&AFPointValues,
5047
+ },
5048
+ 0x12a => { # byte has a value of 2 if corresponding AF point is selected
5049
+ Name => 'AFPointsSelected',
5050
+ Condition => '$$self{Model} eq "PENTAX K-3 Mark III"', # any other models?
5051
+ Notes => q{
5052
+ K-3III only. 41 selectable AF points from a total of 101 available in a 13x9
5053
+ grid. Columns are labelled A-M and rows are 1-9. The center point is G5
5054
+ },
5055
+ Format => 'int8u[41]',
5056
+ PrintConv => 'Image::ExifTool::Pentax::AFPointsK3iii($val,$self,2)',
5057
+ },
5058
+ #
5059
+ # (maybe not coincidentally, there are 60 unknown bytes
5060
+ # here, and there are also 60 non-selectable AF points)
5061
+ #
5062
+ 0x18f => { # byte has a value of 1 if corresponding AF point is ... in focus maybe?
5063
+ # usually the same points as AFPoints above, but not always
5064
+ Name => 'AFPointsUnknown',
5065
+ Condition => '$$self{Model} eq "PENTAX K-3 Mark III"', # any other models?
5066
+ Unknown => 1,
5067
+ Format => 'int8u[41]',
5068
+ PrintConv => \&AFPointsK3iii,
5069
+ },
5019
5070
  0x1fa => {
5020
5071
  Name => 'LiveView',
5021
5072
  Notes => 'decoded only for the K-3 III',
@@ -5739,6 +5790,7 @@ my %binaryDataAttrs = (
5739
5790
  # more quickly than CameraTemperature when shooting video.)
5740
5791
  0x0c => {
5741
5792
  Name => 'SensorTemperature', #forum6677 (was CameraTemperature2)
5793
+ Condition => '$$self{Model} !~ /K-3 Mark III/', # (and maybe others?)
5742
5794
  Format => 'int16s',
5743
5795
  ValueConv => '$val / 10',
5744
5796
  ValueConvInv => '$val * 10',
@@ -5747,6 +5799,7 @@ my %binaryDataAttrs = (
5747
5799
  },
5748
5800
  0x0e => {
5749
5801
  Name => 'SensorTemperature2', #forum6677 (was CameraTemperature3)
5802
+ Condition => '$$self{Model} !~ /K-3 Mark III/', # (and maybe others?)
5750
5803
  Format => 'int16s',
5751
5804
  ValueConv => '$val / 10',
5752
5805
  ValueConvInv => '$val * 10',
@@ -5768,6 +5821,15 @@ my %binaryDataAttrs = (
5768
5821
  PrintConvInv => '$val=~s/ ?c$//i; $val',
5769
5822
  },
5770
5823
  # 0x18,0x1a,0x1c,0x1e = int16u[4] BlackPoint - PH
5824
+ 0x2a => {
5825
+ Name => 'SensorTemperature',
5826
+ Condition => '$$self{Model} =~ /K-3 Mark III/',
5827
+ Format => 'int16s',
5828
+ ValueConv => '$val / 10',
5829
+ ValueConvInv => '$val * 10',
5830
+ PrintConv => 'sprintf("%.1f C", $val)',
5831
+ PrintConvInv => '$val=~s/ ?c$//i; $val',
5832
+ },
5771
5833
  );
5772
5834
 
5773
5835
  # currently unknown info
@@ -6356,6 +6418,45 @@ sub DecodeAFPoints($$$$;$)
6356
6418
  return join(',', @bitList);
6357
6419
  }
6358
6420
 
6421
+ #------------------------------------------------------------------------------
6422
+ # Print AF Point names for K-3III (ref PH)
6423
+ # Inputs: 0) value, 1) ExifTool ref, 2) optional value to match
6424
+ sub AFPointsK3iii($$;$)
6425
+ {
6426
+ my @a = split ' ', $_[0];
6427
+ my $match = $_[2];
6428
+ my @pts;
6429
+ if ($match) {
6430
+ $a[$_] == $match and push @pts, $k3iiiAF[$_] || "Unknown($_)" foreach 0..$#a;
6431
+ } else {
6432
+ $a[$_] and push @pts, $k3iiiAF[$_] || "Unknown($_)" foreach 0..$#a;
6433
+ }
6434
+ return @pts ? join ',', sort @pts : '(none)';
6435
+ }
6436
+
6437
+ #------------------------------------------------------------------------------
6438
+ # Print AF point values for K-3III (ref PH)
6439
+ # Inputs: 0) value, 1) ExifTool ref
6440
+ # Notes: this is experimental and not well understood
6441
+ sub AFPointValues($$)
6442
+ {
6443
+ my @a = split ' ', shift;
6444
+ my @vals;
6445
+ # (I really don't understand why Pentax seemed to use 28 instead of 41 for
6446
+ # the first index of the 2nd value, because as it stands there is
6447
+ # overlap between the ranges of the 1st and 2nd values, and there is
6448
+ # no way to tell which is which for cases were multiple points have values)
6449
+ foreach (0 .. $#a) {
6450
+ next unless $a[$_];
6451
+ my $pt = $k3iiiAF[$_] ? $k3iiiAF[$_] . '=' : $k3iiiAF[$_-28] . '=/';
6452
+ push @vals, "$pt$a[$_]";
6453
+ next unless $a[$_ + 28];
6454
+ $vals[-1] .= '/' . $a[$_ + 28];
6455
+ $a[$_ + 28] = undef;
6456
+ }
6457
+ return @vals ? join ',', sort @vals : '(none)';
6458
+ }
6459
+
6359
6460
  #------------------------------------------------------------------------------
6360
6461
  # Convert Pentax hex-based EV (modulo 8) to real number
6361
6462
  # Inputs: 0) value to convert
@@ -11,7 +11,7 @@ package Image::ExifTool::Plot;
11
11
  use strict;
12
12
  use vars qw($VERSION);
13
13
 
14
- $VERSION = '1.02';
14
+ $VERSION = '1.03';
15
15
 
16
16
  # default plot settings (lower-case settings may be overridden by the user)
17
17
  my %defaults = (
@@ -262,23 +262,35 @@ sub Draw($$)
262
262
  {
263
263
  my ($self, $fp) = @_;
264
264
  my ($min, $max, $xmin, $xmax, $name, $style) = @$self{qw(Min Max XMin XMax Name style)};
265
+ my ($plotNum, $multiMulti);
265
266
 
266
267
  if (not defined $min or not defined $xmin) {
267
268
  $$self{Error} = 'Nothing to plot';
268
269
  return;
269
270
  }
270
- my ($i, $n, %col, %class, $dx, $dy, $dx2, $xAxis, $x, $y, $px, $py, @og);
271
- my ($noLegend, $xname, $xdat, $xdiff, $diff, %markID, $plotNum);
272
271
  my $scat = $$self{type} =~ /^s/ ? 1 : 0;
273
272
  my $hist = $$self{type} =~ /^h/ ? [ ] : 0;
274
- my $multi = int($$self{multi} || 0);
273
+ my $multi = $$self{multi} || 0;
274
+ my @multi = $multi =~ /\d+/g;
275
+ my @names = @$name;
276
+ shift @names if $scat;
277
+ $multi = shift @multi;
275
278
  $multi = 0 unless $multi > 0;
276
279
  $style or $style = $hist ? 'line+fill' : 'line';
277
280
  unless ($style =~ /\b[mpl]/ or ($hist and $style =~ /\bf/)) {
278
281
  $$self{Error} = 'Invalid plot Style setting';
279
282
  return;
280
283
  }
281
- my $numPlots = $multi ? scalar(@$name) - $scat : 1;
284
+ my $numPlots = 0;
285
+ if ($multi) {
286
+ my $n;
287
+ for ($n=0; $n<scalar(@$name)-$scat; ++$numPlots) {
288
+ $n += ($multi[$numPlots] || 1);
289
+ $multiMulti = 1 if $multi[$numPlots] and $multi[$numPlots] > 1;
290
+ }
291
+ } else {
292
+ $numPlots = 1;
293
+ }
282
294
  my @size = @{$$self{size}};
283
295
  my $sy = $size[1];
284
296
  if ($multi) {
@@ -293,6 +305,8 @@ sub Draw($$)
293
305
  <title>$tmp</title>};
294
306
  # loop through all plots
295
307
  for ($plotNum=0; $plotNum<$numPlots; ++$plotNum) {
308
+ my ($i, $n, %col, %class, $dx, $dy, $dx2, $xAxis, $x, $y, $px, $py, @og);
309
+ my ($noLegend, $xname, $xdat, $xdiff, $diff, %markID);
296
310
  if ($numPlots > 1) {
297
311
  print $fp "\n<g transform='translate(", ($plotNum % $multi) * $size[0],
298
312
  ',', int($plotNum/$multi) * $size[1], ")'>";
@@ -304,14 +318,19 @@ sub Draw($$)
304
318
  }
305
319
  $name = $$self{Name} = [ ];
306
320
  push @{$$self{Name}}, $$self{SaveName}[0] if $scat;
307
- push @{$$self{Name}}, $$self{SaveName}[$scat + $plotNum];
308
- my $dat = $$self{Data}{$$self{Name}[$scat]};
321
+ foreach (0 .. (($multi[$plotNum] || 1) - 1)) {
322
+ push @{$$self{Name}}, shift(@names);
323
+ }
324
+ warn "@{$$self{Name}}\n";
309
325
  undef $min; undef $max;
310
- foreach (@$dat) {
311
- defined or next;
312
- defined $min or $min = $max = $_, next;
313
- $min > $_ and $min = $_;
314
- $max < $_ and $max = $_;
326
+ foreach ($scat .. (@{$$self{Name}} - 1)) {
327
+ my $dat = $$self{Data}{$$self{Name}[$_]};
328
+ foreach (@$dat) {
329
+ defined or next;
330
+ defined $min or $min = $max = $_, next;
331
+ $min > $_ and $min = $_;
332
+ $max < $_ and $max = $_;
333
+ }
315
334
  }
316
335
  }
317
336
  my ($data, $title, $xlabel, $ylabel, $cols, $marks, $tpad, $wid) =
@@ -321,12 +340,12 @@ sub Draw($$)
321
340
 
322
341
  # set reasonable default titles and labels
323
342
  $xname = shift @name if $scat;
324
- $title = "$name[0] vs $xname" if $scat and defined $title and not $title and @name == 1;
343
+ $title = "$name[0] vs $xname" if $scat and defined $title and not $title and @name == 1 and not $multi;
325
344
  if ($scat || $hist and defined $xlabel and not $xlabel) {
326
345
  $xlabel = $$name[0];
327
346
  $noLegend = 1 if $hist;
328
347
  }
329
- if (defined $ylabel and not $ylabel and @name == 1) {
348
+ if (defined $ylabel and not $ylabel and @name == 1 and not $multiMulti) {
330
349
  $ylabel = $hist ? 'Count' : $name[0];
331
350
  $noLegend = 1 unless $hist;
332
351
  }
@@ -645,7 +664,9 @@ Change plot settings.
645
664
  Title, XLabel, YLabel - plot title and x/y axis labels (no default)
646
665
  XMin, XMax - x axis minimum/maximum (autoscaling if not set)
647
666
  YMin, YMax - y axis minimum/maximum
648
- Multi - flag to draw multiple plots, one for each dataset
667
+ Multi - number of columns when drawing multiple plots,
668
+ followed optional number of datasets for each
669
+ plot (1 by default) using any separator
649
670
  Split - flag to split strings of numbers into lists
650
671
  (> 1 to split into lists of N items)
651
672
  "Grid=darkgray" - grid color
@@ -38,6 +38,7 @@
38
38
  # 26) https://github.com/SamsungVR/android_upload_sdk/blob/master/SDKLib/src/main/java/com/samsung/msca/samsungvr/sdk/UserVideo.java
39
39
  # 27) https://exiftool.org/forum/index.php?topic=11517.0
40
40
  # 28) https://docs.mp3tag.de/mapping/
41
+ # 29) https://developer.apple.com/documentation/quicktime-file-format/media_data_reference_atom
41
42
  #------------------------------------------------------------------------------
42
43
 
43
44
  package Image::ExifTool::QuickTime;
@@ -48,7 +49,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
48
49
  use Image::ExifTool::Exif;
49
50
  use Image::ExifTool::GPS;
50
51
 
51
- $VERSION = '3.14';
52
+ $VERSION = '3.16';
52
53
 
53
54
  sub ProcessMOV($$;$);
54
55
  sub ProcessKeys($$$);
@@ -502,7 +503,7 @@ my %qtFlags = ( #12
502
503
  # (used only to avoid warnings when Validate-ing)
503
504
  my %dupTagOK = ( mdat => 1, trak => 1, free => 1, infe => 1, sgpd => 1, dimg => 1, CCDT => 1,
504
505
  sbgp => 1, csgm => 1, uuid => 1, cdsc => 1, maxr => 1, '----' => 1 );
505
- my %dupDirOK = ( ipco => 1, '----' => 1 );
506
+ my %dupDirOK = ( ipco => 1, iref => 1, '----' => 1 );
506
507
 
507
508
  # the usual atoms required to decode timed metadata with the ExtractEmbedded option
508
509
  my %eeStd = ( stco => 'stbl', co64 => 'stbl', stsz => 'stbl', stz2 => 'stbl',
@@ -814,6 +815,13 @@ my %userDefined = (
814
815
  TagTable => 'Image::ExifTool::QuickTime::Stream',
815
816
  ProcessProc => 'Image::ExifTool::LigoGPS::ProcessLigoJSON',
816
817
  },
818
+ },{
819
+ Name => 'GKUData',
820
+ Condition => '$$valPt =~ /^.{8}__V35AX_QVDATA__/',
821
+ SubDirectory => {
822
+ TagTable => 'Image::ExifTool::QuickTime::Stream',
823
+ ProcessProc => 'Image::ExifTool::LigoGPS::ProcessGKU',
824
+ },
817
825
  },{
818
826
  Name => 'FLIRData',
819
827
  SubDirectory => { TagTable => 'Image::ExifTool::FLIR::UserData' },
@@ -944,7 +952,7 @@ my %userDefined = (
944
952
  Notes => 'MP4-format video saved in Samsung motion-photo HEIC images.',
945
953
  Binary => 1,
946
954
  # note that this may be written and/or deleted, but can't currently be added back again
947
- Writable => 1,
955
+ Writable => 'undef',
948
956
  },
949
957
  # '35AX'? - seen "AT" (Yada RoadCam Pro 4K dashcam)
950
958
  cust => 'CustomInfo', # 70mai A810
@@ -952,6 +960,15 @@ my %userDefined = (
952
960
  Name => 'SEAL',
953
961
  SubDirectory => { TagTable => 'Image::ExifTool::XMP::SEAL' },
954
962
  },
963
+ inst => {
964
+ Name => 'Insta360Info',
965
+ DontRead => 1, # don't read into memory when extracting
966
+ WriteLast => 1, # must go at end of file
967
+ SubDirectory => {
968
+ TagTable => 'Image::ExifTool::QuickTime::Stream',
969
+ ProcessProc => \&ProcessInsta360,
970
+ },
971
+ },
955
972
  );
956
973
 
957
974
  # stuff seen in 'skip' atom (70mai Pro Plus+ MP4 videos)
@@ -1227,6 +1244,7 @@ my %userDefined = (
1227
1244
  # clip - clipping --> contains crgn (clip region) (ref 12)
1228
1245
  # mvex - movie extends --> contains mehd (movie extends header), trex (track extends) (ref 14)
1229
1246
  # ICAT - 4 bytes: "6350" (Nikon CoolPix S6900), "6500" (Panasonic FT7)
1247
+ # ctab - color table (ref 29)
1230
1248
  );
1231
1249
 
1232
1250
  # (ref CFFMediaFormat-2_1.pdf)
@@ -1426,6 +1444,7 @@ my %userDefined = (
1426
1444
  # load - track loading settings
1427
1445
  # imap - track input map --> contains ' in' --> contains ' ty', obid
1428
1446
  # prfl - Profile (ref 12)
1447
+ # txas - track exclude from autoselection (ref 29)
1429
1448
  );
1430
1449
 
1431
1450
  # track header data block
@@ -1630,6 +1649,10 @@ my %userDefined = (
1630
1649
  Start => 4, # must skip 4-byte version number header
1631
1650
  },
1632
1651
  },
1652
+ tnam => { #29 (NC)
1653
+ Name => 'TrackName',
1654
+ IText => 4,
1655
+ },
1633
1656
  'ptv '=> {
1634
1657
  Name => 'PrintToVideo',
1635
1658
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Video' },
@@ -2380,6 +2403,19 @@ my %userDefined = (
2380
2403
  Groups => { 2 => 'Preview' },
2381
2404
  Binary => 1,
2382
2405
  },
2406
+ # ---- Insta360 ----
2407
+ nail => {
2408
+ Name => 'ThumbnailTIFF',
2409
+ Notes => 'image found in some Insta360 videos, converted to TIFF format',
2410
+ Groups => { 2 => 'Preview' },
2411
+ RawConv => q{
2412
+ return undef if length $val < 8;
2413
+ my ($w, $h) = unpack('NN', $val);
2414
+ return undef if length $val < $w * $h + 8;
2415
+ return MakeTiffHeader($w, $h, 1, 8) . substr($val, 8, $w * $h);
2416
+ },
2417
+ Binary => 1,
2418
+ },
2383
2419
  # ---- Nextbase ----
2384
2420
  info => 'FirmwareVersion',
2385
2421
  'time' => {
@@ -2801,6 +2837,8 @@ my %userDefined = (
2801
2837
  Name => 'Unknown_grpl',
2802
2838
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::grpl' },
2803
2839
  },
2840
+ # ctry - country list (ref 29)
2841
+ # lang - language list (ref 29)
2804
2842
  );
2805
2843
 
2806
2844
  # unknown grpl container
@@ -3279,21 +3317,28 @@ my %userDefined = (
3279
3317
  %Image::ExifTool::QuickTime::TrackRef = (
3280
3318
  PROCESS_PROC => \&ProcessMOV,
3281
3319
  GROUPS => { 1 => 'Track#', 2 => 'Video' },
3282
- chap => { Name => 'ChapterListTrackID', Format => 'int32u' },
3283
- tmcd => { Name => 'TimeCode', Format => 'int32u' },
3320
+ chap => { Name => 'ChapterListTrackID', Format => 'int32u' },
3321
+ tmcd => { Name => 'TimecodeTrack', Format => 'int32u' },
3284
3322
  mpod => { #PH (FLIR MP4)
3285
3323
  Name => 'ElementaryStreamTrack',
3286
3324
  Format => 'int32u',
3287
3325
  ValueConv => '$val =~ s/^1 //; $val', # (why 2 numbers? -- ignore the first if "1")
3288
3326
  },
3289
- # also: sync, scpt, ssrc, iTunesInfo
3327
+ # also: iTunesInfo
3290
3328
  cdsc => {
3291
3329
  Name => 'ContentDescribes',
3292
3330
  Format => 'int32u',
3293
3331
  PrintConv => '"Track $val"',
3294
3332
  },
3295
- # cdep (Structural Dependency QT tag?)
3296
- # fall - ? int32u, seen: 2
3333
+ clcp => { Name => 'ClosedCaptionTrack', Format => 'int32u' }, #29
3334
+ fall => { Name => 'AlternateFormatTrack', Format => 'int32u' }, #29
3335
+ folw => { Name => 'SubtitleTrack', Format => 'int32u' }, #29
3336
+ forc => { Name => 'ForcedSubtitleTrack', Format => 'int32u' }, #29
3337
+ scpt => { Name => 'TranscriptTrack', Format => 'int32u' }, #29
3338
+ ssrc => { Name => 'Non-primarySourceTrack', Format => 'int32u' }, #29
3339
+ sync => { Name => 'SyncronizedTrack', Format => 'int32u' }, #29
3340
+ # hint - Original media for hint track (ref 29)
3341
+ # cdep (Structural Dependency QT tag?)
3297
3342
  );
3298
3343
 
3299
3344
  # track aperture mode dimensions atoms
@@ -6582,7 +6627,6 @@ my %userDefined = (
6582
6627
  'apple.photos.variation-identifier' => { Name => 'ApplePhotosVariationIdentifier', Writable => 'int64s' },
6583
6628
  'direction.facing' => { Name => 'CameraDirection', Groups => { 2 => 'Location' } },
6584
6629
  'direction.motion' => { Name => 'CameraMotion', Groups => { 2 => 'Location' } },
6585
- 'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } },
6586
6630
  'player.version' => 'PlayerVersion',
6587
6631
  'player.movie.visual.brightness'=> 'Brightness',
6588
6632
  'player.movie.visual.color' => 'Color',
@@ -7046,6 +7090,7 @@ my %userDefined = (
7046
7090
  Name => 'MediaInfo',
7047
7091
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MediaInfo' },
7048
7092
  },
7093
+ elng => 'ExtendedLanguageTag', #29 (NC) eg. "zh-CN"
7049
7094
  );
7050
7095
 
7051
7096
  # MP4 media header box (ref 5)
@@ -7637,6 +7682,8 @@ my %userDefined = (
7637
7682
  mrlh => { Name => 'MarlinHeader', SubDirectory => { TagTable => 'Image::ExifTool::GM::mrlh' } },
7638
7683
  mrlv => { Name => 'MarlinValues', SubDirectory => { TagTable => 'Image::ExifTool::GM::mrlv' } },
7639
7684
  mrld => { Name => 'MarlinDictionary',SubDirectory => { TagTable => 'Image::ExifTool::GM::mrld' } },
7685
+ # tbox - text box (ref 29)
7686
+ # styl - subtitle style (ref 29)
7640
7687
  );
7641
7688
 
7642
7689
  # AMR decode config box (ref 3)
@@ -9725,6 +9772,7 @@ sub IdentifyTrailers($)
9725
9772
  } else {
9726
9773
  last;
9727
9774
  }
9775
+ # 0) trailer type, 1) trailer start, 2) trailer length, 3) pointer to next trailer
9728
9776
  $trailer = [ $type , $raf->Tell() - $len, $len, $nextTrail ];
9729
9777
  $nextTrail = $trailer;
9730
9778
  $offset += $len;
@@ -9999,7 +10047,7 @@ sub ProcessMOV($$;$)
9999
10047
  }
10000
10048
  }
10001
10049
  }
10002
- if (defined $tagInfo and not $ignore) {
10050
+ if (defined $tagInfo and not $ignore and not ($tagInfo and $$tagInfo{DontRead})) {
10003
10051
  # set document number for this item property if necessary
10004
10052
  if ($$et{IsItemProperty}) {
10005
10053
  my $items = $$et{ItemInfo};
@@ -10052,7 +10100,7 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10052
10100
  # use value to get tag info if necessary
10053
10101
  $tagInfo or $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val);
10054
10102
  my $hasData = ($$dirInfo{HasData} and $val =~ /^....data\0/s);
10055
- if ($verbose and not $hasData) {
10103
+ if ($verbose and defined $val and not $hasData) {
10056
10104
  my $tval;
10057
10105
  if ($tagInfo and $$tagInfo{Format}) {
10058
10106
  $tval = ReadValue(\$val, 0, $$tagInfo{Format}, $$tagInfo{Count}, length($val));
@@ -10371,7 +10419,25 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10371
10419
  Size => $size,
10372
10420
  Extra => sprintf(' at offset 0x%.4x', $raf->Tell()),
10373
10421
  ) if $verbose;
10374
- if ($size and (not $raf->Seek($size-1, 1) or $raf->Read($buff, 1) != 1)) {
10422
+ my $seekTo = $raf->Tell() + $size;
10423
+ if ($tagInfo and $$tagInfo{DontRead} and $$tagInfo{SubDirectory}) {
10424
+ # ignore first trailer if it is the payload of this box
10425
+ $trailer = $$trailer[3] if $trailer and $$trailer[1] == $raf->Tell();
10426
+ my $subdir = $$tagInfo{SubDirectory};
10427
+ my %dirInfo = (
10428
+ RAF => $raf,
10429
+ DirName => $$tagInfo{Name},
10430
+ DirID => $tag,
10431
+ DirEnd => $seekTo,
10432
+ );
10433
+ my $subTable = GetTagTable($$subdir{TagTable});
10434
+ my $proc = $$subdir{ProcessProc};
10435
+ # make ProcessMOV() the default processing procedure for subdirectories
10436
+ $proc = \&ProcessMOV unless $proc or $$subTable{PROCESS_PROC};
10437
+ $et->ProcessDirectory(\%dirInfo, $subTable, $proc);
10438
+ $raf->Seek($seekTo);
10439
+ }
10440
+ unless ($raf->Seek($seekTo-1) and $raf->Read($buff, 1) == 1) {
10375
10441
  my $t = PrintableTagID($tag,2);
10376
10442
  $warnStr = sprintf("Truncated '${t}' data at offset 0x%x", $lastPos);
10377
10443
  last;