exiftool_vendored 12.41.0 → 12.50.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.
- checksums.yaml +4 -4
- data/bin/Changes +209 -6
- data/bin/MANIFEST +12 -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 +115 -96
- 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 +71 -33
- data/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
- data/bin/lib/Image/ExifTool/CanonVRD.pm +7 -8
- data/bin/lib/Image/ExifTool/DJI.pm +60 -1
- data/bin/lib/Image/ExifTool/DNG.pm +8 -2
- 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 +26 -12
- data/bin/lib/Image/ExifTool/FLAC.pm +17 -3
- data/bin/lib/Image/ExifTool/FLIR.pm +4 -3
- 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 +21 -1
- data/bin/lib/Image/ExifTool/Geotag.pm +25 -5
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +12 -9
- data/bin/lib/Image/ExifTool/ICO.pm +143 -0
- data/bin/lib/Image/ExifTool/ID3.pm +11 -11
- data/bin/lib/Image/ExifTool/IPTC.pm +5 -1
- data/bin/lib/Image/ExifTool/LNK.pm +5 -2
- 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 +8 -1
- data/bin/lib/Image/ExifTool/Matroska.pm +24 -16
- data/bin/lib/Image/ExifTool/Motorola.pm +8 -2
- data/bin/lib/Image/ExifTool/Nikon.pm +293 -122
- data/bin/lib/Image/ExifTool/NikonCustom.pm +4 -1
- data/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
- data/bin/lib/Image/ExifTool/Olympus.pm +22 -2
- data/bin/lib/Image/ExifTool/PDF.pm +2 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +30 -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 +8 -3
- data/bin/lib/Image/ExifTool/Photoshop.pm +35 -8
- data/bin/lib/Image/ExifTool/QuickTime.pm +163 -13
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +119 -13
- data/bin/lib/Image/ExifTool/README +13 -3
- data/bin/lib/Image/ExifTool/RIFF.pm +106 -9
- data/bin/lib/Image/ExifTool/Samsung.pm +234 -3
- data/bin/lib/Image/ExifTool/Shortcuts.pm +2 -1
- 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 +71 -43
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +3 -1
- data/bin/lib/Image/ExifTool/TagLookup.pm +4752 -4516
- data/bin/lib/Image/ExifTool/TagNames.pod +1885 -1434
- 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/WriteRIFF.pl +359 -0
- data/bin/lib/Image/ExifTool/Writer.pl +14 -6
- data/bin/lib/Image/ExifTool/XMP.pm +78 -59
- data/bin/lib/Image/ExifTool/XMP2.pl +19 -4
- data/bin/lib/Image/ExifTool.pm +120 -33
- 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 +9 -4
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
47
47
|
use Image::ExifTool::Exif;
|
48
48
|
use Image::ExifTool::GPS;
|
49
49
|
|
50
|
-
$VERSION = '2.
|
50
|
+
$VERSION = '2.80';
|
51
51
|
|
52
52
|
sub ProcessMOV($$;$);
|
53
53
|
sub ProcessKeys($$$);
|
@@ -66,6 +66,7 @@ sub ProcessRIFFTrailer($$$);
|
|
66
66
|
sub ProcessTTAD($$$);
|
67
67
|
sub ProcessNMEA($$$);
|
68
68
|
sub ProcessGPSLog($$$);
|
69
|
+
sub ProcessGarminGPS($$$);
|
69
70
|
sub SaveMetaKeys($$$);
|
70
71
|
# ++^^^^^^^^^^^^++
|
71
72
|
sub ParseItemLocation($$);
|
@@ -521,6 +522,12 @@ my %eeBox2 = (
|
|
521
522
|
return substr($val, 12, $len);
|
522
523
|
},
|
523
524
|
},
|
525
|
+
{
|
526
|
+
Name => 'SkipInfo', # (found in 70mai Pro Plus+ MP4 videos)
|
527
|
+
# (look for something that looks like a QuickTime atom header)
|
528
|
+
Condition => '$$valPt =~ /^\0[\0-\x04]..[a-zA-Z ]{4}/s',
|
529
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SkipInfo' },
|
530
|
+
},
|
524
531
|
{ Name => 'Skip', Unknown => 1, Binary => 1 },
|
525
532
|
],
|
526
533
|
wide => { Unknown => 1, Binary => 1 },
|
@@ -556,12 +563,16 @@ my %eeBox2 = (
|
|
556
563
|
mdat => { Name => 'MediaData', Unknown => 1, Binary => 1 },
|
557
564
|
'mdat-size' => {
|
558
565
|
Name => 'MediaDataSize',
|
566
|
+
RawConv => '$$self{MediaDataSize} = $val',
|
559
567
|
Notes => q{
|
560
568
|
not a real tag ID, this tag represents the size of the 'mdat' data in bytes
|
561
569
|
and is used in the AvgBitrate calculation
|
562
570
|
},
|
563
571
|
},
|
564
|
-
'mdat-offset' =>
|
572
|
+
'mdat-offset' => {
|
573
|
+
Name => 'MediaDataOffset',
|
574
|
+
RawConv => '$$self{MediaDataOffset} = $val',
|
575
|
+
},
|
565
576
|
junk => { Unknown => 1, Binary => 1 }, #8
|
566
577
|
uuid => [
|
567
578
|
{ #9 (MP4 files)
|
@@ -754,6 +765,19 @@ my %eeBox2 = (
|
|
754
765
|
# 'samn'? - seen in Vantrue N2S sample video
|
755
766
|
);
|
756
767
|
|
768
|
+
# stuff seen in 'skip' atom (70mai Pro Plus+ MP4 videos)
|
769
|
+
%Image::ExifTool::QuickTime::SkipInfo = (
|
770
|
+
PROCESS_PROC => \&ProcessMOV,
|
771
|
+
GROUPS => { 2 => 'Video' },
|
772
|
+
'ver ' => 'Version',
|
773
|
+
# tima - int32u: seen 0x3c
|
774
|
+
thma => {
|
775
|
+
Name => 'ThumbnailImage',
|
776
|
+
Groups => { 2 => 'Preview' },
|
777
|
+
Binary => 1,
|
778
|
+
},
|
779
|
+
);
|
780
|
+
|
757
781
|
# MPEG-4 'ftyp' atom
|
758
782
|
# (ref http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html)
|
759
783
|
%Image::ExifTool::QuickTime::FileType = (
|
@@ -897,7 +921,7 @@ my %eeBox2 = (
|
|
897
921
|
},
|
898
922
|
colr => {
|
899
923
|
Name => 'ColorRepresentation',
|
900
|
-
|
924
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ColorRep' },
|
901
925
|
},
|
902
926
|
pasp => {
|
903
927
|
Name => 'PixelAspectRatio',
|
@@ -1118,6 +1142,23 @@ my %eeBox2 = (
|
|
1118
1142
|
Start => 16,
|
1119
1143
|
},
|
1120
1144
|
},
|
1145
|
+
{
|
1146
|
+
Name => 'GarminGPS',
|
1147
|
+
Condition => '$$valPt=~/^\x9b\x63\x0f\x8d\x63\x74\x40\xec\x82\x04\xbc\x5f\xf5\x09\x17\x28/ and $$self{OPTIONS}{ExtractEmbedded}',
|
1148
|
+
SubDirectory => {
|
1149
|
+
TagTable => 'Image::ExifTool::QuickTime::Stream',
|
1150
|
+
ProcessProc => \&ProcessGarminGPS,
|
1151
|
+
},
|
1152
|
+
},
|
1153
|
+
{
|
1154
|
+
Name => 'GarminGPS',
|
1155
|
+
Condition => '$$valPt=~/^\x9b\x63\x0f\x8d\x63\x74\x40\xec\x82\x04\xbc\x5f\xf5\x09\x17\x28/',
|
1156
|
+
Notes => 'Garmin GPS sensor data',
|
1157
|
+
RawConv => q{
|
1158
|
+
$self->WarnOnce('Use the ExtractEmbedded option to decode timed Garmin GPS',3);
|
1159
|
+
return \$val;
|
1160
|
+
},
|
1161
|
+
},
|
1121
1162
|
{
|
1122
1163
|
Name => 'UUID-Unknown',
|
1123
1164
|
%unknownInfo,
|
@@ -2732,7 +2773,7 @@ my %eeBox2 = (
|
|
2732
2773
|
},
|
2733
2774
|
},{
|
2734
2775
|
Name => 'ColorRepresentation',
|
2735
|
-
|
2776
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ColorRep' },
|
2736
2777
|
}],
|
2737
2778
|
irot => {
|
2738
2779
|
Name => 'Rotation',
|
@@ -2792,6 +2833,78 @@ my %eeBox2 = (
|
|
2792
2833
|
},
|
2793
2834
|
);
|
2794
2835
|
|
2836
|
+
# ref https://aomediacodec.github.io/av1-spec/av1-spec.pdf
|
2837
|
+
%Image::ExifTool::QuickTime::ColorRep = (
|
2838
|
+
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
2839
|
+
GROUPS => { 2 => 'Video' },
|
2840
|
+
FIRST_ENTRY => 0,
|
2841
|
+
0 => { Name => 'ColorProfiles', Format => 'undef[4]' },
|
2842
|
+
4 => {
|
2843
|
+
Name => 'ColorPrimaries',
|
2844
|
+
Format => 'int16u',
|
2845
|
+
PrintConv => {
|
2846
|
+
1 => 'BT.709',
|
2847
|
+
2 => 'Unspecified',
|
2848
|
+
4 => 'BT.470 System M (historical)',
|
2849
|
+
5 => 'BT.470 System B, G (historical)',
|
2850
|
+
6 => 'BT.601',
|
2851
|
+
7 => 'SMPTE 240',
|
2852
|
+
8 => 'Generic film (color filters using illuminant C)',
|
2853
|
+
9 => 'BT.2020, BT.2100',
|
2854
|
+
10 => 'SMPTE 428 (CIE 1921 XYZ)',
|
2855
|
+
11 => 'SMPTE RP 431-2',
|
2856
|
+
12 => 'SMPTE EG 432-1',
|
2857
|
+
22 => 'EBU Tech. 3213-E',
|
2858
|
+
},
|
2859
|
+
},
|
2860
|
+
6 => {
|
2861
|
+
Name => 'TransferCharacteristics',
|
2862
|
+
Format => 'int16u',
|
2863
|
+
PrintConv => {
|
2864
|
+
0 => 'For future use (0)',
|
2865
|
+
1 => 'BT.709',
|
2866
|
+
2 => 'Unspecified',
|
2867
|
+
3 => 'For future use (3)',
|
2868
|
+
4 => 'BT.470 System M (historical)',
|
2869
|
+
5 => 'BT.470 System B, G (historical)',
|
2870
|
+
6 => 'BT.601',
|
2871
|
+
7 => 'SMPTE 240 M',
|
2872
|
+
8 => 'Linear',
|
2873
|
+
9 => 'Logarithmic (100 : 1 range)',
|
2874
|
+
10 => 'Logarithmic (100 * Sqrt(10) : 1 range)',
|
2875
|
+
11 => 'IEC 61966-2-4',
|
2876
|
+
12 => 'BT.1361',
|
2877
|
+
13 => 'sRGB or sYCC',
|
2878
|
+
14 => 'BT.2020 10-bit systems',
|
2879
|
+
15 => 'BT.2020 12-bit systems',
|
2880
|
+
16 => 'SMPTE ST 2084, ITU BT.2100 PQ',
|
2881
|
+
17 => 'SMPTE ST 428',
|
2882
|
+
18 => 'BT.2100 HLG, ARIB STD-B67',
|
2883
|
+
},
|
2884
|
+
},
|
2885
|
+
8 => {
|
2886
|
+
Name => 'MatrixCoefficients',
|
2887
|
+
Format => 'int16u',
|
2888
|
+
PrintConv => {
|
2889
|
+
0 => 'Identity matrix',
|
2890
|
+
1 => 'BT.709',
|
2891
|
+
2 => 'Unspecified',
|
2892
|
+
3 => 'For future use (3)',
|
2893
|
+
4 => 'US FCC 73.628',
|
2894
|
+
5 => 'BT.470 System B, G (historical)',
|
2895
|
+
6 => 'BT.601',
|
2896
|
+
7 => 'SMPTE 240 M',
|
2897
|
+
8 => 'YCgCo',
|
2898
|
+
9 => 'BT.2020 non-constant luminance, BT.2100 YCbCr',
|
2899
|
+
10 => 'BT.2020 constant luminance',
|
2900
|
+
11 => 'SMPTE ST 2085 YDzDx',
|
2901
|
+
12 => 'Chromaticity-derived non-constant luminance',
|
2902
|
+
13 => 'Chromaticity-derived constant luminance',
|
2903
|
+
14 => 'BT.2100 ICtCp',
|
2904
|
+
},
|
2905
|
+
},
|
2906
|
+
);
|
2907
|
+
|
2795
2908
|
# HEVC configuration (ref https://github.com/MPEGGroup/isobmff/blob/master/IsoLib/libisomediafile/src/HEVCConfigAtom.c)
|
2796
2909
|
%Image::ExifTool::QuickTime::HEVCConfig = (
|
2797
2910
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
@@ -7516,6 +7629,12 @@ my %eeBox2 = (
|
|
7516
7629
|
Format => 'undef[4]',
|
7517
7630
|
RawConv => '$$self{MetaFormat} = $val',
|
7518
7631
|
},
|
7632
|
+
8 => { # starts at 8 for MetaFormat eq 'camm', and 17 for 'mett'
|
7633
|
+
Name => 'MetaType',
|
7634
|
+
Format => 'undef[$size-8]',
|
7635
|
+
# may start at various locations!
|
7636
|
+
RawConv => '$$self{MetaType} = ($val=~/(application[^\0]+)/ ? $1 : undef)',
|
7637
|
+
},
|
7519
7638
|
#
|
7520
7639
|
# Observed offsets for child atoms of various MetaFormat types:
|
7521
7640
|
#
|
@@ -7548,6 +7667,11 @@ my %eeBox2 = (
|
|
7548
7667
|
Format => 'undef[4]',
|
7549
7668
|
RawConv => '$$self{MetaFormat} = $val', # (yes, use MetaFormat for this too)
|
7550
7669
|
},
|
7670
|
+
24 => {
|
7671
|
+
Condition => '$$self{MetaFormat} eq "tmcd"',
|
7672
|
+
Name => 'PlaybackFrameRate', # (may differ from recorded FrameRate eg. ../pics/FujiFilmX-H1.mov)
|
7673
|
+
Format => 'rational64u',
|
7674
|
+
},
|
7551
7675
|
#
|
7552
7676
|
# Observed offsets for child atoms of various OtherFormat types:
|
7553
7677
|
#
|
@@ -8000,9 +8124,12 @@ sub AUTOLOAD
|
|
8000
8124
|
# Returns: 9-element rotation matrix as a string (with 0 x/y offsets)
|
8001
8125
|
sub GetRotationMatrix($)
|
8002
8126
|
{
|
8003
|
-
my $ang = 3.
|
8127
|
+
my $ang = 3.14159265358979323846264 * shift() / 180;
|
8004
8128
|
my $cos = cos $ang;
|
8005
8129
|
my $sin = sin $ang;
|
8130
|
+
# round to zero
|
8131
|
+
$cos = 0 if abs($cos) < 1e-12;
|
8132
|
+
$sin = 0 if abs($sin) < 1e-12;
|
8006
8133
|
my $msn = -$sin;
|
8007
8134
|
return "$cos $sin 0 $msn $cos 0 0 0 1";
|
8008
8135
|
}
|
@@ -8583,7 +8710,7 @@ sub HandleItemInfo($)
|
|
8583
8710
|
$et->VPrint(0, "$$et{INDENT}Item $id) '${type}' ($len bytes)\n");
|
8584
8711
|
}
|
8585
8712
|
# get ExifTool name for this item
|
8586
|
-
my $name = { Exif => 'EXIF', 'application/rdf+xml' => 'XMP' }->{$type} || '';
|
8713
|
+
my $name = { Exif => 'EXIF', 'application/rdf+xml' => 'XMP', jpeg => 'PreviewImage' }->{$type} || '';
|
8587
8714
|
my ($warn, $extent);
|
8588
8715
|
$warn = "Can't currently decode encoded $type metadata" if $$item{ContentEncoding};
|
8589
8716
|
$warn = "Can't currently decode protected $type metadata" if $$item{ProtectionIndex};
|
@@ -8660,6 +8787,21 @@ sub HandleItemInfo($)
|
|
8660
8787
|
}
|
8661
8788
|
$subTable = GetTagTable('Image::ExifTool::Exif::Main');
|
8662
8789
|
$proc = \&Image::ExifTool::ProcessTIFF;
|
8790
|
+
} elsif ($name eq 'PreviewImage') {
|
8791
|
+
# take a quick stab at determining the size of the image
|
8792
|
+
# (based on JPEG previews found in Fuji X-H2S HIF images)
|
8793
|
+
my $type = 'PreviewImage';
|
8794
|
+
if ($buff =~ /^.{556}\xff\xc0\0\x11.(.{4})/s) {
|
8795
|
+
my ($h, $w) = unpack('n2', $1);
|
8796
|
+
# (not sure if $h is ever the long dimension, but test it just in case)
|
8797
|
+
if ($w == 160 or $h == 160) {
|
8798
|
+
$type = 'ThumbnailImage';
|
8799
|
+
} elsif ($w == 1920 or $h == 1920) {
|
8800
|
+
$type = 'OtherImage'; # (large preview)
|
8801
|
+
} # (PreviewImage is 640x480)
|
8802
|
+
}
|
8803
|
+
$et->FoundTag($type => $buff);
|
8804
|
+
next;
|
8663
8805
|
} else {
|
8664
8806
|
$start = 0;
|
8665
8807
|
$subTable = GetTagTable('Image::ExifTool::XMP::Main');
|
@@ -9100,12 +9242,13 @@ sub ProcessMOV($$;$)
|
|
9100
9242
|
# temporarily set ExtractEmbedded option for CRX files
|
9101
9243
|
$saveOptions{ExtractEmbedded} = $et->Options(ExtractEmbedded => 1) if $fileType eq 'CRX';
|
9102
9244
|
} else {
|
9103
|
-
$et->SetFileType();
|
9245
|
+
$et->SetFileType(); # MOV
|
9104
9246
|
}
|
9105
9247
|
SetByteOrder('MM');
|
9106
9248
|
$$et{PRIORITY_DIR} = 'XMP'; # have XMP take priority
|
9107
9249
|
}
|
9108
|
-
|
9250
|
+
my $fast = $$et{OPTIONS}{FastScan} || 0;
|
9251
|
+
$$raf{NoBuffer} = 1 if $fast; # disable buffering in FastScan mode
|
9109
9252
|
|
9110
9253
|
my $ee = $$et{OPTIONS}{ExtractEmbedded};
|
9111
9254
|
if ($ee) {
|
@@ -9133,8 +9276,10 @@ sub ProcessMOV($$;$)
|
|
9133
9276
|
$et->VPrint(0,"$$et{INDENT}Tag '${t}' extends to end of file");
|
9134
9277
|
if ($$tagTablePtr{"$tag-size"}) {
|
9135
9278
|
my $pos = $raf->Tell();
|
9136
|
-
$
|
9137
|
-
|
9279
|
+
unless ($fast) {
|
9280
|
+
$raf->Seek(0, 2);
|
9281
|
+
$et->HandleTag($tagTablePtr, "$tag-size", $raf->Tell() - $pos);
|
9282
|
+
}
|
9138
9283
|
$et->HandleTag($tagTablePtr, "$tag-offset", $pos) if $$tagTablePtr{"$tag-offset"};
|
9139
9284
|
}
|
9140
9285
|
}
|
@@ -9237,6 +9382,8 @@ sub ProcessMOV($$;$)
|
|
9237
9382
|
$et->HandleTag($tagTablePtr, "$tag-size", $size);
|
9238
9383
|
$et->HandleTag($tagTablePtr, "$tag-offset", $raf->Tell()) if $$tagTablePtr{"$tag-offset"};
|
9239
9384
|
}
|
9385
|
+
# stop processing at mdat/idat if -fast2 is used
|
9386
|
+
last if $fast > 1 and ($tag eq 'mdat' or $tag eq 'idat');
|
9240
9387
|
# load values only if associated with a tag (or verbose) and not too big
|
9241
9388
|
if ($size > 0x2000000) { # start to get worried above 32 MB
|
9242
9389
|
# check for RIFF trailer (written by Auto-Vox dashcam)
|
@@ -9555,10 +9702,14 @@ ItemID: foreach $id (keys %$items) {
|
|
9555
9702
|
require Image::ExifTool::Font;
|
9556
9703
|
$lang = $Image::ExifTool::Font::ttLang{Macintosh}{$lang};
|
9557
9704
|
}
|
9705
|
+
} else {
|
9706
|
+
# for the default language code of 0x0000, use UTF-8 instead
|
9707
|
+
# of the CharsetQuickTime setting if obviously UTF8
|
9708
|
+
$enc = 'UTF8' if Image::ExifTool::IsUTF8(\$str) > 0;
|
9558
9709
|
}
|
9559
9710
|
# the spec says only "Macintosh text encoding", but
|
9560
9711
|
# allow this to be configured by the user
|
9561
|
-
$enc = $charsetQuickTime;
|
9712
|
+
$enc = $charsetQuickTime unless $enc;
|
9562
9713
|
} else {
|
9563
9714
|
# convert language code to ASCII (ignore read-only bit)
|
9564
9715
|
$lang = UnpackLang($lang);
|
@@ -9599,8 +9750,7 @@ ItemID: foreach $id (keys %$items) {
|
|
9599
9750
|
if (not ref $$vp and length($$vp) <= 65536 and $$vp =~ /[\x80-\xff]/) {
|
9600
9751
|
# the encoding of this is not specified, so use CharsetQuickTime
|
9601
9752
|
# unless the string is valid UTF-8
|
9602
|
-
|
9603
|
-
my $enc = Image::ExifTool::XMP::IsUTF8($vp) > 0 ? 'UTF8' : $charsetQuickTime;
|
9753
|
+
my $enc = Image::ExifTool::IsUTF8($vp) > 0 ? 'UTF8' : $charsetQuickTime;
|
9604
9754
|
$$vp = $et->Decode($$vp, $enc);
|
9605
9755
|
}
|
9606
9756
|
}
|
@@ -27,6 +27,8 @@ sub ProcessFreeGPS2($$$);
|
|
27
27
|
sub Process360Fly($$$);
|
28
28
|
sub ProcessFMAS($$$);
|
29
29
|
|
30
|
+
my $debug; # set to 1 for extra debugging messages
|
31
|
+
|
30
32
|
# QuickTime data types that have ExifTool equivalents
|
31
33
|
# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35)
|
32
34
|
my %qtFmt = (
|
@@ -80,7 +82,7 @@ my %processByMetaFormat = (
|
|
80
82
|
|
81
83
|
# data lengths for each INSV record type
|
82
84
|
my %insvDataLen = (
|
83
|
-
0x300 =>
|
85
|
+
0x300 => 0, # accelerometer (could be either 20 or 56 bytes)
|
84
86
|
0x400 => 16, # exposure (ref 6)
|
85
87
|
0x600 => 8, # timestamps (ref 6)
|
86
88
|
0x700 => 53, # GPS
|
@@ -99,7 +101,7 @@ my %insvLimit = (
|
|
99
101
|
The tags below are extracted from timed metadata in QuickTime and other
|
100
102
|
formats of video files when the ExtractEmbedded option is used. Although
|
101
103
|
most of these tags are combined into the single table below, ExifTool
|
102
|
-
currently reads
|
104
|
+
currently reads 62 different formats of timed GPS metadata from video files.
|
103
105
|
},
|
104
106
|
VARS => { NO_ID => 1 },
|
105
107
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
@@ -896,10 +898,15 @@ sub Process_text($$$)
|
|
896
898
|
my $time = "$1:$2:$3";
|
897
899
|
if ($$et{LastTime}) {
|
898
900
|
if ($$et{LastTime} eq $time) {
|
901
|
+
# combine with the previous NMEA sentence
|
899
902
|
$$et{DOC_NUM} = $$et{LastDoc};
|
900
903
|
} elsif (%tags) {
|
904
|
+
# handle existing tags and start a new document
|
905
|
+
# (see https://exiftool.org/forum/index.php?msg=75422)
|
901
906
|
HandleTextTags($et, $tagTbl, \%tags);
|
902
|
-
|
907
|
+
undef %tags;
|
908
|
+
# increment document number and update document count if necessary
|
909
|
+
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
903
910
|
}
|
904
911
|
}
|
905
912
|
$$et{LastTime} = $time;
|
@@ -918,7 +925,8 @@ sub Process_text($$$)
|
|
918
925
|
$$et{DOC_NUM} = $$et{LastDoc};
|
919
926
|
} elsif (%tags) {
|
920
927
|
HandleTextTags($et, $tagTbl, \%tags);
|
921
|
-
|
928
|
+
undef %tags;
|
929
|
+
$$et{DOC_COUNT} < ++$$et{DOC_NUM} and $$et{DOC_COUNT} = $$et{DOC_NUM};
|
922
930
|
}
|
923
931
|
}
|
924
932
|
$$et{LastTime} = $time;
|
@@ -1416,6 +1424,7 @@ sub ProcessFreeGPS($$$)
|
|
1416
1424
|
} elsif ($buf2 =~ /^.{173}([-+]\d{3})([-+]\d{3})([-+]\d{3})/s) { # (Azdome)
|
1417
1425
|
@acc = ($1/100, $2/100, $3/100);
|
1418
1426
|
}
|
1427
|
+
$debug and $et->FoundTag(GPSType => '1A');
|
1419
1428
|
|
1420
1429
|
} elsif ($$dataPt =~ /^.{52}(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/s) {
|
1421
1430
|
|
@@ -1444,6 +1453,7 @@ sub ProcessFreeGPS($$$)
|
|
1444
1453
|
# change to signed integer and divide by 256
|
1445
1454
|
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
1446
1455
|
}
|
1456
|
+
$debug and $et->FoundTag(GPSType => '1B');
|
1447
1457
|
|
1448
1458
|
} elsif ($$dataPt =~ /^.{37}\0\0\0A([NS])([EW])/s) {
|
1449
1459
|
|
@@ -1454,13 +1464,27 @@ sub ProcessFreeGPS($$$)
|
|
1454
1464
|
# 0030: f1 47 40 46 66 66 d2 41 85 eb 83 41 00 00 00 00 [.G@Fff.A...A....]
|
1455
1465
|
($latRef, $lonRef) = ($1, $2);
|
1456
1466
|
($hr,$min,$sec,$yr,$mon,$day) = unpack('x16V6', $$dataPt);
|
1457
|
-
$yr
|
1467
|
+
if ($yr < 2000) {
|
1468
|
+
$yr += 2000;
|
1469
|
+
} else {
|
1470
|
+
# Kenwood dashcam sometimes stores absolute year and local time
|
1471
|
+
# (but sometimes year since 2000 and UTC time in same video!)
|
1472
|
+
require Time::Local;
|
1473
|
+
my $time = Image::ExifTool::TimeLocal($sec,$min,$hr,$day,$mon-1,$yr-1900);
|
1474
|
+
($sec,$min,$hr,$day,$mon,$yr) = gmtime($time);
|
1475
|
+
$yr += 1900;
|
1476
|
+
++$mon;
|
1477
|
+
$et->WarnOnce('Converting GPSDateTime to UTC based on local time zone',1);
|
1478
|
+
}
|
1458
1479
|
SetByteOrder('II');
|
1459
1480
|
$lat = GetFloat($dataPt, 0x2c);
|
1460
1481
|
$lon = GetFloat($dataPt, 0x30);
|
1461
1482
|
$spd = GetFloat($dataPt, 0x34) * $knotsToKph; # (convert knots to km/h)
|
1462
1483
|
$trk = GetFloat($dataPt, 0x38);
|
1484
|
+
@acc = unpack('x60V3', $$dataPt); # (may be all zeros if not valid)
|
1485
|
+
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc;
|
1463
1486
|
SetByteOrder('MM');
|
1487
|
+
$debug and $et->FoundTag(GPSType => '1C');
|
1464
1488
|
|
1465
1489
|
} elsif ($$dataPt =~ /^.{21}\0\0\0A([NS])([EW])/s) {
|
1466
1490
|
|
@@ -1489,6 +1513,7 @@ sub ProcessFreeGPS($$$)
|
|
1489
1513
|
$acc[1] = GetFloat($dataPt, 0x30);
|
1490
1514
|
$acc[2] = GetFloat($dataPt, 0x34);
|
1491
1515
|
SetByteOrder('MM');
|
1516
|
+
$debug and $et->FoundTag(GPSType => '1D');
|
1492
1517
|
|
1493
1518
|
} elsif ($$dataPt =~ /^.{60}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s) {
|
1494
1519
|
|
@@ -1509,6 +1534,7 @@ sub ProcessFreeGPS($$$)
|
|
1509
1534
|
$trk = GetFloat($dataPt, 0x54) + 180; # (why is this off by 180?)
|
1510
1535
|
$trk -= 360 if $trk >= 360;
|
1511
1536
|
SetByteOrder('MM');
|
1537
|
+
$debug and $et->FoundTag(GPSType => '1E');
|
1512
1538
|
|
1513
1539
|
} elsif ($$dataPt =~ /^.{60}4W`b]S</s and length($$dataPt) >= 140) {
|
1514
1540
|
|
@@ -1526,8 +1552,9 @@ sub ProcessFreeGPS($$$)
|
|
1526
1552
|
$yr += ($yr >= 70 ? 1900 : 2000);
|
1527
1553
|
$spd = $9 * $knotsToKph if length $9;
|
1528
1554
|
$trk = $10 if length $10;
|
1555
|
+
$debug and $et->FoundTag(GPSType => '1F');
|
1529
1556
|
|
1530
|
-
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0/s) {
|
1557
|
+
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0{5}/s) {
|
1531
1558
|
|
1532
1559
|
# Akaso V1 dascham
|
1533
1560
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 00 00 00 [....freeGPS x...]
|
@@ -1569,6 +1596,7 @@ sub ProcessFreeGPS($$$)
|
|
1569
1596
|
|
1570
1597
|
SetByteOrder('MM');
|
1571
1598
|
#my $serialNum = substr($$dataPt, 0x68, 20);
|
1599
|
+
$debug and $et->FoundTag(GPSType => '1G');
|
1572
1600
|
|
1573
1601
|
} elsif ($$dataPt =~ /^.{12}\xac\0\0\0.{44}(.{72})/s) {
|
1574
1602
|
|
@@ -1591,6 +1619,7 @@ sub ProcessFreeGPS($$$)
|
|
1591
1619
|
# bytes 7-12 are the timestamp in ASCII HHMMSS after xor-ing with 0x70
|
1592
1620
|
substr($time,7,6) = pack 'C*', map { $_ ^= 0x70 } unpack 'C*', substr($time,7,6);
|
1593
1621
|
# (other values are currently unknown)
|
1622
|
+
$debug and $et->FoundTag(GPSType => '1H');
|
1594
1623
|
|
1595
1624
|
} elsif ($$dataPt =~ /^.{64}A([NS])([EW])\0/s) {
|
1596
1625
|
|
@@ -1616,6 +1645,7 @@ sub ProcessFreeGPS($$$)
|
|
1616
1645
|
$trk = GetFloat($dataPt, 0x68);
|
1617
1646
|
$alt = GetFloat($dataPt, 0x6c);
|
1618
1647
|
SetByteOrder('MM');
|
1648
|
+
$debug and $et->FoundTag(GPSType => '1I');
|
1619
1649
|
|
1620
1650
|
} else {
|
1621
1651
|
|
@@ -1624,6 +1654,9 @@ sub ProcessFreeGPS($$$)
|
|
1624
1654
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...]
|
1625
1655
|
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
1626
1656
|
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
1657
|
+
# 0030: 10 00 00 00 2d 00 00 00 14 00 00 00 11 00 00 00 [....-...........]
|
1658
|
+
# 0040: 0c 00 00 00 1f 00 00 00 41 4e 45 00 5d 9a a9 45 [........ANE.]..E]
|
1659
|
+
# 0050: ab 1e e5 44 ec 51 f0 40 b8 5e a5 43 00 00 00 00 [...D.Q.@.^.C....]
|
1627
1660
|
# (records are same structure as Type 3 Novatek GPS in ProcessFreeGPS2() below)
|
1628
1661
|
($hr,$min,$sec,$yr,$mon,$day,$stat,$latRef,$lonRef,$lat,$lon,$spd,$trk) =
|
1629
1662
|
unpack('x48V6a1a1a1x1V4', $$dataPt);
|
@@ -1649,6 +1682,7 @@ sub ProcessFreeGPS($$$)
|
|
1649
1682
|
$yr += 2000 if $yr < 2000;
|
1650
1683
|
$spd *= $knotsToKph; # convert speed to km/h
|
1651
1684
|
# ($trk is not confirmed; may be GPSImageDirection, ref PH)
|
1685
|
+
$debug and $et->FoundTag(GPSType => '1J');
|
1652
1686
|
}
|
1653
1687
|
#
|
1654
1688
|
# save tag values extracted by above code
|
@@ -1802,6 +1836,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1802
1836
|
}
|
1803
1837
|
# save position of most recent record (needed when parsing the next freeGPS block)
|
1804
1838
|
$$et{FreeGPS2}{RecentRecPos} = $lastRecPos;
|
1839
|
+
$debug and $et->FoundTag(GPSType => '2A');
|
1805
1840
|
return 1;
|
1806
1841
|
|
1807
1842
|
} elsif ($$dataPt =~ /^.{60}A\0.{10}([NS])\0.{14}([EW])\0/s) {
|
@@ -1833,6 +1868,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1833
1868
|
$lon = GetDouble($dataPt, 0x50);
|
1834
1869
|
$spd = GetDouble($dataPt, 0x60) * $knotsToKph;
|
1835
1870
|
$trk = GetDouble($dataPt, 0x68);
|
1871
|
+
$debug and $et->FoundTag(GPSType => '2B');
|
1836
1872
|
|
1837
1873
|
} elsif ($$dataPt =~ /^.{72}A([NS])([EW])/s) {
|
1838
1874
|
|
@@ -1869,6 +1905,8 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1869
1905
|
$lon = abs Get32s($dataPt, 0x50) / 1e7;
|
1870
1906
|
$spd = Get32s($dataPt, 0x54) / 100 * $mpsToKph;
|
1871
1907
|
$alt = GetFloat($dataPt, 0x58) / 1000; # (NC)
|
1908
|
+
$debug and $et->FoundTag(GPSType => '2C');
|
1909
|
+
|
1872
1910
|
} else {
|
1873
1911
|
# Type 3 (ref 2)
|
1874
1912
|
# (no sample with this format)
|
@@ -1876,6 +1914,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1876
1914
|
$lon = GetFloat($dataPt, 0x50);
|
1877
1915
|
$spd = GetFloat($dataPt, 0x54) * $knotsToKph;
|
1878
1916
|
$trk = GetFloat($dataPt, 0x58);
|
1917
|
+
$debug and $et->FoundTag(GPSType => '2D');
|
1879
1918
|
}
|
1880
1919
|
|
1881
1920
|
} elsif ($$dataPt =~ /^.{60}A\0.{6}([NS])\0.{6}([EW])\0/s and $dirLen >= 112) {
|
@@ -1896,6 +1935,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1896
1935
|
$lon = GetFloat($dataPt, 0x48);
|
1897
1936
|
$spd = GetFloat($dataPt, 0x50);
|
1898
1937
|
$trk = GetFloat($dataPt, 0x54);
|
1938
|
+
$debug and $et->FoundTag(GPSType => '2E');
|
1899
1939
|
|
1900
1940
|
} elsif ($$dataPt =~ /^.{16}A([NS])([EW])\0/s) {
|
1901
1941
|
|
@@ -1916,6 +1956,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1916
1956
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
1917
1957
|
$et->HandleTag($tagTbl, Accelerometer => "@acc");
|
1918
1958
|
}
|
1959
|
+
$debug and $et->FoundTag(GPSType => '2F');
|
1919
1960
|
return 1;
|
1920
1961
|
|
1921
1962
|
} else {
|
@@ -1962,6 +2003,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
1962
2003
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
1963
2004
|
last if $pos += 0x20 > length($$dataPt) - 0x1e;
|
1964
2005
|
}
|
2006
|
+
$debug and $et->FoundTag(GPSType => '2G');
|
1965
2007
|
return $$et{DOC_NUM} ? 1 : 0; # return 0 if nothing extracted
|
1966
2008
|
}
|
1967
2009
|
#
|
@@ -2530,7 +2572,7 @@ sub ProcessTTAD($$$)
|
|
2530
2572
|
# (I think "5" may be the number of satellites. seen: 5,6,7 - PH)
|
2531
2573
|
FoundSomething($et, $tagTbl, $sampleTime / 1000);
|
2532
2574
|
my $t = GetDouble($dataPt, $pos);
|
2533
|
-
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3).'Z');
|
2575
|
+
$et->HandleTag($tagTbl, GPSDateTime => Image::ExifTool::ConvertUnixTime($t,undef,3) . 'Z');
|
2534
2576
|
$et->HandleTag($tagTbl, GPSLatitude => GetDouble($dataPt, $pos+0x1c));
|
2535
2577
|
$et->HandleTag($tagTbl, GPSLongitude => GetDouble($dataPt, $pos+0x24));
|
2536
2578
|
$et->HandleTag($tagTbl, GPSAltitude => GetDouble($dataPt, $pos+0x14));
|
@@ -2621,8 +2663,33 @@ sub ProcessInsta360($;$)
|
|
2621
2663
|
if ($verbose) {
|
2622
2664
|
$et->VPrint(0, sprintf("Insta360 Record 0x%x (offset 0x%x, %d bytes):\n", $id, $fileEnd + $epos, $len));
|
2623
2665
|
}
|
2666
|
+
# there are 2 types of record 0x300:
|
2667
|
+
# 1. 56 byte records
|
2668
|
+
# 0000: 4a f7 02 00 00 00 00 00 00 00 00 00 00 1e e7 3f [J..............?]
|
2669
|
+
# 0010: 00 00 00 00 00 b2 ef bf 00 00 00 00 00 70 c1 bf [.............p..]
|
2670
|
+
# 0020: 00 00 00 e0 91 5c 8c bf 00 00 00 20 8f ff 87 bf [.....\..... ....]
|
2671
|
+
# 0030: 00 00 00 00 88 7f c9 bf
|
2672
|
+
# 2. 20 byte records
|
2673
|
+
# 0000: c1 d8 d9 0b 00 00 00 00 f5 83 14 80 df 7f fe 7f [................]
|
2674
|
+
# 0010: fe 7f 01 80
|
2675
|
+
if ($id == 0x300) {
|
2676
|
+
if ($len % 20 and not $len % 56) {
|
2677
|
+
$dlen = 56;
|
2678
|
+
} elsif ($len % 56 and not $len % 20) {
|
2679
|
+
$dlen = 20;
|
2680
|
+
} else {
|
2681
|
+
if ($raf->Read($buff, 20) == 20) {
|
2682
|
+
if (substr($buff, 16, 3) eq "\0\0\0") {
|
2683
|
+
$dlen = 56;
|
2684
|
+
} else {
|
2685
|
+
$dlen = 20;
|
2686
|
+
}
|
2687
|
+
}
|
2688
|
+
$raf->Seek($epos, 2) or last;
|
2689
|
+
}
|
2690
|
+
}
|
2624
2691
|
# limit the number of records we read if necessary
|
2625
|
-
if ($insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
|
2692
|
+
if ($dlen and $insvLimit{$id} and $len > $insvLimit{$id}[1] * $dlen and
|
2626
2693
|
$et->Warn("Insta360 $insvLimit{$id}[0] data is huge. Processing only the first $insvLimit{$id}[1] records",2))
|
2627
2694
|
{
|
2628
2695
|
$len = $insvLimit{$id}[1] * $dlen;
|
@@ -2630,11 +2697,18 @@ sub ProcessInsta360($;$)
|
|
2630
2697
|
$raf->Read($buff, $len) == $len or last;
|
2631
2698
|
$et->VerboseDump(\$buff) if $verbose > 2;
|
2632
2699
|
if ($dlen) {
|
2633
|
-
$len % $dlen
|
2634
|
-
|
2700
|
+
if ($len % $dlen) {
|
2701
|
+
$et->Warn(sprintf('Unexpected Insta360 record 0x%x length',$id));
|
2702
|
+
} elsif ($id == 0x300) {
|
2635
2703
|
for ($p=0; $p<$len; $p+=$dlen) {
|
2636
2704
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
2637
|
-
my @a
|
2705
|
+
my @a;
|
2706
|
+
if ($dlen == 56) {
|
2707
|
+
@a = map { GetDouble(\$buff, $p + 8 * $_) } 1..6;
|
2708
|
+
} else {
|
2709
|
+
@a = unpack("x${p}x8v6", $buff);
|
2710
|
+
map { $_ = ($_ - 0x8000) / 1000 } @a;
|
2711
|
+
}
|
2638
2712
|
$et->HandleTag($tagTbl, TimeCode => sprintf('%.3f', Get64u(\$buff, $p) / 1000));
|
2639
2713
|
$et->HandleTag($tagTbl, Accelerometer => "@a[0..2]"); # (NC)
|
2640
2714
|
$et->HandleTag($tagTbl, AngularVelocity => "@a[3..5]"); # (NC)
|
@@ -2699,6 +2773,38 @@ sub ProcessInsta360($;$)
|
|
2699
2773
|
return 1;
|
2700
2774
|
}
|
2701
2775
|
|
2776
|
+
#------------------------------------------------------------------------------
|
2777
|
+
# Process Garmin GPS 'uuid' atom (ref PH)
|
2778
|
+
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
2779
|
+
# Returns: 1 on success
|
2780
|
+
# Note: This format is used by the Garmin DriveAssist 51, but the DriveAssist 50
|
2781
|
+
# uses a completely different format. :(
|
2782
|
+
sub ProcessGarminGPS($$$)
|
2783
|
+
{
|
2784
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
2785
|
+
my $dataPt = $$dirInfo{DataPt};
|
2786
|
+
my $dataLen = length $$dataPt;
|
2787
|
+
my $pos = 33;
|
2788
|
+
my $epoch = (66 * 365 + 17) * 24 * 3600; # time is relative to Jan 1, 1904
|
2789
|
+
my $scl = 180 / (32768 * 65536); # scaling factor for lat/lon
|
2790
|
+
$et->VerboseDir('GarminGPS');
|
2791
|
+
while ($pos + 20 <= $dataLen) {
|
2792
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
2793
|
+
my $time = Image::ExifTool::ConvertUnixTime(Get32u($dataPt, $pos) - $epoch) . 'Z';
|
2794
|
+
my $lat = Get32s($dataPt, $pos + 12) * $scl;
|
2795
|
+
my $lon = Get32s($dataPt, $pos + 16) * $scl;
|
2796
|
+
my $spd = Get16u($dataPt, $pos + 4); # (in mph)
|
2797
|
+
$et->HandleTag($tagTbl, 'GPSDateTime', $time);
|
2798
|
+
$et->HandleTag($tagTbl, 'GPSLatitude', $lat);
|
2799
|
+
$et->HandleTag($tagTbl, 'GPSLongitude', $lon);
|
2800
|
+
$et->HandleTag($tagTbl, 'GPSSpeed', $spd);
|
2801
|
+
$et->HandleTag($tagTbl, 'GPSSpeedRef', 'M');
|
2802
|
+
$pos += 20;
|
2803
|
+
}
|
2804
|
+
delete $$et{DOC_NUM};
|
2805
|
+
return 1;
|
2806
|
+
}
|
2807
|
+
|
2702
2808
|
#------------------------------------------------------------------------------
|
2703
2809
|
# Process 360Fly 'uuid' atom containing sensor data
|
2704
2810
|
# (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
|
@@ -2776,9 +2882,9 @@ sub ScanMediaData($)
|
|
2776
2882
|
my ($pos, $buf2) = (0, '');
|
2777
2883
|
|
2778
2884
|
# don't rescan for freeGPS if we already found embedded metadata
|
2779
|
-
my $dataPos = $$et{
|
2885
|
+
my $dataPos = $$et{MediaDataOffset};
|
2780
2886
|
if ($dataPos and not $$et{DOC_COUNT}) {
|
2781
|
-
$dataLen = $$et{
|
2887
|
+
$dataLen = $$et{MediaDataSize};
|
2782
2888
|
if ($dataLen) {
|
2783
2889
|
if ($raf->Seek($dataPos, 0)) {
|
2784
2890
|
$$et{FreeGPS2} = { }; # initialize variable space for FreeGPS2()
|