exiftool_vendored 13.10.0 → 13.14.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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +82 -19
  3. data/bin/MANIFEST +6 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +3 -3
  7. data/bin/arg_files/exif2xmp.args +4 -0
  8. data/bin/arg_files/xmp2exif.args +2 -1
  9. data/bin/build_geolocation +1 -1
  10. data/bin/exiftool +208 -150
  11. data/bin/lib/File/RandomAccess.pm +1 -1
  12. data/bin/lib/File/RandomAccess.pod +2 -2
  13. data/bin/lib/Image/ExifTool/AAC.pm +1 -1
  14. data/bin/lib/Image/ExifTool/AES.pm +1 -1
  15. data/bin/lib/Image/ExifTool/AFCP.pm +6 -6
  16. data/bin/lib/Image/ExifTool/AIFF.pm +1 -1
  17. data/bin/lib/Image/ExifTool/APE.pm +1 -1
  18. data/bin/lib/Image/ExifTool/APP12.pm +1 -1
  19. data/bin/lib/Image/ExifTool/ASF.pm +1 -1
  20. data/bin/lib/Image/ExifTool/Apple.pm +1 -1
  21. data/bin/lib/Image/ExifTool/Audible.pm +1 -1
  22. data/bin/lib/Image/ExifTool/BMP.pm +1 -1
  23. data/bin/lib/Image/ExifTool/BPG.pm +1 -1
  24. data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
  25. data/bin/lib/Image/ExifTool/BigTIFF.pm +1 -1
  26. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +29 -18
  27. data/bin/lib/Image/ExifTool/CBOR.pm +1 -1
  28. data/bin/lib/Image/ExifTool/Canon.pm +8 -4
  29. data/bin/lib/Image/ExifTool/CanonCustom.pm +1 -1
  30. data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
  31. data/bin/lib/Image/ExifTool/CanonVRD.pm +1 -1
  32. data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
  33. data/bin/lib/Image/ExifTool/Casio.pm +1 -1
  34. data/bin/lib/Image/ExifTool/Charset.pm +1 -1
  35. data/bin/lib/Image/ExifTool/DICOM.pm +1 -1
  36. data/bin/lib/Image/ExifTool/DJI.pm +150 -46
  37. data/bin/lib/Image/ExifTool/DNG.pm +1 -1
  38. data/bin/lib/Image/ExifTool/DPX.pm +1 -1
  39. data/bin/lib/Image/ExifTool/DV.pm +1 -1
  40. data/bin/lib/Image/ExifTool/DarwinCore.pm +1 -1
  41. data/bin/lib/Image/ExifTool/DjVu.pm +1 -1
  42. data/bin/lib/Image/ExifTool/EXE.pm +123 -32
  43. data/bin/lib/Image/ExifTool/Exif.pm +7 -4
  44. data/bin/lib/Image/ExifTool/FITS.pm +1 -1
  45. data/bin/lib/Image/ExifTool/FLAC.pm +1 -1
  46. data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
  47. data/bin/lib/Image/ExifTool/FLIR.pm +1 -1
  48. data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
  49. data/bin/lib/Image/ExifTool/Flash.pm +1 -1
  50. data/bin/lib/Image/ExifTool/FlashPix.pm +1 -1
  51. data/bin/lib/Image/ExifTool/Font.pm +1 -1
  52. data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
  53. data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -1
  54. data/bin/lib/Image/ExifTool/GE.pm +1 -1
  55. data/bin/lib/Image/ExifTool/GIF.pm +1 -1
  56. data/bin/lib/Image/ExifTool/GIMP.pm +1 -1
  57. data/bin/lib/Image/ExifTool/GM.pm +1 -1
  58. data/bin/lib/Image/ExifTool/GPS.pm +1 -1
  59. data/bin/lib/Image/ExifTool/GeoTiff.pm +1 -1
  60. data/bin/lib/Image/ExifTool/Geolocation.pm +17 -8
  61. data/bin/lib/Image/ExifTool/Geotag.pm +1 -1
  62. data/bin/lib/Image/ExifTool/GoPro.pm +1 -1
  63. data/bin/lib/Image/ExifTool/H264.pm +1 -1
  64. data/bin/lib/Image/ExifTool/HP.pm +1 -1
  65. data/bin/lib/Image/ExifTool/HTML.pm +1 -1
  66. data/bin/lib/Image/ExifTool/HtmlDump.pm +1 -1
  67. data/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
  68. data/bin/lib/Image/ExifTool/ICO.pm +1 -1
  69. data/bin/lib/Image/ExifTool/ID3.pm +1 -1
  70. data/bin/lib/Image/ExifTool/IPTC.pm +8 -5
  71. data/bin/lib/Image/ExifTool/ISO.pm +1 -1
  72. data/bin/lib/Image/ExifTool/ITC.pm +1 -1
  73. data/bin/lib/Image/ExifTool/Import.pm +5 -4
  74. data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
  75. data/bin/lib/Image/ExifTool/InfiRay.pm +1 -1
  76. data/bin/lib/Image/ExifTool/JPEG.pm +6 -2
  77. data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  78. data/bin/lib/Image/ExifTool/JSON.pm +1 -1
  79. data/bin/lib/Image/ExifTool/JVC.pm +1 -1
  80. data/bin/lib/Image/ExifTool/Jpeg2000.pm +1 -1
  81. data/bin/lib/Image/ExifTool/Kodak.pm +1 -1
  82. data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
  83. data/bin/lib/Image/ExifTool/LIF.pm +1 -1
  84. data/bin/lib/Image/ExifTool/LNK.pm +1 -1
  85. data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
  86. data/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
  87. data/bin/lib/Image/ExifTool/Lang/en_ca.pm +1 -1
  88. data/bin/lib/Image/ExifTool/Lang/en_gb.pm +1 -1
  89. data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
  90. data/bin/lib/Image/ExifTool/Lang/fi.pm +1 -1
  91. data/bin/lib/Image/ExifTool/Lang/fr.pm +1 -1
  92. data/bin/lib/Image/ExifTool/Lang/it.pm +1 -1
  93. data/bin/lib/Image/ExifTool/Lang/ja.pm +1 -1
  94. data/bin/lib/Image/ExifTool/Lang/ko.pm +1 -1
  95. data/bin/lib/Image/ExifTool/Lang/nl.pm +1 -1
  96. data/bin/lib/Image/ExifTool/Lang/pl.pm +1 -1
  97. data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
  98. data/bin/lib/Image/ExifTool/Lang/sk.pm +1 -1
  99. data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
  100. data/bin/lib/Image/ExifTool/Lang/tr.pm +1 -1
  101. data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
  102. data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
  103. data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
  104. data/bin/lib/Image/ExifTool/LigoGPS.pm +409 -0
  105. data/bin/lib/Image/ExifTool/Lytro.pm +1 -1
  106. data/bin/lib/Image/ExifTool/M2TS.pm +22 -13
  107. data/bin/lib/Image/ExifTool/MIE.pm +1 -1
  108. data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
  109. data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
  110. data/bin/lib/Image/ExifTool/MISB.pm +1 -1
  111. data/bin/lib/Image/ExifTool/MNG.pm +1 -1
  112. data/bin/lib/Image/ExifTool/MOI.pm +1 -1
  113. data/bin/lib/Image/ExifTool/MPC.pm +1 -1
  114. data/bin/lib/Image/ExifTool/MPEG.pm +1 -1
  115. data/bin/lib/Image/ExifTool/MPF.pm +1 -1
  116. data/bin/lib/Image/ExifTool/MRC.pm +1 -1
  117. data/bin/lib/Image/ExifTool/MWG.pm +1 -1
  118. data/bin/lib/Image/ExifTool/MXF.pm +1 -1
  119. data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
  120. data/bin/lib/Image/ExifTool/MakerNotes.pm +1 -1
  121. data/bin/lib/Image/ExifTool/Matroska.pm +12 -4
  122. data/bin/lib/Image/ExifTool/Microsoft.pm +1 -1
  123. data/bin/lib/Image/ExifTool/Minolta.pm +1 -1
  124. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
  125. data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
  126. data/bin/lib/Image/ExifTool/Nikon.pm +166 -35
  127. data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
  128. data/bin/lib/Image/ExifTool/NikonCustom.pm +1 -1
  129. data/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  130. data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
  131. data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
  132. data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
  133. data/bin/lib/Image/ExifTool/Olympus.pm +1 -1
  134. data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
  135. data/bin/lib/Image/ExifTool/Opus.pm +1 -1
  136. data/bin/lib/Image/ExifTool/Other.pm +1 -1
  137. data/bin/lib/Image/ExifTool/PCX.pm +1 -1
  138. data/bin/lib/Image/ExifTool/PDF.pm +1 -1
  139. data/bin/lib/Image/ExifTool/PGF.pm +1 -1
  140. data/bin/lib/Image/ExifTool/PICT.pm +1 -1
  141. data/bin/lib/Image/ExifTool/PLIST.pm +1 -1
  142. data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
  143. data/bin/lib/Image/ExifTool/PNG.pm +1 -1
  144. data/bin/lib/Image/ExifTool/PPM.pm +1 -1
  145. data/bin/lib/Image/ExifTool/PSP.pm +1 -1
  146. data/bin/lib/Image/ExifTool/Palm.pm +1 -1
  147. data/bin/lib/Image/ExifTool/Panasonic.pm +20 -2
  148. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +1 -1
  149. data/bin/lib/Image/ExifTool/Parrot.pm +1 -1
  150. data/bin/lib/Image/ExifTool/Pentax.pm +1 -1
  151. data/bin/lib/Image/ExifTool/PhaseOne.pm +1 -1
  152. data/bin/lib/Image/ExifTool/PhotoCD.pm +1 -1
  153. data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
  154. data/bin/lib/Image/ExifTool/Photoshop.pm +1 -1
  155. data/bin/lib/Image/ExifTool/PostScript.pm +1 -1
  156. data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
  157. data/bin/lib/Image/ExifTool/Protobuf.pm +48 -20
  158. data/bin/lib/Image/ExifTool/Qualcomm.pm +1 -1
  159. data/bin/lib/Image/ExifTool/QuickTime.pm +206 -66
  160. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +21 -303
  161. data/bin/lib/Image/ExifTool/README +4 -0
  162. data/bin/lib/Image/ExifTool/RIFF.pm +1 -1
  163. data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
  164. data/bin/lib/Image/ExifTool/RTF.pm +1 -1
  165. data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
  166. data/bin/lib/Image/ExifTool/Rawzor.pm +1 -1
  167. data/bin/lib/Image/ExifTool/Real.pm +1 -1
  168. data/bin/lib/Image/ExifTool/Reconyx.pm +1 -1
  169. data/bin/lib/Image/ExifTool/Red.pm +1 -1
  170. data/bin/lib/Image/ExifTool/Ricoh.pm +1 -1
  171. data/bin/lib/Image/ExifTool/Samsung.pm +2 -2
  172. data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
  173. data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
  174. data/bin/lib/Image/ExifTool/Shift.pl +1 -1
  175. data/bin/lib/Image/ExifTool/Shortcuts.pm +1 -1
  176. data/bin/lib/Image/ExifTool/Sigma.pm +1 -1
  177. data/bin/lib/Image/ExifTool/SigmaRaw.pm +1 -1
  178. data/bin/lib/Image/ExifTool/Sony.pm +1 -1
  179. data/bin/lib/Image/ExifTool/SonyIDC.pm +1 -1
  180. data/bin/lib/Image/ExifTool/Stim.pm +1 -1
  181. data/bin/lib/Image/ExifTool/TagInfoXML.pm +2 -2
  182. data/bin/lib/Image/ExifTool/TagLookup.pm +3449 -3435
  183. data/bin/lib/Image/ExifTool/TagNames.pod +164 -47
  184. data/bin/lib/Image/ExifTool/Text.pm +1 -1
  185. data/bin/lib/Image/ExifTool/Theora.pm +1 -1
  186. data/bin/lib/Image/ExifTool/Torrent.pm +3 -3
  187. data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
  188. data/bin/lib/Image/ExifTool/VCard.pm +1 -1
  189. data/bin/lib/Image/ExifTool/Validate.pm +1 -1
  190. data/bin/lib/Image/ExifTool/Vivo.pm +124 -0
  191. data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
  192. data/bin/lib/Image/ExifTool/WPG.pm +1 -1
  193. data/bin/lib/Image/ExifTool/WTV.pm +1 -1
  194. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  195. data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
  196. data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
  197. data/bin/lib/Image/ExifTool/WritePDF.pl +1 -1
  198. data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
  199. data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
  200. data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -1
  201. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +74 -43
  202. data/bin/lib/Image/ExifTool/WriteRIFF.pl +1 -1
  203. data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  204. data/bin/lib/Image/ExifTool/Writer.pl +21 -16
  205. data/bin/lib/Image/ExifTool/XISF.pm +1 -1
  206. data/bin/lib/Image/ExifTool/XMP.pm +1 -1
  207. data/bin/lib/Image/ExifTool/XMP2.pl +1 -1
  208. data/bin/lib/Image/ExifTool/XMPStruct.pl +1 -1
  209. data/bin/lib/Image/ExifTool/ZIP.pm +1 -1
  210. data/bin/lib/Image/ExifTool/ZISRAW.pm +1 -1
  211. data/bin/lib/Image/ExifTool/iWork.pm +1 -1
  212. data/bin/lib/Image/ExifTool.pm +34 -12
  213. data/bin/lib/Image/ExifTool.pod +57 -46
  214. data/bin/perl-Image-ExifTool.spec +1 -1
  215. data/lib/exiftool_vendored/version.rb +1 -1
  216. metadata +4 -2
@@ -43,12 +43,12 @@
43
43
  package Image::ExifTool::QuickTime;
44
44
 
45
45
  use strict;
46
- use vars qw($VERSION $AUTOLOAD %stringEncoding);
46
+ use vars qw($VERSION $AUTOLOAD %stringEncoding %avType);
47
47
  use Image::ExifTool qw(:DataAccess :Utils);
48
48
  use Image::ExifTool::Exif;
49
49
  use Image::ExifTool::GPS;
50
50
 
51
- $VERSION = '3.07';
51
+ $VERSION = '3.09';
52
52
 
53
53
  sub ProcessMOV($$;$);
54
54
  sub ProcessKeys($$$);
@@ -69,8 +69,6 @@ sub Process_gps0($$$);
69
69
  sub Process_gsen($$$);
70
70
  sub Process_gdat($$$);
71
71
  sub Process_nbmt($$$);
72
- sub ProcessLigoGPS($$$;$);
73
- sub ProcessLigoJSON($$$);
74
72
  sub ProcessKenwood($$$);
75
73
  sub ProcessRIFFTrailer($$$);
76
74
  sub ProcessTTAD($$$);
@@ -253,15 +251,20 @@ my %timeInfo = (
253
251
  # Note: This value will be in UTC if generated by a system that is aware of the time zone
254
252
  # (also note: this code is duplicated for the CreateDate tag)
255
253
  RawConv => q{
256
- my $offset = (66 * 365 + 17) * 24 * 3600;
257
- return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC};
258
- if ($val and not $$self{IsWriting}) {
259
- $self->Warn('Patched incorrect time zero for QuickTime date/time tag',1);
254
+ if ($val) {
255
+ my $offset = (66 * 365 + 17) * 24 * 3600;
256
+ if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) {
257
+ $val -= $offset;
258
+ } elsif (not $$self{IsWriting}) {
259
+ $self->Warn('Patched incorrect time zero for QuickTime date/time tag',1);
260
+ }
261
+ } else {
262
+ undef $val if $self->Options('StrictDate');
260
263
  }
261
264
  return $val;
262
265
  },
263
266
  RawConvInv => q{
264
- if ($$self{FileType} eq 'CR3' and not $self->Options('QuickTimeUTC')) {
267
+ if ($val and $$self{FileType} eq 'CR3' and not $self->Options('QuickTimeUTC')) {
265
268
  # convert to UTC
266
269
  my $offset = (66 * 365 + 17) * 24 * 3600;
267
270
  $val = ConvertUnixTime($val - $offset);
@@ -274,10 +277,14 @@ my %timeInfo = (
274
277
  ValueConvInv => q{
275
278
  $val = GetUnixTime($val, $self->Options("QuickTimeUTC"));
276
279
  return undef unless defined $val;
280
+ return $val unless $val;
277
281
  return $val + (66 * 365 + 17) * 24 * 3600;
278
282
  },
279
283
  PrintConv => '$self->ConvertDateTime($val)',
280
- PrintConvInv => '$self->InverseDateTime($val)',
284
+ PrintConvInv => q{
285
+ return $val if $val eq '0000:00:00 00:00:00';
286
+ return $self->InverseDateTime($val);
287
+ }
281
288
  # (can't put Groups here because they aren't constant!)
282
289
  );
283
290
  # properties for ISO 8601 format date/time tags
@@ -351,6 +358,19 @@ my %vendorID = (
351
358
  5 => 'UTF16',
352
359
  );
353
360
 
361
+ # media types for which we have separate Keys tables (AudioKeys, VideoKeys)
362
+ %avType = (
363
+ soun => 'Audio',
364
+ vide => 'Video',
365
+ );
366
+
367
+ # path to Keys/ItemList/UserData tags stored in tracks
368
+ my %trackPath = (
369
+ 'MOV-Movie-Track-Meta-ItemList' => 'Keys',
370
+ 'MOV-Movie-Track-UserData-Meta-ItemList' => 'ItemList',
371
+ 'MOV-Movie-Track-UserData' => 'UserData',
372
+ );
373
+
354
374
  my %graphicsMode = (
355
375
  # (ref http://homepage.mac.com/vanhoek/MovieGuts%20docs/64.html)
356
376
  0x00 => 'srcCopy',
@@ -587,13 +607,24 @@ my %userDefined = (
587
607
  },
588
608
  {
589
609
  Name => 'LigoGPSInfo',
590
- Condition => '$$valPt =~ /^LIGOGPSINFO\0/',
591
- SubDirectory => {
610
+ Condition => '$$valPt =~ /^LIGOGPSINFO\0/ and $$self{OPTIONS}{ExtractEmbedded}',
611
+ SubDirectory => {
592
612
  TagTable => 'Image::ExifTool::QuickTime::Stream',
593
- ProcessProc => \&ProcessLigoGPS,
613
+ ProcessProc => 'Image::ExifTool::LigoGPS::ProcessLigoGPS',
594
614
  },
595
615
  },
596
- { Name => 'Skip', Unknown => 1, Binary => 1 },
616
+ {
617
+ Name => 'Skip',
618
+ RawConv => q{
619
+ if ($val =~ /^LIGOGPSINFO\0/) {
620
+ $self->Warn('Use the ExtractEmbedded option to decode timed GPS',3);
621
+ return undef;
622
+ }
623
+ return $val;
624
+ },
625
+ Unknown => 1,
626
+ Binary => 1,
627
+ },
597
628
  ],
598
629
  wide => { Unknown => 1, Binary => 1 },
599
630
  ftyp => { #MP4
@@ -775,7 +806,7 @@ my %userDefined = (
775
806
  Condition => '$$valPt =~ /^LIGOGPSINFO \{/',
776
807
  SubDirectory => {
777
808
  TagTable => 'Image::ExifTool::QuickTime::Stream',
778
- ProcessProc => \&ProcessLigoJSON,
809
+ ProcessProc => 'Image::ExifTool::LigoGPS::ProcessLigoJSON',
779
810
  },
780
811
  },{
781
812
  Name => 'FLIRData',
@@ -1412,11 +1443,15 @@ my %userDefined = (
1412
1443
  Groups => { 2 => 'Time' },
1413
1444
  %timeInfo,
1414
1445
  RawConv => q{
1415
- my $offset = (66 * 365 + 17) * 24 * 3600;
1416
- if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) {
1417
- $val -= $offset;
1418
- } elsif ($val and not $$self{IsWriting}) {
1419
- $self->Warn('Patched incorrect time zero for QuickTime date/time tag',1);
1446
+ if ($val) {
1447
+ my $offset = (66 * 365 + 17) * 24 * 3600;
1448
+ if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) {
1449
+ $val -= $offset;
1450
+ } elsif (not $$self{IsWriting}) {
1451
+ $self->Warn('Patched incorrect time zero for QuickTime date/time tag',1);
1452
+ }
1453
+ } else {
1454
+ undef $val if $$self{OPTIONS}{StrictDate};
1420
1455
  }
1421
1456
  return $$self{CreateDate} = $val;
1422
1457
  },
@@ -1514,7 +1549,7 @@ my %userDefined = (
1514
1549
  # (this tag is readable/writable as a block through the Extra SphericalVideoXML tags)
1515
1550
  Condition => '$$valPt=~/^\xff\xcc\x82\x63\xf8\x55\x4a\x93\x88\x14\x58\x7a\x02\x52\x1f\xdd/',
1516
1551
  WriteGroup => 'GSpherical', # write only GSpherical XMP tags here
1517
- HandlerType => 'vide', # only write in video tracks
1552
+ MediaType => 'vide', # only write in video tracks
1518
1553
  SubDirectory => {
1519
1554
  TagTable => 'Image::ExifTool::XMP::Main',
1520
1555
  Start => 16,
@@ -2842,10 +2877,18 @@ my %userDefined = (
2842
2877
  IgnoreProp => { NonRealTimeMeta => 1 }, # ignore container for Sony 'nrtm'
2843
2878
  },
2844
2879
  },
2845
- 'keys' => {
2880
+ 'keys' => [{
2881
+ Name => 'AudioKeys',
2882
+ Condition => '$$self{MediaType} eq "soun"',
2883
+ SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AudioKeys' },
2884
+ },{
2885
+ Name => 'VideoKeys',
2886
+ Condition => '$$self{MediaType} eq "vide"',
2887
+ SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::VideoKeys' },
2888
+ },{
2846
2889
  Name => 'Keys',
2847
2890
  SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Keys' },
2848
- },
2891
+ }],
2849
2892
  bxml => {
2850
2893
  Name => 'BinaryXML',
2851
2894
  Flags => ['Binary','Unknown'],
@@ -3586,7 +3629,7 @@ my %userDefined = (
3586
3629
  my $id = Image::ExifTool::ID3::GetGenreID($val);
3587
3630
  return unless defined $id and $id =~ /^\d+$/;
3588
3631
  return $id + 1;
3589
- },
3632
+ },
3590
3633
  },
3591
3634
  egid => 'EpisodeGlobalUniqueID', #7
3592
3635
  geID => { #10
@@ -6588,7 +6631,7 @@ my %userDefined = (
6588
6631
  PROCESS_PROC => \&ProcessKeys,
6589
6632
  WRITE_PROC => \&WriteKeys,
6590
6633
  CHECK_PROC => \&CheckQTValue,
6591
- VARS => { LONG_TAGS => 9 },
6634
+ VARS => { LONG_TAGS => 8 },
6592
6635
  WRITABLE => 1,
6593
6636
  # (not PREFERRED when writing)
6594
6637
  GROUPS => { 1 => 'Keys' },
@@ -6634,21 +6677,11 @@ my %userDefined = (
6634
6677
  publisher => { },
6635
6678
  software => { },
6636
6679
  year => { Groups => { 2 => 'Time' } },
6637
- 'camera.identifier' => 'CameraIdentifier', # (iPhone 4)
6638
- 'camera.framereadouttimeinmicroseconds' => { # (iPhone 4)
6639
- Name => 'FrameReadoutTime',
6640
- ValueConv => '$val * 1e-6',
6641
- ValueConvInv => 'int($val * 1e6 + 0.5)',
6642
- PrintConv => '$val * 1e6 . " microseconds"',
6643
- PrintConvInv => '$val =~ s/ .*//; $val * 1e-6',
6644
- },
6645
- # 'camera.focal_length.35mm_equivalent' - not top level (written to Keys in video track)
6646
- # 'camera.lens_model' - not top level (written to Keys in video track)
6647
6680
  'location.ISO6709' => {
6648
6681
  Name => 'GPSCoordinates',
6649
6682
  Groups => { 2 => 'Location' },
6650
6683
  Notes => q{
6651
- Google Photos may ignore this if the coorinates have more than 5 digits
6684
+ Google Photos may ignore this if the coordinates have more than 5 digits
6652
6685
  after the decimal
6653
6686
  },
6654
6687
  ValueConv => \&ConvertISO6709,
@@ -6704,7 +6737,6 @@ my %userDefined = (
6704
6737
  #
6705
6738
  # the following tags aren't in the com.apple.quicktime namespace:
6706
6739
  #
6707
- 'com.apple.photos.captureMode' => 'CaptureMode',
6708
6740
  'com.android.version' => 'AndroidVersion',
6709
6741
  'com.android.capture.fps' => { Name => 'AndroidCaptureFPS', Writable => 'float' },
6710
6742
  'com.android.manufacturer' => 'AndroidMake',
@@ -6804,6 +6836,58 @@ my %userDefined = (
6804
6836
  # (mdta)com.apple.proapps.image.{TIFF}.Software (eg. "9.0")
6805
6837
  );
6806
6838
 
6839
+ # Keys tags in the audio track (ref PH)
6840
+ %Image::ExifTool::QuickTime::AudioKeys = (
6841
+ PROCESS_PROC => \&ProcessKeys,
6842
+ WRITE_PROC => \&WriteKeys,
6843
+ CHECK_PROC => \&CheckQTValue,
6844
+ WRITABLE => 1,
6845
+ GROUPS => { 1 => 'AudioKeys', 2 => 'Audio' },
6846
+ WRITE_GROUP => 'AudioKeys',
6847
+ LANG_INFO => \&GetLangInfo,
6848
+ NOTES => q{
6849
+ Keys tags written in the audio track by some Apple devices. These tags
6850
+ belong to the ExifTool AudioKeys family 1 gorup.
6851
+ },
6852
+ 'player.movie.audio.gain' => 'AudioGain',
6853
+ 'player.movie.audio.treble' => 'Treble',
6854
+ 'player.movie.audio.bass' => 'Bass',
6855
+ 'player.movie.audio.balance' => 'Balance',
6856
+ 'player.movie.audio.pitchshift' => 'PitchShift',
6857
+ 'player.movie.audio.mute' => {
6858
+ Name => 'Mute',
6859
+ Format => 'int8u',
6860
+ PrintConv => { 0 => 'Off', 1 => 'On' },
6861
+ },
6862
+ );
6863
+
6864
+ # Keys tags in the video track (ref PH)
6865
+ %Image::ExifTool::QuickTime::VideoKeys = (
6866
+ PROCESS_PROC => \&ProcessKeys,
6867
+ WRITE_PROC => \&WriteKeys,
6868
+ CHECK_PROC => \&CheckQTValue,
6869
+ VARS => { LONG_TAGS => 2 },
6870
+ WRITABLE => 1,
6871
+ GROUPS => { 1 => 'VideoKeys', 2 => 'Camera' },
6872
+ WRITE_GROUP => 'VideoKeys',
6873
+ LANG_INFO => \&GetLangInfo,
6874
+ NOTES => q{
6875
+ Keys tags written in the video track. These tags belong to the ExifTool
6876
+ VideoKeys family 1 gorup.
6877
+ },
6878
+ 'camera.identifier' => 'CameraIdentifier',
6879
+ 'camera.lens_model' => 'LensModel',
6880
+ 'camera.focal_length.35mm_equivalent' => 'FocalLengthIn35mmFormat',
6881
+ 'camera.framereadouttimeinmicroseconds' => {
6882
+ Name => 'FrameReadoutTime',
6883
+ ValueConv => '$val * 1e-6',
6884
+ ValueConvInv => 'int($val * 1e6 + 0.5)',
6885
+ PrintConv => '$val * 1e6 . " microseconds"',
6886
+ PrintConvInv => '$val =~ s/ .*//; $val * 1e-6',
6887
+ },
6888
+ 'com.apple.photos.captureMode' => 'CaptureMode',
6889
+ );
6890
+
6807
6891
  # iTunes info ('----') atoms
6808
6892
  %Image::ExifTool::QuickTime::iTunesInfo = (
6809
6893
  PROCESS_PROC => \&ProcessMOV,
@@ -7269,7 +7353,7 @@ my %userDefined = (
7269
7353
  {
7270
7354
  Name => 'VideoFrameRate',
7271
7355
  Notes => 'average rate calculated from time-to-sample table for video media',
7272
- Condition => '$$self{HandlerType} and $$self{HandlerType} eq "vide"',
7356
+ Condition => '$$self{MediaType} eq "vide"',
7273
7357
  Format => 'undef', # (necessary to prevent decoding as string!)
7274
7358
  # (must be RawConv so appropriate MediaTS is used in calculation)
7275
7359
  RawConv => 'Image::ExifTool::QuickTime::CalcSampleRate($self, \$val)',
@@ -7860,7 +7944,6 @@ my %userDefined = (
7860
7944
  mode => 'ModeFlags', #PH (?) 0x04 is HD flag (https://compilr.com/heksesang/requiem-mac/UnDrm.java)
7861
7945
  # sing - seen 4 zeros
7862
7946
  # hi32 - seen "00 00 00 04"
7863
-
7864
7947
  );
7865
7948
 
7866
7949
  # MP4 hint sample description box (ref 5)
@@ -8108,6 +8191,7 @@ my %userDefined = (
8108
8191
  Format => 'undef[4]',
8109
8192
  RawConv => q{
8110
8193
  $$self{HandlerType} = $val unless $val eq 'alis' or $val eq 'url ';
8194
+ $$self{MediaType} = $val if @{$$self{PATH}} > 1 and $$self{PATH}[-2] eq 'Media';
8111
8195
  $$self{HasHandler}{$val} = 1; # remember all our handlers
8112
8196
  return $val;
8113
8197
  },
@@ -9527,6 +9611,8 @@ sub ProcessKeys($$$)
9527
9611
  my $groups = $$tagInfo{Groups};
9528
9612
  $$newInfo{Groups} = $groups ? { %$groups } : { };
9529
9613
  $$newInfo{Groups}{$_} or $$newInfo{Groups}{$_} = $$tagTablePtr{GROUPS}{$_} foreach 0..2;
9614
+ # set Keys group. This is necessary for logic when reading the associated ItemList entry,
9615
+ # but note that the group name will be overridden by TAG_EXTRA G1 for tags in a track
9530
9616
  $$newInfo{Groups}{1} = 'Keys';
9531
9617
  } elsif ($tag =~ /^[-\w. ]+$/ or $tag =~ /\w{4}/) {
9532
9618
  # create info for tags with reasonable id's
@@ -9594,7 +9680,7 @@ sub ProcessMOV($$;$)
9594
9680
 
9595
9681
  my $topLevel = not $$et{InQuickTime};
9596
9682
  $$et{InQuickTime} = 1;
9597
- $$et{HandlerType} = $$et{MetaFormat} = '' unless defined $$et{HandlerType};
9683
+ $$et{HandlerType} = $$et{MetaFormat} = $$et{MediaType} = '' if $topLevel;
9598
9684
 
9599
9685
  unless (defined $$et{KeysCount}) {
9600
9686
  $$et{KeysCount} = 0; # initialize ItemList key directory count
@@ -9620,13 +9706,15 @@ sub ProcessMOV($$;$)
9620
9706
  }
9621
9707
  ($size, $tag) = unpack('Na4', $buff);
9622
9708
  my $fast = $$et{OPTIONS}{FastScan} || 0;
9623
- # check for Insta360 trailer
9709
+ # check for Insta360 or LIGOGPSINFO trailer
9624
9710
  if ($topLevel and not $fast) {
9625
9711
  my $pos = $raf->Tell();
9626
- if ($raf->Seek(-40, 2) and $raf->Read($buff, 40) == 40 and
9627
- substr($buff, 8) eq '8db42d694ccc418790edff439fe026bf')
9628
- {
9629
- $trailer = [ 'Insta360', $raf->Tell() - unpack('V',$buff) ];
9712
+ if ($raf->Seek(-40, 2) and $raf->Read($buff, 40) == 40) {
9713
+ if (substr($buff, 8) eq '8db42d694ccc418790edff439fe026bf') {
9714
+ $trailer = [ 'Insta360', $raf->Tell() - unpack('V',$buff) ];
9715
+ } elsif ($buff =~ /\&\&\&\&(.{4})$/) {
9716
+ $trailer = [ 'LigoGPS', $raf->Tell() - Get32u(\$buff, 36) ];
9717
+ }
9630
9718
  }
9631
9719
  $raf->Seek($pos,0) or return 0;
9632
9720
  }
@@ -9743,16 +9831,18 @@ sub ProcessMOV($$;$)
9743
9831
  }
9744
9832
  if ($isUserData and $$et{SET_GROUP1}) {
9745
9833
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
9746
- # add track name to UserData tags inside tracks
9747
- $tag = $$et{SET_GROUP1} . $tag;
9748
- if (not $$tagTablePtr{$tag} and $tagInfo) {
9749
- my %newInfo = %$tagInfo;
9750
- foreach ('Name', 'Description') {
9751
- next unless $$tagInfo{$_};
9752
- $newInfo{$_} = $$et{SET_GROUP1} . $$tagInfo{$_};
9753
- $newInfo{$_} =~ s/^(Track\d+)Track/$1/; # remove duplicate "Track" in name
9834
+ unless ($$tagInfo{SubDirectory}) {
9835
+ # add track name to UserData tags inside tracks
9836
+ $tag = $$et{SET_GROUP1} . $tag;
9837
+ if (not $$tagTablePtr{$tag} and $tagInfo) {
9838
+ my %newInfo = %$tagInfo;
9839
+ foreach ('Name', 'Description') {
9840
+ next unless $$tagInfo{$_};
9841
+ $newInfo{$_} = $$et{SET_GROUP1} . $$tagInfo{$_};
9842
+ $newInfo{$_} =~ s/^(Track\d+)Track/$1/; # remove duplicate "Track" in name
9843
+ }
9844
+ AddTagToTable($tagTablePtr, $tag, \%newInfo);
9754
9845
  }
9755
- AddTagToTable($tagTablePtr, $tag, \%newInfo);
9756
9846
  }
9757
9847
  }
9758
9848
  # set flag to store additional information for ExtractEmbedded option
@@ -9819,7 +9909,7 @@ sub ProcessMOV($$;$)
9819
9909
  # check for RIFF trailer (written by Auto-Vox dashcam)
9820
9910
  if ($buff =~ /^(gpsa|gps0|gsen|gsea)...\0/s) { # (yet seen only gpsa as first record)
9821
9911
  $et->VPrint(0, sprintf("Found RIFF trailer at offset 0x%x",$lastPos));
9822
- if ($et->Options('ExtractEmbedded')) {
9912
+ if ($ee) {
9823
9913
  $raf->Seek(-8, 1) or last; # seek back to start of trailer
9824
9914
  my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
9825
9915
  ProcessRIFFTrailer($et, { RAF => $raf }, $tbl);
@@ -9969,6 +10059,7 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
9969
10059
  }
9970
10060
  }
9971
10061
  if ($tagInfo) {
10062
+ my @found;
9972
10063
  my $subdir = $$tagInfo{SubDirectory};
9973
10064
  if ($subdir) {
9974
10065
  my $start = $$subdir{Start} || 0;
@@ -10087,21 +10178,23 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10087
10178
  Index => $index,
10088
10179
  Extra => sprintf(", Type='${type}', Flags=0x%x%s, Lang=0x%.4x",$flags,$str,$lang),
10089
10180
  ) if $verbose;
10090
- # use "Keys" in path instead of ItemList if this was defined by a Keys tag
10091
- my $isKey = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys';
10092
- if ($isKey) {
10093
- $oldDir = $$et{PATH}[-1];
10094
- $$et{PATH}[-1] = 'Keys';
10181
+ if (defined $value) {
10182
+ # use "Keys" in path instead of ItemList if this was defined by a Keys tag
10183
+ # (the only reason for this is to have "Keys" in the family 5 group name)
10184
+ # Note that the Keys group is specifically set by the ProcessKeys routine,
10185
+ # even though this tag would be in the ItemList table
10186
+ my $isKeys = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys';
10187
+ $isKeys and $oldDir = $$et{PATH}[-1], $$et{PATH}[-1] = 'Keys';
10188
+ push @found, $et->FoundTag($langInfo, $value);
10189
+ $$et{PATH}[-1] = $oldDir if $isKeys;
10095
10190
  }
10096
- $et->FoundTag($langInfo, $value) if defined $value;
10097
- $$et{PATH}[-1] = $oldDir if $isKey;
10098
10191
  $pos += $len;
10099
10192
  }
10100
10193
  } elsif ($tag =~ /^\xa9/ or $$tagInfo{IText}) {
10101
10194
  # parse international text to extract all languages
10102
10195
  my $pos = 0;
10103
10196
  if ($$tagInfo{Format}) {
10104
- $et->FoundTag($tagInfo, ReadValue(\$val, 0, $$tagInfo{Format}, undef, length($val)));
10197
+ push @found, $et->FoundTag($tagInfo, ReadValue(\$val, 0, $$tagInfo{Format}, undef, length($val)));
10105
10198
  $pos = $size;
10106
10199
  }
10107
10200
  for (;;) {
@@ -10166,7 +10259,7 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10166
10259
  $str = substr($val, $pos-$n-2, $n) . $str;
10167
10260
  }
10168
10261
  $langInfo = GetLangInfoQT($et, $tagInfo, $lang) if $lang;
10169
- $et->FoundTag($langInfo || $tagInfo, $str);
10262
+ push @found, $et->FoundTag($langInfo || $tagInfo, $str);
10170
10263
  $pos += $len;
10171
10264
  }
10172
10265
  } else {
@@ -10180,6 +10273,7 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10180
10273
  $$et{BASE} = $dataPos;
10181
10274
  }
10182
10275
  my $key = $et->FoundTag($tagInfo, $val);
10276
+ push @found, $key;
10183
10277
  $$et{BASE} = $oldBase if defined $oldBase;
10184
10278
  # decode if necessary (NOTE: must be done after RawConv)
10185
10279
  if (defined $key and (not $format or $format =~ /^string/) and
@@ -10195,6 +10289,14 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10195
10289
  }
10196
10290
  }
10197
10291
  }
10292
+ # tweak family 1 group names for Keys/ItemList/UserData tags in a track
10293
+ if ($$et{SET_GROUP1} and ($dirID eq 'ilst' or $dirID eq 'udta') and @found) {
10294
+ my $type = $trackPath{join '-', @{$$et{PATH}}};
10295
+ if ($type) {
10296
+ my $grp = ($avType{$$et{MediaType}} || $$et{SET_GROUP1}) . $type;
10297
+ defined and $et->SetGroup($_, $grp) foreach @found;
10298
+ }
10299
+ }
10198
10300
  }
10199
10301
  } else {
10200
10302
  $et->VerboseInfo($tag, $tagInfo,
@@ -10207,6 +10309,7 @@ ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
10207
10309
  last;
10208
10310
  }
10209
10311
  }
10312
+ $$et{MediaType} = '' if $tag eq 'trak'; # reset track type at end of track
10210
10313
  $dataPos += $size + 8; # point to start of next atom data
10211
10314
  last if $dirEnd and $dataPos >= $dirEnd; # (note: ignores last value if 0 bytes)
10212
10315
  $lastPos = $raf->Tell() + $dirBase;
@@ -10262,7 +10365,26 @@ QTLang: foreach $tag (@{$$et{QTLang}}) {
10262
10365
  # process item information now that we are done processing its 'meta' container
10263
10366
  HandleItemInfo($et) if $topLevel or $dirID eq 'meta';
10264
10367
 
10265
- ScanMediaData($et) if $ee and $topLevel; # brute force scan for metadata embedded in media data
10368
+ # process LigoGPS trailer now if it exists and we haven't already processed it
10369
+ if ($trailer and $$trailer[0] eq 'LigoGPS' and $lastPos <= $$trailer[1] and
10370
+ $raf->Seek($$trailer[1]) and $raf->Read($buff, 8) == 8 and $buff =~ /skip$/)
10371
+ {
10372
+ if ($ee) {
10373
+ my $len = Get32u(\$buff, 0) - 16;
10374
+ if ($len > 0 and $raf->Read($buff, $len) == $len and $buff =~ /^LIGOGPSINFO\0/) {
10375
+ my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
10376
+ my %dirInfo = ( DataPt => \$buff, DataPos => $$trailer[1] + 8, DirName => 'LigoGPSTrailer' );
10377
+ Image::ExifTool::LigoGPS::ProcessLigoGPS($et, \%dirInfo, $tbl);
10378
+ } else {
10379
+ $et->Warn('Unrecognized data in LigoGPS trailer');
10380
+ }
10381
+ } else {
10382
+ $et->Warn('Use the ExtractEmbedded option to decode timed GPS',3);
10383
+ }
10384
+ }
10385
+ # brute force scan for metadata embedded in media data
10386
+ # (and process Insta360 trailer if it exists)
10387
+ ScanMediaData($et) if $ee and $topLevel;
10266
10388
 
10267
10389
  # restore any changed options
10268
10390
  $et->Options($_ => $saveOptions{$_}) foreach keys %saveOptions;
@@ -10280,6 +10402,24 @@ sub ProcessQTIF($$)
10280
10402
  return ProcessMOV($et, $dirInfo, $table);
10281
10403
  }
10282
10404
 
10405
+ #==============================================================================
10406
+ # Autoload LigoGPS module if necessary
10407
+ # NOTE: Switches to package LigoGPS!
10408
+ #
10409
+ package Image::ExifTool::LigoGPS;
10410
+ use vars qw($AUTOLOAD);
10411
+ sub AUTOLOAD {
10412
+ require Image::ExifTool::LigoGPS;
10413
+ unless (defined &$AUTOLOAD) {
10414
+ my @caller = caller(0);
10415
+ # reproduce Perl's standard 'undefined subroutine' message:
10416
+ die "Undefined subroutine $AUTOLOAD called at $caller[1] line $caller[2]\n";
10417
+ }
10418
+ no strict 'refs';
10419
+ return &$AUTOLOAD(@_); # call the function
10420
+ }
10421
+ #==============================================================================
10422
+
10283
10423
  1; # end
10284
10424
 
10285
10425
  __END__
@@ -10299,7 +10439,7 @@ information from QuickTime and MP4 video, M4A audio, and HEIC image files.
10299
10439
 
10300
10440
  =head1 AUTHOR
10301
10441
 
10302
- Copyright 2003-2024, Phil Harvey (philharvey66 at gmail.com)
10442
+ Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
10303
10443
 
10304
10444
  This library is free software; you can redistribute it and/or modify it
10305
10445
  under the same terms as Perl itself.