exiftool_vendored 13.10.0 → 13.12.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 +33 -0
- data/bin/MANIFEST +1 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +3 -3
- data/bin/exiftool +206 -148
- data/bin/lib/File/RandomAccess.pm +1 -1
- data/bin/lib/File/RandomAccess.pod +2 -2
- data/bin/lib/Image/ExifTool/AAC.pm +1 -1
- data/bin/lib/Image/ExifTool/AES.pm +1 -1
- data/bin/lib/Image/ExifTool/AFCP.pm +1 -1
- data/bin/lib/Image/ExifTool/AIFF.pm +1 -1
- data/bin/lib/Image/ExifTool/APE.pm +1 -1
- data/bin/lib/Image/ExifTool/APP12.pm +1 -1
- data/bin/lib/Image/ExifTool/ASF.pm +1 -1
- data/bin/lib/Image/ExifTool/Apple.pm +1 -1
- data/bin/lib/Image/ExifTool/Audible.pm +1 -1
- data/bin/lib/Image/ExifTool/BMP.pm +1 -1
- data/bin/lib/Image/ExifTool/BPG.pm +1 -1
- data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
- data/bin/lib/Image/ExifTool/BigTIFF.pm +1 -1
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +6 -6
- data/bin/lib/Image/ExifTool/CBOR.pm +1 -1
- data/bin/lib/Image/ExifTool/Canon.pm +8 -4
- data/bin/lib/Image/ExifTool/CanonCustom.pm +1 -1
- data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/CanonVRD.pm +1 -1
- data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
- data/bin/lib/Image/ExifTool/Casio.pm +1 -1
- data/bin/lib/Image/ExifTool/Charset.pm +1 -1
- data/bin/lib/Image/ExifTool/DICOM.pm +1 -1
- data/bin/lib/Image/ExifTool/DJI.pm +96 -45
- data/bin/lib/Image/ExifTool/DNG.pm +1 -1
- data/bin/lib/Image/ExifTool/DPX.pm +1 -1
- data/bin/lib/Image/ExifTool/DV.pm +1 -1
- data/bin/lib/Image/ExifTool/DarwinCore.pm +1 -1
- data/bin/lib/Image/ExifTool/DjVu.pm +1 -1
- data/bin/lib/Image/ExifTool/EXE.pm +123 -32
- data/bin/lib/Image/ExifTool/Exif.pm +7 -4
- data/bin/lib/Image/ExifTool/FITS.pm +1 -1
- data/bin/lib/Image/ExifTool/FLAC.pm +1 -1
- data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
- data/bin/lib/Image/ExifTool/FLIR.pm +1 -1
- data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
- data/bin/lib/Image/ExifTool/Flash.pm +1 -1
- data/bin/lib/Image/ExifTool/FlashPix.pm +1 -1
- data/bin/lib/Image/ExifTool/Font.pm +1 -1
- data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
- data/bin/lib/Image/ExifTool/FujiFilm.pm +1 -1
- data/bin/lib/Image/ExifTool/GE.pm +1 -1
- data/bin/lib/Image/ExifTool/GIF.pm +1 -1
- data/bin/lib/Image/ExifTool/GIMP.pm +1 -1
- data/bin/lib/Image/ExifTool/GM.pm +1 -1
- data/bin/lib/Image/ExifTool/GPS.pm +1 -1
- data/bin/lib/Image/ExifTool/GeoTiff.pm +1 -1
- data/bin/lib/Image/ExifTool/Geolocation.pm +1 -1
- data/bin/lib/Image/ExifTool/Geotag.pm +1 -1
- data/bin/lib/Image/ExifTool/GoPro.pm +1 -1
- data/bin/lib/Image/ExifTool/H264.pm +1 -1
- data/bin/lib/Image/ExifTool/HP.pm +1 -1
- data/bin/lib/Image/ExifTool/HTML.pm +1 -1
- data/bin/lib/Image/ExifTool/HtmlDump.pm +1 -1
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
- data/bin/lib/Image/ExifTool/ICO.pm +1 -1
- data/bin/lib/Image/ExifTool/ID3.pm +1 -1
- data/bin/lib/Image/ExifTool/IPTC.pm +8 -5
- data/bin/lib/Image/ExifTool/ISO.pm +1 -1
- data/bin/lib/Image/ExifTool/ITC.pm +1 -1
- data/bin/lib/Image/ExifTool/Import.pm +5 -4
- data/bin/lib/Image/ExifTool/InDesign.pm +1 -1
- data/bin/lib/Image/ExifTool/InfiRay.pm +1 -1
- data/bin/lib/Image/ExifTool/JPEG.pm +1 -1
- data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
- data/bin/lib/Image/ExifTool/JSON.pm +1 -1
- data/bin/lib/Image/ExifTool/JVC.pm +1 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +1 -1
- data/bin/lib/Image/ExifTool/Kodak.pm +1 -1
- data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/LIF.pm +1 -1
- data/bin/lib/Image/ExifTool/LNK.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/en_ca.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/en_gb.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/es.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/fi.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/fr.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/it.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/ja.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/ko.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/nl.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/pl.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/sk.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/tr.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
- data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
- data/bin/lib/Image/ExifTool/LigoGPS.pm +408 -0
- data/bin/lib/Image/ExifTool/Lytro.pm +1 -1
- data/bin/lib/Image/ExifTool/M2TS.pm +22 -13
- data/bin/lib/Image/ExifTool/MIE.pm +1 -1
- data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
- data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
- data/bin/lib/Image/ExifTool/MISB.pm +1 -1
- data/bin/lib/Image/ExifTool/MNG.pm +1 -1
- data/bin/lib/Image/ExifTool/MOI.pm +1 -1
- data/bin/lib/Image/ExifTool/MPC.pm +1 -1
- data/bin/lib/Image/ExifTool/MPEG.pm +1 -1
- data/bin/lib/Image/ExifTool/MPF.pm +1 -1
- data/bin/lib/Image/ExifTool/MRC.pm +1 -1
- data/bin/lib/Image/ExifTool/MWG.pm +1 -1
- data/bin/lib/Image/ExifTool/MXF.pm +1 -1
- data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
- data/bin/lib/Image/ExifTool/MakerNotes.pm +1 -1
- data/bin/lib/Image/ExifTool/Matroska.pm +12 -4
- data/bin/lib/Image/ExifTool/Microsoft.pm +1 -1
- data/bin/lib/Image/ExifTool/Minolta.pm +1 -1
- data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +164 -35
- data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
- data/bin/lib/Image/ExifTool/NikonCustom.pm +1 -1
- data/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
- data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
- data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
- data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
- data/bin/lib/Image/ExifTool/Olympus.pm +1 -1
- data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
- data/bin/lib/Image/ExifTool/Opus.pm +1 -1
- data/bin/lib/Image/ExifTool/Other.pm +1 -1
- data/bin/lib/Image/ExifTool/PCX.pm +1 -1
- data/bin/lib/Image/ExifTool/PDF.pm +1 -1
- data/bin/lib/Image/ExifTool/PGF.pm +1 -1
- data/bin/lib/Image/ExifTool/PICT.pm +1 -1
- data/bin/lib/Image/ExifTool/PLIST.pm +1 -1
- data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
- data/bin/lib/Image/ExifTool/PNG.pm +1 -1
- data/bin/lib/Image/ExifTool/PPM.pm +1 -1
- data/bin/lib/Image/ExifTool/PSP.pm +1 -1
- data/bin/lib/Image/ExifTool/Palm.pm +1 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +20 -2
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/Parrot.pm +1 -1
- data/bin/lib/Image/ExifTool/Pentax.pm +1 -1
- data/bin/lib/Image/ExifTool/PhaseOne.pm +1 -1
- data/bin/lib/Image/ExifTool/PhotoCD.pm +1 -1
- data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
- data/bin/lib/Image/ExifTool/Photoshop.pm +1 -1
- data/bin/lib/Image/ExifTool/PostScript.pm +1 -1
- data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
- data/bin/lib/Image/ExifTool/Protobuf.pm +24 -14
- data/bin/lib/Image/ExifTool/Qualcomm.pm +1 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +46 -17
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +20 -302
- data/bin/lib/Image/ExifTool/README +4 -0
- data/bin/lib/Image/ExifTool/RIFF.pm +1 -1
- data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
- data/bin/lib/Image/ExifTool/RTF.pm +1 -1
- data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
- data/bin/lib/Image/ExifTool/Rawzor.pm +1 -1
- data/bin/lib/Image/ExifTool/Real.pm +1 -1
- data/bin/lib/Image/ExifTool/Reconyx.pm +1 -1
- data/bin/lib/Image/ExifTool/Red.pm +1 -1
- data/bin/lib/Image/ExifTool/Ricoh.pm +1 -1
- data/bin/lib/Image/ExifTool/Samsung.pm +1 -1
- data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
- data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
- data/bin/lib/Image/ExifTool/Shift.pl +1 -1
- data/bin/lib/Image/ExifTool/Shortcuts.pm +1 -1
- data/bin/lib/Image/ExifTool/Sigma.pm +1 -1
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/Sony.pm +1 -1
- data/bin/lib/Image/ExifTool/SonyIDC.pm +1 -1
- data/bin/lib/Image/ExifTool/Stim.pm +1 -1
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +2 -2
- data/bin/lib/Image/ExifTool/TagLookup.pm +11 -5
- data/bin/lib/Image/ExifTool/TagNames.pod +84 -34
- data/bin/lib/Image/ExifTool/Text.pm +1 -1
- data/bin/lib/Image/ExifTool/Theora.pm +1 -1
- data/bin/lib/Image/ExifTool/Torrent.pm +1 -1
- data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
- data/bin/lib/Image/ExifTool/VCard.pm +1 -1
- data/bin/lib/Image/ExifTool/Validate.pm +1 -1
- data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
- data/bin/lib/Image/ExifTool/WPG.pm +1 -1
- data/bin/lib/Image/ExifTool/WTV.pm +1 -1
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePDF.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +5 -3
- data/bin/lib/Image/ExifTool/WriteRIFF.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
- data/bin/lib/Image/ExifTool/Writer.pl +9 -8
- data/bin/lib/Image/ExifTool/XISF.pm +1 -1
- data/bin/lib/Image/ExifTool/XMP.pm +1 -1
- data/bin/lib/Image/ExifTool/XMP2.pl +1 -1
- data/bin/lib/Image/ExifTool/XMPStruct.pl +1 -1
- data/bin/lib/Image/ExifTool/ZIP.pm +1 -1
- data/bin/lib/Image/ExifTool/ZISRAW.pm +1 -1
- data/bin/lib/Image/ExifTool/iWork.pm +1 -1
- data/bin/lib/Image/ExifTool.pm +13 -7
- data/bin/lib/Image/ExifTool.pod +14 -5
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +3 -2
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
#------------------------------------------------------------------------------
|
|
2
|
+
# File: LigoGPS.pm
|
|
3
|
+
#
|
|
4
|
+
# Description: Read LIGOGPSINFO timed GPS records
|
|
5
|
+
#
|
|
6
|
+
# Revisions: 2024-12-30 - P. Harvey Created
|
|
7
|
+
#------------------------------------------------------------------------------
|
|
8
|
+
package Image::ExifTool::LigoGPS;
|
|
9
|
+
|
|
10
|
+
use strict;
|
|
11
|
+
use vars qw($VERSION);
|
|
12
|
+
use Image::ExifTool;
|
|
13
|
+
|
|
14
|
+
$VERSION = '1.02';
|
|
15
|
+
|
|
16
|
+
sub ProcessLigoGPS($$$;$);
|
|
17
|
+
sub ProcessLigoJSON($$$);
|
|
18
|
+
sub OrderCipherDigits($$$;$);
|
|
19
|
+
|
|
20
|
+
my $knotsToKph = 1.852; # knots --> km/h
|
|
21
|
+
|
|
22
|
+
#------------------------------------------------------------------------------
|
|
23
|
+
# Clean up cipher variables and print warning if deciphering was unsuccessful
|
|
24
|
+
# Inputs: 0) ExifTool ref
|
|
25
|
+
sub CleanupCipher($)
|
|
26
|
+
{
|
|
27
|
+
my $et = shift;
|
|
28
|
+
if ($$et{LigoCipher} and $$et{LigoCipher}{'next'}) {
|
|
29
|
+
$et->Warn('Not enough GPS points to determine cipher for decoding LIGOGPSINFO');
|
|
30
|
+
}
|
|
31
|
+
delete $$et{LigoCipher};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#------------------------------------------------------------------------------
|
|
35
|
+
# Un-do LIGOGPS fuzzing
|
|
36
|
+
# Inputs: 0) fuzzed latitude, 1) fuzzed longitude, 2) scale factor
|
|
37
|
+
# Returns: 0) latitude, 1) longitude
|
|
38
|
+
sub UnfuzzLigoGPS($$$)
|
|
39
|
+
{
|
|
40
|
+
my ($lat, $lon, $scl) = @_;
|
|
41
|
+
my $lat2 = int($lat / 10) * 10;
|
|
42
|
+
my $lon2 = int($lon / 10) * 10;
|
|
43
|
+
return($lat2 + ($lon - $lon2) * $scl, $lon2 + ($lat - $lat2) * $scl);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#------------------------------------------------------------------------------
|
|
47
|
+
# Decrypt LIGOGPSINFO record (starting with "####")
|
|
48
|
+
# Inputs: 0) encrypted GPS record incuding 8-byte header
|
|
49
|
+
# Returns: decrypted record including 4-byte uint32 header, or undef on error
|
|
50
|
+
sub DecryptLigoGPS($)
|
|
51
|
+
{
|
|
52
|
+
my $str = shift;
|
|
53
|
+
my $num = unpack('x4V',$str);
|
|
54
|
+
return undef if $num < 4;
|
|
55
|
+
$num = 0x84 if $num > 0x84; # (be safe)
|
|
56
|
+
my @in = unpack("x8C$num",$str);
|
|
57
|
+
my @out;
|
|
58
|
+
while (@in) {
|
|
59
|
+
my $b = shift @in; # get next byte in data
|
|
60
|
+
# upper 3 bits steer the decryption for this round
|
|
61
|
+
my $steeringBits = $b & 0xe0;
|
|
62
|
+
if ($steeringBits >= 0xc0) {
|
|
63
|
+
return undef if @in < 4; # next 4 bytes are encrypted data
|
|
64
|
+
push @out, (shift(@in) | $b & 0x01) ^ 0x20,
|
|
65
|
+
(shift(@in) | $b & 0x02) ^ 0x20,
|
|
66
|
+
(shift(@in) | $b & 0x0c) ^ 0x20,
|
|
67
|
+
shift(@in) ^ 0x20 | $b & 0x30;
|
|
68
|
+
} elsif ($steeringBits >= 0x40) {
|
|
69
|
+
return undef if @in < 3; # next 3 bytes are encrypted data
|
|
70
|
+
if ($steeringBits == 0x40) {
|
|
71
|
+
push @out, 0x20,
|
|
72
|
+
(shift(@in) | $b & 0x01) ^ 0x20,
|
|
73
|
+
(shift(@in) | $b & 0x06) ^ 0x20,
|
|
74
|
+
(shift(@in) | $b & 0x18) ^ 0x20;
|
|
75
|
+
} elsif ($steeringBits == 0x60) {
|
|
76
|
+
push @out, (shift(@in) | $b & 0x03) ^ 0x20,
|
|
77
|
+
0x20,
|
|
78
|
+
(shift(@in) | $b & 0x04) ^ 0x20,
|
|
79
|
+
(shift(@in) | $b & 0x18) ^ 0x20;
|
|
80
|
+
} elsif ($steeringBits == 0x80) {
|
|
81
|
+
push @out, (shift(@in) | $b & 0x03) ^ 0x20,
|
|
82
|
+
(shift(@in) | $b & 0x0c) ^ 0x20,
|
|
83
|
+
0x20,
|
|
84
|
+
(shift(@in) | $b & 0x10) ^ 0x20;
|
|
85
|
+
} else {
|
|
86
|
+
push @out, (shift(@in) | $b & 0x01) ^ 0x20,
|
|
87
|
+
(shift(@in) | $b & 0x06) ^ 0x20,
|
|
88
|
+
(shift(@in) | $b & 0x18) ^ 0x20,
|
|
89
|
+
0x20;
|
|
90
|
+
}
|
|
91
|
+
} elsif ($steeringBits == 0x00) {
|
|
92
|
+
return undef if @in < 1; # next byte is encrypted data
|
|
93
|
+
push @out, shift(@in) | $b & 0x13;
|
|
94
|
+
} else {
|
|
95
|
+
return undef; # (shouldn't happen)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return pack 'C*', @out;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
#------------------------------------------------------------------------------
|
|
102
|
+
# Determine correct ordering of enciphered digits (unit digits of seconds)
|
|
103
|
+
# Inputs: 0) starting character code, 1) lookup for next character(s) in sequence
|
|
104
|
+
# 2) i/o list of ordered characters, 3) hash of used characters
|
|
105
|
+
# Returns: true if a consistent ordering was found
|
|
106
|
+
# - loops through all possible orders based on $next sequence until a complete
|
|
107
|
+
# cycle is established
|
|
108
|
+
# - this complexity is necessary because GPS may skip some seconds
|
|
109
|
+
sub OrderCipherDigits($$$;$)
|
|
110
|
+
{
|
|
111
|
+
my ($ch, $next, $order, $did) = @_;
|
|
112
|
+
$did or $did = { };
|
|
113
|
+
while ($$next{$ch}) {
|
|
114
|
+
if (@$order < 10) {
|
|
115
|
+
last if $$did{$ch};
|
|
116
|
+
} else {
|
|
117
|
+
# success if we have cycled through all 10 digits and back to the first
|
|
118
|
+
return 1 if @$order == 10 and $ch eq $$order[0];
|
|
119
|
+
last;
|
|
120
|
+
}
|
|
121
|
+
push @$order, $ch;
|
|
122
|
+
$$did{$ch} = 1;
|
|
123
|
+
# continue with next character if there is only one possibility
|
|
124
|
+
@{$$next{$ch}} == 1 and $ch = $$next{$ch}[0], next;
|
|
125
|
+
# otherwise, test all possibilities
|
|
126
|
+
my $n = $#$order;
|
|
127
|
+
foreach (@{$$next{$ch}}) {
|
|
128
|
+
my %did = %$did; # make a copy of the used-character lookup
|
|
129
|
+
return 1 if OrderCipherDigits($_, $next, $order, \%did);
|
|
130
|
+
$#$order = $n; # restore order and try next possibility
|
|
131
|
+
}
|
|
132
|
+
last;
|
|
133
|
+
}
|
|
134
|
+
return 0; # failure
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#------------------------------------------------------------------------------
|
|
138
|
+
# Decipher and parse LIGOGPSINFO record (starting with "####")
|
|
139
|
+
# Inputs: 0) ExifTool ref, 1) enciphered string, 2) tag table ref
|
|
140
|
+
# 3) true if GPS coordinates don't need de-fuzzing
|
|
141
|
+
# Returns: true if this looked like an enciphered string
|
|
142
|
+
# Notes: handles contained tags, but may defer handling until full cipher is known
|
|
143
|
+
sub DecipherLigoGPS($$$;$)
|
|
144
|
+
{
|
|
145
|
+
my ($et, $str, $tagTbl, $noFuzz) = @_;
|
|
146
|
+
|
|
147
|
+
# (enciphered characters must be in the range 0x30-0x5f ('0' - '_'))
|
|
148
|
+
$str =~ m[^####.{4}([0-_])[0-_]{3}/[0-_]{2}/[0-_]{2} ..([0-_])..([0-_]).([0-_]) ]s or return undef;
|
|
149
|
+
return undef unless $2 eq $3; # (colons in time string must be the same)
|
|
150
|
+
|
|
151
|
+
my $cipherInfo = $$et{LigoCipher};
|
|
152
|
+
unless ($cipherInfo) {
|
|
153
|
+
$cipherInfo = $$et{LigoCipher} = { cache => [ ], 'next' => { } };
|
|
154
|
+
$et->AddCleanup(\&CleanupCipher);
|
|
155
|
+
};
|
|
156
|
+
my $decipher = $$cipherInfo{decipher};
|
|
157
|
+
my $cache = $$cipherInfo{cache};
|
|
158
|
+
|
|
159
|
+
# determine the cipher code table based on the advancing 1's digit of seconds
|
|
160
|
+
unless ($decipher) {
|
|
161
|
+
push @$cache, $str; # cache records until we can decipher them
|
|
162
|
+
my $next = $$cipherInfo{next};
|
|
163
|
+
my ($millennium, $colon, $ch2) = ($1, $2, $4);
|
|
164
|
+
# determine the cipher lookup table
|
|
165
|
+
# (only characters in range 0x30-0x5f are encrypted)
|
|
166
|
+
my $ch1 = $$cipherInfo{ch1};
|
|
167
|
+
$$cipherInfo{ch1} = $ch2;
|
|
168
|
+
return 1 if not defined $ch1 or $ch1 eq $ch2; # ignore duplicate sequential digits
|
|
169
|
+
if ($$next{$ch1}) {
|
|
170
|
+
return 1 if grep /\Q$ch2\E/, @{$$next{$ch1}}; # don't add twice
|
|
171
|
+
push @{$$next{$ch1}}, $ch2;
|
|
172
|
+
} else {
|
|
173
|
+
$$next{$ch1} = [ $ch2 ];
|
|
174
|
+
}
|
|
175
|
+
# must wait until the lookup contains all 10 digits
|
|
176
|
+
scalar(keys %$next) < 10 and return 1;
|
|
177
|
+
# protect against trying to decipher bad data
|
|
178
|
+
scalar(keys %$next) > 10 and $$cipherInfo{'next'} = { }, return 1;
|
|
179
|
+
my (@order, $two);
|
|
180
|
+
return 1 unless OrderCipherDigits($ch1, $next, \@order);
|
|
181
|
+
# get index of enciphered "2" in ordered array
|
|
182
|
+
$order[$_] eq $millennium and $two = $_, last foreach 0..9;
|
|
183
|
+
defined $two or $et->Warn('Problem deciphering LIGOGPSINFO'), return 1;
|
|
184
|
+
delete $$cipherInfo{'next'}; # all done with 'next' lookup
|
|
185
|
+
my %decipher = ( $colon => ':' ); # (':' is the time separator)
|
|
186
|
+
foreach (0..9) {
|
|
187
|
+
my $ch = $order[($_ + $two - 2 + 10) % 10];
|
|
188
|
+
$decipher{$ch} = chr($_ + 0x30);
|
|
189
|
+
}
|
|
190
|
+
# may also know the lat/lon quadrant from the signs of the coordinates
|
|
191
|
+
if ($str =~ / ([0-_])$colon(-?).*? ([0-_])$colon(-?)/) {
|
|
192
|
+
@decipher{$1,$3} = ($2 ? 'S' : 'N', $4 ? 'W' : 'E');
|
|
193
|
+
unless ($2 or $4) {
|
|
194
|
+
my ($ns, $ew) = ($1, $3);
|
|
195
|
+
if ($$et{OPTIONS}{GPSQuadrant} and $$et{OPTIONS}{GPSQuadrant} =~ /^([NS])([EW])$/i) {
|
|
196
|
+
@decipher{$ns,$ew} = (uc($1), uc($2));
|
|
197
|
+
} else {
|
|
198
|
+
$et->Warn('May need to set API GPSQuadrant option (eg. "NW")');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
# fill in unknown entries with '?' (only chars 0x30-0x5f are enciphered)
|
|
203
|
+
defined $decipher{$_} or $decipher{$_} = '?' foreach map(chr, 0x30..0x5f);
|
|
204
|
+
$decipher = $$cipherInfo{decipher} = \%decipher;
|
|
205
|
+
$str = shift @$cache; # start deciphering at oldest cache entry
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
# apply reverse cipher and extract GPS information
|
|
209
|
+
do {
|
|
210
|
+
my $pre = substr($str, 4, 4); # save second 4 bytes of header
|
|
211
|
+
($str = substr($str,8)) =~ s/\0+$//; # remove 8-byte header and null padding
|
|
212
|
+
$str =~ s/([0-_])/$$decipher{$1}/g; # decipher
|
|
213
|
+
if ($$et{OPTIONS}{Verbose} > 1) {
|
|
214
|
+
$et->VPrint(1, "$$et{INDENT}\(Deciphered: ".unpack('H8',$pre)." $str)\n");
|
|
215
|
+
}
|
|
216
|
+
# add back leading 4 bytes (int16u counter plus 2 unknown bytes), and parse
|
|
217
|
+
ParseLigoGPS($et, "$pre$str", $tagTbl, $noFuzz);
|
|
218
|
+
} while $str = shift @$cache;
|
|
219
|
+
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#------------------------------------------------------------------------------
|
|
224
|
+
# Parse decrypted/deciphered (but not defuzzed) LIGOGPSINFO record
|
|
225
|
+
# (record starts with 4-byte int32u counter followed by date/time, etc)
|
|
226
|
+
# Inputs: 0) ExifTool ref, 1) GPS string, 2) tag table ref, 3) not fuzzed
|
|
227
|
+
# Returns: nothing
|
|
228
|
+
sub ParseLigoGPS($$$;$)
|
|
229
|
+
{
|
|
230
|
+
my ($et, $str, $tagTbl, $noFuzz) = @_;
|
|
231
|
+
|
|
232
|
+
# example string input
|
|
233
|
+
# "....2022/09/19 12:45:24 N:31.285065 W:124.759483 46.93 km/h x:-0.000 y:-0.000 z:-0.000"
|
|
234
|
+
unless ($str=~ /^.{4}(\S+ \S+)\s+([NS?]):(-?)([.\d]+)\s+([EW?]):(-?)([\.\d]+)\s+([.\d]+)/s) {
|
|
235
|
+
$et->Warn('LIGOGPSINFO format error');
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
my ($time,$latRef,$latNeg,$lat,$lonRef,$lonNeg,$lon,$spd) = ($1,$2,$3,$4,$5,$6,$7,$8);
|
|
239
|
+
my %gpsScl = ( 1 => 1.524855137, 2 => 1.456027985, 3 => 1.15368 );
|
|
240
|
+
my $spdScl = $noFuzz ? $knotsToKph : 1.85407333;
|
|
241
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
242
|
+
$time =~ tr(/)(:);
|
|
243
|
+
# convert from DDMM.MMMMMM to DD.DDDDDD if necessary
|
|
244
|
+
# (speed wasn't scaled in my 1 sample with this format)
|
|
245
|
+
$lat =~ /^\d{3}/ and Image::ExifTool::QuickTime::ConvertLatLon($lat,$lon), $spdScl = 1;
|
|
246
|
+
unless ($noFuzz) { # unfuzz the coordinates if necessary
|
|
247
|
+
my $scl = $$et{OPTIONS}{LigoGPSScale} || $$et{LigoGPSScale} || 1;
|
|
248
|
+
$scl = $gpsScl{$scl} if $gpsScl{$scl};
|
|
249
|
+
($lat, $lon) = UnfuzzLigoGPS($lat, $lon, $scl);
|
|
250
|
+
}
|
|
251
|
+
# a final sanity check
|
|
252
|
+
($lat > 90 or $lon > 180) and $et->Warn('LIGOGPSINFO coordinates out of range'), return;
|
|
253
|
+
$$et{SET_GROUP1} = 'LIGO';
|
|
254
|
+
$et->HandleTag($tagTbl, 'GPSDateTime', $time);
|
|
255
|
+
# (ignore N/S/E/W if coordinate is signed)
|
|
256
|
+
$et->HandleTag($tagTbl, 'GPSLatitude', $lat * (($latNeg or $latRef eq 'S') ? -1 : 1));
|
|
257
|
+
$et->HandleTag($tagTbl, 'GPSLongitude', $lon * (($lonNeg or $lonRef eq 'W') ? -1 : 1));
|
|
258
|
+
$et->HandleTag($tagTbl, 'GPSSpeed', $spd * $spdScl);
|
|
259
|
+
$et->HandleTag($tagTbl, 'GPSTrack', $1) if $str =~ /\bA:(\S+)/;
|
|
260
|
+
$et->HandleTag($tagTbl, 'GPSAltitude', $1) if $str =~ /\bH:(\S+)/;
|
|
261
|
+
$et->HandleTag($tagTbl, 'MagneticVariation', $1) if $str =~ /\bM:(\S+)/;
|
|
262
|
+
# (have a sample where tab is used to separate acc components)
|
|
263
|
+
$et->HandleTag($tagTbl, 'Accelerometer',"$1 $2 $3") if $str =~ /x:(\S+)\sy:(\S+)\sz:(\S+)/;
|
|
264
|
+
delete $$et{SET_GROUP1};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
#------------------------------------------------------------------------------
|
|
268
|
+
# Process LIGOGPSINFO data (non-JSON format)
|
|
269
|
+
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
|
270
|
+
# 3) 1=LIGOGPS lat/lon/spd weren't fuzzed
|
|
271
|
+
# Returns: 1 on success
|
|
272
|
+
sub ProcessLigoGPS($$$;$)
|
|
273
|
+
{
|
|
274
|
+
my ($et, $dirInfo, $tagTbl, $noFuzz) = @_;
|
|
275
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
276
|
+
my $pos = ($$dirInfo{DirStart} || 0) + 0x14;
|
|
277
|
+
return undef if $pos > length $$dataPt;
|
|
278
|
+
my $cipherInfo = $$et{LigoCipher};
|
|
279
|
+
my $dirName = $$dirInfo{DirName} || 'LigoGPS';
|
|
280
|
+
push @{$$et{PATH}}, $dirName unless $$dirInfo{DirID};
|
|
281
|
+
# not fuzzed if header =~ /LIGOGPSINFO\0\0\0\0[\x01\x14]/ (\x01=BlueSkySeaDV688)
|
|
282
|
+
$noFuzz = 1 if substr($$dataPt, $pos-8, 4) =~ /^\0\0\0[\x01\x14]/;
|
|
283
|
+
$et->VerboseDir($dirName);
|
|
284
|
+
for (; $pos + 0x84 <= length($$dataPt); $pos+=0x84) {
|
|
285
|
+
my $dat = substr($$dataPt, $pos, 0x84);
|
|
286
|
+
$dat =~ /^####/ or next; # (have seen blank records filled with zeros, so keep trying)
|
|
287
|
+
# decipher if we already know the encryption
|
|
288
|
+
$cipherInfo and $$cipherInfo{decipher} and DecipherLigoGPS($et, $dat, $tagTbl, $noFuzz) and next;
|
|
289
|
+
my $str = DecryptLigoGPS($dat);
|
|
290
|
+
defined $str or DecipherLigoGPS($et, $dat, $tagTbl, $noFuzz), next; # try to decipher
|
|
291
|
+
$et->VPrint(1, "$$et{INDENT}\(Decrypted: ",unpack('V',$str),' ',substr($str,4),")\n") if $$et{OPTIONS}{Verbose} > 1;
|
|
292
|
+
ParseLigoGPS($et, $str, $tagTbl, $noFuzz);
|
|
293
|
+
}
|
|
294
|
+
pop @{$$et{PATH}} unless $$dirInfo{DirID};
|
|
295
|
+
delete $$et{DOC_NUM};
|
|
296
|
+
return 1;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
#------------------------------------------------------------------------------
|
|
300
|
+
# Process LIGOGPSINFO JSON-format GPS (Yada RoadCam Pro 4K BT58189)
|
|
301
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
|
302
|
+
# Returns: 1 on success
|
|
303
|
+
# Sample data (chained 512-byte records starting like this):
|
|
304
|
+
# 0000: 4c 49 47 4f 47 50 53 49 4e 46 4f 20 7b 22 48 6f [LIGOGPSINFO {"Ho]
|
|
305
|
+
# 0010: 75 72 22 3a 20 22 32 33 22 2c 20 22 4d 69 6e 75 [ur": "23", "Minu]
|
|
306
|
+
# 0020: 74 65 22 3a 20 22 31 30 22 2c 20 22 53 65 63 6f [te": "10", "Seco]
|
|
307
|
+
# 0030: 6e 64 22 3a 20 22 32 32 22 2c 20 22 59 65 61 72 [nd": "22", "Year]
|
|
308
|
+
# 0040: 22 3a 20 22 32 30 32 33 22 2c 20 22 4d 6f 6e 74 [": "2023", "Mont]
|
|
309
|
+
# 0050: 68 22 3a 20 22 31 32 22 2c 20 22 44 61 79 22 3a [h": "12", "Day":]
|
|
310
|
+
# 0060: 20 22 32 38 22 2c 20 22 73 74 61 74 75 73 22 3a [ "28", "status":]
|
|
311
|
+
sub ProcessLigoJSON($$$)
|
|
312
|
+
{
|
|
313
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
|
314
|
+
my $dataPt = $$dirInfo{DataPt};
|
|
315
|
+
my $dirLen = $$dirInfo{DirLen};
|
|
316
|
+
require Image::ExifTool::Import;
|
|
317
|
+
$et->VerboseDir('LIGO_JSON', undef, length($$dataPt));
|
|
318
|
+
$$et{SET_GROUP1} = 'LIGO';
|
|
319
|
+
while ($$dataPt =~ /LIGOGPSINFO (\{.*?\})/g) {
|
|
320
|
+
my $json = $1;
|
|
321
|
+
my %dbase;
|
|
322
|
+
Image::ExifTool::Import::ReadJSON(\$json, \%dbase);
|
|
323
|
+
my $info = $dbase{'*'} or next;
|
|
324
|
+
# my sample contains the following JSON fields (in this order):
|
|
325
|
+
# Hour Minute Second Year Month Day (GPS UTC time)
|
|
326
|
+
# status NS EW Latitude Longitude Speed (speed in knots)
|
|
327
|
+
# GsensorX GsensorY GsensorZ (units? - only seen "000" for all)
|
|
328
|
+
# MHour MMinute MSecond MYear MMonth MDay (local dashcam clock time)
|
|
329
|
+
# OLatitude OLongitude (? same values as Latitude/Longitude)
|
|
330
|
+
next unless defined $$info{status} and $$info{status} eq 'A'; # only read if GPS is active
|
|
331
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
332
|
+
my $num = 0;
|
|
333
|
+
defined $$info{$_} and ++$num foreach qw(Year Month Day Hour Minute Second);
|
|
334
|
+
if ($num == 6) {
|
|
335
|
+
# this is the GPS time in UTC
|
|
336
|
+
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ',@$info{qw{Year Month Day Hour Minute Second}});
|
|
337
|
+
$et->HandleTag($tagTbl, GPSDateTime => $time);
|
|
338
|
+
}
|
|
339
|
+
if ($$info{Latitude} and $$info{Longitude}) {
|
|
340
|
+
my $lat = $$info{Latitude};
|
|
341
|
+
$lat = -$lat if $$info{NS} and $$info{NS} eq 'S';
|
|
342
|
+
my $lon = $$info{Longitude};
|
|
343
|
+
$lon = -$lon if $$info{EW} and $$info{EW} eq 'W';
|
|
344
|
+
$et->HandleTag($tagTbl, GPSLatitude => $lat);
|
|
345
|
+
$et->HandleTag($tagTbl, GPSLongitude => $lon);
|
|
346
|
+
}
|
|
347
|
+
$et->HandleTag($tagTbl, GPSSpeed => $$info{Speed} * $knotsToKph) if defined $$info{Speed};
|
|
348
|
+
if (defined $$info{GsensorX} and defined $$info{GsensorY} and defined $$info{GsensorZ}) {
|
|
349
|
+
# (don't know conversion factor for accel data, so leave it raw for now)
|
|
350
|
+
$et->HandleTag($tagTbl, Accelerometer => "$$info{GsensorX} $$info{GsensorY} $$info{GsensorZ}");
|
|
351
|
+
}
|
|
352
|
+
$num = 0;
|
|
353
|
+
defined $$info{$_} and ++$num foreach qw(MYear MMonth MDay MHour MMinute MSecond);
|
|
354
|
+
if ($num == 6) {
|
|
355
|
+
# this is the dashcam clock time (local time zone)
|
|
356
|
+
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d',@$info{qw{MYear MMonth MDay MHour MMinute MSecond}});
|
|
357
|
+
$et->HandleTag($tagTbl, DateTimeOriginal => $time);
|
|
358
|
+
}
|
|
359
|
+
if (defined $$info{OLatitude} and defined $$info{OLongitude}) {
|
|
360
|
+
my $lat = $$info{OLatitude};
|
|
361
|
+
$lat = -$lat if $$info{NS} and $$info{NS} eq 'S';
|
|
362
|
+
my $lon = $$info{OLongitude};
|
|
363
|
+
$lon = -$lon if $$info{EW} and $$info{EW} eq 'W';
|
|
364
|
+
$et->HandleTag($tagTbl, GPSLatitude2 => $lat);
|
|
365
|
+
$et->HandleTag($tagTbl, GPSLongitude2 => $lon);
|
|
366
|
+
}
|
|
367
|
+
unless ($et->Options('ExtractEmbedded')) {
|
|
368
|
+
$et->Warn('Use the ExtractEmbedded option to extract all timed GPS',3);
|
|
369
|
+
last;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
delete $$et{DOC_NUM};
|
|
373
|
+
delete $$et{SET_GROUP1};
|
|
374
|
+
return 1;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
1; #end
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
__END__
|
|
381
|
+
|
|
382
|
+
=head1 NAME
|
|
383
|
+
|
|
384
|
+
Image::ExifTool::LigoGPS - Read LIGOGPSINFO timed GPS records
|
|
385
|
+
|
|
386
|
+
=head1 SYNOPSIS
|
|
387
|
+
|
|
388
|
+
This module is loaded automatically by Image::ExifTool when required.
|
|
389
|
+
|
|
390
|
+
=head1 DESCRIPTION
|
|
391
|
+
|
|
392
|
+
This module decrypts, deciphers and decodes timed GPS metadata from
|
|
393
|
+
LIGOGPSINFO records found in various locations of MP4 and M2TS videos from a
|
|
394
|
+
variety of dashcam makes and models.
|
|
395
|
+
|
|
396
|
+
=head1 AUTHOR
|
|
397
|
+
|
|
398
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
399
|
+
|
|
400
|
+
This library is free software; you can redistribute it and/or modify it
|
|
401
|
+
under the same terms as Perl itself.
|
|
402
|
+
|
|
403
|
+
=head1 SEE ALSO
|
|
404
|
+
|
|
405
|
+
L<Image::ExifTool::TagNames/QuickTime Stream Tags>,
|
|
406
|
+
L<Image::ExifTool(3pm)|Image::ExifTool>
|
|
407
|
+
|
|
408
|
+
=cut
|
|
@@ -192,7 +192,7 @@ from Lytro Light Field Picture (LFP) files.
|
|
|
192
192
|
|
|
193
193
|
=head1 AUTHOR
|
|
194
194
|
|
|
195
|
-
Copyright 2003-
|
|
195
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
196
196
|
|
|
197
197
|
This library is free software; you can redistribute it and/or modify it
|
|
198
198
|
under the same terms as Perl itself.
|
|
@@ -32,7 +32,7 @@ use strict;
|
|
|
32
32
|
use vars qw($VERSION);
|
|
33
33
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
34
34
|
|
|
35
|
-
$VERSION = '1.
|
|
35
|
+
$VERSION = '1.29';
|
|
36
36
|
|
|
37
37
|
# program map table "stream_type" lookup (ref 6/1/9)
|
|
38
38
|
my %streamType = (
|
|
@@ -310,7 +310,7 @@ sub ParsePID($$$$$)
|
|
|
310
310
|
if ($$dataPt =~ /^LIGOGPSINFO/s) {
|
|
311
311
|
my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
|
312
312
|
my %dirInfo = ( DataPt => $dataPt, DirName => 'Ligo0x0300' );
|
|
313
|
-
Image::ExifTool::
|
|
313
|
+
Image::ExifTool::LigoGPS::ProcessLigoGPS($et, \%dirInfo, $tbl, 1);
|
|
314
314
|
$$et{FoundGoodGPS} = 1;
|
|
315
315
|
$more = 1;
|
|
316
316
|
}
|
|
@@ -437,13 +437,16 @@ sub ParsePID($$$$$)
|
|
|
437
437
|
$more = 1;
|
|
438
438
|
} elsif ($$dataPt =~ /\$GPRMC,/) {
|
|
439
439
|
# Jomise T860S-GM dashcam
|
|
440
|
-
# $GPRMC,hhmmss.ss,A,ddmm.mmmmm,N,dddmm.mmmmm,W,spd-kts,dir-dg,DDMMYY
|
|
441
|
-
# $GPRMC,172255.00,A,:985.95194,N,17170.14674,W,029.678,170.68,240822,,,D*7B
|
|
442
|
-
# $GPRMC,
|
|
443
|
-
#
|
|
444
|
-
#
|
|
445
|
-
#
|
|
446
|
-
#
|
|
440
|
+
# $GPRMC,hhmmss.ss,A,ddmm.mmmmm,N,dddmm.mmmmm,W,spd-kts,dir-dg,DDMMYY,,M*cs - lat,lon,spd from video
|
|
441
|
+
# $GPRMC,172255.00,A,:985.95194,N,17170.14674,W,029.678,170.68,240822,,,D*7B - N47.70428,W122.15338,35mph
|
|
442
|
+
# $GPRMC,192643.00,A,:987.94979,N,17171.07268,W,010.059,079.61,111122,,,A*73 - N47.71862,W122.16437,12mph
|
|
443
|
+
# $GPRMC,192743.00,A,:988.72110,N,17171.04873,W,017.477,001.03,111122,,,A*78 - N47.72421,W122.16408,20mph
|
|
444
|
+
# $GPRMC,192844.00,A,:989.43771,N,17171.03538,W,016.889,001.20,111122,,,A*7B - N47.72932,W122.16393,19mph
|
|
445
|
+
# $GPRMC,005241.00,A,:987.70873,N,17171.81293,W,000.284,354.78,141122,,,A*7F - N47.71687,W122.17318,0mph
|
|
446
|
+
# $GPRMC,005341.00,A,:987.90851,N,17171.85380,W,000.080,349.36,141122,,,A*7C - N47.71832,W122.17367,0mph
|
|
447
|
+
# $GPRMC,005441.00,A,:987.94538,N,17171.21783,W,029.686,091.09,141122,,,A*7A - N47.71859,W122.16630,35mph
|
|
448
|
+
# $GPRMC,002816.00,A,6820.67273,N,13424.26599,W,000.045,000.00,261122,,,A*79 - N29.52096,W95.55953,0mph (seattle)
|
|
449
|
+
# $GPRMC,035136.00,A,:981.47322,N,17170.14105,W,024.594,180.50,291122,,,D*79 - N47.67180,W122.15328,28mph
|
|
447
450
|
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
|
448
451
|
while ($$dataPt =~ /\$[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(.{2})(\d{2}\.\d+),([NS]),(.{3})(\d{2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/g and
|
|
449
452
|
# do some basic sanity checks on the date
|
|
@@ -477,6 +480,11 @@ sub ParsePID($$$$$)
|
|
|
477
480
|
$et->HandleTag($tagTbl, GPSLongitude => (($lo || 0) + (($9-70.14674)/1.460987654320988+9.2028)/60) * ($10 eq 'E' ? 1 : -1));
|
|
478
481
|
}
|
|
479
482
|
}
|
|
483
|
+
} elsif ($$dataPt =~ /\$GSENSORD,\s*(\d+),\s*(\d+),\s*(\d+),/) {
|
|
484
|
+
# Jomise T860S-GM dashcam
|
|
485
|
+
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
|
486
|
+
$$et{DOC_NUM} = $$et{DOC_COUNT};
|
|
487
|
+
$et->HandleTag($tagTbl, Accelerometer => "$1 $2 $3"); # (NC - values range from 0 to 6)
|
|
480
488
|
} elsif ($$dataPt =~ /^.{44}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s and length($$dataPt) >= 84) {
|
|
481
489
|
#forum11320
|
|
482
490
|
SetByteOrder('II');
|
|
@@ -531,7 +539,7 @@ sub ParsePID($$$$$)
|
|
|
531
539
|
# only extract data from the first one)
|
|
532
540
|
my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
|
533
541
|
my %dirInfo = ( DataPt => $dataPt, DirStart => 8, DirName => sprintf('Ligo0x%.4x',$pid));
|
|
534
|
-
Image::ExifTool::
|
|
542
|
+
Image::ExifTool::LigoGPS::ProcessLigoGPS($et, \%dirInfo, $tbl, 1);
|
|
535
543
|
$$et{FoundGoodGPS} = 1;
|
|
536
544
|
} elsif ($$et{FoundGoodGPS}) {
|
|
537
545
|
$more = 1;
|
|
@@ -592,7 +600,8 @@ sub ProcessM2TS($$)
|
|
|
592
600
|
my %gpsPID = (
|
|
593
601
|
0x0300 => 1, # Novatek INNOVV, DOD_LS600W
|
|
594
602
|
0x01e4 => 1, # vsys a6l dashcam
|
|
595
|
-
0x0e1b => 1, # Jomise T860S-GM dashcam
|
|
603
|
+
0x0e1b => 1, # Jomise T860S-GM dashcam GPS
|
|
604
|
+
0x0e1a => 1, # Jomise T860S-GM dashcam accelerometer
|
|
596
605
|
);
|
|
597
606
|
my $pEnd = 0;
|
|
598
607
|
|
|
@@ -980,7 +989,7 @@ sub ProcessM2TS($$)
|
|
|
980
989
|
if ($len < $raf->Tell() and $raf->Seek(-$len, 2) and $raf->Read($buff,$len) == $len) {
|
|
981
990
|
my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
|
982
991
|
my %dirInfo = ( DataPt => \$buff, DirStart => 8, DirName => 'LigoTrailer' );
|
|
983
|
-
Image::ExifTool::
|
|
992
|
+
Image::ExifTool::LigoGPS::ProcessLigoGPS($et, \%dirInfo, $tbl);
|
|
984
993
|
}
|
|
985
994
|
}
|
|
986
995
|
|
|
@@ -1007,7 +1016,7 @@ video.
|
|
|
1007
1016
|
|
|
1008
1017
|
=head1 AUTHOR
|
|
1009
1018
|
|
|
1010
|
-
Copyright 2003-
|
|
1019
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
1011
1020
|
|
|
1012
1021
|
This library is free software; you can redistribute it and/or modify it
|
|
1013
1022
|
under the same terms as Perl itself.
|
|
@@ -2557,7 +2557,7 @@ tag name. For example:
|
|
|
2557
2557
|
|
|
2558
2558
|
=head1 AUTHOR
|
|
2559
2559
|
|
|
2560
|
-
Copyright 2003-
|
|
2560
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
2561
2561
|
|
|
2562
2562
|
This library is free software; you can redistribute it and/or modify it
|
|
2563
2563
|
under the same terms as Perl itself. The MIE format itself is also
|
|
@@ -356,7 +356,7 @@ A few examples of combined units strings:
|
|
|
356
356
|
|
|
357
357
|
=head1 AUTHOR
|
|
358
358
|
|
|
359
|
-
Copyright 2003-
|
|
359
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
360
360
|
|
|
361
361
|
This library is free software; you can redistribute it and/or modify it
|
|
362
362
|
under the same terms as Perl itself.
|
|
@@ -255,7 +255,7 @@ This module contains routines required by Image::ExifTool to read MIFF
|
|
|
255
255
|
|
|
256
256
|
=head1 AUTHOR
|
|
257
257
|
|
|
258
|
-
Copyright 2003-
|
|
258
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
259
259
|
|
|
260
260
|
This library is free software; you can redistribute it and/or modify it
|
|
261
261
|
under the same terms as Perl itself.
|
|
@@ -468,7 +468,7 @@ Board (MISB) KLV-format metadata from M2TS videos.
|
|
|
468
468
|
|
|
469
469
|
=head1 AUTHOR
|
|
470
470
|
|
|
471
|
-
Copyright 2003-
|
|
471
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
472
472
|
|
|
473
473
|
This library is free software; you can redistribute it and/or modify it
|
|
474
474
|
under the same terms as Perl itself.
|
|
@@ -661,7 +661,7 @@ This module contains definitions required by Image::ExifTool to read MNG
|
|
|
661
661
|
|
|
662
662
|
=head1 AUTHOR
|
|
663
663
|
|
|
664
|
-
Copyright 2003-
|
|
664
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
665
665
|
|
|
666
666
|
This library is free software; you can redistribute it and/or modify it
|
|
667
667
|
under the same terms as Perl itself.
|
|
@@ -137,7 +137,7 @@ information from MOI files.
|
|
|
137
137
|
|
|
138
138
|
=head1 AUTHOR
|
|
139
139
|
|
|
140
|
-
Copyright 2003-
|
|
140
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
141
141
|
|
|
142
142
|
This library is free software; you can redistribute it and/or modify it
|
|
143
143
|
under the same terms as Perl itself.
|
|
@@ -134,7 +134,7 @@ information from Musepack (MPC) audio files.
|
|
|
134
134
|
|
|
135
135
|
=head1 AUTHOR
|
|
136
136
|
|
|
137
|
-
Copyright 2003-
|
|
137
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
138
138
|
|
|
139
139
|
This library is free software; you can redistribute it and/or modify it
|
|
140
140
|
under the same terms as Perl itself.
|
|
@@ -704,7 +704,7 @@ based on unofficial sources which may be incomplete, inaccurate or outdated.
|
|
|
704
704
|
|
|
705
705
|
=head1 AUTHOR
|
|
706
706
|
|
|
707
|
-
Copyright 2003-
|
|
707
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
708
708
|
|
|
709
709
|
This library is free software; you can redistribute it and/or modify it
|
|
710
710
|
under the same terms as Perl itself.
|
|
@@ -267,7 +267,7 @@ Format (MPF) information from JPEG images.
|
|
|
267
267
|
|
|
268
268
|
=head1 AUTHOR
|
|
269
269
|
|
|
270
|
-
Copyright 2003-
|
|
270
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
271
271
|
|
|
272
272
|
This library is free software; you can redistribute it and/or modify it
|
|
273
273
|
under the same terms as Perl itself.
|
|
@@ -315,7 +315,7 @@ metadata from Medical Research Council (MRC) images.
|
|
|
315
315
|
|
|
316
316
|
=head1 AUTHOR
|
|
317
317
|
|
|
318
|
-
Copyright 2003-
|
|
318
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
319
319
|
|
|
320
320
|
This library is free software; you can redistribute it and/or modify it
|
|
321
321
|
under the same terms as Perl itself.
|
|
@@ -757,7 +757,7 @@ must be loaded explicitly as described above.
|
|
|
757
757
|
|
|
758
758
|
=head1 AUTHOR
|
|
759
759
|
|
|
760
|
-
Copyright 2003-
|
|
760
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
761
761
|
|
|
762
762
|
This library is free software; you can redistribute it and/or modify it
|
|
763
763
|
under the same terms as Perl itself.
|
|
@@ -2987,7 +2987,7 @@ information from MXF (Material Exchange Format) files.
|
|
|
2987
2987
|
|
|
2988
2988
|
=head1 AUTHOR
|
|
2989
2989
|
|
|
2990
|
-
Copyright 2003-
|
|
2990
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
2991
2991
|
|
|
2992
2992
|
This library is free software; you can redistribute it and/or modify it
|
|
2993
2993
|
under the same terms as Perl itself.
|
|
@@ -737,7 +737,7 @@ Writable tags use "xattr", "setfile" or "osascript" for writing.
|
|
|
737
737
|
|
|
738
738
|
=head1 AUTHOR
|
|
739
739
|
|
|
740
|
-
Copyright 2003-
|
|
740
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
741
741
|
|
|
742
742
|
This library is free software; you can redistribute it and/or modify it
|
|
743
743
|
under the same terms as Perl itself.
|
|
@@ -1831,7 +1831,7 @@ maker notes in EXIF information.
|
|
|
1831
1831
|
|
|
1832
1832
|
=head1 AUTHOR
|
|
1833
1833
|
|
|
1834
|
-
Copyright 2003-
|
|
1834
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
|
1835
1835
|
|
|
1836
1836
|
This library is free software; you can redistribute it and/or modify it
|
|
1837
1837
|
under the same terms as Perl itself.
|