exiftool_vendored 13.10.0 → 13.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/Changes +82 -19
- data/bin/MANIFEST +6 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +3 -3
- data/bin/arg_files/exif2xmp.args +4 -0
- data/bin/arg_files/xmp2exif.args +2 -1
- data/bin/build_geolocation +1 -1
- data/bin/exiftool +208 -150
- 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 +6 -6
- 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 +29 -18
- 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 +150 -46
- 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 +17 -8
- 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 +6 -2
- 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 +409 -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 +166 -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 +48 -20
- data/bin/lib/Image/ExifTool/Qualcomm.pm +1 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +206 -66
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +21 -303
- 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 +2 -2
- 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 +3449 -3435
- data/bin/lib/Image/ExifTool/TagNames.pod +164 -47
- 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 +3 -3
- 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/Vivo.pm +124 -0
- 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 +74 -43
- 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 +21 -16
- 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 +34 -12
- data/bin/lib/Image/ExifTool.pod +57 -46
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +4 -2
@@ -1258,7 +1258,7 @@ and values.
|
|
1258
1258
|
|
1259
1259
|
=head1 AUTHOR
|
1260
1260
|
|
1261
|
-
Copyright 2003-
|
1261
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
1262
1262
|
|
1263
1263
|
This library is free software; you can redistribute it and/or modify it
|
1264
1264
|
under the same terms as Perl itself.
|
@@ -5718,7 +5718,7 @@ and values.
|
|
5718
5718
|
|
5719
5719
|
=head1 AUTHOR
|
5720
5720
|
|
5721
|
-
Copyright 2003-
|
5721
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
5722
5722
|
|
5723
5723
|
This library is free software; you can redistribute it and/or modify it
|
5724
5724
|
under the same terms as Perl itself.
|
@@ -1789,7 +1789,7 @@ and values.
|
|
1789
1789
|
|
1790
1790
|
=head1 AUTHOR
|
1791
1791
|
|
1792
|
-
Copyright 2003-
|
1792
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
1793
1793
|
|
1794
1794
|
This library is free software; you can redistribute it and/or modify it
|
1795
1795
|
under the same terms as Perl itself.
|
@@ -620,7 +620,7 @@ and values.
|
|
620
620
|
|
621
621
|
=head1 AUTHOR
|
622
622
|
|
623
|
-
Copyright 2003-
|
623
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
624
624
|
|
625
625
|
This library is free software; you can redistribute it and/or modify it
|
626
626
|
under the same terms as Perl itself.
|
@@ -528,7 +528,7 @@ and values.
|
|
528
528
|
|
529
529
|
=head1 AUTHOR
|
530
530
|
|
531
|
-
Copyright 2003-
|
531
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
532
532
|
|
533
533
|
This library is free software; you can redistribute it and/or modify it
|
534
534
|
under the same terms as Perl itself.
|
@@ -1313,7 +1313,7 @@ and values.
|
|
1313
1313
|
|
1314
1314
|
=head1 AUTHOR
|
1315
1315
|
|
1316
|
-
Copyright 2003-
|
1316
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
1317
1317
|
|
1318
1318
|
This library is free software; you can redistribute it and/or modify it
|
1319
1319
|
under the same terms as Perl itself.
|
@@ -784,7 +784,7 @@ and values.
|
|
784
784
|
|
785
785
|
=head1 AUTHOR
|
786
786
|
|
787
|
-
Copyright 2003-
|
787
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
788
788
|
|
789
789
|
This library is free software; you can redistribute it and/or modify it
|
790
790
|
under the same terms as Perl itself.
|
@@ -504,7 +504,7 @@ Capture.
|
|
504
504
|
|
505
505
|
=head1 AUTHOR
|
506
506
|
|
507
|
-
Copyright 2003-
|
507
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
508
508
|
|
509
509
|
This library is free software; you can redistribute it and/or modify it
|
510
510
|
under the same terms as Perl itself.
|
@@ -0,0 +1,409 @@
|
|
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
|
+
# Notes: The directory data should start with the string "LIGOGPSINFO\0"
|
273
|
+
sub ProcessLigoGPS($$$;$)
|
274
|
+
{
|
275
|
+
my ($et, $dirInfo, $tagTbl, $noFuzz) = @_;
|
276
|
+
my $dataPt = $$dirInfo{DataPt};
|
277
|
+
my $pos = ($$dirInfo{DirStart} || 0) + 0x14;
|
278
|
+
return undef if $pos > length $$dataPt;
|
279
|
+
my $cipherInfo = $$et{LigoCipher};
|
280
|
+
my $dirName = $$dirInfo{DirName} || 'LigoGPS';
|
281
|
+
push @{$$et{PATH}}, $dirName unless $$dirInfo{DirID};
|
282
|
+
# not fuzzed if header =~ /LIGOGPSINFO\0\0\0\0[\x01\x14]/ (\x01=BlueSkySeaDV688)
|
283
|
+
$noFuzz = 1 if substr($$dataPt, $pos-8, 4) =~ /^\0\0\0[\x01\x14]/;
|
284
|
+
$et->VerboseDir($dirName);
|
285
|
+
for (; $pos + 0x84 <= length($$dataPt); $pos+=0x84) {
|
286
|
+
my $dat = substr($$dataPt, $pos, 0x84);
|
287
|
+
$dat =~ /^####/ or next; # (have seen blank records filled with zeros, so keep trying)
|
288
|
+
# decipher if we already know the encryption
|
289
|
+
$cipherInfo and $$cipherInfo{decipher} and DecipherLigoGPS($et, $dat, $tagTbl, $noFuzz) and next;
|
290
|
+
my $str = DecryptLigoGPS($dat);
|
291
|
+
defined $str or DecipherLigoGPS($et, $dat, $tagTbl, $noFuzz), next; # try to decipher
|
292
|
+
$et->VPrint(1, "$$et{INDENT}\(Decrypted: ",unpack('V',$str),' ',substr($str,4),")\n") if $$et{OPTIONS}{Verbose} > 1;
|
293
|
+
ParseLigoGPS($et, $str, $tagTbl, $noFuzz);
|
294
|
+
}
|
295
|
+
pop @{$$et{PATH}} unless $$dirInfo{DirID};
|
296
|
+
delete $$et{DOC_NUM};
|
297
|
+
return 1;
|
298
|
+
}
|
299
|
+
|
300
|
+
#------------------------------------------------------------------------------
|
301
|
+
# Process LIGOGPSINFO JSON-format GPS (Yada RoadCam Pro 4K BT58189)
|
302
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
|
303
|
+
# Returns: 1 on success
|
304
|
+
# Sample data (chained 512-byte records starting like this):
|
305
|
+
# 0000: 4c 49 47 4f 47 50 53 49 4e 46 4f 20 7b 22 48 6f [LIGOGPSINFO {"Ho]
|
306
|
+
# 0010: 75 72 22 3a 20 22 32 33 22 2c 20 22 4d 69 6e 75 [ur": "23", "Minu]
|
307
|
+
# 0020: 74 65 22 3a 20 22 31 30 22 2c 20 22 53 65 63 6f [te": "10", "Seco]
|
308
|
+
# 0030: 6e 64 22 3a 20 22 32 32 22 2c 20 22 59 65 61 72 [nd": "22", "Year]
|
309
|
+
# 0040: 22 3a 20 22 32 30 32 33 22 2c 20 22 4d 6f 6e 74 [": "2023", "Mont]
|
310
|
+
# 0050: 68 22 3a 20 22 31 32 22 2c 20 22 44 61 79 22 3a [h": "12", "Day":]
|
311
|
+
# 0060: 20 22 32 38 22 2c 20 22 73 74 61 74 75 73 22 3a [ "28", "status":]
|
312
|
+
sub ProcessLigoJSON($$$)
|
313
|
+
{
|
314
|
+
my ($et, $dirInfo, $tagTbl) = @_;
|
315
|
+
my $dataPt = $$dirInfo{DataPt};
|
316
|
+
my $dirLen = $$dirInfo{DirLen};
|
317
|
+
require Image::ExifTool::Import;
|
318
|
+
$et->VerboseDir('LIGO_JSON', undef, length($$dataPt));
|
319
|
+
$$et{SET_GROUP1} = 'LIGO';
|
320
|
+
while ($$dataPt =~ /LIGOGPSINFO (\{.*?\})/g) {
|
321
|
+
my $json = $1;
|
322
|
+
my %dbase;
|
323
|
+
Image::ExifTool::Import::ReadJSON(\$json, \%dbase);
|
324
|
+
my $info = $dbase{'*'} or next;
|
325
|
+
# my sample contains the following JSON fields (in this order):
|
326
|
+
# Hour Minute Second Year Month Day (GPS UTC time)
|
327
|
+
# status NS EW Latitude Longitude Speed (speed in knots)
|
328
|
+
# GsensorX GsensorY GsensorZ (units? - only seen "000" for all)
|
329
|
+
# MHour MMinute MSecond MYear MMonth MDay (local dashcam clock time)
|
330
|
+
# OLatitude OLongitude (? same values as Latitude/Longitude)
|
331
|
+
next unless defined $$info{status} and $$info{status} eq 'A'; # only read if GPS is active
|
332
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
333
|
+
my $num = 0;
|
334
|
+
defined $$info{$_} and ++$num foreach qw(Year Month Day Hour Minute Second);
|
335
|
+
if ($num == 6) {
|
336
|
+
# this is the GPS time in UTC
|
337
|
+
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ',@$info{qw{Year Month Day Hour Minute Second}});
|
338
|
+
$et->HandleTag($tagTbl, GPSDateTime => $time);
|
339
|
+
}
|
340
|
+
if ($$info{Latitude} and $$info{Longitude}) {
|
341
|
+
my $lat = $$info{Latitude};
|
342
|
+
$lat = -$lat if $$info{NS} and $$info{NS} eq 'S';
|
343
|
+
my $lon = $$info{Longitude};
|
344
|
+
$lon = -$lon if $$info{EW} and $$info{EW} eq 'W';
|
345
|
+
$et->HandleTag($tagTbl, GPSLatitude => $lat);
|
346
|
+
$et->HandleTag($tagTbl, GPSLongitude => $lon);
|
347
|
+
}
|
348
|
+
$et->HandleTag($tagTbl, GPSSpeed => $$info{Speed} * $knotsToKph) if defined $$info{Speed};
|
349
|
+
if (defined $$info{GsensorX} and defined $$info{GsensorY} and defined $$info{GsensorZ}) {
|
350
|
+
# (don't know conversion factor for accel data, so leave it raw for now)
|
351
|
+
$et->HandleTag($tagTbl, Accelerometer => "$$info{GsensorX} $$info{GsensorY} $$info{GsensorZ}");
|
352
|
+
}
|
353
|
+
$num = 0;
|
354
|
+
defined $$info{$_} and ++$num foreach qw(MYear MMonth MDay MHour MMinute MSecond);
|
355
|
+
if ($num == 6) {
|
356
|
+
# this is the dashcam clock time (local time zone)
|
357
|
+
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d',@$info{qw{MYear MMonth MDay MHour MMinute MSecond}});
|
358
|
+
$et->HandleTag($tagTbl, DateTimeOriginal => $time);
|
359
|
+
}
|
360
|
+
if (defined $$info{OLatitude} and defined $$info{OLongitude}) {
|
361
|
+
my $lat = $$info{OLatitude};
|
362
|
+
$lat = -$lat if $$info{NS} and $$info{NS} eq 'S';
|
363
|
+
my $lon = $$info{OLongitude};
|
364
|
+
$lon = -$lon if $$info{EW} and $$info{EW} eq 'W';
|
365
|
+
$et->HandleTag($tagTbl, GPSLatitude2 => $lat);
|
366
|
+
$et->HandleTag($tagTbl, GPSLongitude2 => $lon);
|
367
|
+
}
|
368
|
+
unless ($et->Options('ExtractEmbedded')) {
|
369
|
+
$et->Warn('Use the ExtractEmbedded option to extract all timed GPS',3);
|
370
|
+
last;
|
371
|
+
}
|
372
|
+
}
|
373
|
+
delete $$et{DOC_NUM};
|
374
|
+
delete $$et{SET_GROUP1};
|
375
|
+
return 1;
|
376
|
+
}
|
377
|
+
|
378
|
+
1; #end
|
379
|
+
|
380
|
+
|
381
|
+
__END__
|
382
|
+
|
383
|
+
=head1 NAME
|
384
|
+
|
385
|
+
Image::ExifTool::LigoGPS - Read LIGOGPSINFO timed GPS records
|
386
|
+
|
387
|
+
=head1 SYNOPSIS
|
388
|
+
|
389
|
+
This module is loaded automatically by Image::ExifTool when required.
|
390
|
+
|
391
|
+
=head1 DESCRIPTION
|
392
|
+
|
393
|
+
This module decrypts, deciphers and decodes timed GPS metadata from
|
394
|
+
LIGOGPSINFO records found in various locations of MP4 and M2TS videos from a
|
395
|
+
variety of dashcam makes and models.
|
396
|
+
|
397
|
+
=head1 AUTHOR
|
398
|
+
|
399
|
+
Copyright 2003-2025, Phil Harvey (philharvey66 at gmail.com)
|
400
|
+
|
401
|
+
This library is free software; you can redistribute it and/or modify it
|
402
|
+
under the same terms as Perl itself.
|
403
|
+
|
404
|
+
=head1 SEE ALSO
|
405
|
+
|
406
|
+
L<Image::ExifTool::TagNames/QuickTime Stream Tags>,
|
407
|
+
L<Image::ExifTool(3pm)|Image::ExifTool>
|
408
|
+
|
409
|
+
=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.
|