exiftool_vendored 12.42.0 → 12.52.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/Changes +226 -6
- data/bin/MANIFEST +14 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +45 -44
- data/bin/config_files/acdsee.config +2 -1
- data/bin/config_files/frameCount.config +56 -0
- data/bin/config_files/tiff_version.config +1 -1
- data/bin/exiftool +116 -97
- data/bin/fmt_files/gpx.fmt +3 -0
- data/bin/fmt_files/gpx_wpt.fmt +3 -0
- data/bin/lib/Image/ExifTool/Apple.pm +16 -3
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +23 -12
- data/bin/lib/Image/ExifTool/Canon.pm +66 -37
- data/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
- data/bin/lib/Image/ExifTool/CanonVRD.pm +7 -8
- data/bin/lib/Image/ExifTool/Casio.pm +3 -3
- data/bin/lib/Image/ExifTool/DJI.pm +2 -1
- data/bin/lib/Image/ExifTool/DarwinCore.pm +13 -1
- data/bin/lib/Image/ExifTool/EXE.pm +9 -1
- data/bin/lib/Image/ExifTool/Exif.pm +17 -12
- data/bin/lib/Image/ExifTool/FLAC.pm +17 -3
- data/bin/lib/Image/ExifTool/FLIR.pm +9 -7
- data/bin/lib/Image/ExifTool/FlashPix.pm +26 -3
- data/bin/lib/Image/ExifTool/FujiFilm.pm +51 -4
- data/bin/lib/Image/ExifTool/GPS.pm +31 -5
- data/bin/lib/Image/ExifTool/Geotag.pm +36 -8
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +3 -2
- data/bin/lib/Image/ExifTool/ICO.pm +143 -0
- data/bin/lib/Image/ExifTool/ID3.pm +6 -6
- data/bin/lib/Image/ExifTool/IPTC.pm +5 -1
- data/bin/lib/Image/ExifTool/JPEG.pm +1 -0
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +24 -3
- data/bin/lib/Image/ExifTool/LNK.pm +5 -2
- data/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/fr.pm +6015 -759
- data/bin/lib/Image/ExifTool/Lang/sk.pm +1927 -0
- data/bin/lib/Image/ExifTool/M2TS.pm +98 -8
- data/bin/lib/Image/ExifTool/MIE.pm +9 -3
- data/bin/lib/Image/ExifTool/MISB.pm +494 -0
- data/bin/lib/Image/ExifTool/MakerNotes.pm +3 -1
- data/bin/lib/Image/ExifTool/Matroska.pm +272 -48
- data/bin/lib/Image/ExifTool/Motorola.pm +8 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +746 -382
- data/bin/lib/Image/ExifTool/NikonCustom.pm +139 -106
- data/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
- data/bin/lib/Image/ExifTool/Olympus.pm +6 -4
- data/bin/lib/Image/ExifTool/PNG.pm +8 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +21 -4
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +25 -5
- data/bin/lib/Image/ExifTool/Parrot.pm +96 -2
- data/bin/lib/Image/ExifTool/Pentax.pm +7 -2
- data/bin/lib/Image/ExifTool/Photoshop.pm +29 -3
- data/bin/lib/Image/ExifTool/QuickTime.pm +166 -13
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +161 -22
- data/bin/lib/Image/ExifTool/README +15 -4
- data/bin/lib/Image/ExifTool/RIFF.pm +106 -9
- data/bin/lib/Image/ExifTool/Samsung.pm +2 -2
- data/bin/lib/Image/ExifTool/Sigma.pm +27 -1
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +37 -13
- data/bin/lib/Image/ExifTool/Sony.pm +75 -47
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +13 -6
- data/bin/lib/Image/ExifTool/TagLookup.pm +4791 -4519
- data/bin/lib/Image/ExifTool/TagNames.pod +2056 -1446
- data/bin/lib/Image/ExifTool/Text.pm +3 -4
- data/bin/lib/Image/ExifTool/Torrent.pm +2 -3
- data/bin/lib/Image/ExifTool/Validate.pm +3 -3
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +7 -0
- data/bin/lib/Image/ExifTool/WriteExif.pl +100 -23
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +2 -6
- data/bin/lib/Image/ExifTool/WritePhotoshop.pl +5 -5
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +12 -7
- data/bin/lib/Image/ExifTool/WriteRIFF.pl +359 -0
- data/bin/lib/Image/ExifTool/WriteXMP.pl +15 -1
- data/bin/lib/Image/ExifTool/Writer.pl +46 -18
- data/bin/lib/Image/ExifTool/XMP.pm +78 -59
- data/bin/lib/Image/ExifTool/XMP2.pl +19 -4
- data/bin/lib/Image/ExifTool/ZIP.pm +19 -7
- data/bin/lib/Image/ExifTool.pm +146 -38
- data/bin/lib/Image/ExifTool.pod +83 -69
- data/bin/perl-Image-ExifTool.spec +43 -43
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +10 -4
@@ -26,6 +26,9 @@ sub ProcessFreeGPS($$$);
|
|
26
26
|
sub ProcessFreeGPS2($$$);
|
27
27
|
sub Process360Fly($$$);
|
28
28
|
sub ProcessFMAS($$$);
|
29
|
+
sub ProcessCAMM($$$);
|
30
|
+
|
31
|
+
my $debug; # set to 1 for extra debugging messages
|
29
32
|
|
30
33
|
# QuickTime data types that have ExifTool equivalents
|
31
34
|
# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35)
|
@@ -80,7 +83,7 @@ my %processByMetaFormat = (
|
|
80
83
|
|
81
84
|
# data lengths for each INSV record type
|
82
85
|
my %insvDataLen = (
|
83
|
-
0x300 =>
|
86
|
+
0x300 => 0, # accelerometer (could be either 20 or 56 bytes)
|
84
87
|
0x400 => 16, # exposure (ref 6)
|
85
88
|
0x600 => 8, # timestamps (ref 6)
|
86
89
|
0x700 => 53, # GPS
|
@@ -99,7 +102,7 @@ my %insvLimit = (
|
|
99
102
|
The tags below are extracted from timed metadata in QuickTime and other
|
100
103
|
formats of video files when the ExtractEmbedded option is used. Although
|
101
104
|
most of these tags are combined into the single table below, ExifTool
|
102
|
-
currently reads
|
105
|
+
currently reads 62 different formats of timed GPS metadata from video files.
|
103
106
|
},
|
104
107
|
VARS => { NO_ID => 1 },
|
105
108
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
@@ -234,7 +237,7 @@ my %insvLimit = (
|
|
234
237
|
camm => [{
|
235
238
|
Name => 'camm0',
|
236
239
|
# (according to the spec. the first 2 bytes are reserved and should be zero,
|
237
|
-
# but I have
|
240
|
+
# but I have samples where these bytes are non-zero, so allow anything here)
|
238
241
|
Condition => '$$valPt =~ /^..\0\0/s',
|
239
242
|
SubDirectory => {
|
240
243
|
TagTable => 'Image::ExifTool::QuickTime::camm0',
|
@@ -316,7 +319,7 @@ my %insvLimit = (
|
|
316
319
|
|
317
320
|
# tags found in 'camm' type 0 timed metadata (ref 4)
|
318
321
|
%Image::ExifTool::QuickTime::camm0 = (
|
319
|
-
PROCESS_PROC => \&
|
322
|
+
PROCESS_PROC => \&ProcessCAMM,
|
320
323
|
GROUPS => { 2 => 'Location' },
|
321
324
|
FIRST_ENTRY => 0,
|
322
325
|
NOTES => q{
|
@@ -334,7 +337,7 @@ my %insvLimit = (
|
|
334
337
|
|
335
338
|
# tags found in 'camm' type 1 timed metadata (ref 4)
|
336
339
|
%Image::ExifTool::QuickTime::camm1 = (
|
337
|
-
PROCESS_PROC => \&
|
340
|
+
PROCESS_PROC => \&ProcessCAMM,
|
338
341
|
GROUPS => { 2 => 'Camera' },
|
339
342
|
FIRST_ENTRY => 0,
|
340
343
|
4 => {
|
@@ -353,7 +356,7 @@ my %insvLimit = (
|
|
353
356
|
|
354
357
|
# tags found in 'camm' type 2 timed metadata (ref PH, Insta360Pro)
|
355
358
|
%Image::ExifTool::QuickTime::camm2 = (
|
356
|
-
PROCESS_PROC => \&
|
359
|
+
PROCESS_PROC => \&ProcessCAMM,
|
357
360
|
GROUPS => { 2 => 'Location' },
|
358
361
|
FIRST_ENTRY => 0,
|
359
362
|
4 => {
|
@@ -365,7 +368,7 @@ my %insvLimit = (
|
|
365
368
|
|
366
369
|
# tags found in 'camm' type 3 timed metadata (ref PH, Insta360Pro)
|
367
370
|
%Image::ExifTool::QuickTime::camm3 = (
|
368
|
-
PROCESS_PROC => \&
|
371
|
+
PROCESS_PROC => \&ProcessCAMM,
|
369
372
|
GROUPS => { 2 => 'Location' },
|
370
373
|
FIRST_ENTRY => 0,
|
371
374
|
4 => {
|
@@ -377,7 +380,7 @@ my %insvLimit = (
|
|
377
380
|
|
378
381
|
# tags found in 'camm' type 4 timed metadata (ref 4)
|
379
382
|
%Image::ExifTool::QuickTime::camm4 = (
|
380
|
-
PROCESS_PROC => \&
|
383
|
+
PROCESS_PROC => \&ProcessCAMM,
|
381
384
|
GROUPS => { 2 => 'Location' },
|
382
385
|
FIRST_ENTRY => 0,
|
383
386
|
4 => {
|
@@ -389,7 +392,7 @@ my %insvLimit = (
|
|
389
392
|
|
390
393
|
# tags found in 'camm' type 5 timed metadata (ref 4)
|
391
394
|
%Image::ExifTool::QuickTime::camm5 = (
|
392
|
-
PROCESS_PROC => \&
|
395
|
+
PROCESS_PROC => \&ProcessCAMM,
|
393
396
|
GROUPS => { 2 => 'Location' },
|
394
397
|
FIRST_ENTRY => 0,
|
395
398
|
4 => {
|
@@ -414,7 +417,7 @@ my %insvLimit = (
|
|
414
417
|
|
415
418
|
# tags found in 'camm' type 6 timed metadata (ref PH/4, Insta360)
|
416
419
|
%Image::ExifTool::QuickTime::camm6 = (
|
417
|
-
PROCESS_PROC => \&
|
420
|
+
PROCESS_PROC => \&ProcessCAMM,
|
418
421
|
GROUPS => { 2 => 'Location' },
|
419
422
|
FIRST_ENTRY => 0,
|
420
423
|
0x04 => {
|
@@ -480,7 +483,7 @@ my %insvLimit = (
|
|
480
483
|
|
481
484
|
# tags found in 'camm' type 7 timed metadata (ref 4)
|
482
485
|
%Image::ExifTool::QuickTime::camm7 = (
|
483
|
-
PROCESS_PROC => \&
|
486
|
+
PROCESS_PROC => \&ProcessCAMM,
|
484
487
|
GROUPS => { 2 => 'Location' },
|
485
488
|
FIRST_ENTRY => 0,
|
486
489
|
4 => {
|
@@ -896,10 +899,15 @@ sub Process_text($$$)
|
|
896
899
|
my $time = "$1:$2:$3";
|
897
900
|
if ($$et{LastTime}) {
|
898
901
|
if ($$et{LastTime} eq $time) {
|
902
|
+
# combine with the previous NMEA sentence
|
899
903
|
$$et{DOC_NUM} = $$et{LastDoc};
|
900
904
|
} elsif (%tags) {
|
905
|
+
# handle existing tags and start a new document
|
906
|
+
# (see https://exiftool.org/forum/index.php?msg=75422)
|
901
907
|
HandleTextTags($et, $tagTbl, \%tags);
|
902
|
-
|
908
|
+
undef %tags;
|
909
|
+
# increment document number and update document count if necessary
|
910
|
+
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
903
911
|
}
|
904
912
|
}
|
905
913
|
$$et{LastTime} = $time;
|
@@ -918,7 +926,8 @@ sub Process_text($$$)
|
|
918
926
|
$$et{DOC_NUM} = $$et{LastDoc};
|
919
927
|
} elsif (%tags) {
|
920
928
|
HandleTextTags($et, $tagTbl, \%tags);
|
921
|
-
|
929
|
+
undef %tags;
|
930
|
+
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
922
931
|
}
|
923
932
|
}
|
924
933
|
$$et{LastTime} = $time;
|
@@ -1416,6 +1425,7 @@ sub ProcessFreeGPS($$$)
|
|
1416
1425
|
} elsif ($buf2 =~ /^.{173}([-+]\d{3})([-+]\d{3})([-+]\d{3})/s) { # (Azdome)
|
1417
1426
|
@acc = ($1/100, $2/100, $3/100);
|
1418
1427
|
}
|
1428
|
+
$debug and $et->FoundTag(GPSType => '1A');
|
1419
1429
|
|
1420
1430
|
} elsif ($$dataPt =~ /^.{52}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/s) {
|
1421
1431
|
|
@@ -1444,6 +1454,7 @@ sub ProcessFreeGPS($$$)
|
|
1444
1454
|
# change to signed integer and divide by 256
|
1445
1455
|
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
1446
1456
|
}
|
1457
|
+
$debug and $et->FoundTag(GPSType => '1B');
|
1447
1458
|
|
1448
1459
|
} elsif ($$dataPt =~ /^.{37}\0\0\0A([NS])([EW])/s) {
|
1449
1460
|
|
@@ -1454,13 +1465,31 @@ sub ProcessFreeGPS($$$)
|
|
1454
1465
|
# 0030: f1 47 40 46 66 66 d2 41 85 eb 83 41 00 00 00 00 [.G@Fff.A...A....]
|
1455
1466
|
($latRef, $lonRef) = ($1, $2);
|
1456
1467
|
($hr,$min,$sec,$yr,$mon,$day) = unpack('x16V6', $$dataPt);
|
1457
|
-
$yr
|
1468
|
+
if ($yr < 2000) {
|
1469
|
+
$yr += 2000;
|
1470
|
+
} else {
|
1471
|
+
# Kenwood dashcam sometimes stores absolute year and local time
|
1472
|
+
# (but sometimes year since 2000 and UTC time in same video!)
|
1473
|
+
require Time::Local;
|
1474
|
+
my $time = Image::ExifTool::TimeLocal($sec,$min,$hr,$day,$mon-1,$yr-1900);
|
1475
|
+
($sec,$min,$hr,$day,$mon,$yr) = gmtime($time);
|
1476
|
+
$yr += 1900;
|
1477
|
+
++$mon;
|
1478
|
+
$et->WarnOnce('Converting GPSDateTime to UTC based on local time zone',1);
|
1479
|
+
}
|
1458
1480
|
SetByteOrder('II');
|
1459
1481
|
$lat = GetFloat($dataPt, 0x2c);
|
1460
1482
|
$lon = GetFloat($dataPt, 0x30);
|
1461
1483
|
$spd = GetFloat($dataPt, 0x34) * $knotsToKph; # (convert knots to km/h)
|
1462
1484
|
$trk = GetFloat($dataPt, 0x38);
|
1485
|
+
# (may be all zeros or int16u counting from 1 to 6 if not valid)
|
1486
|
+
my $tmp = substr($$dataPt, 60, 12);
|
1487
|
+
if ($tmp ne "\0\0\0\0\0\0\0\0\0\0\0\0" and $tmp ne "\x01\0\x02\0\x03\0\x04\0\x05\0\x06\0") {
|
1488
|
+
@acc = unpack('V3', $tmp);
|
1489
|
+
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
1490
|
+
}
|
1463
1491
|
SetByteOrder('MM');
|
1492
|
+
$debug and $et->FoundTag(GPSType => '1C');
|
1464
1493
|
|
1465
1494
|
} elsif ($$dataPt =~ /^.{21}\0\0\0A([NS])([EW])/s) {
|
1466
1495
|
|
@@ -1489,6 +1518,7 @@ sub ProcessFreeGPS($$$)
|
|
1489
1518
|
$acc[1] = GetFloat($dataPt, 0x30);
|
1490
1519
|
$acc[2] = GetFloat($dataPt, 0x34);
|
1491
1520
|
SetByteOrder('MM');
|
1521
|
+
$debug and $et->FoundTag(GPSType => '1D');
|
1492
1522
|
|
1493
1523
|
} elsif ($$dataPt =~ /^.{60}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s) {
|
1494
1524
|
|
@@ -1509,6 +1539,7 @@ sub ProcessFreeGPS($$$)
|
|
1509
1539
|
$trk = GetFloat($dataPt, 0x54) + 180; # (why is this off by 180?)
|
1510
1540
|
$trk -= 360 if $trk >= 360;
|
1511
1541
|
SetByteOrder('MM');
|
1542
|
+
$debug and $et->FoundTag(GPSType => '1E');
|
1512
1543
|
|
1513
1544
|
} elsif ($$dataPt =~ /^.{60}4W`b]S</s and length($$dataPt) >= 140) {
|
1514
1545
|
|
@@ -1526,8 +1557,9 @@ sub ProcessFreeGPS($$$)
|
|
1526
1557
|
$yr += ($yr >= 70 ? 1900 : 2000);
|
1527
1558
|
$spd = $9 * $knotsToKph if length $9;
|
1528
1559
|
$trk = $10 if length $10;
|
1560
|
+
$debug and $et->FoundTag(GPSType => '1F');
|
1529
1561
|
|
1530
|
-
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0/s) {
|
1562
|
+
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0{5}/s) {
|
1531
1563
|
|
1532
1564
|
# Akaso V1 dascham
|
1533
1565
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 00 00 00 [....freeGPS x...]
|
@@ -1569,6 +1601,7 @@ sub ProcessFreeGPS($$$)
|
|
1569
1601
|
|
1570
1602
|
SetByteOrder('MM');
|
1571
1603
|
#my $serialNum = substr($$dataPt, 0x68, 20);
|
1604
|
+
$debug and $et->FoundTag(GPSType => '1G');
|
1572
1605
|
|
1573
1606
|
} elsif ($$dataPt =~ /^.{12}\xac\0\0\0.{44}(.{72})/s) {
|
1574
1607
|
|
@@ -1591,6 +1624,7 @@ sub ProcessFreeGPS($$$)
|
|
1591
1624
|
# bytes 7-12 are the timestamp in ASCII HHMMSS after xor-ing with 0x70
|
1592
1625
|
substr($time,7,6) = pack 'C*', map { $_ ^= 0x70 } unpack 'C*', substr($time,7,6);
|
1593
1626
|
# (other values are currently unknown)
|
1627
|
+
$debug and $et->FoundTag(GPSType => '1H');
|
1594
1628
|
|
1595
1629
|
} elsif ($$dataPt =~ /^.{64}A([NS])([EW])\0/s) {
|
1596
1630
|
|
@@ -1616,6 +1650,7 @@ sub ProcessFreeGPS($$$)
|
|
1616
1650
|
$trk = GetFloat($dataPt, 0x68);
|
1617
1651
|
$alt = GetFloat($dataPt, 0x6c);
|
1618
1652
|
SetByteOrder('MM');
|
1653
|
+
$debug and $et->FoundTag(GPSType => '1I');
|
1619
1654
|
|
1620
1655
|
} else {
|
1621
1656
|
|
@@ -1624,6 +1659,9 @@ sub ProcessFreeGPS($$$)
|
|
1624
1659
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...]
|
1625
1660
|
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
1626
1661
|
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
1662
|
+
# 0030: 10 00 00 00 2d 00 00 00 14 00 00 00 11 00 00 00 [....-...........]
|
1663
|
+
# 0040: 0c 00 00 00 1f 00 00 00 41 4e 45 00 5d 9a a9 45 [........ANE.]..E]
|
1664
|
+
# 0050: ab 1e e5 44 ec 51 f0 40 b8 5e a5 43 00 00 00 00 [...D.Q.@.^.C....]
|
1627
1665
|
# (records are same structure as Type 3 Novatek GPS in ProcessFreeGPS2() below)
|
1628
1666
|
($hr,$min,$sec,$yr,$mon,$day,$stat,$latRef,$lonRef,$lat,$lon,$spd,$trk) =
|
1629
1667
|
unpack('x48V6a1a1a1x1V4', $$dataPt);
|
@@ -1649,6 +1687,7 @@ sub ProcessFreeGPS($$$)
|
|
1649
1687
|
$yr += 2000 if $yr < 2000;
|
1650
1688
|
$spd *= $knotsToKph; # convert speed to km/h
|
1651
1689
|
# ($trk is not confirmed; may be GPSImageDirection, ref PH)
|
1690
|
+
$debug and $et->FoundTag(GPSType => '1J');
|
1652
1691
|
}
|
1653
1692
|
#
|
1654
1693
|
# save tag values extracted by above code
|
@@ -1802,6 +1841,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1802
1841
|
}
|
1803
1842
|
# save position of most recent record (needed when parsing the next freeGPS block)
|
1804
1843
|
$$et{FreeGPS2}{RecentRecPos} = $lastRecPos;
|
1844
|
+
$debug and $et->FoundTag(GPSType => '2A');
|
1805
1845
|
return 1;
|
1806
1846
|
|
1807
1847
|
} elsif ($$dataPt =~ /^.{60}A\0.{10}([NS])\0.{14}([EW])\0/s) {
|
@@ -1833,6 +1873,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1833
1873
|
$lon = GetDouble($dataPt, 0x50);
|
1834
1874
|
$spd = GetDouble($dataPt, 0x60) * $knotsToKph;
|
1835
1875
|
$trk = GetDouble($dataPt, 0x68);
|
1876
|
+
$debug and $et->FoundTag(GPSType => '2B');
|
1836
1877
|
|
1837
1878
|
} elsif ($$dataPt =~ /^.{72}A([NS])([EW])/s) {
|
1838
1879
|
|
@@ -1869,6 +1910,8 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1869
1910
|
$lon = abs Get32s($dataPt, 0x50) / 1e7;
|
1870
1911
|
$spd = Get32s($dataPt, 0x54) / 100 * $mpsToKph;
|
1871
1912
|
$alt = GetFloat($dataPt, 0x58) / 1000; # (NC)
|
1913
|
+
$debug and $et->FoundTag(GPSType => '2C');
|
1914
|
+
|
1872
1915
|
} else {
|
1873
1916
|
# Type 3 (ref 2)
|
1874
1917
|
# (no sample with this format)
|
@@ -1876,6 +1919,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1876
1919
|
$lon = GetFloat($dataPt, 0x50);
|
1877
1920
|
$spd = GetFloat($dataPt, 0x54) * $knotsToKph;
|
1878
1921
|
$trk = GetFloat($dataPt, 0x58);
|
1922
|
+
$debug and $et->FoundTag(GPSType => '2D');
|
1879
1923
|
}
|
1880
1924
|
|
1881
1925
|
} elsif ($$dataPt =~ /^.{60}A\0.{6}([NS])\0.{6}([EW])\0/s and $dirLen >= 112) {
|
@@ -1896,6 +1940,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1896
1940
|
$lon = GetFloat($dataPt, 0x48);
|
1897
1941
|
$spd = GetFloat($dataPt, 0x50);
|
1898
1942
|
$trk = GetFloat($dataPt, 0x54);
|
1943
|
+
$debug and $et->FoundTag(GPSType => '2E');
|
1899
1944
|
|
1900
1945
|
} elsif ($$dataPt =~ /^.{16}A([NS])([EW])\0/s) {
|
1901
1946
|
|
@@ -1916,6 +1961,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1916
1961
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
1917
1962
|
$et->HandleTag($tagTbl, Accelerometer => "@acc");
|
1918
1963
|
}
|
1964
|
+
$debug and $et->FoundTag(GPSType => '2F');
|
1919
1965
|
return 1;
|
1920
1966
|
|
1921
1967
|
} else {
|
@@ -1962,6 +2008,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1962
2008
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
1963
2009
|
last if $pos += 0x20 > length($$dataPt) - 0x1e;
|
1964
2010
|
}
|
2011
|
+
$debug and $et->FoundTag(GPSType => '2G');
|
1965
2012
|
return $$et{DOC_NUM} ? 1 : 0; # return 0 if nothing extracted
|
1966
2013
|
}
|
1967
2014
|
#
|
@@ -2530,7 +2577,7 @@ sub ProcessTTAD($$$)
|
|
2530
2577
|
# (I think "5" may be the number of satellites. seen: 5,6,7 - PH)
|
2531
2578
|
FoundSomething($et, $tagTbl, $sampleTime / 1000);
|
2532
2579
|
my $t = GetDouble($dataPt, $pos);
|
2533
|
-
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3).'Z');
|
2580
|
+
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3) . 'Z');
|
2534
2581
|
$et->HandleTag($tagTbl, GPSLatitude => GetDouble($dataPt, $pos+0x1c));
|
2535
2582
|
$et->HandleTag($tagTbl, GPSLongitude => GetDouble($dataPt, $pos+0x24));
|
2536
2583
|
$et->HandleTag($tagTbl, GPSAltitude => GetDouble($dataPt, $pos+0x14));
|
@@ -2621,8 +2668,33 @@ sub ProcessInsta360($;$)
|
|
2621
2668
|
if ($verbose) {
|
2622
2669
|
$et->VPrint(0, sprintf("Insta360 Record 0x%x (offset 0x%x, %d bytes):\n", $id, $fileEnd + $epos, $len));
|
2623
2670
|
}
|
2671
|
+
# there are 2 types of record 0x300:
|
2672
|
+
# 1. 56 byte records
|
2673
|
+
# 0000: 4a f7 02 00 00 00 00 00 00 00 00 00 00 1e e7 3f [J..............?]
|
2674
|
+
# 0010: 00 00 00 00 00 b2 ef bf 00 00 00 00 00 70 c1 bf [.............p..]
|
2675
|
+
# 0020: 00 00 00 e0 91 5c 8c bf 00 00 00 20 8f ff 87 bf [.....\..... ....]
|
2676
|
+
# 0030: 00 00 00 00 88 7f c9 bf
|
2677
|
+
# 2. 20 byte records
|
2678
|
+
# 0000: c1 d8 d9 0b 00 00 00 00 f5 83 14 80 df 7f fe 7f [................]
|
2679
|
+
# 0010: fe 7f 01 80
|
2680
|
+
if ($id == 0x300) {
|
2681
|
+
if ($len % 20 and not $len % 56) {
|
2682
|
+
$dlen = 56;
|
2683
|
+
} elsif ($len % 56 and not $len % 20) {
|
2684
|
+
$dlen = 20;
|
2685
|
+
} else {
|
2686
|
+
if ($raf->Read($buff, 20) == 20) {
|
2687
|
+
if (substr($buff, 16, 3) eq "\0\0\0") {
|
2688
|
+
$dlen = 56;
|
2689
|
+
} else {
|
2690
|
+
$dlen = 20;
|
2691
|
+
}
|
2692
|
+
}
|
2693
|
+
$raf->Seek($epos, 2) or last;
|
2694
|
+
}
|
2695
|
+
}
|
2624
2696
|
# limit the number of records we read if necessary
|
2625
|
-
if ($insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
|
2697
|
+
if ($dlen and $insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
|
2626
2698
|
$et->Warn("Insta360 $insvLimit{$id}[0] data is huge. Processing only the first $insvLimit{$id}[1] records",2))
|
2627
2699
|
{
|
2628
2700
|
$len = $insvLimit{$id}[1] * $dlen;
|
@@ -2630,11 +2702,18 @@ sub ProcessInsta360($;$)
|
|
2630
2702
|
$raf->Read($buff, $len) == $len or last;
|
2631
2703
|
$et->VerboseDump(\$buff) if $verbose > 2;
|
2632
2704
|
if ($dlen) {
|
2633
|
-
$len % $dlen
|
2634
|
-
|
2705
|
+
if ($len % $dlen) {
|
2706
|
+
$et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
|
2707
|
+
} elsif ($id == 0x300) {
|
2635
2708
|
for ($p=0; $p<$len; $p+=$dlen) {
|
2636
2709
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
2637
|
-
my @a
|
2710
|
+
my @a;
|
2711
|
+
if ($dlen == 56) {
|
2712
|
+
@a = map { GetDouble(\$buff, $p + 8 * $_) } 1..6;
|
2713
|
+
} else {
|
2714
|
+
@a = unpack("x${p}x8v6", $buff);
|
2715
|
+
map { $_ = ($_ - 0x8000) / 1000 } @a;
|
2716
|
+
}
|
2638
2717
|
$et->HandleTag($tagTbl, TimeCode => sprintf('%.3f', Get64u(\$buff, $p) / 1000));
|
2639
2718
|
$et->HandleTag($tagTbl, Accelerometer => "@a[0..2]"); # (NC)
|
2640
2719
|
$et->HandleTag($tagTbl, AngularVelocity => "@a[3..5]"); # (NC)
|
@@ -2699,6 +2778,66 @@ sub ProcessInsta360($;$)
|
|
2699
2778
|
return 1;
|
2700
2779
|
}
|
2701
2780
|
|
2781
|
+
#------------------------------------------------------------------------------
|
2782
|
+
# Process CAMM metadata (ref PH)
|
2783
|
+
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
2784
|
+
# Returns: 1 on success
|
2785
|
+
sub ProcessCAMM($$$)
|
2786
|
+
{
|
2787
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
2788
|
+
my $dataPt = $$dirInfo{DataPt};
|
2789
|
+
my $pos = $$dirInfo{DirStart} || 0;
|
2790
|
+
my $end = $pos + ($$dirInfo{DirLen} || length($$dataPt) - $pos);
|
2791
|
+
# camm record size for each type, including 4-byte header
|
2792
|
+
my %size = ( 1 => 12, 2 => 16, 3 => 16, 4 => 16, 5 => 28, 6 => 60, 7 => 16 );
|
2793
|
+
my $rtnVal = 0;
|
2794
|
+
while ($pos + 4 < $end) {
|
2795
|
+
my $type = Get16u($dataPt, $pos + 2);
|
2796
|
+
my $size = $size{$type} or $et->WarnOnce("Unknown camm record type $type"), last;
|
2797
|
+
$pos + $size > $end and $et->WarnOnce("Truncated camm record $type"), last;
|
2798
|
+
my $tagTbl = GetTagTable("Image::ExifTool::QuickTime::camm$type");
|
2799
|
+
$$dirInfo{DirStart} = $pos;
|
2800
|
+
$$dirInfo{DirLen} = $size;
|
2801
|
+
$et->ProcessBinaryData($dirInfo, $tagTbl) and $rtnVal = 1;
|
2802
|
+
# not sure if this is according to specification, but I have seen multiple
|
2803
|
+
# camm records all in a single sample, so step forward to process the next one
|
2804
|
+
$pos += $size;
|
2805
|
+
}
|
2806
|
+
return $rtnVal;
|
2807
|
+
}
|
2808
|
+
|
2809
|
+
#------------------------------------------------------------------------------
|
2810
|
+
# Process Garmin GPS 'uuid' atom (ref PH)
|
2811
|
+
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
2812
|
+
# Returns: 1 on success
|
2813
|
+
# Note: This format is used by the Garmin DriveAssist 51, but the DriveAssist 50
|
2814
|
+
# uses a completely different format. :(
|
2815
|
+
sub ProcessGarminGPS($$$)
|
2816
|
+
{
|
2817
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
2818
|
+
my $dataPt = $$dirInfo{DataPt};
|
2819
|
+
my $dataLen = length $$dataPt;
|
2820
|
+
my $pos = 33;
|
2821
|
+
my $epoch = (66 * 365 + 17) * 24 * 3600; # time is relative to Jan 1, 1904
|
2822
|
+
my $scl = 180 / (32768 * 65536); # scaling factor for lat/lon
|
2823
|
+
$et->VerboseDir('GarminGPS');
|
2824
|
+
while ($pos + 20 <= $dataLen) {
|
2825
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
2826
|
+
my $time = Image::ExifTool::ConvertUnixTime(Get32u($dataPt, $pos) - $epoch) . 'Z';
|
2827
|
+
my $lat = Get32s($dataPt, $pos + 12) * $scl;
|
2828
|
+
my $lon = Get32s($dataPt, $pos + 16) * $scl;
|
2829
|
+
my $spd = Get16u($dataPt, $pos + 4); # (in mph)
|
2830
|
+
$et->HandleTag($tagTbl, 'GPSDateTime', $time);
|
2831
|
+
$et->HandleTag($tagTbl, 'GPSLatitude', $lat);
|
2832
|
+
$et->HandleTag($tagTbl, 'GPSLongitude', $lon);
|
2833
|
+
$et->HandleTag($tagTbl, 'GPSSpeed', $spd);
|
2834
|
+
$et->HandleTag($tagTbl, 'GPSSpeedRef', 'M');
|
2835
|
+
$pos += 20;
|
2836
|
+
}
|
2837
|
+
delete $$et{DOC_NUM};
|
2838
|
+
return 1;
|
2839
|
+
}
|
2840
|
+
|
2702
2841
|
#------------------------------------------------------------------------------
|
2703
2842
|
# Process 360Fly 'uuid' atom containing sensor data
|
2704
2843
|
# (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
|
@@ -2776,9 +2915,9 @@ sub ScanMediaData($)
|
|
2776
2915
|
my ($pos, $buf2) = (0, '');
|
2777
2916
|
|
2778
2917
|
# don't rescan for freeGPS if we already found embedded metadata
|
2779
|
-
my $dataPos = $$et{
|
2918
|
+
my $dataPos = $$et{MediaDataOffset};
|
2780
2919
|
if ($dataPos and not $$et{DOC_COUNT}) {
|
2781
|
-
$dataLen = $$et{
|
2920
|
+
$dataLen = $$et{MediaDataSize};
|
2782
2921
|
if ($dataLen) {
|
2783
2922
|
if ($raf->Seek($dataPos, 0)) {
|
2784
2923
|
$$et{FreeGPS2} = { }; # initialize variable space for FreeGPS2()
|
@@ -395,7 +395,9 @@ numerical, and generated automatically otherwise.
|
|
395
395
|
be accessible.
|
396
396
|
|
397
397
|
'Hidden' - set to hide tag from the TagName documentation.
|
398
|
-
Also suppresses verbose output of a BinaryData tag.
|
398
|
+
Also suppresses verbose output of a BinaryData tag. The
|
399
|
+
RawConv of a Hidden tag should return undef so the tag value
|
400
|
+
is not seen by the user.
|
399
401
|
|
400
402
|
'IsComposite' - flag set for Composite tags
|
401
403
|
|
@@ -531,7 +533,8 @@ numerical, and generated automatically otherwise.
|
|
531
533
|
SubIFD's where the PutFirst flag is valid.
|
532
534
|
|
533
535
|
'Unknown' - this is an unknown tag (only extracted when the
|
534
|
-
Unknown option is set).
|
536
|
+
Unknown option is set). This is set to 2 for Unknown tags in
|
537
|
+
binary tables (extracted when Unknown is 2).
|
535
538
|
|
536
539
|
'WriteNothing' - flag indicating that nothing is actually
|
537
540
|
written when this tag is set. It is a fake writable tag that
|
@@ -638,7 +641,8 @@ numerical, and generated automatically otherwise.
|
|
638
641
|
expression, a code reference or a list reference. In this
|
639
642
|
expression, $self, $val and $tag may be used as with
|
640
643
|
ValueConv, but if ValueConv was defined then $val is the
|
641
|
-
ValueConv value instead of the Raw value.
|
644
|
+
ValueConv value instead of the Raw value. Composite tags
|
645
|
+
may also use the @val, @prt and @raw lists. The returned value
|
642
646
|
should always be defined. Note that the print conversion is
|
643
647
|
only done if the PrintConv option is enabled (which it is by
|
644
648
|
default), and if the result of the ValueConv is not a scalar
|
@@ -717,7 +721,7 @@ numerical, and generated automatically otherwise.
|
|
717
721
|
condition exists, then a 'true' condition is assumed. The
|
718
722
|
expression may use $self to access the ExifTool object. The
|
719
723
|
first 128 bytes of the raw data value are accessible through
|
720
|
-
the reference $valPt for EXIF, Jpeg2000, QuickTime and
|
724
|
+
the reference $valPt for EXIF, Jpeg2000, QuickTime, FLAC and
|
721
725
|
BinaryData tags only (note that for BinaryData tags, the raw
|
722
726
|
data of $$valPt is always 'undef' type, and may not be used
|
723
727
|
when writing except for SubDirectory tags). EXIF tags (and
|
@@ -964,6 +968,10 @@ numerical, and generated automatically otherwise.
|
|
964
968
|
OtherLang : [reserved] Used internally by QuickTime module to store a list
|
965
969
|
of tag ID's for alternate-language tags based on this one.
|
966
970
|
|
971
|
+
ParentTagInfo : [reserved] Used internally to store a reference to the tag
|
972
|
+
information hash of the parent structure for flattened
|
973
|
+
structure tags.
|
974
|
+
|
967
975
|
RootTagInfo : [reserved] Used internally to store a reference to the tag
|
968
976
|
information hash of the top-level structure for flattened
|
969
977
|
structure tags.
|
@@ -975,6 +983,9 @@ numerical, and generated automatically otherwise.
|
|
975
983
|
alternate language tags (eg. 'fr'). Only used with formats
|
976
984
|
which support alternate languages (eg. XMP, MIE, etc).
|
977
985
|
|
986
|
+
AddedUnknown : [reserved] Used internally to mark Unknown tags that were
|
987
|
+
added to the table at run time.
|
988
|
+
|
978
989
|
SubDirectory { If it exists, this specifies the start of a new subdirectory.
|
979
990
|
It contains a collection of variables which specify the type
|
980
991
|
and location of the subdirectory. Note that ValueConv and
|