exiftool-vendored.pl 12.45.0 → 12.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/Changes +122 -6
- package/bin/MANIFEST +12 -0
- package/bin/META.json +1 -1
- package/bin/META.yml +1 -1
- package/bin/README +45 -44
- package/bin/config_files/acdsee.config +2 -1
- package/bin/config_files/frameCount.config +56 -0
- package/bin/config_files/tiff_version.config +1 -1
- package/bin/exiftool +89 -75
- package/bin/lib/Image/ExifTool/Apple.pm +6 -2
- package/bin/lib/Image/ExifTool/BuildTagLookup.pm +17 -9
- package/bin/lib/Image/ExifTool/Canon.pm +31 -14
- package/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
- package/bin/lib/Image/ExifTool/Exif.pm +13 -8
- package/bin/lib/Image/ExifTool/FLAC.pm +17 -3
- package/bin/lib/Image/ExifTool/FlashPix.pm +4 -2
- package/bin/lib/Image/ExifTool/FujiFilm.pm +31 -5
- package/bin/lib/Image/ExifTool/Geotag.pm +1 -1
- package/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
- package/bin/lib/Image/ExifTool/ICO.pm +143 -0
- package/bin/lib/Image/ExifTool/ID3.pm +5 -5
- package/bin/lib/Image/ExifTool/IPTC.pm +5 -1
- package/bin/lib/Image/ExifTool/M2TS.pm +98 -8
- package/bin/lib/Image/ExifTool/MIE.pm +9 -3
- package/bin/lib/Image/ExifTool/MISB.pm +494 -0
- package/bin/lib/Image/ExifTool/MakerNotes.pm +3 -1
- package/bin/lib/Image/ExifTool/Nikon.pm +220 -109
- package/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
- package/bin/lib/Image/ExifTool/Olympus.pm +2 -1
- package/bin/lib/Image/ExifTool/Panasonic.pm +21 -4
- package/bin/lib/Image/ExifTool/PanasonicRaw.pm +12 -5
- package/bin/lib/Image/ExifTool/Pentax.pm +7 -2
- package/bin/lib/Image/ExifTool/Photoshop.pm +29 -3
- package/bin/lib/Image/ExifTool/QuickTime.pm +78 -10
- package/bin/lib/Image/ExifTool/QuickTimeStream.pl +76 -5
- package/bin/lib/Image/ExifTool/README +5 -1
- package/bin/lib/Image/ExifTool/RIFF.pm +106 -9
- package/bin/lib/Image/ExifTool/Samsung.pm +2 -2
- package/bin/lib/Image/ExifTool/Sigma.pm +27 -1
- package/bin/lib/Image/ExifTool/SigmaRaw.pm +37 -13
- package/bin/lib/Image/ExifTool/Sony.pm +35 -16
- package/bin/lib/Image/ExifTool/TagInfoXML.pm +3 -1
- package/bin/lib/Image/ExifTool/TagLookup.pm +4700 -4520
- package/bin/lib/Image/ExifTool/TagNames.pod +4796 -4463
- package/bin/lib/Image/ExifTool/Text.pm +3 -4
- package/bin/lib/Image/ExifTool/Torrent.pm +2 -3
- package/bin/lib/Image/ExifTool/WriteCanonRaw.pl +7 -0
- package/bin/lib/Image/ExifTool/WriteExif.pl +19 -1
- package/bin/lib/Image/ExifTool/WriteRIFF.pl +359 -0
- package/bin/lib/Image/ExifTool/Writer.pl +6 -2
- package/bin/lib/Image/ExifTool/XMP.pm +72 -57
- package/bin/lib/Image/ExifTool/XMP2.pl +9 -1
- package/bin/lib/Image/ExifTool.pm +81 -18
- package/bin/lib/Image/ExifTool.pod +64 -60
- package/bin/perl-Image-ExifTool.spec +43 -43
- package/bin/pp_build_exe.args +7 -4
- package/package.json +2 -2
|
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
21
21
|
use Image::ExifTool::Exif;
|
|
22
22
|
use Image::ExifTool::ASF; # for GetGUID()
|
|
23
23
|
|
|
24
|
-
$VERSION = '1.
|
|
24
|
+
$VERSION = '1.41';
|
|
25
25
|
|
|
26
26
|
sub ProcessFPX($$);
|
|
27
27
|
sub ProcessFPXR($$$);
|
|
@@ -1338,7 +1338,9 @@ sub ConvertDTTM($)
|
|
|
1338
1338
|
my $hr = ($val >> 6) & 0x1f;
|
|
1339
1339
|
my $min = ($val & 0x3f);
|
|
1340
1340
|
$yr += 1900 if $val;
|
|
1341
|
-
|
|
1341
|
+
# ExifTool 12.48 dropped the "Z" on the time here because a test .doc
|
|
1342
|
+
# file written by Word 2011 on Mac certainly used local time here
|
|
1343
|
+
return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00",$yr,$mon,$day,$hr,$min);
|
|
1342
1344
|
}
|
|
1343
1345
|
|
|
1344
1346
|
#------------------------------------------------------------------------------
|
|
@@ -31,7 +31,7 @@ use vars qw($VERSION);
|
|
|
31
31
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
32
32
|
use Image::ExifTool::Exif;
|
|
33
33
|
|
|
34
|
-
$VERSION = '1.
|
|
34
|
+
$VERSION = '1.84';
|
|
35
35
|
|
|
36
36
|
sub ProcessFujiDir($$$);
|
|
37
37
|
sub ProcessFaceRec($$$);
|
|
@@ -254,6 +254,23 @@ my %faceCategories = (
|
|
|
254
254
|
0x2e0 => '-4 (weakest)', #10 (-4)
|
|
255
255
|
},
|
|
256
256
|
},
|
|
257
|
+
0x100f => { #PR158
|
|
258
|
+
Name => 'Clarity',
|
|
259
|
+
Writable => 'int32s', #PH
|
|
260
|
+
PrintConv => {
|
|
261
|
+
-5000 => '-5',
|
|
262
|
+
-4000 => '-4',
|
|
263
|
+
-3000 => '-3',
|
|
264
|
+
-2000 => '-2',
|
|
265
|
+
-1000 => '-1',
|
|
266
|
+
0 => '0',
|
|
267
|
+
1000 => '1',
|
|
268
|
+
2000 => '2',
|
|
269
|
+
3000 => '3',
|
|
270
|
+
4000 => '4',
|
|
271
|
+
5000 => '5',
|
|
272
|
+
},
|
|
273
|
+
},
|
|
257
274
|
0x1010 => {
|
|
258
275
|
Name => 'FujiFlashMode',
|
|
259
276
|
Writable => 'int16u',
|
|
@@ -444,7 +461,7 @@ my %faceCategories = (
|
|
|
444
461
|
PrintConv => { 0 => 'Off', 1 => 'On' },
|
|
445
462
|
},
|
|
446
463
|
0x1047 => { #12
|
|
447
|
-
Name => '
|
|
464
|
+
Name => 'GrainEffectRoughness',
|
|
448
465
|
Writable => 'int32s',
|
|
449
466
|
PrintConv => {
|
|
450
467
|
0 => 'Off',
|
|
@@ -469,6 +486,15 @@ my %faceCategories = (
|
|
|
469
486
|
PrintConvInv => '$val + 0',
|
|
470
487
|
},
|
|
471
488
|
# 0x104b - BWAdjustment for Green->Magenta (forum10800)
|
|
489
|
+
0x104c => { #PR158
|
|
490
|
+
Name => "GrainEffectSize",
|
|
491
|
+
Writable => 'int16u', #PH
|
|
492
|
+
PrintConv => {
|
|
493
|
+
0 => 'Off',
|
|
494
|
+
16 => 'Small',
|
|
495
|
+
32 => 'Large',
|
|
496
|
+
},
|
|
497
|
+
},
|
|
472
498
|
0x104d => { #forum9634
|
|
473
499
|
Name => 'CropMode',
|
|
474
500
|
Writable => 'int16u',
|
|
@@ -763,8 +789,8 @@ my %faceCategories = (
|
|
|
763
789
|
},
|
|
764
790
|
PrintConvInv => '$val=~/(0x[0-9a-f]+)/i; hex $1',
|
|
765
791
|
},
|
|
766
|
-
0x1447 => { Name => '
|
|
767
|
-
0x1448 => { Name => '
|
|
792
|
+
0x1447 => { Name => 'FujiModel', Writable => 'string' },
|
|
793
|
+
0x1448 => { Name => 'FujiModel2', Writable => 'string' },
|
|
768
794
|
0x3803 => { #forum10037
|
|
769
795
|
Name => 'VideoRecordingMode',
|
|
770
796
|
Groups => { 2 => 'Video' },
|
|
@@ -1046,7 +1072,7 @@ my %faceCategories = (
|
|
|
1046
1072
|
Mask => 0x000000ff,
|
|
1047
1073
|
PrintConv => {
|
|
1048
1074
|
0 => 'Single',
|
|
1049
|
-
1 => 'Continuous Low',
|
|
1075
|
+
1 => 'Continuous Low', # not used by X-H2S? (see forum13777)
|
|
1050
1076
|
2 => 'Continuous High',
|
|
1051
1077
|
},
|
|
1052
1078
|
},
|
|
@@ -558,7 +558,7 @@ DoneFix: $isDate = 1;
|
|
|
558
558
|
} elsif ($nmea eq 'RMC') {
|
|
559
559
|
# $GPRMC,092204.999,A,4250.5589,S,14718.5084,E,0.00,89.68,211200,,*25
|
|
560
560
|
# $GPRMC,093657.007,,3652.835020,N,01053.104094,E,1.642,,290913,,,A*0F
|
|
561
|
-
# $GPRMC,hhmmss.sss,A/V,ddmm.mmmm,N/S,
|
|
561
|
+
# $GPRMC,hhmmss.sss,A/V,ddmm.mmmm,N/S,dddmm.mmmm,E/W,spd(knots),dir(deg),DDMMYY,,*cs
|
|
562
562
|
/^\$[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+)/ or next;
|
|
563
563
|
next if $13 > 31 or $14 > 12 or $15 > 99; # validate day/month/year
|
|
564
564
|
$fix{lat} = (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1);
|
|
@@ -627,7 +627,7 @@ my %manuSig = ( #6
|
|
|
627
627
|
swpt => 'SpectralWhitePoint',
|
|
628
628
|
s2cp => 'StandardToCustomPcc',
|
|
629
629
|
smap => 'SurfaceMap',
|
|
630
|
-
# smwp ? (seen in some v5 samples)
|
|
630
|
+
# smwp ? (seen in some v5 samples [was a mistake in sample production])
|
|
631
631
|
|
|
632
632
|
# the following entry represents the ICC profile header, and doesn't
|
|
633
633
|
# exist as a tag in the directory. It is only in this table to provide
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#------------------------------------------------------------------------------
|
|
2
|
+
# File: ICO.pm
|
|
3
|
+
#
|
|
4
|
+
# Description: Read Windows ICO and CUR files
|
|
5
|
+
#
|
|
6
|
+
# Revisions: 2020-10-18 - P. Harvey Created
|
|
7
|
+
#
|
|
8
|
+
# References: 1) https://docs.fileformat.com/image/ico/
|
|
9
|
+
#------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
package Image::ExifTool::ICO;
|
|
12
|
+
|
|
13
|
+
use strict;
|
|
14
|
+
use vars qw($VERSION);
|
|
15
|
+
use Image::ExifTool qw(:DataAccess :Utils);
|
|
16
|
+
|
|
17
|
+
$VERSION = '1.00';
|
|
18
|
+
|
|
19
|
+
%Image::ExifTool::ICO::Main = (
|
|
20
|
+
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
|
21
|
+
GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' },
|
|
22
|
+
NOTES => 'Information extracted from Windows ICO (icon) and CUR (cursor) files.',
|
|
23
|
+
2 => {
|
|
24
|
+
Name => 'ImageType',
|
|
25
|
+
Format => 'int16u',
|
|
26
|
+
PrintConv => { 1 => 'Icon', 2 => 'Cursor' },
|
|
27
|
+
},
|
|
28
|
+
4 => {
|
|
29
|
+
Name => 'ImageCount',
|
|
30
|
+
Format => 'int16u',
|
|
31
|
+
RawConv => '$$self{ImageCount} = $val',
|
|
32
|
+
},
|
|
33
|
+
6 => {
|
|
34
|
+
Name => 'IconDir',
|
|
35
|
+
SubDirectory => { TagTable => 'Image::ExifTool::ICO::IconDir' },
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
%Image::ExifTool::ICO::IconDir = (
|
|
40
|
+
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
|
41
|
+
GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' },
|
|
42
|
+
0 => {
|
|
43
|
+
Name => 'ImageWidth',
|
|
44
|
+
ValueConv => '$val or $val + 256',
|
|
45
|
+
},
|
|
46
|
+
1 => {
|
|
47
|
+
Name => 'ImageHeight',
|
|
48
|
+
ValueConv => '$val or $val + 256',
|
|
49
|
+
},
|
|
50
|
+
2 => 'NumColors',
|
|
51
|
+
4 => [{
|
|
52
|
+
Name => 'ColorPlanes',
|
|
53
|
+
Condition => '$$self{FileType} eq "ICO"',
|
|
54
|
+
Format => 'int16u',
|
|
55
|
+
Notes => 'ICO files',
|
|
56
|
+
},{
|
|
57
|
+
Name => 'HotspotX',
|
|
58
|
+
Format => 'int16u',
|
|
59
|
+
Notes => 'CUR files',
|
|
60
|
+
}],
|
|
61
|
+
6 => [{
|
|
62
|
+
Name => 'BitsPerPixel',
|
|
63
|
+
Condition => '$$self{FileType} eq "ICO"',
|
|
64
|
+
Format => 'int16u',
|
|
65
|
+
Notes => 'ICO files',
|
|
66
|
+
},{
|
|
67
|
+
Name => 'HotspotY',
|
|
68
|
+
Format => 'int16u',
|
|
69
|
+
Notes => 'CUR files',
|
|
70
|
+
}],
|
|
71
|
+
8 => {
|
|
72
|
+
Name => 'ImageLength',
|
|
73
|
+
Format => 'int32u',
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
#------------------------------------------------------------------------------
|
|
78
|
+
# Process ICO/CUR file
|
|
79
|
+
# Inputs: 0) ExifTool ref, 1) dirInfo ref
|
|
80
|
+
# Returns: 1 on success, 0 if this wasn't a valid ICO/CUR file
|
|
81
|
+
sub ProcessICO($$$)
|
|
82
|
+
{
|
|
83
|
+
my ($et, $dirInfo) = @_;
|
|
84
|
+
my $raf = $$dirInfo{RAF};
|
|
85
|
+
my ($i, $buff);
|
|
86
|
+
# verify this is a valid ICO/CUR file
|
|
87
|
+
return 0 unless $raf->Read($buff, 6) == 6;
|
|
88
|
+
return 0 unless $buff =~ /^\0\0([\x01\x02])\0[^0]\0/s;
|
|
89
|
+
# (note: have seen cursor files in the wild with an 0x01 here,
|
|
90
|
+
# but SetFileType will use the .cur extension to identify these)
|
|
91
|
+
$et->SetFileType($1 eq "\x01" ? 'ICO' : 'CUR');
|
|
92
|
+
SetByteOrder('II');
|
|
93
|
+
my $tagTbl = GetTagTable('Image::ExifTool::ICO::Main');
|
|
94
|
+
my $num = Get16u(\$buff, 4);
|
|
95
|
+
$et->HandleTag($tagTbl, 4, $num);
|
|
96
|
+
for ($i=0; $i<$num; ++$i) {
|
|
97
|
+
$raf->Read($buff, 16) == 16 or $et->Warn('Truncated file'), last;
|
|
98
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT} if $i;
|
|
99
|
+
$et->HandleTag($tagTbl, 6, $buff);
|
|
100
|
+
}
|
|
101
|
+
delete $$et{DOC_NUM};
|
|
102
|
+
return 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
1; # end
|
|
106
|
+
|
|
107
|
+
__END__
|
|
108
|
+
|
|
109
|
+
=head1 NAME
|
|
110
|
+
|
|
111
|
+
Image::ExifTool::ICO - Read ICO meta information
|
|
112
|
+
|
|
113
|
+
=head1 SYNOPSIS
|
|
114
|
+
|
|
115
|
+
This module is used by Image::ExifTool
|
|
116
|
+
|
|
117
|
+
=head1 DESCRIPTION
|
|
118
|
+
|
|
119
|
+
This module contains definitions required by Image::ExifTool to read
|
|
120
|
+
information from Windows ICO (icon) and CUR (cursor) files.
|
|
121
|
+
|
|
122
|
+
=head1 AUTHOR
|
|
123
|
+
|
|
124
|
+
Copyright 2003-2022, Phil Harvey (philharvey66 at gmail.com)
|
|
125
|
+
|
|
126
|
+
This library is free software; you can redistribute it and/or modify it
|
|
127
|
+
under the same terms as Perl itself.
|
|
128
|
+
|
|
129
|
+
=head1 REFERENCES
|
|
130
|
+
|
|
131
|
+
=over 4
|
|
132
|
+
|
|
133
|
+
=item L<https://docs.fileformat.com/image/ico/>
|
|
134
|
+
|
|
135
|
+
=back
|
|
136
|
+
|
|
137
|
+
=head1 SEE ALSO
|
|
138
|
+
|
|
139
|
+
L<Image::ExifTool::TagNames/ICO Tags>,
|
|
140
|
+
L<Image::ExifTool(3pm)|Image::ExifTool>
|
|
141
|
+
|
|
142
|
+
=cut
|
|
143
|
+
|
|
@@ -18,7 +18,7 @@ use strict;
|
|
|
18
18
|
use vars qw($VERSION);
|
|
19
19
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
20
20
|
|
|
21
|
-
$VERSION = '1.
|
|
21
|
+
$VERSION = '1.58';
|
|
22
22
|
|
|
23
23
|
sub ProcessID3v2($$$);
|
|
24
24
|
sub ProcessPrivate($$$);
|
|
@@ -1414,13 +1414,13 @@ sub ProcessID3($$)
|
|
|
1414
1414
|
if ($flags & 0x40) {
|
|
1415
1415
|
# skip the extended header
|
|
1416
1416
|
$size >= 4 or $et->Warn('Bad ID3 extended header'), last;
|
|
1417
|
-
my $len = unpack('N', $hBuff);
|
|
1418
|
-
if ($len > length($hBuff)
|
|
1417
|
+
my $len = UnSyncSafe(unpack('N', $hBuff));
|
|
1418
|
+
if ($len > length($hBuff)) {
|
|
1419
1419
|
$et->Warn('Truncated ID3 extended header');
|
|
1420
1420
|
last;
|
|
1421
1421
|
}
|
|
1422
|
-
$hBuff = substr($hBuff, $len
|
|
1423
|
-
$pos += $len
|
|
1422
|
+
$hBuff = substr($hBuff, $len);
|
|
1423
|
+
$pos += $len;
|
|
1424
1424
|
}
|
|
1425
1425
|
if ($flags & 0x10) {
|
|
1426
1426
|
# ignore v2.4 footer (10 bytes long)
|
|
@@ -15,7 +15,7 @@ use strict;
|
|
|
15
15
|
use vars qw($VERSION $AUTOLOAD %iptcCharset);
|
|
16
16
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
17
17
|
|
|
18
|
-
$VERSION = '1.
|
|
18
|
+
$VERSION = '1.58';
|
|
19
19
|
|
|
20
20
|
%iptcCharset = (
|
|
21
21
|
"\x1b%G" => 'UTF8',
|
|
@@ -411,6 +411,7 @@ my %fileFormat = (
|
|
|
411
411
|
Shift => 'Time',
|
|
412
412
|
ValueConv => 'Image::ExifTool::Exif::ExifDate($val)',
|
|
413
413
|
ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)',
|
|
414
|
+
PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("$val 00:00:00") : $val',
|
|
414
415
|
PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
|
|
415
416
|
},
|
|
416
417
|
60 => {
|
|
@@ -420,6 +421,7 @@ my %fileFormat = (
|
|
|
420
421
|
Shift => 'Time',
|
|
421
422
|
ValueConv => 'Image::ExifTool::Exif::ExifTime($val)',
|
|
422
423
|
ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)',
|
|
424
|
+
PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("1970:01:01 $val") : $val',
|
|
423
425
|
PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
|
|
424
426
|
},
|
|
425
427
|
62 => {
|
|
@@ -429,6 +431,7 @@ my %fileFormat = (
|
|
|
429
431
|
Shift => 'Time',
|
|
430
432
|
ValueConv => 'Image::ExifTool::Exif::ExifDate($val)',
|
|
431
433
|
ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)',
|
|
434
|
+
PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("$val 00:00:00") : $val',
|
|
432
435
|
PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
|
|
433
436
|
},
|
|
434
437
|
63 => {
|
|
@@ -438,6 +441,7 @@ my %fileFormat = (
|
|
|
438
441
|
Shift => 'Time',
|
|
439
442
|
ValueConv => 'Image::ExifTool::Exif::ExifTime($val)',
|
|
440
443
|
ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)',
|
|
444
|
+
PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("1970:01:01 $val") : $val',
|
|
441
445
|
PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
|
|
442
446
|
},
|
|
443
447
|
65 => {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# 6) http://trac.handbrake.fr/browser/trunk/libhb/stream.c
|
|
14
14
|
# 7) http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=04560141
|
|
15
15
|
# 8) http://www.w6rz.net/xport.zip
|
|
16
|
+
# 9) https://en.wikipedia.org/wiki/Program-specific_information
|
|
16
17
|
#
|
|
17
18
|
# Notes: Variable names containing underlines are the same as in ref 1.
|
|
18
19
|
#
|
|
@@ -31,9 +32,9 @@ use strict;
|
|
|
31
32
|
use vars qw($VERSION);
|
|
32
33
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
33
34
|
|
|
34
|
-
$VERSION = '1.
|
|
35
|
+
$VERSION = '1.23';
|
|
35
36
|
|
|
36
|
-
# program map table "stream_type" lookup (ref 6/1)
|
|
37
|
+
# program map table "stream_type" lookup (ref 6/1/9)
|
|
37
38
|
my %streamType = (
|
|
38
39
|
0x00 => 'Reserved',
|
|
39
40
|
0x01 => 'MPEG-1 Video',
|
|
@@ -56,9 +57,22 @@ my %streamType = (
|
|
|
56
57
|
0x12 => 'MPEG-4 generic',
|
|
57
58
|
0x13 => 'ISO 14496-1 SL-packetized',
|
|
58
59
|
0x14 => 'ISO 13818-6 Synchronized Download Protocol',
|
|
59
|
-
|
|
60
|
+
0x15 => 'Packetized metadata',
|
|
61
|
+
0x16 => 'Sectioned metadata',
|
|
62
|
+
0x17 => 'ISO/IEC 13818-6 DSM CC Data Carousel metadata',
|
|
63
|
+
0x18 => 'ISO/IEC 13818-6 DSM CC Object Carousel metadata',
|
|
64
|
+
0x19 => 'ISO/IEC 13818-6 Synchronized Download Protocol metadata',
|
|
65
|
+
0x1a => 'ISO/IEC 13818-11 IPMP',
|
|
60
66
|
0x1b => 'H.264 (AVC) Video',
|
|
67
|
+
0x1c => 'ISO/IEC 14496-3 (MPEG-4 raw audio)',
|
|
68
|
+
0x1d => 'ISO/IEC 14496-17 (MPEG-4 text)',
|
|
69
|
+
0x1e => 'ISO/IEC 23002-3 (MPEG-4 auxiliary video)',
|
|
70
|
+
0x1f => 'ISO/IEC 14496-10 SVC (MPEG-4 AVC sub-bitstream)',
|
|
71
|
+
0x20 => 'ISO/IEC 14496-10 MVC (MPEG-4 AVC sub-bitstream)',
|
|
72
|
+
0x21 => 'ITU-T Rec. T.800 and ISO/IEC 15444 (JPEG 2000 video)',
|
|
61
73
|
0x24 => 'H.265 (HEVC) Video', #PH
|
|
74
|
+
0x42 => 'Chinese Video Standard',
|
|
75
|
+
0x7f => 'ISO/IEC 13818-11 IPMP (DRM)',
|
|
62
76
|
0x80 => 'DigiCipher II Video',
|
|
63
77
|
0x81 => 'A52/AC-3 Audio',
|
|
64
78
|
0x82 => 'HDMV DTS Audio',
|
|
@@ -145,6 +159,7 @@ my $knotsToKph = 1.852; # knots --> km/h
|
|
|
145
159
|
# the following tags are for documentation purposes only
|
|
146
160
|
_AC3 => { SubDirectory => { TagTable => 'Image::ExifTool::M2TS::AC3' } },
|
|
147
161
|
_H264 => { SubDirectory => { TagTable => 'Image::ExifTool::H264::Main' } },
|
|
162
|
+
_MISB => { SubDirectory => { TagTable => 'Image::ExifTool::MISB::Main' } },
|
|
148
163
|
);
|
|
149
164
|
|
|
150
165
|
# information extracted from AC-3 audio streams
|
|
@@ -278,7 +293,7 @@ sub ParsePID($$$$$)
|
|
|
278
293
|
my $verbose = $et->Options('Verbose');
|
|
279
294
|
if ($verbose > 1) {
|
|
280
295
|
my $out = $et->Options('TextOut');
|
|
281
|
-
printf $out "Parsing stream 0x%.4x (%s)\n", $pid, $pidName;
|
|
296
|
+
printf $out "Parsing stream 0x%.4x (%s) %d bytes\n", $pid, $pidName, length($$dataPt);
|
|
282
297
|
$et->VerboseDump($dataPt);
|
|
283
298
|
}
|
|
284
299
|
my $more = 0;
|
|
@@ -303,6 +318,16 @@ sub ParsePID($$$$$)
|
|
|
303
318
|
} elsif ($type == 0x81 or $type == 0x87 or $type == 0x91) {
|
|
304
319
|
# AC-3 audio
|
|
305
320
|
ParseAC3Audio($et, $dataPt);
|
|
321
|
+
} elsif ($type == 0x15) {
|
|
322
|
+
# packetized metadata (look for MISB code starting after 5-byte header)
|
|
323
|
+
if ($$dataPt =~ /^.{5}\x06\x0e\x2b\x34/s) {
|
|
324
|
+
$more = Image::ExifTool::MISB::ParseMISB($et, $dataPt, GetTagTable('Image::ExifTool::MISB::Main'));
|
|
325
|
+
if (not $$et{OPTIONS}{ExtractEmbedded}) {
|
|
326
|
+
$more = 0; # extract from only the first packet unless ExtractEmbedded is used
|
|
327
|
+
} elsif ($$et{OPTIONS}{ExtractEmbedded} > 2) {
|
|
328
|
+
$more = 1; # read past unknown 0x15 packets if ExtractEmbedded > 2
|
|
329
|
+
}
|
|
330
|
+
}
|
|
306
331
|
} elsif ($type < 0) {
|
|
307
332
|
if ($$dataPt =~ /^(.{164})?(.{24})A[NS][EW]/s) {
|
|
308
333
|
# (Blueskysea B4K, Novatek NT96670)
|
|
@@ -390,6 +415,48 @@ sub ParsePID($$$$$)
|
|
|
390
415
|
}
|
|
391
416
|
}
|
|
392
417
|
$more = 1;
|
|
418
|
+
} elsif ($$dataPt =~ /\$GPRMC,/) {
|
|
419
|
+
# Jomise T860S-GM dashcam
|
|
420
|
+
# $GPRMC,hhmmss.ss,A,ddmm.mmmmm,N,dddmm.mmmmm,W,spd-kts,dir-dg,DDMMYY,,*cs
|
|
421
|
+
# $GPRMC,172255.00,A,:985.95194,N,17170.14674,W,029.678,170.68,240822,,,D*7B
|
|
422
|
+
# $GPRMC,172355.00,A,:984.76779,N,17170.00473,W,032.219,172.04,240822,,,D*7B
|
|
423
|
+
# ddmm.mmmm: from 4742.2568 12209.2028 (should be)
|
|
424
|
+
# to 4741.7696 12209.1056
|
|
425
|
+
# stamped on video: 47.70428N, 122.15338W, 35mph (dd.ddddd)
|
|
426
|
+
# to 47.69616N, 122.15176W, 37mph
|
|
427
|
+
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
|
|
428
|
+
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
|
|
429
|
+
# do some basic sanity checks on the date
|
|
430
|
+
$13 <= 31 and $14 <= 12 and $15 <= 99)
|
|
431
|
+
{
|
|
432
|
+
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
|
|
433
|
+
my $year = $15 + ($15 >= 70 ? 1900 : 2000);
|
|
434
|
+
$et->HandleTag($tagTbl, GPSDateTime => sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', $year, $14, $13, $1, $2, $3));
|
|
435
|
+
#(not this simple)
|
|
436
|
+
#$et->HandleTag($tagTbl, GPSLatitude => (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1));
|
|
437
|
+
#$et->HandleTag($tagTbl, GPSLongitude => (($8 || 0) + $9/60) * ($10 eq 'E' ? 1 : -1));
|
|
438
|
+
$et->HandleTag($tagTbl, GPSSpeed => $11 * $knotsToKph) if length $11;
|
|
439
|
+
$et->HandleTag($tagTbl, GPSTrack => $12) if length $12;
|
|
440
|
+
# it looks like maybe the degrees are xor-ed with something,
|
|
441
|
+
# and the minutes have some scaling factor and offset?
|
|
442
|
+
# (the code below is approximately correct for my only sample)
|
|
443
|
+
my @chars = unpack('C*', $5 . $8);
|
|
444
|
+
my @xor = (0x0e,0x0e,0x00,0x05,0x03); # (empirical based on 1 sample; may be completely off base)
|
|
445
|
+
my $bad;
|
|
446
|
+
foreach (@chars) {
|
|
447
|
+
$_ ^= shift(@xor);
|
|
448
|
+
$bad = 1 if $_ < 0x30 or $_ > 0x39;
|
|
449
|
+
}
|
|
450
|
+
if ($bad) {
|
|
451
|
+
$et->WarnOnce('Error decrypting GPS degrees');
|
|
452
|
+
} else {
|
|
453
|
+
my $la = pack('C*', @chars[0,1]);
|
|
454
|
+
my $lo = pack('C*', @chars[2,3,4]);
|
|
455
|
+
$et->WarnOnce('Decryption of this GPS is highly experimental. More testing samples are required');
|
|
456
|
+
$et->HandleTag($tagTbl, GPSLatitude => (($la || 0) + (($6-85.95194)/2.43051724137931+42.2568)/60) * ($7 eq 'N' ? 1 : -1));
|
|
457
|
+
$et->HandleTag($tagTbl, GPSLongitude => (($lo || 0) + (($9-70.14674)/1.460987654320988+9.2028)/60) * ($10 eq 'E' ? 1 : -1));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
393
460
|
} elsif ($$dataPt =~ /^.{44}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s and length($$dataPt) >= 84) {
|
|
394
461
|
#forum11320
|
|
395
462
|
SetByteOrder('II');
|
|
@@ -426,7 +493,7 @@ sub ProcessM2TS($$)
|
|
|
426
493
|
my ($et, $dirInfo) = @_;
|
|
427
494
|
my $raf = $$dirInfo{RAF};
|
|
428
495
|
my ($buff, $pLen, $upkPrefix, $j, $fileType, $eof);
|
|
429
|
-
my (%pmt, %pidType, %data, %sectLen);
|
|
496
|
+
my (%pmt, %pidType, %data, %sectLen, %packLen, %fromStart);
|
|
430
497
|
my ($startTime, $endTime, $fwdTime, $backScan, $maxBack);
|
|
431
498
|
my $verbose = $et->Options('Verbose');
|
|
432
499
|
my $out = $et->Options('TextOut');
|
|
@@ -468,6 +535,7 @@ sub ProcessM2TS($$)
|
|
|
468
535
|
my %gpsPID = (
|
|
469
536
|
0x0300 => 1, # Novatek INNOVV
|
|
470
537
|
0x01e4 => 1, # vsys a6l dashcam
|
|
538
|
+
0x0e1b => 1, # Jomise T860S-GM dashcam
|
|
471
539
|
);
|
|
472
540
|
my $pEnd = 0;
|
|
473
541
|
|
|
@@ -610,6 +678,7 @@ sub ProcessM2TS($$)
|
|
|
610
678
|
$buf2 = $data{$pid};
|
|
611
679
|
$pos = 0;
|
|
612
680
|
delete $data{$pid};
|
|
681
|
+
delete $fromStart{$pid};
|
|
613
682
|
delete $sectLen{$pid};
|
|
614
683
|
}
|
|
615
684
|
my $slen = length($buf2); # section length
|
|
@@ -736,6 +805,7 @@ sub ProcessM2TS($$)
|
|
|
736
805
|
my $more = ParsePID($et, $pid, $pidType{$pid}, $pidName{$pid}, \$data{$pid});
|
|
737
806
|
# start fresh even if we couldn't process this PID yet
|
|
738
807
|
delete $data{$pid};
|
|
808
|
+
delete $fromStart{$pid};
|
|
739
809
|
unless ($more) {
|
|
740
810
|
delete $needPID{$pid};
|
|
741
811
|
$didPID{$pid} = 1;
|
|
@@ -749,8 +819,8 @@ sub ProcessM2TS($$)
|
|
|
749
819
|
my $start_code = Get32u(\$buff, $pos);
|
|
750
820
|
next unless ($start_code & 0xffffff00) == 0x00000100;
|
|
751
821
|
my $stream_id = $start_code & 0xff;
|
|
822
|
+
my $pes_packet_length = Get16u(\$buff, $pos + 4);
|
|
752
823
|
if ($verbose > 1) {
|
|
753
|
-
my $pes_packet_length = Get16u(\$buff, $pos + 4);
|
|
754
824
|
printf $out " Stream ID: 0x%.2x\n", $stream_id;
|
|
755
825
|
print $out " Packet Len: $pes_packet_length\n";
|
|
756
826
|
}
|
|
@@ -766,6 +836,14 @@ sub ProcessM2TS($$)
|
|
|
766
836
|
next if $pos >= $pEnd;
|
|
767
837
|
}
|
|
768
838
|
$data{$pid} = substr($buff, $pos, $pEnd-$pos);
|
|
839
|
+
# set flag that we read this payload from the start
|
|
840
|
+
$fromStart{$pid} = 1;
|
|
841
|
+
# save the packet length
|
|
842
|
+
if ($pes_packet_length > 8) {
|
|
843
|
+
$packLen{$pid} = $pes_packet_length - 8; # (where are the 8 extra bytes? - PH)
|
|
844
|
+
} else {
|
|
845
|
+
delete $packLen{$pid};
|
|
846
|
+
}
|
|
769
847
|
} else {
|
|
770
848
|
unless (defined $data{$pid}) {
|
|
771
849
|
# (vsys a6l dashcam GPS record doesn't have a start indicator)
|
|
@@ -776,12 +854,24 @@ sub ProcessM2TS($$)
|
|
|
776
854
|
$data{$pid} .= substr($buff, $pos, $pEnd-$pos);
|
|
777
855
|
}
|
|
778
856
|
# save only the first 256 bytes of most streams, except for
|
|
779
|
-
# unknown
|
|
780
|
-
my $saveLen
|
|
857
|
+
# unknown, H.264 or metadata streams where we save up to 1 kB
|
|
858
|
+
my $saveLen;
|
|
859
|
+
if (not $pidType{$pid} or $pidType{$pid} == 0x1b) {
|
|
860
|
+
$saveLen = 1024;
|
|
861
|
+
} elsif ($pidType{$pid} == 0x15) {
|
|
862
|
+
# use 1024 or actual size of metadata packet if smaller
|
|
863
|
+
$saveLen = 1024;
|
|
864
|
+
$saveLen = $packLen{$pid} if defined $packLen{$pid} and $saveLen > $packLen{$pid};
|
|
865
|
+
} else {
|
|
866
|
+
$saveLen = 256;
|
|
867
|
+
}
|
|
781
868
|
if (length($data{$pid}) >= $saveLen) {
|
|
782
869
|
my $more = ParsePID($et, $pid, $pidType{$pid}, $pidName{$pid}, \$data{$pid});
|
|
783
870
|
next if $more < 0; # wait for program map table (hopefully not too long)
|
|
871
|
+
# don't stop parsing if we weren't successful and may have missed the start
|
|
872
|
+
$more = 1 if not $more and not $fromStart{$pid};
|
|
784
873
|
delete $data{$pid};
|
|
874
|
+
delete $fromStart{$pid};
|
|
785
875
|
$more and $needPID{$pid} = -1, next; # parse more of these
|
|
786
876
|
delete $needPID{$pid};
|
|
787
877
|
$didPID{$pid} = 1;
|
|
@@ -14,7 +14,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
14
14
|
use Image::ExifTool::Exif;
|
|
15
15
|
use Image::ExifTool::GPS;
|
|
16
16
|
|
|
17
|
-
$VERSION = '1.
|
|
17
|
+
$VERSION = '1.50';
|
|
18
18
|
|
|
19
19
|
sub ProcessMIE($$);
|
|
20
20
|
sub ProcessMIEGroup($$$);
|
|
@@ -448,6 +448,13 @@ my %offOn = ( 0 => 'Off', 1 => 'On' );
|
|
|
448
448
|
Notes => 'string composed of R, G, B, Y, Cb and Cr',
|
|
449
449
|
},
|
|
450
450
|
Compression => { Name => 'CompressionRatio', Writable => 'rational32u' },
|
|
451
|
+
OriginalImageSize => { # PH added 2022-09-28
|
|
452
|
+
Writable => 'int16u',
|
|
453
|
+
Count => -1,
|
|
454
|
+
Notes => 'size of original image before cropping',
|
|
455
|
+
PrintConv => '$val=~tr/ /x/;$val',
|
|
456
|
+
PrintConvInv => '$val=~tr/x/ /;$val',
|
|
457
|
+
},
|
|
451
458
|
ImageSize => {
|
|
452
459
|
Writable => 'int16u',
|
|
453
460
|
Count => -1,
|
|
@@ -1253,8 +1260,7 @@ sub WriteMIEGroup($$$)
|
|
|
1253
1260
|
# join multiple values into a single string
|
|
1254
1261
|
$newVal = join "\0", @newVals;
|
|
1255
1262
|
# write string as UTF-8,16 or 32 if value contains valid UTF-8 codes
|
|
1256
|
-
|
|
1257
|
-
my $isUTF8 = Image::ExifTool::XMP::IsUTF8(\$newVal);
|
|
1263
|
+
my $isUTF8 = Image::ExifTool::IsUTF8(\$newVal);
|
|
1258
1264
|
if ($isUTF8 > 0) {
|
|
1259
1265
|
$writable = 'utf8';
|
|
1260
1266
|
# write UTF-16 or UTF-32 if it is more compact
|