exiftool_vendored 12.06.0 → 12.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.
Potentially problematic release.
This version of exiftool_vendored might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/Changes +96 -2
- data/bin/MANIFEST +5 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +43 -42
- data/bin/exiftool +156 -82
- data/bin/lib/Image/ExifTool.pm +22 -13
- data/bin/lib/Image/ExifTool.pod +59 -50
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +11 -5
- data/bin/lib/Image/ExifTool/Canon.pm +202 -13
- data/bin/lib/Image/ExifTool/DarwinCore.pm +9 -3
- data/bin/lib/Image/ExifTool/EXE.pm +8 -5
- data/bin/lib/Image/ExifTool/GIF.pm +2 -2
- data/bin/lib/Image/ExifTool/Geotag.pm +30 -11
- data/bin/lib/Image/ExifTool/GoPro.pm +47 -30
- data/bin/lib/Image/ExifTool/IPTC.pm +1 -0
- data/bin/lib/Image/ExifTool/Import.pm +14 -11
- data/bin/lib/Image/ExifTool/JSON.pm +27 -4
- data/bin/lib/Image/ExifTool/MPF.pm +2 -2
- data/bin/lib/Image/ExifTool/MacOS.pm +153 -37
- data/bin/lib/Image/ExifTool/Matroska.pm +3 -1
- data/bin/lib/Image/ExifTool/Minolta.pm +5 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +11 -3
- data/bin/lib/Image/ExifTool/Olympus.pm +8 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +12 -12
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +1 -0
- data/bin/lib/Image/ExifTool/Pentax.pm +10 -3
- data/bin/lib/Image/ExifTool/QuickTime.pm +51 -16
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +68 -45
- data/bin/lib/Image/ExifTool/README +5 -2
- data/bin/lib/Image/ExifTool/RSRC.pm +17 -11
- data/bin/lib/Image/ExifTool/Radiance.pm +7 -2
- data/bin/lib/Image/ExifTool/Sony.pm +56 -35
- data/bin/lib/Image/ExifTool/Stim.pm +2 -2
- data/bin/lib/Image/ExifTool/TagLookup.pm +5756 -5710
- data/bin/lib/Image/ExifTool/TagNames.pod +248 -49
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +7 -6
- data/bin/lib/Image/ExifTool/Writer.pl +5 -3
- data/bin/lib/Image/ExifTool/XMP.pm +63 -18
- data/bin/lib/Image/ExifTool/XMP2.pl +1 -0
- data/bin/perl-Image-ExifTool.spec +42 -41
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +7 -7
@@ -58,7 +58,7 @@ use Image::ExifTool::Exif;
|
|
58
58
|
use Image::ExifTool::GPS;
|
59
59
|
use Image::ExifTool::HP;
|
60
60
|
|
61
|
-
$VERSION = '3.
|
61
|
+
$VERSION = '3.35';
|
62
62
|
|
63
63
|
sub CryptShutterCount($$);
|
64
64
|
sub PrintFilter($$$);
|
@@ -2894,13 +2894,20 @@ my %binaryDataAttrs = (
|
|
2894
2894
|
Writable => 'string',
|
2895
2895
|
Notes => 'left blank by some cameras',
|
2896
2896
|
},
|
2897
|
-
0x022a => { #PH (
|
2897
|
+
0x022a => [{ #PH (RICOH models (GR III))
|
2898
|
+
Name => 'FilterInfo',
|
2899
|
+
Condition => '$$self{Make} =~ /^RICOH/',
|
2900
|
+
SubDirectory => {
|
2901
|
+
TagTable => 'Image::ExifTool::Pentax::FilterInfo',
|
2902
|
+
ByteOrder => 'LittleEndian',
|
2903
|
+
},
|
2904
|
+
},{ #PH (K-5)
|
2898
2905
|
Name => 'FilterInfo',
|
2899
2906
|
SubDirectory => {
|
2900
2907
|
TagTable => 'Image::ExifTool::Pentax::FilterInfo',
|
2901
2908
|
ByteOrder => 'BigEndian',
|
2902
2909
|
},
|
2903
|
-
},
|
2910
|
+
}],
|
2904
2911
|
0x022b => { #PH (K-5)
|
2905
2912
|
Name => 'LevelInfo',
|
2906
2913
|
SubDirectory => { TagTable => 'Image::ExifTool::Pentax::LevelInfo' },
|
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
47
47
|
use Image::ExifTool::Exif;
|
48
48
|
use Image::ExifTool::GPS;
|
49
49
|
|
50
|
-
$VERSION = '2.
|
50
|
+
$VERSION = '2.55';
|
51
51
|
|
52
52
|
sub ProcessMOV($$;$);
|
53
53
|
sub ProcessKeys($$$);
|
@@ -217,8 +217,13 @@ my %ftypLookup = (
|
|
217
217
|
# information for time/date-based tags (time zero is Jan 1, 1904)
|
218
218
|
my %timeInfo = (
|
219
219
|
Notes => 'converted from UTC to local time if the QuickTimeUTC option is set',
|
220
|
+
Shift => 'Time',
|
221
|
+
Writable => 1,
|
222
|
+
Permanent => 1,
|
223
|
+
DelValue => 0,
|
220
224
|
# It is not uncommon for brain-dead software to use the wrong time zero,
|
221
225
|
# so assume a time zero of Jan 1, 1970 if the date is before this
|
226
|
+
# Note: This value will be in UTC if generated by a system that is aware of the time zone
|
222
227
|
RawConv => q{
|
223
228
|
my $offset = (66 * 365 + 17) * 24 * 3600;
|
224
229
|
return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC};
|
@@ -227,12 +232,17 @@ my %timeInfo = (
|
|
227
232
|
}
|
228
233
|
return $val;
|
229
234
|
},
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
235
|
+
RawConvInv => q{
|
236
|
+
if ($$self{FileType} eq 'CR3' and not $self->Options('QuickTimeUTC')) {
|
237
|
+
# convert to UTC
|
238
|
+
my $offset = (66 * 365 + 17) * 24 * 3600;
|
239
|
+
$val = ConvertUnixTime($val - $offset);
|
240
|
+
$val = GetUnixTime($val, 1) + $offset;
|
241
|
+
}
|
242
|
+
return $val;
|
243
|
+
},
|
244
|
+
# (all CR3 files store UTC times - PH)
|
245
|
+
ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3")',
|
236
246
|
ValueConvInv => 'GetUnixTime($val, $self->Options("QuickTimeUTC")) + (66 * 365 + 17) * 24 * 3600',
|
237
247
|
PrintConv => '$self->ConvertDateTime($val)',
|
238
248
|
PrintConvInv => '$self->InverseDateTime($val)',
|
@@ -607,6 +617,11 @@ my %eeBox = (
|
|
607
617
|
Groups => { 2 => 'Preview' },
|
608
618
|
Binary => 1,
|
609
619
|
},
|
620
|
+
'thm ' => { #PH (70mai A800)
|
621
|
+
Name => 'ThumbnailImage',
|
622
|
+
Groups => { 2 => 'Preview' },
|
623
|
+
Binary => 1,
|
624
|
+
},
|
610
625
|
ardt => { #PH
|
611
626
|
Name => 'ARDroneFile',
|
612
627
|
ValueConv => 'length($val) > 4 ? substr($val,4) : $val', # remove length
|
@@ -1913,7 +1928,7 @@ my %eeBox = (
|
|
1913
1928
|
# SETT? 12 bytes (Hero4)
|
1914
1929
|
# MUID? 32 bytes (Hero4, starts with serial number hash)
|
1915
1930
|
# HMMT? 404 bytes (Hero4, all zero)
|
1916
|
-
# BCID? 26 bytes (Hero5, all zero)
|
1931
|
+
# BCID? 26 bytes (Hero5, all zero), 36 bytes GoPro Max
|
1917
1932
|
# GUMI? 16 bytes (Hero5)
|
1918
1933
|
"FOV\0" => 'FieldOfView', #forum8938 (Hero2) seen: "Wide"
|
1919
1934
|
GPMF => {
|
@@ -2550,7 +2565,23 @@ my %eeBox = (
|
|
2550
2565
|
Start => 4,
|
2551
2566
|
},
|
2552
2567
|
},
|
2553
|
-
|
2568
|
+
idat => {
|
2569
|
+
Name => 'MetaImageSize', #PH (NC)
|
2570
|
+
Format => 'int16u',
|
2571
|
+
# (don't know what the first two numbers are for)
|
2572
|
+
PrintConv => '$val =~ s/^(\d+) (\d+) (\d+) (\d+)/${3}x$4/; $val',
|
2573
|
+
},
|
2574
|
+
uuid => [
|
2575
|
+
{ #PH (Canon R5/R6 HIF)
|
2576
|
+
Name => 'MetaVersion', # (NC)
|
2577
|
+
Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/',
|
2578
|
+
RawConv => 'substr($val, 0x14)',
|
2579
|
+
},
|
2580
|
+
{
|
2581
|
+
Name => 'UUID-Unknown',
|
2582
|
+
%unknownInfo,
|
2583
|
+
},
|
2584
|
+
],
|
2554
2585
|
);
|
2555
2586
|
|
2556
2587
|
# additional metadata container (ref ISO14496-12:2015)
|
@@ -2862,12 +2893,16 @@ my %eeBox = (
|
|
2862
2893
|
WRITE_PROC => \&WriteQuickTime,
|
2863
2894
|
GROUPS => { 2 => 'Image' },
|
2864
2895
|
# (Note: ExifTool's ItemRefVersion may be used to test the iref version number)
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2896
|
+
NOTES => q{
|
2897
|
+
The Item reference entries listed in the table below contain information about
|
2898
|
+
the associations between items in the file. This information is used by
|
2899
|
+
ExifTool, but these entries are not extracted as tags.
|
2900
|
+
},
|
2901
|
+
dimg => { Name => 'DerivedImageRef', RawConv => 'undef' },
|
2902
|
+
thmb => { Name => 'ThumbnailRef', RawConv => 'undef' },
|
2903
|
+
auxl => { Name => 'AuxiliaryImageRef', RawConv => 'undef' },
|
2868
2904
|
cdsc => {
|
2869
2905
|
Name => 'ContentDescribes',
|
2870
|
-
Notes => 'parsed, but not extracted as a tag',
|
2871
2906
|
RawConv => \&ParseContentDescribes,
|
2872
2907
|
WriteHook => \&ParseContentDescribes,
|
2873
2908
|
},
|
@@ -6861,7 +6896,7 @@ my %eeBox = (
|
|
6861
6896
|
#
|
6862
6897
|
# AudioFormat Offset Child atoms
|
6863
6898
|
# ----------- ------ ----------------
|
6864
|
-
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params
|
6899
|
+
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max)
|
6865
6900
|
# in24 52 wave, chan
|
6866
6901
|
# "ms\0\x11" 52 wave
|
6867
6902
|
# sowt 52 chan
|
@@ -8613,10 +8648,10 @@ sub ProcessSampleDesc($$$)
|
|
8613
8648
|
my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $pos);
|
8614
8649
|
return 0 if $pos + 8 > $dirLen;
|
8615
8650
|
|
8616
|
-
my $num = Get32u($dataPt, 4); # get number of sample
|
8651
|
+
my $num = Get32u($dataPt, 4); # get number of sample entries in table
|
8617
8652
|
$pos += 8;
|
8618
8653
|
my $i;
|
8619
|
-
for ($i=0; $i<$num; ++$i) { # loop through sample
|
8654
|
+
for ($i=0; $i<$num; ++$i) { # loop through sample entries
|
8620
8655
|
last if $pos + 8 > $dirLen;
|
8621
8656
|
my $size = Get32u($dataPt, $pos);
|
8622
8657
|
last if $pos + $size > $dirLen;
|
@@ -10,6 +10,7 @@
|
|
10
10
|
# 3) https://forum.flitsservice.nl/dashcam-info/dod-ls460w-gps-data-uit-mov-bestand-lezen-t87926.html
|
11
11
|
# 4) https://developers.google.com/streetview/publish/camm-spec
|
12
12
|
# 5) https://sergei.nz/extracting-gps-data-from-viofo-a119-and-other-novatek-powered-cameras/
|
13
|
+
# 6) Thomas Allen https://github.com/exiftool/exiftool/pull/62
|
13
14
|
#------------------------------------------------------------------------------
|
14
15
|
package Image::ExifTool::QuickTime;
|
15
16
|
|
@@ -78,7 +79,8 @@ my %processByMetaFormat = (
|
|
78
79
|
# data lengths for each INSV record type
|
79
80
|
my %insvDataLen = (
|
80
81
|
0x300 => 56, # accelerometer
|
81
|
-
0x400 => 16, #
|
82
|
+
0x400 => 16, # exposure (ref 6)
|
83
|
+
0x600 => 8, # timestamps (ref 6)
|
82
84
|
0x700 => 53, # GPS
|
83
85
|
);
|
84
86
|
|
@@ -121,6 +123,7 @@ my %insvLimit = (
|
|
121
123
|
ExposureCompensation => { PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)', Groups => { 2 => 'Camera' } },
|
122
124
|
ISO => { Groups => { 2 => 'Camera' } },
|
123
125
|
CameraDateTime=>{ PrintConv => '$self->ConvertDateTime($val)', Groups => { 2 => 'Time' } },
|
126
|
+
VideoTimeStamp => { Groups => { 2 => 'Video' } },
|
124
127
|
Accelerometer=> { Notes => '3-axis acceleration in units of g' },
|
125
128
|
AccelerometerData => { },
|
126
129
|
AngularVelocity => { },
|
@@ -162,10 +165,17 @@ my %insvLimit = (
|
|
162
165
|
ProcessProc => \&Process_mebx,
|
163
166
|
},
|
164
167
|
},
|
165
|
-
gpmd => {
|
166
|
-
Name => '
|
168
|
+
gpmd => [{
|
169
|
+
Name => 'gpmd_GoPro',
|
170
|
+
Condition => '$$valPt !~ /^\0\0\xf2\xe1\xf0\xeeTT/',
|
167
171
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
|
168
|
-
},
|
172
|
+
},{
|
173
|
+
Name => 'gpmd_Rove', # Rove Stealth 4K encrypted text
|
174
|
+
SubDirectory => {
|
175
|
+
TagTable => 'Image::ExifTool::QuickTime::Stream',
|
176
|
+
ProcessProc => \&Process_text,
|
177
|
+
},
|
178
|
+
}],
|
169
179
|
fdsc => {
|
170
180
|
Name => 'fdsc',
|
171
181
|
Condition => '$$valPt =~ /^GPRO/',
|
@@ -834,15 +844,21 @@ sub HandleTextTags($$$)
|
|
834
844
|
|
835
845
|
#------------------------------------------------------------------------------
|
836
846
|
# Process subtitle 'text'
|
837
|
-
# Inputs: 0) ExifTool ref, 1)
|
847
|
+
# Inputs: 0) ExifTool ref, 1) data ref or dirInfo ref, 2) tag table ref
|
838
848
|
sub Process_text($$$)
|
839
849
|
{
|
840
|
-
my ($et, $
|
850
|
+
my ($et, $dataPt, $tagTbl) = @_;
|
841
851
|
my %tags;
|
842
852
|
|
843
853
|
return if $$et{NoMoreTextDecoding};
|
844
854
|
|
845
|
-
|
855
|
+
if (ref $dataPt eq 'HASH') {
|
856
|
+
my $dirName = $$dataPt{DirName};
|
857
|
+
$dataPt = $$dataPt{DataPt};
|
858
|
+
$et->VerboseDir($dirName, undef, length($$dataPt));
|
859
|
+
}
|
860
|
+
|
861
|
+
while ($$dataPt =~ /\$(\w+)([^\$]*)/g) {
|
846
862
|
my ($tag, $dat) = ($1, $2);
|
847
863
|
if ($tag =~ /^[A-Z]{2}RMC$/ and $dat =~ /^,(\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+)/) {
|
848
864
|
my $time = "$1:$2:$3";
|
@@ -933,31 +949,31 @@ sub Process_text($$$)
|
|
933
949
|
# 0110: 31 30 38 30 30 30 58 00 58 00 58 00 58 00 58 00 [108000X.X.X.X.X.]
|
934
950
|
# 0120: 58 00 58 00 58 00 58 00 00 00 00 00 00 00 00 00 [X.X.X.X.........]
|
935
951
|
# 0130: 00 00 00 00 00 00 00 [.......]
|
936
|
-
if ($$
|
937
|
-
my $val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
952
|
+
if ($$dataPt =~ /^\0\0(..\xaa\xaa|\xf2\xe1\xf0\xee)/s and length $$dataPt >= 282) {
|
953
|
+
my $val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 8, 14)));
|
938
954
|
if ($val =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/) {
|
939
955
|
$tags{GPSDateTime} = "$1:$2:$3 $4:$5:$6";
|
940
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
956
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 38, 9)));
|
941
957
|
if ($val =~ /^([NS])(\d{2})(\d+$)$/) {
|
942
958
|
$tags{GPSLatitude} = ($2 + $3 / 600000) * ($1 eq 'S' ? -1 : 1);
|
943
959
|
}
|
944
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
960
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 47, 10)));
|
945
961
|
if ($val =~ /^([EW])(\d{3})(\d+$)$/) {
|
946
962
|
$tags{GPSLongitude} = ($2 + $3 / 600000) * ($1 eq 'W' ? -1 : 1);
|
947
963
|
}
|
948
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
964
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x39, 5)));
|
949
965
|
$tags{GPSAltitude} = $val + 0 if $val =~ /^[-+]\d+$/;
|
950
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
966
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x3e, 3)));
|
951
967
|
if ($val =~ /^\d+$/) {
|
952
968
|
$tags{GPSSpeed} = $val + 0;
|
953
969
|
$tags{GPSSpeedRef} = 'K';
|
954
970
|
}
|
955
|
-
if ($$
|
956
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
971
|
+
if ($$dataPt =~ /^\0\0..\xaa\xaa/s) { # (BlueSkySea)
|
972
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0xad, 12)));
|
957
973
|
# the first X,Y,Z accelerometer readings from the AccelerometerData
|
958
974
|
if ($val =~ /^([-+]\d{3})([-+]\d{3})([-+]\d{3})$/) {
|
959
975
|
$tags{Accelerometer} = "$1 $2 $3";
|
960
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
976
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0xba, 96)));
|
961
977
|
my $order = GetByteOrder();
|
962
978
|
SetByteOrder('II');
|
963
979
|
$val = ReadValue(\$val, 0, 'float');
|
@@ -966,7 +982,7 @@ sub Process_text($$$)
|
|
966
982
|
}
|
967
983
|
} else { # (Ambarella)
|
968
984
|
my @acc;
|
969
|
-
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$
|
985
|
+
$val = pack('C*', map { $_ ^ 0xaa } unpack('C*', substr($$dataPt, 0x41, 195)));
|
970
986
|
push @acc, $1, $2, $3 while $val =~ /\G([-+]\d{3})([-+]\d{3})([-+]\d{3})/g;
|
971
987
|
$tags{Accelerometer} = "@acc" if @acc;
|
972
988
|
}
|
@@ -977,36 +993,36 @@ sub Process_text($$$)
|
|
977
993
|
# check for DJI telemetry data, eg:
|
978
994
|
# "F/3.5, SS 1000, ISO 100, EV 0, GPS (8.6499, 53.1665, 18), D 24.26m,
|
979
995
|
# H 6.00m, H.S 2.10m/s, V.S 0.00m/s \n"
|
980
|
-
if ($$
|
996
|
+
if ($$dataPt =~ /GPS \(([-+]?\d*\.\d+),\s*([-+]?\d*\.\d+)/) {
|
981
997
|
$$et{CreateDateAtEnd} = 1; # set flag indicating the file creation date is at the end
|
982
998
|
$tags{GPSLatitude} = $2;
|
983
999
|
$tags{GPSLongitude} = $1;
|
984
|
-
$tags{GPSAltitude} = $1 if $$
|
985
|
-
if ($$
|
1000
|
+
$tags{GPSAltitude} = $1 if $$dataPt =~ /,\s*H\s+([-+]?\d+\.?\d*)m/;
|
1001
|
+
if ($$dataPt =~ /,\s*H.S\s+([-+]?\d+\.?\d*)/) {
|
986
1002
|
$tags{GPSSpeed} = $1 * $mpsToKph;
|
987
1003
|
$tags{GPSSpeedRef} = 'K';
|
988
1004
|
}
|
989
|
-
$tags{Distance} = $1 * $mpsToKph if $$
|
990
|
-
$tags{VerticalSpeed} = $1 if $$
|
991
|
-
$tags{FNumber} = $1 if $$
|
992
|
-
$tags{ExposureTime} = 1 / $1 if $$
|
993
|
-
$tags{ExposureCompensation} = ($1 / ($2 || 1)) if $$
|
994
|
-
$tags{ISO} = $1 if $$
|
1005
|
+
$tags{Distance} = $1 * $mpsToKph if $$dataPt =~ /,\s*D\s+(\d+\.?\d*)m/;
|
1006
|
+
$tags{VerticalSpeed} = $1 if $$dataPt =~ /,\s*V.S\s+([-+]?\d+\.?\d*)/;
|
1007
|
+
$tags{FNumber} = $1 if $$dataPt =~ /\bF\/(\d+\.?\d*)/;
|
1008
|
+
$tags{ExposureTime} = 1 / $1 if $$dataPt =~ /\bSS\s+(\d+\.?\d*)/;
|
1009
|
+
$tags{ExposureCompensation} = ($1 / ($2 || 1)) if $$dataPt =~ /\bEV\s+([-+]?\d+\.?\d*)(\/\d+)?/;
|
1010
|
+
$tags{ISO} = $1 if $$dataPt =~ /\bISO\s+(\d+\.?\d*)/;
|
995
1011
|
HandleTextTags($et, $tagTbl, \%tags);
|
996
1012
|
return;
|
997
1013
|
}
|
998
1014
|
|
999
1015
|
# check for Mini 0806 dashcam GPS, eg:
|
1000
1016
|
# "A,270519,201555.000,3356.8925,N,08420.2071,W,000.0,331.0M,+01.84,-09.80,-00.61;\n"
|
1001
|
-
if ($$
|
1017
|
+
if ($$dataPt =~ /^A,(\d{2})(\d{2})(\d{2}),(\d{2})(\d{2})(\d{2}(\.\d+)?)/) {
|
1002
1018
|
$tags{GPSDateTime} = "20$3:$2:$1 $4:$5:$6Z";
|
1003
|
-
if ($$
|
1019
|
+
if ($$dataPt =~ /^A,.*?,.*?,(\d{2})(\d+\.\d+),([NS])/) {
|
1004
1020
|
$tags{GPSLatitude} = ($1 + $2/60) * ($3 eq 'S' ? -1 : 1);
|
1005
1021
|
}
|
1006
|
-
if ($$
|
1022
|
+
if ($$dataPt =~ /^A,.*?,.*?,.*?,.*?,(\d{3})(\d+\.\d+),([EW])/) {
|
1007
1023
|
$tags{GPSLongitude} = ($1 + $2/60) * ($3 eq 'W' ? -1 : 1);
|
1008
1024
|
}
|
1009
|
-
my @a = split ',', $$
|
1025
|
+
my @a = split ',', $$dataPt;
|
1010
1026
|
$tags{GPSAltitude} = $a[8] if $a[8] and $a[8] =~ s/M$//;
|
1011
1027
|
$tags{GPSSpeed} = $a[7] if $a[7] and $a[7] =~ /^\d+\.\d+$/; # (NC)
|
1012
1028
|
$tags{Accelerometer} = "$a[9] $a[10] $a[11]" if $a[11] and $a[11] =~ s/;\s*$//;
|
@@ -1019,10 +1035,10 @@ sub Process_text($$$)
|
|
1019
1035
|
# decoded:
|
1020
1036
|
# "X0000.2340Y-000.0720Z0000.9900G0001.0400$GPRMC,082138,A,5330.6683,N,00641.9749,W,012.5,87.86,050213,002.1,A"
|
1021
1037
|
# (note: "002.1" is magnetic variation and is not decoded; it should have ",E" or ",W" afterward for direction)
|
1022
|
-
if ($$
|
1038
|
+
if ($$dataPt =~ /\*[0-9A-F]{2}~$/) {
|
1023
1039
|
# (ref https://reverseengineering.stackexchange.com/questions/11582/how-to-reverse-engineer-dash-cam-metadata)
|
1024
1040
|
my @decode = unpack 'C*', '-I8XQWRVNZOYPUTA0B1C2SJ9K.L,M$D3E4F5G6H7';
|
1025
|
-
my @chars = unpack 'C*', substr($$
|
1041
|
+
my @chars = unpack 'C*', substr($$dataPt, 0, -4);
|
1026
1042
|
foreach (@chars) {
|
1027
1043
|
my $n = $_ - 43;
|
1028
1044
|
$_ = $decode[$n] if $n >= 0 and defined $decode[$n];
|
@@ -1031,14 +1047,14 @@ sub Process_text($$$)
|
|
1031
1047
|
if ($buff =~ /X(.*?)Y(.*?)Z(.*?)G(.*?)\$/) {
|
1032
1048
|
# yup. the decoding worked out
|
1033
1049
|
$tags{Accelerometer} = "$1 $2 $3 $4";
|
1034
|
-
$$
|
1050
|
+
$$dataPt = $buff; # (process GPRMC below)
|
1035
1051
|
}
|
1036
1052
|
}
|
1037
1053
|
|
1038
1054
|
# check for Thinkware format (and other NMEA RMC), eg:
|
1039
1055
|
# "gsensori,4,512,-67,-12,100;GNRMC,161313.00,A,4529.87489,N,07337.01215,W,6.225,35.34,310819,,,A*52..;
|
1040
1056
|
# CAR,0,0,0,0.0,0,0,0,0,0,0,0,0"
|
1041
|
-
if ($$
|
1057
|
+
if ($$dataPt =~ /[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+)/ and
|
1042
1058
|
# do some basic sanity checks on the date
|
1043
1059
|
$13 <= 31 and $14 <= 12 and $15 <= 99)
|
1044
1060
|
{
|
@@ -1055,8 +1071,8 @@ sub Process_text($$$)
|
|
1055
1071
|
$tags{GPSTrackRef} = 'T';
|
1056
1072
|
}
|
1057
1073
|
}
|
1058
|
-
$tags{GSensor} = $1 if $$
|
1059
|
-
$tags{Car} = $1 if $$
|
1074
|
+
$tags{GSensor} = $1 if $$dataPt =~ /\bgsensori,(.*?)(;|$)/;
|
1075
|
+
$tags{Car} = $1 if $$dataPt =~ /\bCAR,(.*?)(;|$)/;
|
1060
1076
|
|
1061
1077
|
if (%tags) {
|
1062
1078
|
HandleTextTags($et, $tagTbl, \%tags);
|
@@ -1112,7 +1128,7 @@ sub ProcessSamples($)
|
|
1112
1128
|
($startChunk, $samplesPerChunk, $descIdx) = @{shift @$stsc};
|
1113
1129
|
$nextChunk = $$stsc[0][0] if @$stsc;
|
1114
1130
|
}
|
1115
|
-
@$size < @$start + $samplesPerChunk and $et->WarnOnce('Sample size error'),
|
1131
|
+
@$size < @$start + $samplesPerChunk and $et->WarnOnce('Sample size error'), last;
|
1116
1132
|
my $sampleStart = $chunkStart;
|
1117
1133
|
for ($i=0; ; ) {
|
1118
1134
|
push @$start, $sampleStart;
|
@@ -1215,11 +1231,13 @@ sub ProcessSamples($)
|
|
1215
1231
|
$val =~ tr/\t/ /;
|
1216
1232
|
$et->HandleTag($tagTbl, RawGSensor => $val) if length $val;
|
1217
1233
|
}
|
1218
|
-
} elsif ($buff =~ /^PNDM/
|
1234
|
+
} elsif ($buff =~ /^(\0.{3})?PNDM/s) {
|
1219
1235
|
# Garmin Dashcam format (actually binary, not text)
|
1220
|
-
$
|
1221
|
-
|
1222
|
-
$et->HandleTag($tagTbl,
|
1236
|
+
my $n = $1 ? 4 : 0; # skip leading 4-byte size word if it exists
|
1237
|
+
next if length($buff) < 20 + $n;
|
1238
|
+
$et->HandleTag($tagTbl, GPSLatitude => Get32s(\$buff, 12+$n) * 180/0x80000000);
|
1239
|
+
$et->HandleTag($tagTbl, GPSLongitude => Get32s(\$buff, 16+$n) * 180/0x80000000);
|
1240
|
+
$et->HandleTag($tagTbl, GPSSpeed => Get16u(\$buff, 8+$n));
|
1223
1241
|
$et->HandleTag($tagTbl, GPSSpeedRef => 'M');
|
1224
1242
|
SetGPSDateTime($et, $tagTbl, $time[$i]);
|
1225
1243
|
next; # all done (don't store/process as text)
|
@@ -1228,7 +1246,7 @@ sub ProcessSamples($)
|
|
1228
1246
|
$et->HandleTag($tagTbl, Text => $buff); # just store any other text
|
1229
1247
|
}
|
1230
1248
|
}
|
1231
|
-
Process_text($et, $tagTbl
|
1249
|
+
Process_text($et, \$buff, $tagTbl);
|
1232
1250
|
|
1233
1251
|
} elsif ($processByMetaFormat{$type}) {
|
1234
1252
|
|
@@ -1249,7 +1267,7 @@ sub ProcessSamples($)
|
|
1249
1267
|
# "X0000.0000Y0000.0000Z0000.0000G0000.0000$GPRMC,000125,V,,,,,000.0,,280908,002.1,N*71~, 794021 \x0a"
|
1250
1268
|
FoundSomething($et, $tagTbl, $time[$i], $dur[$i]);
|
1251
1269
|
$et->HandleTag($tagTbl, Accelerometer => "$1 $2 $3 $4") if $buff =~ /X(.*?)Y(.*?)Z(.*?)G(.*?)\$/;
|
1252
|
-
Process_text($et, $tagTbl
|
1270
|
+
Process_text($et, \$buff, $tagTbl);
|
1253
1271
|
}
|
1254
1272
|
} elsif ($verbose) {
|
1255
1273
|
$et->VPrint(0, "Unknown $type format ($metaFormat)");
|
@@ -2444,11 +2462,16 @@ sub ProcessInsta360($;$)
|
|
2444
2462
|
$et->HandleTag($tagTbl, Accelerometer => "@a[0..2]"); # (NC)
|
2445
2463
|
$et->HandleTag($tagTbl, AngularVelocity => "@a[3..5]"); # (NC)
|
2446
2464
|
}
|
2447
|
-
} elsif ($id == 0x400
|
2465
|
+
} elsif ($id == 0x400) {
|
2448
2466
|
for ($p=0; $p<$len; $p+=$dlen) {
|
2449
2467
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
2450
2468
|
$et->HandleTag($tagTbl, TimeCode => sprintf('%.3f', Get64u(\$buff, $p) / 1000));
|
2451
|
-
$et->HandleTag($tagTbl,
|
2469
|
+
$et->HandleTag($tagTbl, ExposureTime => GetDouble(\$buff, $p + 8)); #6
|
2470
|
+
}
|
2471
|
+
} elsif ($id == 0x600) { #6
|
2472
|
+
for ($p=0; $p<$len; $p+=$dlen) {
|
2473
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
2474
|
+
$et->HandleTag($tagTbl, VideoTimeStamp => sprintf('%.3f', Get64u(\$buff, $p) / 1000));
|
2452
2475
|
}
|
2453
2476
|
} elsif ($id == 0x700) {
|
2454
2477
|
for ($p=0; $p<$len; $p+=$dlen) {
|
@@ -387,8 +387,11 @@ numerical, and generated automatically otherwise.
|
|
387
387
|
'Flattened' - [reserved] used internally to mark Struct tags
|
388
388
|
which have been processed to generate flattened equivalents.
|
389
389
|
|
390
|
-
'
|
391
|
-
|
390
|
+
'NotFlat' - [XMP tags only] Flag indicates that this tag ID
|
391
|
+
does not represent a flattened tag. Used to avoid a conflict
|
392
|
+
if the tag ID would be the same as a generated ID for a
|
393
|
+
flattened tag. The result is that the flattened tag will not
|
394
|
+
be accessible.
|
392
395
|
|
393
396
|
'Hidden' - set to hide tag from the TagName documentation.
|
394
397
|
Also suppresses verbose output of a BinaryData tag.
|