exiftool_vendored 12.06.0 → 12.12.0
Sign up to get free protection for your applications and to get access to all the features.
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.
|