exiftool-vendored.exe 12.99.0 → 13.16.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.
- package/bin/exiftool.exe +0 -0
- package/bin/exiftool_files/exiftool.pl +183 -70
- package/bin/exiftool_files/lib/File/RandomAccess.pm +1 -1
- package/bin/exiftool_files/lib/File/RandomAccess.pod +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/AAC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/AES.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/AFCP.pm +6 -6
- package/bin/exiftool_files/lib/Image/ExifTool/AIFF.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/APE.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/APP12.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ASF.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Apple.pm +11 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Audible.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BMP.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BPG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BZZ.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BigTIFF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +36 -22
- package/bin/exiftool_files/lib/Image/ExifTool/CBOR.pm +5 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +66 -27
- package/bin/exiftool_files/lib/Image/ExifTool/CanonCustom.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CanonRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CanonVRD.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CaptureOne.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Casio.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Charset.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DICOM.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DJI.pm +196 -30
- package/bin/exiftool_files/lib/Image/ExifTool/DNG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DPX.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DV.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DarwinCore.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/DjVu.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/EXE.pm +138 -33
- package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +30 -17
- package/bin/exiftool_files/lib/Image/ExifTool/FITS.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/FLAC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/FLIF.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/FLIR.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Fixup.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Flash.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/FlashPix.pm +17 -21
- package/bin/exiftool_files/lib/Image/ExifTool/Font.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/FotoStation.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GE.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GIF.pm +144 -93
- package/bin/exiftool_files/lib/Image/ExifTool/GIMP.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GM.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/GPS.pm +34 -30
- package/bin/exiftool_files/lib/Image/ExifTool/GeoTiff.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Geolocation.dat +0 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Geolocation.pm +19 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +49 -14
- package/bin/exiftool_files/lib/Image/ExifTool/GoPro.pm +120 -8
- package/bin/exiftool_files/lib/Image/ExifTool/H264.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/HP.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/HTML.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/HtmlDump.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ICC_Profile.pm +81 -2
- package/bin/exiftool_files/lib/Image/ExifTool/ICO.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ID3.pm +8 -8
- package/bin/exiftool_files/lib/Image/ExifTool/IPTC.pm +10 -7
- package/bin/exiftool_files/lib/Image/ExifTool/ISO.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/ITC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Import.pm +5 -4
- package/bin/exiftool_files/lib/Image/ExifTool/InDesign.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/InfiRay.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JPEG.pm +32 -5
- package/bin/exiftool_files/lib/Image/ExifTool/JPEGDigest.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JSON.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/JVC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +10 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Kodak.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/LIF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/LNK.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/cs.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/de.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/en_ca.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/en_gb.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/es.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/fi.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/fr.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/it.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/ja.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/ko.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/nl.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/pl.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/ru.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/sk.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/sv.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/tr.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Leaf.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/LigoGPS.pm +409 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Lytro.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/M2TS.pm +58 -19
- package/bin/exiftool_files/lib/Image/ExifTool/MIE.pm +15 -6
- package/bin/exiftool_files/lib/Image/ExifTool/MIEUnits.pod +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MIFF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MISB.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MNG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MOI.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MPC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MPEG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MPF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MRC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MWG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MXF.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/MacOS.pm +3 -2
- package/bin/exiftool_files/lib/Image/ExifTool/MakerNotes.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Matroska.pm +22 -6
- package/bin/exiftool_files/lib/Image/ExifTool/Microsoft.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Minolta.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Motorola.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +495 -39
- package/bin/exiftool_files/lib/Image/ExifTool/NikonCapture.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/NikonCustom.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/NikonSettings.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Nintendo.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/OOXML.pm +8 -8
- package/bin/exiftool_files/lib/Image/ExifTool/Ogg.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Olympus.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/OpenEXR.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Opus.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Other.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PCX.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PDF.pm +49 -18
- package/bin/exiftool_files/lib/Image/ExifTool/PGF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PICT.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PLIST.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/PLUS.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +20 -8
- package/bin/exiftool_files/lib/Image/ExifTool/PPM.pm +12 -3
- package/bin/exiftool_files/lib/Image/ExifTool/PSP.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Palm.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Panasonic.pm +27 -3
- package/bin/exiftool_files/lib/Image/ExifTool/PanasonicRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Parrot.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Pentax.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PhaseOne.pm +6 -5
- package/bin/exiftool_files/lib/Image/ExifTool/PhotoCD.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Photoshop.pm +65 -4
- package/bin/exiftool_files/lib/Image/ExifTool/PostScript.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PrintIM.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Protobuf.pm +270 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Qualcomm.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +326 -88
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +266 -200
- package/bin/exiftool_files/lib/Image/ExifTool/README +12 -2
- package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +21 -6
- package/bin/exiftool_files/lib/Image/ExifTool/RSRC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/RTF.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Radiance.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Rawzor.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Real.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Reconyx.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Red.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Ricoh.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Sanyo.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Scalado.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Shift.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Shortcuts.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Sigma.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/SigmaRaw.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +5 -4
- package/bin/exiftool_files/lib/Image/ExifTool/SonyIDC.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Stim.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/TagInfoXML.pm +6 -5
- package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +7025 -6967
- package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +477 -46
- package/bin/exiftool_files/lib/Image/ExifTool/Text.pm +4 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Theora.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Torrent.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Unknown.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/VCard.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +6 -6
- package/bin/exiftool_files/lib/Image/ExifTool/Vivo.pm +124 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Vorbis.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WPG.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WTV.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/WriteIPTC.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePDF.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePNG.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WritePostScript.pl +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +166 -79
- package/bin/exiftool_files/lib/Image/ExifTool/WriteRIFF.pl +17 -6
- package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +89 -96
- package/bin/exiftool_files/lib/Image/ExifTool/XISF.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +39 -14
- package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +103 -1
- package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +2 -3
- package/bin/exiftool_files/lib/Image/ExifTool/ZIP.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/ZISRAW.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool/iWork.pm +1 -1
- package/bin/exiftool_files/lib/Image/ExifTool.pm +338 -166
- package/bin/exiftool_files/lib/Image/ExifTool.pod +119 -73
- package/bin/exiftool_files/readme_windows.txt +8 -13
- package/bin/exiftool_files/windows_exiftool.txt +102 -53
- package/package.json +11 -11
|
@@ -29,6 +29,7 @@ sub Process360Fly($$$);
|
|
|
29
29
|
sub ProcessFMAS($$$);
|
|
30
30
|
sub ProcessWolfbox($$$);
|
|
31
31
|
sub ProcessCAMM($$$);
|
|
32
|
+
sub OrderCipherDigits($$$;$);
|
|
32
33
|
|
|
33
34
|
# QuickTime data types that have ExifTool equivalents
|
|
34
35
|
# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35)
|
|
@@ -94,6 +95,7 @@ my %insvDataLen = (
|
|
|
94
95
|
# 0xb00 => 10, # ? (Insta360 X3)
|
|
95
96
|
# 0xd00 => 10, # ? (Insta360 Ace Pro)
|
|
96
97
|
# 0x1200 ? # ? (Insta360 Ace Pro)
|
|
98
|
+
# 0x1600 ? # ? (?)
|
|
97
99
|
);
|
|
98
100
|
|
|
99
101
|
# limit the default amount of data we read for some record types
|
|
@@ -109,7 +111,7 @@ my %insvLimit = (
|
|
|
109
111
|
The tags below are extracted from timed metadata in QuickTime and other
|
|
110
112
|
formats of video files when the ExtractEmbedded option is used. Although
|
|
111
113
|
most of these tags are combined into the single table below, ExifTool
|
|
112
|
-
currently reads
|
|
114
|
+
currently reads 100 different types of timed GPS metadata from video files.
|
|
113
115
|
},
|
|
114
116
|
VARS => { NO_ID => 1 },
|
|
115
117
|
GPSLatitude => { PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', RawConv => '$$self{FoundGPSLatitude} = 1; $val' },
|
|
@@ -145,7 +147,7 @@ my %insvLimit = (
|
|
|
145
147
|
CameraDateTime=>{ PrintConv => '$self->ConvertDateTime($val)', Groups => { 2 => 'Time' } },
|
|
146
148
|
DateTimeStamp =>{ PrintConv => '$self->ConvertDateTime($val)', Groups => { 2 => 'Time' } },
|
|
147
149
|
VideoTimeStamp => { Groups => { 2 => 'Video' } },
|
|
148
|
-
Accelerometer=> { Notes => '3-axis acceleration in units of g' },
|
|
150
|
+
Accelerometer=> { Notes => '3-axis acceleration, usually in units of g' },
|
|
149
151
|
AccelerometerData => { },
|
|
150
152
|
AngularVelocity => { },
|
|
151
153
|
GSensor => { },
|
|
@@ -339,14 +341,21 @@ my %insvLimit = (
|
|
|
339
341
|
Groups => { 2 => 'Preview' },
|
|
340
342
|
RawConv => '$self->ValidateImage(\$val,$tag)',
|
|
341
343
|
},
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
344
|
+
djmd => { # (DJI AC003 Osmo Action 4 cam)
|
|
345
|
+
Name => 'DJIMetadata',
|
|
346
|
+
SubDirectory => { TagTable => 'Image::ExifTool::DJI::Protobuf' },
|
|
347
|
+
},
|
|
348
|
+
dbgi => { # (DJI AC003 Osmo Action 4 cam)
|
|
349
|
+
Name => 'DJIDebug',
|
|
350
|
+
Unknown => 2,
|
|
351
|
+
Notes => 'extracted only if Unknown option is 2 or greater',
|
|
352
|
+
SubDirectory => { TagTable => 'Image::ExifTool::DJI::Protobuf' },
|
|
353
|
+
},
|
|
346
354
|
Unknown00 => { Unknown => 1 },
|
|
347
355
|
Unknown01 => { Unknown => 1 },
|
|
348
356
|
Unknown02 => { Unknown => 1 },
|
|
349
357
|
Unknown03 => { Unknown => 1 },
|
|
358
|
+
MagneticVariation => { }, # (from LIGOGPSINFO)
|
|
350
359
|
);
|
|
351
360
|
|
|
352
361
|
# tags found in 'camm' type 0 timed metadata (ref 4)
|
|
@@ -591,8 +600,8 @@ my %insvLimit = (
|
|
|
591
600
|
GROUPS => { 2 => 'Location' },
|
|
592
601
|
FIRST_ENTRY => 0,
|
|
593
602
|
NOTES => q{
|
|
594
|
-
Tags extracted from the tx3g sbtl timed metadata of Yuneec drones,
|
|
595
|
-
subtitle text in some other videos.
|
|
603
|
+
Tags extracted from the tx3g sbtl timed metadata of Yuneec and Autel drones,
|
|
604
|
+
and subtitle text in some other videos.
|
|
596
605
|
},
|
|
597
606
|
Lat => {
|
|
598
607
|
Name => 'GPSLatitude',
|
|
@@ -619,6 +628,32 @@ my %insvLimit = (
|
|
|
619
628
|
PrintConv => '$self->ConvertDateTime($val)',
|
|
620
629
|
},
|
|
621
630
|
Text => { Groups => { 2 => 'Other' } },
|
|
631
|
+
# the following tags are extracted from Autel Evo II drone videos
|
|
632
|
+
GPSDateTime => {
|
|
633
|
+
Groups => { 2 => 'Time' },
|
|
634
|
+
Description => 'GPS Date/Time',
|
|
635
|
+
PrintConv => '$self->ConvertDateTime($val)',
|
|
636
|
+
},
|
|
637
|
+
HomeLat => {
|
|
638
|
+
Name => 'GPSHomeLatitude',
|
|
639
|
+
RawConv => '$$self{FoundGPSLatitude} = 1; $val',
|
|
640
|
+
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
|
|
641
|
+
},
|
|
642
|
+
HomeLon => {
|
|
643
|
+
Name => 'GPSHomeLongitude',
|
|
644
|
+
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
|
|
645
|
+
},
|
|
646
|
+
ISO => { },
|
|
647
|
+
SHUTTER => {
|
|
648
|
+
Name => 'ExposureTime',
|
|
649
|
+
ValueConv => '1 / $val',
|
|
650
|
+
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
|
|
651
|
+
},
|
|
652
|
+
'F-NUM' => {
|
|
653
|
+
Name => 'FNumber',
|
|
654
|
+
PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
|
|
655
|
+
},
|
|
656
|
+
EV => 'ExposureCompensation',
|
|
622
657
|
);
|
|
623
658
|
|
|
624
659
|
%Image::ExifTool::QuickTime::INSV_MakerNotes = (
|
|
@@ -868,7 +903,7 @@ sub FoundSomething($$;$$)
|
|
|
868
903
|
#------------------------------------------------------------------------------
|
|
869
904
|
# Approximate GPSDateTime value from sample time and CreateDate
|
|
870
905
|
# Inputs: 0) ExifTool ref, 1) tag table ptr, 2) sample time (s)
|
|
871
|
-
# 3) true if CreateDate is
|
|
906
|
+
# 3) true if CreateDate is UTC
|
|
872
907
|
# Notes: Uses ExifTool CreateDateAtEnd as flag to subtract video duration
|
|
873
908
|
sub SetGPSDateTime($$$;$)
|
|
874
909
|
{
|
|
@@ -879,9 +914,9 @@ sub SetGPSDateTime($$$;$)
|
|
|
879
914
|
if ($$et{CreateDateAtEnd}) { # adjust if CreateDate is at end of video
|
|
880
915
|
return unless $$value{TimeScale} and $$value{Duration};
|
|
881
916
|
$sampleTime -= $$value{Duration} / $$value{TimeScale};
|
|
882
|
-
$et->
|
|
917
|
+
$et->Warn('Approximating GPSDateTime as CreateDate - Duration + SampleTime', 1);
|
|
883
918
|
} else {
|
|
884
|
-
$et->
|
|
919
|
+
$et->Warn('Approximating GPSDateTime as CreateDate + SampleTime', 1);
|
|
885
920
|
}
|
|
886
921
|
my $utc = $et->Options('QuickTimeUTC');
|
|
887
922
|
$utc = $isUTC unless defined $utc; # (allow QuickTimeUTC=0 to override $isUTC default)
|
|
@@ -1242,7 +1277,7 @@ sub ProcessSamples($)
|
|
|
1242
1277
|
($startChunk, $samplesPerChunk, $descIdx) = @{shift @$stsc};
|
|
1243
1278
|
$nextChunk = $$stsc[0][0] if @$stsc;
|
|
1244
1279
|
}
|
|
1245
|
-
@$size < @$start + $samplesPerChunk and $et->
|
|
1280
|
+
@$size < @$start + $samplesPerChunk and $et->Warn('Sample size error'), last;
|
|
1246
1281
|
last unless defined $chunkStart and length $chunkStart;
|
|
1247
1282
|
my $sampleStart = $chunkStart;
|
|
1248
1283
|
my $chunkSize = 0;
|
|
@@ -1270,7 +1305,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1270
1305
|
push @chunkSize, $chunkSize;
|
|
1271
1306
|
++$iChunk;
|
|
1272
1307
|
}
|
|
1273
|
-
@$start == @$size or $et->
|
|
1308
|
+
@$start == @$size or $et->Warn('Incorrect sample start/size count'), return;
|
|
1274
1309
|
# process as chunks if we are only interested in calculating hash
|
|
1275
1310
|
if ($type eq 'soun' or $type eq 'vide') {
|
|
1276
1311
|
$start = $stco;
|
|
@@ -1300,7 +1335,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1300
1335
|
$hdrFmt = ($hdrLen == 4 ? 'N' : $hdrLen == 2 ? 'n' : 'C');
|
|
1301
1336
|
require Image::ExifTool::H264;
|
|
1302
1337
|
}
|
|
1303
|
-
|
|
1338
|
+
|
|
1304
1339
|
# loop through all samples
|
|
1305
1340
|
for ($i=0; $i<@$start and $i<@$size; ++$i) {
|
|
1306
1341
|
|
|
@@ -1320,11 +1355,11 @@ Sample: for ($i=0; ; ) {
|
|
|
1320
1355
|
}
|
|
1321
1356
|
}
|
|
1322
1357
|
# read the sample data
|
|
1323
|
-
$raf->Seek($$start[$i], 0) or $et->
|
|
1358
|
+
$raf->Seek($$start[$i], 0) or $et->Warn("Seek error in $type data"), next;
|
|
1324
1359
|
my $buff;
|
|
1325
1360
|
my $n = $raf->Read($buff, $size);
|
|
1326
1361
|
unless ($n == $size) {
|
|
1327
|
-
$et->
|
|
1362
|
+
$et->Warn("Error reading $type data");
|
|
1328
1363
|
next unless $n;
|
|
1329
1364
|
$size = $n;
|
|
1330
1365
|
}
|
|
@@ -1406,7 +1441,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1406
1441
|
|
|
1407
1442
|
if ($$tagTbl{$metaFormat}) {
|
|
1408
1443
|
my $tagInfo = $et->GetTagInfo($tagTbl, $metaFormat, \$buff);
|
|
1409
|
-
if ($tagInfo) {
|
|
1444
|
+
if ($tagInfo and (not $$tagInfo{Unknown} or $$et{OPTIONS}{Unknown} >= $$tagInfo{Unknown})) {
|
|
1410
1445
|
FoundSomething($et, $tagTbl, $time[$i], $dur[$i]);
|
|
1411
1446
|
$$et{ee} = $ee; # need ee information for 'keys'
|
|
1412
1447
|
$et->HandleTag($tagTbl, $metaFormat, undef,
|
|
@@ -1416,6 +1451,15 @@ Sample: for ($i=0; ; ) {
|
|
|
1416
1451
|
TagInfo => $tagInfo,
|
|
1417
1452
|
);
|
|
1418
1453
|
delete $$et{ee};
|
|
1454
|
+
# synthesize GPSDateTime if necessary for djmd metadata
|
|
1455
|
+
if ($metaFormat eq 'djmd') {
|
|
1456
|
+
if (defined $$et{GPSLatitude} and defined $$et{GPSLongitude} and not $$et{GPSDateTime}) {
|
|
1457
|
+
SetGPSDateTime($et, $tagTbl, $time[$i], 1); # (NC)
|
|
1458
|
+
}
|
|
1459
|
+
delete $$et{GPSLatitude};
|
|
1460
|
+
delete $$et{GPSLongitude};
|
|
1461
|
+
delete $$et{GPSDateTime};
|
|
1462
|
+
}
|
|
1419
1463
|
} elsif ($metaFormat eq 'camm' and $buff =~ /^X/) {
|
|
1420
1464
|
# seen 'camm' metadata in this format (X/Y/Z acceleration and G force? + GPRMC + ?)
|
|
1421
1465
|
# "X0000.0000Y0000.0000Z0000.0000G0000.0000$GPRMC,000125,V,,,,,000.0,,280908,002.1,N*71~, 794021 \x0a"
|
|
@@ -1468,7 +1512,7 @@ Sample: for ($i=0; ; ) {
|
|
|
1468
1512
|
# clean up
|
|
1469
1513
|
$raf->Seek($tell, 0); # restore original file position
|
|
1470
1514
|
delete $$et{DOC_NUM};
|
|
1471
|
-
$$et{HandlerType} =
|
|
1515
|
+
$$et{HandlerType} = '';
|
|
1472
1516
|
}
|
|
1473
1517
|
|
|
1474
1518
|
#------------------------------------------------------------------------------
|
|
@@ -1519,7 +1563,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1519
1563
|
my ($et, $dirInfo, $tagTbl) = @_;
|
|
1520
1564
|
my $dataPt = $$dirInfo{DataPt};
|
|
1521
1565
|
my $dirLen = length $$dataPt;
|
|
1522
|
-
my ($yr, $mon, $day, $hr, $min, $sec, $stat, $lbl, $ddd);
|
|
1566
|
+
my ($yr, $mon, $day, $hr, $min, $sec, $ss, $stat, $lbl, $ddd, $done);
|
|
1523
1567
|
my ($lat, $latRef, $lon, $lonRef, $spd, $trk, $alt, @acc, @xtra);
|
|
1524
1568
|
|
|
1525
1569
|
return 0 if $dirLen < 82;
|
|
@@ -1644,7 +1688,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1644
1688
|
}
|
|
1645
1689
|
if ($notEnc and $notStr) {
|
|
1646
1690
|
|
|
1647
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1691
|
+
$debug and $et->FoundTag(GPSType => 3);
|
|
1648
1692
|
# decode freeGPS from ViofoA119v3 dashcam (similar to Novatek GPS format)
|
|
1649
1693
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1650
1694
|
# 0010: 05 00 00 00 2f 00 00 00 03 00 00 00 13 00 00 00 [..../...........]
|
|
@@ -1658,7 +1702,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1658
1702
|
($sec,$min,$hr,$day,$mon,$yr) = gmtime($time);
|
|
1659
1703
|
$yr += 1900;
|
|
1660
1704
|
++$mon;
|
|
1661
|
-
$et->
|
|
1705
|
+
$et->Warn('Converting GPSDateTime to UTC based on local time zone',1);
|
|
1662
1706
|
}
|
|
1663
1707
|
$lat = GetFloat($dataPt, 0x2c);
|
|
1664
1708
|
$lon = GetFloat($dataPt, 0x30);
|
|
@@ -1672,7 +1716,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1672
1716
|
|
|
1673
1717
|
} else {
|
|
1674
1718
|
|
|
1675
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1719
|
+
$debug and $et->FoundTag(GPSType => 4);
|
|
1676
1720
|
# decode freeGPS from E-ACE B44 dashcam
|
|
1677
1721
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1678
1722
|
# 0010: 08 00 00 00 22 00 00 00 01 00 00 00 18 00 00 00 [...."...........]
|
|
@@ -1703,40 +1747,76 @@ sub ProcessFreeGPS($$$)
|
|
|
1703
1747
|
($lon = DecryptLucky($ln, $key)) =~ /^\d{1,5}\.\d+$/ or undef($lon), next;
|
|
1704
1748
|
last;
|
|
1705
1749
|
}
|
|
1706
|
-
$lon or $et->
|
|
1750
|
+
$lon or $et->Warn('Unknown encryption for latitude/longitude');
|
|
1707
1751
|
}
|
|
1708
1752
|
}
|
|
1709
1753
|
|
|
1710
|
-
} elsif ($$dataPt =~
|
|
1754
|
+
} elsif ($$dataPt =~ /^(.{16}|.{48}|.{80})LIGOGPSINFO\0/s and length($$dataPt) >= length($1) + 0x84) {
|
|
1711
1755
|
|
|
1712
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1713
|
-
|
|
1714
|
-
#
|
|
1715
|
-
#
|
|
1716
|
-
#
|
|
1717
|
-
#
|
|
1718
|
-
#
|
|
1719
|
-
#
|
|
1720
|
-
#
|
|
1721
|
-
#
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
#
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1756
|
+
$debug and $et->FoundTag(GPSType => 5);
|
|
1757
|
+
my $pos = length $1;
|
|
1758
|
+
# iiway s1 dual dash cam - offset 16, encrypted and fuzzed with scale 1
|
|
1759
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1760
|
+
# 0010: 4c 49 47 4f 47 50 53 49 4e 46 4f 00 00 00 00 05 [LIGOGPSINFO.....]
|
|
1761
|
+
# 0020: 0a 00 00 00 23 23 23 23 6a 00 00 00 c0 20 20 20 [....####j.... ]
|
|
1762
|
+
# 0030: 20 f0 12 10 12 22 e1 0e 10 12 2f 90 10 13 02 f2 [ ...."..../.....]
|
|
1763
|
+
# XGODY 12" 4K Dashcam - offset 16, encrypted and fuzzed with scale 1
|
|
1764
|
+
# 0000: 00 00 00 a8 66 72 65 65 47 50 53 20 98 00 00 00 [....freeGPS ....]
|
|
1765
|
+
# 0010: 4c 49 47 4f 47 50 53 49 4e 46 4f 00 00 00 00 05 [LIGOGPSINFO.....]
|
|
1766
|
+
# 0020: cd 61 00 00 23 23 23 23 6d 00 00 00 c1 ec 41 20 [.a..####m.....A ]
|
|
1767
|
+
# 0030: 20 f0 12 10 12 24 e5 0e 10 11 2f 92 10 12 00 f6 [ ....$..../.....]
|
|
1768
|
+
# ABASK A8 4K Dashcam - offset 16, encrypted and fuzzed with scale 3
|
|
1769
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1770
|
+
# 0010: 4c 49 47 4f 47 50 53 49 4e 46 4f 00 00 00 00 05 [LIGOGPSINFO.....]
|
|
1771
|
+
# 0020: 00 00 00 00 23 23 23 23 69 00 00 00 c0 20 20 20 [....####i.... ]
|
|
1772
|
+
# 0030: 20 f0 12 10 12 23 e5 0e 10 12 2f 99 10 11 02 f2 [ ....#..../.....]
|
|
1773
|
+
# Unknown dashcam (forum16060) - offset 16, enciphered and fuzzed with scale 1
|
|
1774
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 98 00 00 00 [..@.freeGPS ....]
|
|
1775
|
+
# 0010: 4c 49 47 4f 47 50 53 49 4e 46 4f 00 00 00 00 0d [LIGOGPSINFO.....]
|
|
1776
|
+
# 0020: 0a 00 00 00 23 23 23 23 3b 00 a0 34 46 44 46 31 [....####;..4FDF1]
|
|
1777
|
+
# 0030: 2f 44 39 2f 45 38 20 44 3d 4c 47 4a 4c 39 38 20 [/D9/E8 D=LGJL98 ]
|
|
1778
|
+
# Rexing dashcam V1GW-4K - offset 48, encrypted and fuzzed with scale 1
|
|
1779
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
1780
|
+
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
1781
|
+
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
1782
|
+
# 0030: 4c 49 47 4f 47 50 53 49 4e 46 4f 00 00 00 00 05 [LIGOGPSINFO.....]
|
|
1783
|
+
# 0040: 01 00 00 00 23 23 23 23 73 00 00 00 c0 20 20 20 [....####s.... ]
|
|
1784
|
+
# 0050: 20 f0 12 10 12 23 e5 0e 10 12 2f 95 10 12 01 f3 [ ....#..../.....]
|
|
1785
|
+
# Kingslim D4 dashcam - offset 80, encrypted and fuzzed with scale 1
|
|
1786
|
+
# 0000: 0a 00 00 00 0b 00 00 00 07 00 00 00 e5 07 00 00 [................]
|
|
1787
|
+
# 0010: 06 00 00 00 03 00 00 00 41 4e 57 31 91 52 83 45 [........ANW1.R.E]
|
|
1788
|
+
# 0020: 15 70 fe c5 29 5c c3 41 ae c7 af 42 00 00 d1 be [.p..)\.A...B....]
|
|
1789
|
+
# 0030: 00 00 80 3b 00 00 2c 3e 00 00 00 00 00 00 00 00 [...;..,>........]
|
|
1790
|
+
# 0040: 00 00 00 00 00 00 00 00 00 00 00 00 26 26 26 26 [............&&&&]
|
|
1791
|
+
# 0050: 4c 49 47 4f 47 50 53 49 4e 46 4f 00 00 00 00 05 [LIGOGPSINFO.....]
|
|
1792
|
+
# 0060: 01 00 00 00 23 23 23 23 75 00 00 00 c0 22 20 20 [....####u...." ]
|
|
1793
|
+
# 0070: 20 f0 12 10 12 21 e5 0e 10 12 2f 90 10 13 01 f2 [ ....!..../.....]
|
|
1794
|
+
my %dirInfo = ( DataPt => $dataPt, DirStart => $pos, DirName => "LigoGPS_$pos" );
|
|
1795
|
+
# (this is weak, but the only difference I could find between these 2 headers)
|
|
1796
|
+
# (NOTE: ../testpics/gps_video/forum16229.mp4 uses this word for a counter!)
|
|
1797
|
+
$$et{LigoGPSScale} = 3 if $pos == 16 and $$dataPt =~ /^.{12}\xf0\x03\0\0.{16}\0{4}/s;
|
|
1798
|
+
Image::ExifTool::LigoGPS::ProcessLigoGPS($et, \%dirInfo, $tagTbl);
|
|
1799
|
+
$done = 1;
|
|
1800
|
+
|
|
1801
|
+
# also... when offset is 0x50 (Kingslim), the GPS also exists in this format:
|
|
1802
|
+
# ($latRef, $lonRef) = ($1, $2);
|
|
1803
|
+
# ($hr,$min,$sec,$yr,$mon,$day) = unpack("V6", $$dataPt);
|
|
1804
|
+
# # lat/lon aren't decoded properly, but spd,trk,acc are
|
|
1805
|
+
# $lat = GetFloat($dataPt, 0x1c);
|
|
1806
|
+
# $lon = GetFloat($dataPt, 0x20);
|
|
1807
|
+
# $et->VPrint(0, sprintf("Raw lat/lon = %.9f %.9f\n", $lat, $lon));
|
|
1808
|
+
# $et->Warn('GPSLatitude/Longitude encryption is not yet known, so these will be wrong');
|
|
1809
|
+
# $lat = abs $lat;
|
|
1810
|
+
# $lon = abs $lon;
|
|
1811
|
+
# $spd = GetFloat($dataPt, 0x24) * $knotsToKph; # (convert knots to km/h)
|
|
1812
|
+
# $trk = GetFloat($dataPt, 0x28);
|
|
1813
|
+
# $acc[0] = GetFloat($dataPt, 0x2c);
|
|
1814
|
+
# $acc[1] = GetFloat($dataPt, 0x30);
|
|
1815
|
+
# $acc[2] = GetFloat($dataPt, 0x34);
|
|
1736
1816
|
|
|
1737
1817
|
} elsif ($$dataPt =~ /^.{60}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s) {
|
|
1738
1818
|
|
|
1739
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1819
|
+
$debug and $et->FoundTag(GPSType => 6);
|
|
1740
1820
|
# decode freeGPS from Akaso dashcam
|
|
1741
1821
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 60 00 00 00 [....freeGPS `...]
|
|
1742
1822
|
# 0010: 78 2e 78 78 00 00 00 00 00 00 00 00 00 00 00 00 [x.xx............]
|
|
@@ -1770,7 +1850,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1770
1850
|
|
|
1771
1851
|
} elsif ($$dataPt =~ /^.{60}4W`b]S</s and length($$dataPt) >= 140) {
|
|
1772
1852
|
|
|
1773
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1853
|
+
$debug and $et->FoundTag(GPSType => 7);
|
|
1774
1854
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 01 00 00 [..@.freeGPS ....]
|
|
1775
1855
|
# 0010: 5a 58 53 42 4e 58 59 53 00 00 00 00 00 00 00 00 [ZXSBNXYS........]
|
|
1776
1856
|
# 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
@@ -1780,18 +1860,18 @@ sub ProcessFreeGPS($$$)
|
|
|
1780
1860
|
# 0060: 42 3e 49 49 40 42 45 3c 55 3c 45 47 3e 45 43 41 [B>II@BE<U<EG>ECA]
|
|
1781
1861
|
# decipher $GPRMC by subtracting 16 from each character value
|
|
1782
1862
|
$_ = pack 'C*', map { $_>=16 and $_-=16 } unpack('x60C80', $$dataPt);
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1863
|
+
if (/[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(\d*?\d{1,2}\.\d+),([NS]),(\d*?\d{1,2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/) {
|
|
1864
|
+
($yr,$mon,$day,$hr,$min,$sec,$lat,$latRef,$lon,$lonRef) = ($13,$12,$11,$1,$2,$3,$5,$6,$7,$8);
|
|
1865
|
+
$yr += ($yr >= 70 ? 1900 : 2000);
|
|
1866
|
+
$spd = $9 * $knotsToKph if length $9;
|
|
1867
|
+
$trk = $10 if length $10;
|
|
1868
|
+
} else {
|
|
1869
|
+
$done = 1;
|
|
1786
1870
|
}
|
|
1787
|
-
($yr,$mon,$day,$hr,$min,$sec,$lat,$latRef,$lon,$lonRef) = ($13,$12,$11,$1,$2,$3,$5,$6,$7,$8);
|
|
1788
|
-
$yr += ($yr >= 70 ? 1900 : 2000);
|
|
1789
|
-
$spd = $9 * $knotsToKph if length $9;
|
|
1790
|
-
$trk = $10 if length $10;
|
|
1791
1871
|
|
|
1792
1872
|
} elsif ($$dataPt =~ /^.{64}[\x01-\x0c]\0{3}[\x01-\x1f]\0{3}A[NS][EW]\0{5}/s) {
|
|
1793
1873
|
|
|
1794
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1874
|
+
$debug and $et->FoundTag(GPSType => 8);
|
|
1795
1875
|
# Akaso V1 dascham
|
|
1796
1876
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 00 00 00 [....freeGPS x...]
|
|
1797
1877
|
# 0010: 59 6e 64 41 6b 61 73 6f 43 61 72 00 00 00 00 00 [YndAkasoCar.....]
|
|
@@ -1816,7 +1896,7 @@ sub ProcessFreeGPS($$$)
|
|
|
1816
1896
|
($hr,$min,$sec,$yr,$mon,$day,$stat,$latRef,$lonRef) =
|
|
1817
1897
|
unpack('x48V6a1a1a1x1', $$dataPt);
|
|
1818
1898
|
|
|
1819
|
-
$et->
|
|
1899
|
+
$et->Warn('GPSLatitude/Longitude encryption is not yet known, so these will be wrong');
|
|
1820
1900
|
# (see https://exiftool.org/forum/index.php?topic=11320.0)
|
|
1821
1901
|
|
|
1822
1902
|
$spd = GetFloat($dataPt, 0x60);
|
|
@@ -1824,11 +1904,11 @@ sub ProcessFreeGPS($$$)
|
|
|
1824
1904
|
$lat = GetDouble($dataPt, 0x50); # latitude is here, but encrypted somehow
|
|
1825
1905
|
$lon = GetDouble($dataPt, 0x58); # longitude is here, but encrypted somehow
|
|
1826
1906
|
$ddd = 1; # don't convert until we know what the format is
|
|
1827
|
-
#my $serialNum = substr($$dataPt, 0x68, 20);
|
|
1907
|
+
#my $serialNum = substr($$dataPt, 0x68, 20); # (confirmed)
|
|
1828
1908
|
|
|
1829
1909
|
} elsif ($$dataPt =~ /^.{12}\xac\0\0\0.{44}(.{72})/s) {
|
|
1830
1910
|
|
|
1831
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1911
|
+
$debug and $et->FoundTag(GPSType => 9);
|
|
1832
1912
|
# EACHPAI dash cam
|
|
1833
1913
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 ac 00 00 00 [....freeGPS ....]
|
|
1834
1914
|
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
@@ -1840,19 +1920,18 @@ sub ProcessFreeGPS($$$)
|
|
|
1840
1920
|
# 0070: 43 41 3c 40 42 40 46 42 40 3c 3c 3c 51 3a 47 46 [CA<@B@FB@<<<Q:GF]
|
|
1841
1921
|
# 0080: 00 2a 36 35 00 00 00 00 00 00 00 00 00 00 00 00 [.*65............]
|
|
1842
1922
|
|
|
1843
|
-
$et->
|
|
1923
|
+
$et->Warn("Can't yet decrypt EACHPAI timed GPS", 1);
|
|
1844
1924
|
# (see https://exiftool.org/forum/index.php?topic=5095.msg61266#msg61266)
|
|
1845
|
-
|
|
1846
|
-
return 1;
|
|
1925
|
+
$done = 1;
|
|
1847
1926
|
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1927
|
+
# my $time = pack 'C*', map { $_ ^= 0 } unpack 'C*', $1;
|
|
1928
|
+
# # bytes 7-12 are the timestamp in ASCII HHMMSS after xor-ing with 0x70
|
|
1929
|
+
# substr($time,7,6) = pack 'C*', map { $_ ^= 0x70 } unpack 'C*', substr($time,7,6);
|
|
1930
|
+
# # (other values are currently unknown)
|
|
1852
1931
|
|
|
1853
1932
|
} elsif ($$dataPt =~ /^.{64}A([NS])([EW])\0/s) {
|
|
1854
1933
|
|
|
1855
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1934
|
+
$debug and $et->FoundTag(GPSType => 10);
|
|
1856
1935
|
# Vantrue S1 dashcam
|
|
1857
1936
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 00 00 00 [....freeGPS x...]
|
|
1858
1937
|
# 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
|
|
@@ -1864,21 +1943,21 @@ sub ProcessFreeGPS($$$)
|
|
|
1864
1943
|
# 0070: 05 00 00 00 7f 00 00 00 07 01 00 00 00 00 00 00 [................]
|
|
1865
1944
|
($latRef, $lonRef) = ($1, $2);
|
|
1866
1945
|
($yr,$mon,$day,$hr,$min,$sec,@acc) = unpack('x68V6x20V3', $$dataPt);
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1946
|
+
if ($mon>=1 and $mon<=12 and $day>=1 and $day<=31) {
|
|
1947
|
+
# (not sure about acc scaling)
|
|
1948
|
+
@acc = map { SignedInt32 / 1000 } @acc;
|
|
1949
|
+
$lon = GetFloat($dataPt, 0x5c);
|
|
1950
|
+
$lat = GetFloat($dataPt, 0x60);
|
|
1951
|
+
$spd = GetFloat($dataPt, 0x64) * $knotsToKph;
|
|
1952
|
+
$trk = GetFloat($dataPt, 0x68);
|
|
1953
|
+
$alt = GetFloat($dataPt, 0x6c);
|
|
1954
|
+
} else {
|
|
1955
|
+
$done = 1;
|
|
1870
1956
|
}
|
|
1871
|
-
# (not sure about acc scaling)
|
|
1872
|
-
@acc = map { SignedInt32 / 1000 } @acc;
|
|
1873
|
-
$lon = GetFloat($dataPt, 0x5c);
|
|
1874
|
-
$lat = GetFloat($dataPt, 0x60);
|
|
1875
|
-
$spd = GetFloat($dataPt, 0x64) * $knotsToKph;
|
|
1876
|
-
$trk = GetFloat($dataPt, 0x68);
|
|
1877
|
-
$alt = GetFloat($dataPt, 0x6c);
|
|
1878
1957
|
|
|
1879
1958
|
} elsif (substr($$dataPt,0x45,3) eq 'ATC') {
|
|
1880
1959
|
|
|
1881
|
-
$debug and $et->FoundTag(GPSType =>
|
|
1960
|
+
$debug and $et->FoundTag(GPSType => 11);
|
|
1882
1961
|
# header looks like this: (sample 1)
|
|
1883
1962
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 38 06 00 00 [....freeGPS 8...]
|
|
1884
1963
|
# 0010: 49 51 53 32 30 31 33 30 33 30 36 42 00 00 00 00 [IQS20130306B....]
|
|
@@ -1919,7 +1998,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1919
1998
|
my $i;
|
|
1920
1999
|
for ($i=0; $i<@dateMax; ++$i) {
|
|
1921
2000
|
next if $now[$i] <= $dateMax[$i];
|
|
1922
|
-
$et->
|
|
2001
|
+
$et->Warn('Invalid GPS date/time');
|
|
1923
2002
|
next ATCRec; # ignore this record
|
|
1924
2003
|
}
|
|
1925
2004
|
# look for next ATC record in temporal sequence
|
|
@@ -1986,12 +2065,11 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
1986
2065
|
}
|
|
1987
2066
|
# save position of most recent record (needed when parsing the next freeGPS block)
|
|
1988
2067
|
$$et{FreeGPS2}{RecentRecPos} = $lastRecPos;
|
|
1989
|
-
|
|
1990
|
-
return 1;
|
|
2068
|
+
$done = 1;
|
|
1991
2069
|
|
|
1992
2070
|
} elsif ($$dataPt =~ /^.{60}A\0.{10}([NS])\0.{14}([EW])\0/s and $dirLen >= 0x88) {
|
|
1993
2071
|
|
|
1994
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2072
|
+
$debug and $et->FoundTag(GPSType => 12);
|
|
1995
2073
|
# header looks like this in my sample:
|
|
1996
2074
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 08 01 00 00 [....freeGPS ....]
|
|
1997
2075
|
# 0010: 32 30 31 33 30 38 31 35 2e 30 31 00 00 00 00 00 [20130815.01.....]
|
|
@@ -2022,9 +2100,14 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2022
2100
|
|
|
2023
2101
|
} elsif ($$dataPt =~ /^.{16}A([NS])([EW])\0/s) {
|
|
2024
2102
|
|
|
2025
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2103
|
+
$debug and $et->FoundTag(GPSType => 13);
|
|
2026
2104
|
# INNOVV MP4 video (same format as INNOVV TS)
|
|
2027
|
-
|
|
2105
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
2106
|
+
# 0010: 41 4e 45 00 e4 56 96 45 86 b1 ca 44 5c 8f e2 40 [ANE..V.E...D\..@]
|
|
2107
|
+
# 0020: 33 33 58 43 c3 00 00 00 30 00 00 00 a0 fe ff ff [33XC....0.......]
|
|
2108
|
+
# 0030: 41 4e 45 00 e3 56 96 45 82 b1 ca 44 5c 8f fa 40 [ANE..V.E...D\..@]
|
|
2109
|
+
# 0040: c3 75 56 43 8c ff ff ff 8c 00 00 00 c3 fd ff ff [.uVC............]
|
|
2110
|
+
while ($$dataPt =~ /(A[NS][EW]\0.{28})/sg) {
|
|
2028
2111
|
my $dat = $1;
|
|
2029
2112
|
$lat = abs(GetFloat(\$dat, 4)); # (abs just to be safe)
|
|
2030
2113
|
$lon = abs(GetFloat(\$dat, 8)); # (abs just to be safe)
|
|
@@ -2039,12 +2122,35 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2039
2122
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
2040
2123
|
$et->HandleTag($tagTbl, Accelerometer => "@acc");
|
|
2041
2124
|
}
|
|
2042
|
-
|
|
2043
|
-
|
|
2125
|
+
$done = 1;
|
|
2126
|
+
|
|
2127
|
+
} elsif ($$dataPt =~ /^.{20}[\0-\x18][\0-\x3b]{2}[\0-\x09]A([NS])([EW])/s) {
|
|
2128
|
+
|
|
2129
|
+
$debug and $et->FoundTag(GPSType => 14);
|
|
2130
|
+
# XBHT motorcycle dashcam Model XB702
|
|
2131
|
+
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
2132
|
+
# 0010: 00 17 05 11 0d 25 18 00 41 4e 45 64 83 3f 00 00 [.....%..ANEd.?..]
|
|
2133
|
+
# 0020: 44 3d c5 02 48 6d ff 07 df 03 00 00 6b 00 00 00 [D=..Hm......k...]
|
|
2134
|
+
# 0030: 00 00 00 00 00 17 05 11 0d 25 18 01 41 4e 45 64 [.........%..ANEd]
|
|
2135
|
+
# 0040: 8b 3f 00 00 30 3d c5 02 50 6d ff 07 df 03 00 00 [.?..0=..Pm......]
|
|
2136
|
+
while ($$dataPt =~ /(.{7}[\0-\x09]A[NS][EW].{25})/sg) {
|
|
2137
|
+
my $dat = $1;
|
|
2138
|
+
($yr,$mon,$day,$hr,$min,$sec,$ss,$latRef,$lonRef,$lat,$lon,$spd) =
|
|
2139
|
+
unpack('xC7xCCx5VVx4v', $dat);
|
|
2140
|
+
$yr += 2000; $lat /= 1e4; $lon /= 1e4;
|
|
2141
|
+
ConvertLatLon($lat, $lon);
|
|
2142
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
2143
|
+
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d.%d',$yr,$mon,$day,$hr,$min,$sec,$ss);
|
|
2144
|
+
$et->HandleTag($tagTbl, GPSDateTime => $time);
|
|
2145
|
+
$et->HandleTag($tagTbl, GPSLatitude => $lat * ($latRef eq 'S' ? -1 : 1));
|
|
2146
|
+
$et->HandleTag($tagTbl, GPSLongitude => $lon * ($lonRef eq 'W' ? -1 : 1));
|
|
2147
|
+
$et->HandleTag($tagTbl, GPSSpeed => $spd);
|
|
2148
|
+
}
|
|
2149
|
+
$done = 1;
|
|
2044
2150
|
|
|
2045
2151
|
} elsif ($$dataPt =~ /^.{28}A.{11}([NS]).{15}([EW])/s) {
|
|
2046
2152
|
|
|
2047
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2153
|
+
$debug and $et->FoundTag(GPSType => 15);
|
|
2048
2154
|
# Vantrue N4 dashcam
|
|
2049
2155
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 f0 03 00 00 [..@.freeGPS ....]
|
|
2050
2156
|
# 0010: 0d 00 00 00 16 00 00 00 1e 00 00 00 41 00 00 00 [............A...]
|
|
@@ -2101,7 +2207,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2101
2207
|
($hr,$min,$sec,$yr,$mon,$day,$stat,$latRef,$lonRef) =
|
|
2102
2208
|
unpack('x48V6a1a1a1x1V4', $$dataPt);
|
|
2103
2209
|
if (substr($$dataPt, 16, 3) eq 'IQS') {
|
|
2104
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2210
|
+
$debug and $et->FoundTag(GPSType => 16);
|
|
2105
2211
|
# Type 3b (ref PH)
|
|
2106
2212
|
# header looks like this in my sample:
|
|
2107
2213
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 4c 00 00 00 [....freeGPS L...]
|
|
@@ -2113,7 +2219,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2113
2219
|
$spd = Get32s($dataPt, 0x54) / 100 * $mpsToKph;
|
|
2114
2220
|
$alt = GetFloat($dataPt, 0x58) / 1000; # (NC)
|
|
2115
2221
|
} else {
|
|
2116
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2222
|
+
$debug and $et->FoundTag(GPSType => 17);
|
|
2117
2223
|
$lat = GetFloat($dataPt, 0x4c);
|
|
2118
2224
|
$lon = GetFloat($dataPt, 0x50);
|
|
2119
2225
|
$spd = GetFloat($dataPt, 0x54) * $knotsToKph;
|
|
@@ -2133,7 +2239,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2133
2239
|
|
|
2134
2240
|
} elsif ($$dataPt =~ m<^.{23}(\d{4})/(\d{2})/(\d{2}) (\d{2}):(\d{2}):(\d{2}) [N|S]>s) {
|
|
2135
2241
|
|
|
2136
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2242
|
+
$debug and $et->FoundTag(GPSType => 18);
|
|
2137
2243
|
# XGODY 12" 4K Dashcam
|
|
2138
2244
|
# 0000: 00 00 00 a8 66 72 65 65 47 50 53 20 98 00 00 00 [....freeGPS ....]
|
|
2139
2245
|
# 0010: 6e 6f 72 6d 61 6c 3a 32 30 32 34 2f 30 35 2f 32 [normal:2024/05/2]
|
|
@@ -2164,8 +2270,8 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2164
2270
|
}
|
|
2165
2271
|
|
|
2166
2272
|
} elsif ($$dataPt =~ m/^.{30}A.{20}VV/) {
|
|
2167
|
-
|
|
2168
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2273
|
+
|
|
2274
|
+
$debug and $et->FoundTag(GPSType => 19);
|
|
2169
2275
|
# 70mai A810 dashcam (note: no timestamps in the samples I have)
|
|
2170
2276
|
# 0000: 00 00 40 00 66 72 65 65 47 50 53 20 ed 01 00 00 [..@.freeGPS ....]
|
|
2171
2277
|
# 0010: 03 00 ed 01 00 00 00 0f 00 00 70 08 00 00 41 66 [..........p...Af]
|
|
@@ -2182,7 +2288,7 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2182
2288
|
|
|
2183
2289
|
} else {
|
|
2184
2290
|
|
|
2185
|
-
$debug and $et->FoundTag(GPSType =>
|
|
2291
|
+
$debug and $et->FoundTag(GPSType => 20);
|
|
2186
2292
|
# (look for binary GPS as stored by Nextbase 512G, ref PH)
|
|
2187
2293
|
# 0000: 00 00 80 00 66 72 65 65 47 50 53 20 78 01 00 00 [....freeGPS x...]
|
|
2188
2294
|
# 0010: 78 2e 78 78 00 00 00 00 00 00 00 00 00 00 00 00 [x.xx............]
|
|
@@ -2228,14 +2334,14 @@ ATCRec: for ($recPos = 0x30; $recPos + 52 < $dirLen; $recPos += 52) {
|
|
|
2228
2334
|
$et->HandleTag($tagTbl, GPSTrack => $trk);
|
|
2229
2335
|
last if $pos += 0x20 > length($$dataPt) - 0x1e;
|
|
2230
2336
|
}
|
|
2231
|
-
|
|
2232
|
-
return $$et{DOC_NUM} ? 1 : 0; # return 0 if nothing extracted
|
|
2337
|
+
$done = 1;
|
|
2233
2338
|
}
|
|
2339
|
+
SetByteOrder($oldOrder);
|
|
2340
|
+
return $$et{DOC_NUM} ? 1 : 0 if $done;
|
|
2341
|
+
return 0 if defined $yr and $mon < 1 or $mon > 12; # quick sanity check
|
|
2234
2342
|
#
|
|
2235
2343
|
# save tag values extracted by above code
|
|
2236
2344
|
#
|
|
2237
|
-
SetByteOrder($oldOrder);
|
|
2238
|
-
return 0 if defined $yr and $mon < 1 or $mon > 12; # quick sanity check
|
|
2239
2345
|
FoundSomething($et, $tagTbl, $$dirInfo{SampleTime}, $$dirInfo{SampleDuration});
|
|
2240
2346
|
$sec = '0' . $sec unless $sec =~ /^\d{2}/; # pad integer part of seconds to 2 digits
|
|
2241
2347
|
if (defined $yr) {
|
|
@@ -2361,7 +2467,7 @@ sub ParseTag($$$)
|
|
|
2361
2467
|
}
|
|
2362
2468
|
|
|
2363
2469
|
#------------------------------------------------------------------------------
|
|
2364
|
-
# Process Yuneec 'tx3g' sbtl metadata (ref PH)
|
|
2470
|
+
# Process Yuneec 'tx3g' and Autel sbtl metadata (ref PH)
|
|
2365
2471
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
2366
2472
|
# Returns: 1 on success
|
|
2367
2473
|
sub Process_tx3g($$$)
|
|
@@ -2369,13 +2475,49 @@ sub Process_tx3g($$$)
|
|
|
2369
2475
|
my ($et, $dirInfo, $tagTablePtr) = @_;
|
|
2370
2476
|
my $dataPt = $$dirInfo{DataPt};
|
|
2371
2477
|
return 0 if length $$dataPt < 2;
|
|
2372
|
-
pos($$dataPt) = 2; # skip 2-byte length word
|
|
2373
2478
|
$et->VerboseDir('tx3g', undef, length($$dataPt)-2);
|
|
2374
|
-
$
|
|
2375
|
-
|
|
2479
|
+
my $text = substr($$dataPt, 2); # remove 2-byte length word
|
|
2480
|
+
$et->HandleTag($tagTablePtr, 'Text', $text);
|
|
2481
|
+
if ($text =~ /^HOME\(/) {
|
|
2482
|
+
# --- sample text from Autel Evo II drone ---
|
|
2483
|
+
# HOME(W: 109.318642, N: 40.769371) 2023-09-12 10:28:07
|
|
2484
|
+
# GPS(W: 109.339287, N: 40.768574, 2371.76m)
|
|
2485
|
+
# HDR ISO:100 SHUTTER:1000 EV:-0.7 F-NUM:1.8
|
|
2486
|
+
# F.PRY (1.0\xc2\xb0, -3.7\xc2\xb0, -59.0\xc2\xb0), G.PRY (-51.1\xc2\xb0, 0.0\xc2\xb0, -58.9\xc2\xb0)
|
|
2487
|
+
my $line;
|
|
2488
|
+
foreach $line (split /\x0a/, $text) {
|
|
2489
|
+
if ($line =~ /^HOME\(([EW]):\s*(\d+\.\d+),\s*([NS]):\s*(\d+\.\d+)\)\s*(.*)/) {
|
|
2490
|
+
my ($lon, $lat, $time) = ($2, $4, $5);
|
|
2491
|
+
$lon = -$lon if $1 eq 'W';
|
|
2492
|
+
$lat = -$lat if $3 eq 'S';
|
|
2493
|
+
$time =~ tr/-/:/; # (likely local time zone, but not confirmed)
|
|
2494
|
+
$et->HandleTag($tagTablePtr, GPSDateTime => $time);
|
|
2495
|
+
$et->HandleTag($tagTablePtr, HomeLat => $lat);
|
|
2496
|
+
$et->HandleTag($tagTablePtr, HomeLon => $lon);
|
|
2497
|
+
} elsif ($line =~ /^GPS\(([EW]):\s*(\d+\.\d+),\s*([NS]):\s*(\d+\.\d+),\s*(.*)m/) {
|
|
2498
|
+
my ($lon, $lat, $alt) = ($2, $4, $5);
|
|
2499
|
+
$lon = -$lon if $1 eq 'W';
|
|
2500
|
+
$lat = -$lat if $3 eq 'S';
|
|
2501
|
+
$et->HandleTag($tagTablePtr, Lat => $lat);
|
|
2502
|
+
$et->HandleTag($tagTablePtr, Lon => $lon);
|
|
2503
|
+
$et->HandleTag($tagTablePtr, Alt => $alt);
|
|
2504
|
+
} elsif ($line =~ /^F\.PRY\s*\((-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0/) {
|
|
2505
|
+
$et->HandleTag($tagTablePtr, Yaw => $1);
|
|
2506
|
+
$et->HandleTag($tagTablePtr, Pitch => $2);
|
|
2507
|
+
$et->HandleTag($tagTablePtr, Roll => $3);
|
|
2508
|
+
if ($line =~ /G\.PRY\s*\((-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0,\s*(-?[\d.]+)\xc2\xb0/) {
|
|
2509
|
+
$et->HandleTag($tagTablePtr, GimYaw => $1);
|
|
2510
|
+
$et->HandleTag($tagTablePtr, GimPitch => $2);
|
|
2511
|
+
$et->HandleTag($tagTablePtr, GimRoll => $3);
|
|
2512
|
+
}
|
|
2513
|
+
} else {
|
|
2514
|
+
$et->HandleTag($tagTablePtr, $1, $2) while $line =~ /([-\w]+):([^:]*[^:\s])(\s|$)/sg;
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
} elsif ($text =~ /^\w{3} (\d{4})-(\d{2})-(\d{2}) (\d{2}:\d{2}:\d{2}) ?([-+])(\d{2}):?(\d{2})$/s) {
|
|
2376
2518
|
$et->HandleTag($tagTablePtr, 'DateTime', "$1:$2:$3 $4$5$6:$7");
|
|
2377
2519
|
} else {
|
|
2378
|
-
$et->HandleTag($tagTablePtr, $1, $2) while
|
|
2520
|
+
$et->HandleTag($tagTablePtr, $1, $2) while $text =~ /(\w+):([^:]*[^:\s])(\s|$)/sg;
|
|
2379
2521
|
}
|
|
2380
2522
|
return 1;
|
|
2381
2523
|
}
|
|
@@ -2417,7 +2559,7 @@ sub Process_mebx($$$)
|
|
|
2417
2559
|
Size => $len - 8,
|
|
2418
2560
|
);
|
|
2419
2561
|
} else {
|
|
2420
|
-
$et->
|
|
2562
|
+
$et->Warn('No key information for mebx ID ' . PrintableTagID($id,1));
|
|
2421
2563
|
}
|
|
2422
2564
|
}
|
|
2423
2565
|
return 1;
|
|
@@ -2540,7 +2682,7 @@ sub Process_gdat($$$)
|
|
|
2540
2682
|
{
|
|
2541
2683
|
my ($et, $dirInfo, $tagTbl) = @_;
|
|
2542
2684
|
unless ($$et{OPTIONS}{ExtractEmbedded}) {
|
|
2543
|
-
$et->
|
|
2685
|
+
$et->Warn('Use the ExtractEmbedded option to extract timed GPSData',3);
|
|
2544
2686
|
return 0;
|
|
2545
2687
|
}
|
|
2546
2688
|
my $dataPt = $$dirInfo{DataPt};
|
|
@@ -2591,87 +2733,11 @@ sub Process_nbmt($$$)
|
|
|
2591
2733
|
delete $$et{NoMoreTextDecoding};
|
|
2592
2734
|
delete $$et{DOC_NUM};
|
|
2593
2735
|
} else {
|
|
2594
|
-
$et->
|
|
2736
|
+
$et->Warn('Use the ExtractEmbedded option to extract timed GPSData',3);
|
|
2595
2737
|
}
|
|
2596
2738
|
return 1;
|
|
2597
2739
|
}
|
|
2598
2740
|
|
|
2599
|
-
#------------------------------------------------------------------------------
|
|
2600
|
-
# Process LIGOGPS JSON-format GPS from Yada RoadCam Pro 4K BT58189
|
|
2601
|
-
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
2602
|
-
# Returns: 1 on success
|
|
2603
|
-
# Sample data (chained 512-byte records starting like this):
|
|
2604
|
-
# 0000: 4c 49 47 4f 47 50 53 49 4e 46 4f 20 7b 22 48 6f [LIGOGPSINFO {"Ho]
|
|
2605
|
-
# 0010: 75 72 22 3a 20 22 32 33 22 2c 20 22 4d 69 6e 75 [ur": "23", "Minu]
|
|
2606
|
-
# 0020: 74 65 22 3a 20 22 31 30 22 2c 20 22 53 65 63 6f [te": "10", "Seco]
|
|
2607
|
-
# 0030: 6e 64 22 3a 20 22 32 32 22 2c 20 22 59 65 61 72 [nd": "22", "Year]
|
|
2608
|
-
# 0040: 22 3a 20 22 32 30 32 33 22 2c 20 22 4d 6f 6e 74 [": "2023", "Mont]
|
|
2609
|
-
# 0050: 68 22 3a 20 22 31 32 22 2c 20 22 44 61 79 22 3a [h": "12", "Day":]
|
|
2610
|
-
# 0060: 20 22 32 38 22 2c 20 22 73 74 61 74 75 73 22 3a [ "28", "status":]
|
|
2611
|
-
sub ProcessLIGO_JSON($$$)
|
|
2612
|
-
{
|
|
2613
|
-
my ($et, $dirInfo, $tagTbl) = @_;
|
|
2614
|
-
my $dataPt = $$dirInfo{DataPt};
|
|
2615
|
-
my $dirLen = $$dirInfo{DirLen};
|
|
2616
|
-
require Image::ExifTool::Import;
|
|
2617
|
-
$et->VerboseDir('LIGO_JSON', undef, length($$dataPt));
|
|
2618
|
-
while ($$dataPt =~ /LIGOGPSINFO (\{.*?\})/g) {
|
|
2619
|
-
my $json = $1;
|
|
2620
|
-
my %dbase;
|
|
2621
|
-
Image::ExifTool::Import::ReadJSON(\$json, \%dbase);
|
|
2622
|
-
my $info = $dbase{'*'} or next;
|
|
2623
|
-
# my sample contains the following JSON fields (in this order):
|
|
2624
|
-
# Hour Minute Second Year Month Day (GPS UTC time)
|
|
2625
|
-
# status NS EW Latitude Longitude Speed (speed in knots)
|
|
2626
|
-
# GsensorX GsensorY GsensorZ (units? - only seen "000" for all)
|
|
2627
|
-
# MHour MMinute MSecond MYear MMonth MDay (local dashcam clock time)
|
|
2628
|
-
# OLatitude OLongitude (? same values as Latitude/Longitude)
|
|
2629
|
-
next unless defined $$info{status} and $$info{status} eq 'A'; # only read if GPS is active
|
|
2630
|
-
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
2631
|
-
my $num = 0;
|
|
2632
|
-
defined $$info{$_} and ++$num foreach qw(Year Month Day Hour Minute Second);
|
|
2633
|
-
if ($num == 6) {
|
|
2634
|
-
# this is the GPS time in UTC
|
|
2635
|
-
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ',@$info{qw{Year Month Day Hour Minute Second}});
|
|
2636
|
-
$et->HandleTag($tagTbl, GPSDateTime => $time);
|
|
2637
|
-
}
|
|
2638
|
-
if ($$info{Latitude} and $$info{Longitude}) {
|
|
2639
|
-
my $lat = $$info{Latitude};
|
|
2640
|
-
$lat = -$lat if $$info{NS} and $$info{NS} eq 'S';
|
|
2641
|
-
my $lon = $$info{Longitude};
|
|
2642
|
-
$lon = -$lon if $$info{EW} and $$info{EW} eq 'W';
|
|
2643
|
-
$et->HandleTag($tagTbl, GPSLatitude => $lat);
|
|
2644
|
-
$et->HandleTag($tagTbl, GPSLongitude => $lon);
|
|
2645
|
-
}
|
|
2646
|
-
$et->HandleTag($tagTbl, GPSSpeed => $$info{Speed} * $knotsToKph) if defined $$info{Speed};
|
|
2647
|
-
if (defined $$info{GsensorX} and defined $$info{GsensorY} and defined $$info{GsensorZ}) {
|
|
2648
|
-
# (don't know conversion factor for accel data, so leave it raw for now)
|
|
2649
|
-
$et->HandleTag($tagTbl, Accelerometer => "$$info{GsensorX} $$info{GsensorY} $$info{GsensorZ}");
|
|
2650
|
-
}
|
|
2651
|
-
$num = 0;
|
|
2652
|
-
defined $$info{$_} and ++$num foreach qw(MYear MMonth MDay MHour MMinute MSecond);
|
|
2653
|
-
if ($num == 6) {
|
|
2654
|
-
# this is the dashcam clock time (local time zone)
|
|
2655
|
-
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d',@$info{qw{MYear MMonth MDay MHour MMinute MSecond}});
|
|
2656
|
-
$et->HandleTag($tagTbl, DateTimeOriginal => $time);
|
|
2657
|
-
}
|
|
2658
|
-
if (defined $$info{OLatitude} and defined $$info{OLongitude}) {
|
|
2659
|
-
my $lat = $$info{OLatitude};
|
|
2660
|
-
$lat = -$lat if $$info{NS} and $$info{NS} eq 'S';
|
|
2661
|
-
my $lon = $$info{OLongitude};
|
|
2662
|
-
$lon = -$lon if $$info{EW} and $$info{EW} eq 'W';
|
|
2663
|
-
$et->HandleTag($tagTbl, GPSLatitude2 => $lat);
|
|
2664
|
-
$et->HandleTag($tagTbl, GPSLongitude2 => $lon);
|
|
2665
|
-
}
|
|
2666
|
-
unless ($et->Options('ExtractEmbedded')) {
|
|
2667
|
-
$et->WarnOnce('Use the ExtractEmbedded option to extract all timed GPS',3);
|
|
2668
|
-
last;
|
|
2669
|
-
}
|
|
2670
|
-
}
|
|
2671
|
-
delete $$et{DOC_NUM};
|
|
2672
|
-
return 1;
|
|
2673
|
-
}
|
|
2674
|
-
|
|
2675
2741
|
#------------------------------------------------------------------------------
|
|
2676
2742
|
# Process Kenwood drv-a301w dashcam 'udta' atom (ref PH)
|
|
2677
2743
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
@@ -2711,7 +2777,7 @@ sub ProcessKenwood($$$)
|
|
|
2711
2777
|
}
|
|
2712
2778
|
$et->HandleTag($tagTbl, Accelerometer => "@acc") if @acc;
|
|
2713
2779
|
unless ($et->Options('ExtractEmbedded')) {
|
|
2714
|
-
$et->
|
|
2780
|
+
$et->Warn('Use the ExtractEmbedded option to extract all timed GPS',3);
|
|
2715
2781
|
last;
|
|
2716
2782
|
}
|
|
2717
2783
|
}
|
|
@@ -2834,7 +2900,7 @@ sub ProcessKenwoodTrailer($$$)
|
|
|
2834
2900
|
$raf->Read($buff, 14) and $buff eq 'CCCCCCCCCCCCCC' or return 0;
|
|
2835
2901
|
$et->VerboseDir('Kenwood trailer', undef, undef);
|
|
2836
2902
|
unless ($$et{OPTIONS}{ExtractEmbedded}) {
|
|
2837
|
-
$et->
|
|
2903
|
+
$et->Warn('Use the ExtractEmbedded option to extract timed GPSData from Kenwood trailer',3);
|
|
2838
2904
|
return 1;
|
|
2839
2905
|
}
|
|
2840
2906
|
while ($raf->Read($buff, 121) and $buff =~ /^GPSDATA--(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/) {
|
|
@@ -3057,7 +3123,7 @@ sub ProcessTTAD($$$)
|
|
|
3057
3123
|
$et->HandleTag($tagTbl, "Unknown0$type" => "@a");
|
|
3058
3124
|
}
|
|
3059
3125
|
} else {
|
|
3060
|
-
$et->
|
|
3126
|
+
$et->Warn("Unknown TTAD record type $type",1);
|
|
3061
3127
|
}
|
|
3062
3128
|
# without -ee, stop after we find types 0,3,5 (ie. bitmask 0x29)
|
|
3063
3129
|
$eeOpt or ($found & 0x29) != 0x29 or EEWarn($et), last;
|
|
@@ -3088,16 +3154,18 @@ sub ProcessInsta360($;$)
|
|
|
3088
3154
|
my $verbose = $et->Options('Verbose');
|
|
3089
3155
|
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
|
3090
3156
|
my $fileEnd = $raf->Tell();
|
|
3157
|
+
my $trailEnd = $fileEnd - $offset;
|
|
3091
3158
|
my $trailerLen = unpack('x38V', $buff);
|
|
3092
|
-
$trailerLen > $
|
|
3159
|
+
$trailerLen > $trailEnd and $et->Warn('Bad Insta360 trailer size'), return 0;
|
|
3093
3160
|
if ($dirInfo) {
|
|
3094
3161
|
$$dirInfo{DirLen} = $trailerLen;
|
|
3095
|
-
$$dirInfo{DataPos} = $
|
|
3162
|
+
$$dirInfo{DataPos} = $trailEnd - $trailerLen;
|
|
3096
3163
|
if ($$dirInfo{OutFile}) {
|
|
3097
3164
|
if ($$et{DEL_GROUP}{Insta360}) {
|
|
3098
3165
|
++$$et{CHANGED};
|
|
3166
|
+
return 1;
|
|
3099
3167
|
# just copy the trailer when writing
|
|
3100
|
-
} elsif ($trailerLen > $
|
|
3168
|
+
} elsif ($trailerLen > $trailEnd or not $raf->Seek($$dirInfo{DataPos}, 0) or
|
|
3101
3169
|
$raf->Read(${$$dirInfo{OutFile}}, $trailerLen) != $trailerLen)
|
|
3102
3170
|
{
|
|
3103
3171
|
return 0;
|
|
@@ -3109,13 +3177,13 @@ sub ProcessInsta360($;$)
|
|
|
3109
3177
|
}
|
|
3110
3178
|
unless ($et->Options('ExtractEmbedded')) {
|
|
3111
3179
|
# can arrive here when reading Insta360 trailer on JPEG image (INSP file)
|
|
3112
|
-
$et->
|
|
3180
|
+
$et->Warn('Use ExtractEmbedded option to extract timed metadata from Insta360 trailer',3);
|
|
3113
3181
|
return 1;
|
|
3114
3182
|
}
|
|
3115
3183
|
|
|
3116
3184
|
my $unknown = $et->Options('Unknown');
|
|
3117
3185
|
# position relative to end of trailer (avoids using large offsets for files > 2 GB)
|
|
3118
|
-
my $epos = -78
|
|
3186
|
+
my $epos = -78;
|
|
3119
3187
|
my ($i, $p);
|
|
3120
3188
|
$$et{SET_GROUP0} = 'Trailer';
|
|
3121
3189
|
$$et{SET_GROUP1} = 'Insta360';
|
|
@@ -3124,7 +3192,7 @@ sub ProcessInsta360($;$)
|
|
|
3124
3192
|
for (;;) {
|
|
3125
3193
|
my ($id, $len) = unpack('vV', $buff);
|
|
3126
3194
|
($epos -= $len) + $trailerLen < 0 and last;
|
|
3127
|
-
$raf->Seek($epos, 2) or last;
|
|
3195
|
+
$raf->Seek($epos-$offset, 2) or last;
|
|
3128
3196
|
if ($verbose) {
|
|
3129
3197
|
$et->VPrint(0, sprintf("Insta360 Record 0x%x (offset 0x%x, %d bytes):\n", $id, $fileEnd + $epos, $len));
|
|
3130
3198
|
}
|
|
@@ -3152,7 +3220,7 @@ sub ProcessInsta360($;$)
|
|
|
3152
3220
|
$dlen = 20;
|
|
3153
3221
|
}
|
|
3154
3222
|
}
|
|
3155
|
-
$raf->Seek($epos, 2) or last;
|
|
3223
|
+
$raf->Seek($epos-$offset, 2) or last;
|
|
3156
3224
|
}
|
|
3157
3225
|
} elsif ($id == 0x200) {
|
|
3158
3226
|
$dlen = $len;
|
|
@@ -3281,8 +3349,8 @@ sub ProcessInsta360($;$)
|
|
|
3281
3349
|
} else {
|
|
3282
3350
|
($epos -= 6) + $trailerLen < 0 and last; # step back to previous record
|
|
3283
3351
|
}
|
|
3284
|
-
$raf->Seek($epos, 2) or last;
|
|
3285
|
-
$raf->Read($buff, 6) == 6 or last;
|
|
3352
|
+
$raf->Seek($epos-$offset, 2) or last; # seek to start of next footer
|
|
3353
|
+
$raf->Read($buff, 6) == 6 or last; # read footer
|
|
3286
3354
|
}
|
|
3287
3355
|
delete $$et{DOC_NUM};
|
|
3288
3356
|
SetByteOrder('MM');
|
|
@@ -3306,8 +3374,8 @@ sub ProcessCAMM($$$)
|
|
|
3306
3374
|
my $rtnVal = 0;
|
|
3307
3375
|
while ($pos + 4 < $end) {
|
|
3308
3376
|
my $type = Get16u($dataPt, $pos + 2);
|
|
3309
|
-
my $size = $size{$type} or $et->
|
|
3310
|
-
$pos + $size > $end and $et->
|
|
3377
|
+
my $size = $size{$type} or $et->Warn("Unknown camm record type $type"), last;
|
|
3378
|
+
$pos + $size > $end and $et->Warn("Truncated camm record $type"), last;
|
|
3311
3379
|
my $tagTbl = GetTagTable("Image::ExifTool::QuickTime::camm$type");
|
|
3312
3380
|
$$dirInfo{DirStart} = $pos;
|
|
3313
3381
|
$$dirInfo{DirLen} = $size;
|
|
@@ -3541,8 +3609,6 @@ sub ScanMediaData($)
|
|
|
3541
3609
|
$et->VPrint(0, "--------------------------\n");
|
|
3542
3610
|
$$et{INDENT} = substr $$et{INDENT}, 0, -2;
|
|
3543
3611
|
}
|
|
3544
|
-
# process Insta360 trailer if it exists
|
|
3545
|
-
ProcessInsta360($et);
|
|
3546
3612
|
}
|
|
3547
3613
|
|
|
3548
3614
|
1; # end
|
|
@@ -3564,7 +3630,7 @@ information like GPS tracks from MOV, MP4 and INSV media data.
|
|
|
3564
3630
|
|
|
3565
3631
|
=head1 AUTHOR
|
|
3566
3632
|
|
|
3567
|
-
Copyright 2003-
|
|
3633
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
3568
3634
|
|
|
3569
3635
|
This library is free software; you can redistribute it and/or modify it
|
|
3570
3636
|
under the same terms as Perl itself.
|