exiftool-vendored.exe 12.60.0 → 12.65.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/LICENSE +254 -254
- package/bin/exiftool_files/Changes +110 -0
- package/bin/exiftool_files/LICENSE +674 -0
- package/bin/exiftool_files/Makefile.PL +7 -1
- package/bin/exiftool_files/README +50 -45
- package/bin/exiftool_files/config_files/guano.config +161 -0
- package/bin/exiftool_files/exiftool.pl +162 -104
- package/bin/exiftool_files/lib/Image/ExifTool/7Z.pm +793 -0
- package/bin/exiftool_files/lib/Image/ExifTool/Apple.pm +14 -7
- package/bin/exiftool_files/lib/Image/ExifTool/BMP.pm +0 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BigTIFF.pm +8 -1
- package/bin/exiftool_files/lib/Image/ExifTool/BuildTagLookup.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/Canon.pm +4 -1
- package/bin/exiftool_files/lib/Image/ExifTool/CanonRaw.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/CanonVRD.pm +4 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Exif.pm +31 -14
- package/bin/exiftool_files/lib/Image/ExifTool/FlashPix.pm +9 -2
- package/bin/exiftool_files/lib/Image/ExifTool/FujiFilm.pm +3 -3
- package/bin/exiftool_files/lib/Image/ExifTool/GPS.pm +5 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Geotag.pm +4 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Jpeg2000.pm +243 -20
- package/bin/exiftool_files/lib/Image/ExifTool/Lang/fr.pm +1467 -202
- package/bin/exiftool_files/lib/Image/ExifTool/MPF.pm +2 -1
- package/bin/exiftool_files/lib/Image/ExifTool/Matroska.pm +16 -1
- package/bin/exiftool_files/lib/Image/ExifTool/MinoltaRaw.pm +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Nikon.pm +941 -33
- package/bin/exiftool_files/lib/Image/ExifTool/NikonCustom.pm +874 -63
- package/bin/exiftool_files/lib/Image/ExifTool/PDF.pm +39 -12
- package/bin/exiftool_files/lib/Image/ExifTool/PLIST.pm +8 -1
- package/bin/exiftool_files/lib/Image/ExifTool/PNG.pm +6 -6
- package/bin/exiftool_files/lib/Image/ExifTool/PhaseOne.pm +5 -5
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTime.pm +96 -32
- package/bin/exiftool_files/lib/Image/ExifTool/QuickTimeStream.pl +68 -37
- package/bin/exiftool_files/lib/Image/ExifTool/README +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/RIFF.pm +11 -9
- package/bin/exiftool_files/lib/Image/ExifTool/Samsung.pm +227 -227
- package/bin/exiftool_files/lib/Image/ExifTool/Shortcuts.pm +2 -1
- package/bin/exiftool_files/lib/Image/ExifTool/SigmaRaw.pm +4 -4
- package/bin/exiftool_files/lib/Image/ExifTool/Sony.pm +237 -32
- package/bin/exiftool_files/lib/Image/ExifTool/TagLookup.pm +4762 -4629
- package/bin/exiftool_files/lib/Image/ExifTool/TagNames.pod +737 -20
- package/bin/exiftool_files/lib/Image/ExifTool/Validate.pm +17 -1
- package/bin/exiftool_files/lib/Image/ExifTool/WPG.pm +296 -0
- package/bin/exiftool_files/lib/Image/ExifTool/WriteExif.pl +9 -7
- package/bin/exiftool_files/lib/Image/ExifTool/WritePDF.pl +7 -8
- package/bin/exiftool_files/lib/Image/ExifTool/WriteQuickTime.pl +21 -9
- package/bin/exiftool_files/lib/Image/ExifTool/WriteXMP.pl +2 -2
- package/bin/exiftool_files/lib/Image/ExifTool/Writer.pl +47 -16
- package/bin/exiftool_files/lib/Image/ExifTool/XMP.pm +30 -6
- package/bin/exiftool_files/lib/Image/ExifTool/XMP2.pl +32 -0
- package/bin/exiftool_files/lib/Image/ExifTool/XMPStruct.pl +96 -28
- package/bin/exiftool_files/lib/Image/ExifTool/ZIP.pm +159 -41
- package/bin/exiftool_files/lib/Image/ExifTool.pm +280 -164
- package/bin/exiftool_files/lib/Image/ExifTool.pod +117 -52
- package/package.json +3 -2
|
@@ -21,7 +21,7 @@ use vars qw($VERSION $AUTOLOAD $lastFetched);
|
|
|
21
21
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
22
22
|
require Exporter;
|
|
23
23
|
|
|
24
|
-
$VERSION = '1.
|
|
24
|
+
$VERSION = '1.57';
|
|
25
25
|
|
|
26
26
|
sub FetchObject($$$$);
|
|
27
27
|
sub ExtractObject($$;$$);
|
|
@@ -41,7 +41,7 @@ my $cryptStream; # flag that streams are encrypted
|
|
|
41
41
|
my $lastOffset; # last fetched object offset
|
|
42
42
|
my %streamObjs; # hash of stream objects
|
|
43
43
|
my %fetched; # dicts fetched in verbose mode (to avoid cyclical recursion)
|
|
44
|
-
my $pdfVer; # version of PDF file being processed
|
|
44
|
+
my $pdfVer; # version of PDF file being processed (from header)
|
|
45
45
|
|
|
46
46
|
# filters supported in DecodeStream()
|
|
47
47
|
my %supportedFilter = (
|
|
@@ -109,12 +109,24 @@ my %supportedFilter = (
|
|
|
109
109
|
Title => { },
|
|
110
110
|
Author => { Groups => { 2 => 'Author' } },
|
|
111
111
|
Subject => { },
|
|
112
|
-
Keywords => {
|
|
112
|
+
Keywords => {
|
|
113
|
+
List => 'string', # this is a string list
|
|
114
|
+
Notes => q{
|
|
115
|
+
stored as a string but treated as a comma- or semicolon-separated list of
|
|
116
|
+
items when reading if the string contains commas or semicolons, whichever is
|
|
117
|
+
more numerous, otherwise it is treated a space-separated list of items.
|
|
118
|
+
Written as a comma-separated list. The list behaviour may be defeated by
|
|
119
|
+
setting the API NoPDFList option. Note that the corresponding
|
|
120
|
+
XMP-pdf:Keywords tag is not treated as a list, so the NoPDFList option
|
|
121
|
+
should be used when copying between these two.
|
|
122
|
+
},
|
|
123
|
+
},
|
|
113
124
|
Creator => { },
|
|
114
125
|
Producer => { },
|
|
115
126
|
CreationDate => {
|
|
116
127
|
Name => 'CreateDate',
|
|
117
128
|
Writable => 'date',
|
|
129
|
+
PDF2 => 1, # not deprecated in PDF 2.0
|
|
118
130
|
Groups => { 2 => 'Time' },
|
|
119
131
|
Shift => 'Time',
|
|
120
132
|
PrintConv => '$self->ConvertDateTime($val)',
|
|
@@ -123,6 +135,7 @@ my %supportedFilter = (
|
|
|
123
135
|
ModDate => {
|
|
124
136
|
Name => 'ModifyDate',
|
|
125
137
|
Writable => 'date',
|
|
138
|
+
PDF2 => 1, # not deprecated in PDF 2.0
|
|
126
139
|
Groups => { 2 => 'Time' },
|
|
127
140
|
Shift => 'Time',
|
|
128
141
|
PrintConv => '$self->ConvertDateTime($val)',
|
|
@@ -168,7 +181,10 @@ my %supportedFilter = (
|
|
|
168
181
|
Lang => 'Language',
|
|
169
182
|
PageLayout => { },
|
|
170
183
|
PageMode => { },
|
|
171
|
-
Version =>
|
|
184
|
+
Version => {
|
|
185
|
+
Name => 'PDFVersion',
|
|
186
|
+
RawConv => '$$self{PDFVersion} = $val if $$self{PDFVersion} < $val; $val',
|
|
187
|
+
},
|
|
172
188
|
);
|
|
173
189
|
|
|
174
190
|
# tags extracted from the PDF Encrypt dictionary
|
|
@@ -1749,12 +1765,13 @@ sub ExpandArray($)
|
|
|
1749
1765
|
# 4) nesting depth, 5) dictionary capture type
|
|
1750
1766
|
sub ProcessDict($$$$;$$)
|
|
1751
1767
|
{
|
|
1768
|
+
local $_;
|
|
1752
1769
|
my ($et, $tagTablePtr, $dict, $xref, $nesting, $type) = @_;
|
|
1753
1770
|
my $verbose = $et->Options('Verbose');
|
|
1754
1771
|
my $unknown = $$tagTablePtr{EXTRACT_UNKNOWN};
|
|
1755
1772
|
my $embedded = (defined $unknown and not $unknown and $et->Options('ExtractEmbedded'));
|
|
1756
1773
|
my @tags = @{$$dict{_tags}};
|
|
1757
|
-
my ($next, %join);
|
|
1774
|
+
my ($next, %join, $validInfo);
|
|
1758
1775
|
my $index = 0;
|
|
1759
1776
|
|
|
1760
1777
|
$nesting = ($nesting || 0) + 1;
|
|
@@ -1775,6 +1792,7 @@ sub ProcessDict($$$$;$$)
|
|
|
1775
1792
|
last;
|
|
1776
1793
|
}
|
|
1777
1794
|
}
|
|
1795
|
+
$validInfo = ($et->Options('Validate') and $tagTablePtr eq \%Image::ExifTool::PDF::Info);
|
|
1778
1796
|
#
|
|
1779
1797
|
# extract information from all tags in the dictionary
|
|
1780
1798
|
#
|
|
@@ -1810,6 +1828,10 @@ sub ProcessDict($$$$;$$)
|
|
|
1810
1828
|
$isSubDoc = 1; # treat as a sub-document
|
|
1811
1829
|
}
|
|
1812
1830
|
}
|
|
1831
|
+
if ($validInfo and $$et{PDFVersion} >= 2.0 and (not $tagInfo or not $$tagInfo{PDF2})) {
|
|
1832
|
+
my $name = $tagInfo ? ":$$tagInfo{Name}" : " Info tag '${tag}'";
|
|
1833
|
+
$et->Warn("PDF$name is deprecated in PDF 2.0");
|
|
1834
|
+
}
|
|
1813
1835
|
if ($verbose) {
|
|
1814
1836
|
my ($val2, $extra);
|
|
1815
1837
|
if (ref $val eq 'SCALAR') {
|
|
@@ -2007,10 +2029,16 @@ sub ProcessDict($$$$;$$)
|
|
|
2007
2029
|
}
|
|
2008
2030
|
if ($$tagInfo{List} and not $$et{OPTIONS}{NoPDFList}) {
|
|
2009
2031
|
# separate tokens in comma or whitespace delimited lists
|
|
2010
|
-
my
|
|
2011
|
-
|
|
2012
|
-
|
|
2032
|
+
my $comma = $val =~ tr/,/,/;
|
|
2033
|
+
my $semi = $val =~ tr/;/;/;
|
|
2034
|
+
my $split;
|
|
2035
|
+
if ($comma or $semi) {
|
|
2036
|
+
$split = $comma > $semi ? ',+\\s*' : ';+\\s*';
|
|
2037
|
+
} else {
|
|
2038
|
+
$split = ' ';
|
|
2013
2039
|
}
|
|
2040
|
+
my @values = split $split, $val;
|
|
2041
|
+
$et->FoundTag($tagInfo, $_) foreach @values;
|
|
2014
2042
|
} else {
|
|
2015
2043
|
# a simple tag value
|
|
2016
2044
|
$et->FoundTag($tagInfo, $val);
|
|
@@ -2118,9 +2146,8 @@ sub ReadPDF($$)
|
|
|
2118
2146
|
$raf->Read($buff, 1024) >= 8 or return 0;
|
|
2119
2147
|
$buff =~ /^(\s*)%PDF-(\d+\.\d+)/ or return 0;
|
|
2120
2148
|
$$et{PDFBase} = length $1 and $et->Warn('PDF header is not at start of file',1);
|
|
2121
|
-
$pdfVer = $2;
|
|
2149
|
+
$pdfVer = $$et{PDFVersion} = $2;
|
|
2122
2150
|
$et->SetFileType(); # set the FileType tag
|
|
2123
|
-
$et->Warn("The PDF $pdfVer specification is held hostage by the ISO") if $pdfVer >= 2.0;
|
|
2124
2151
|
# store PDFVersion tag
|
|
2125
2152
|
my $tagTablePtr = GetTagTable('Image::ExifTool::PDF::Root');
|
|
2126
2153
|
$et->HandleTag($tagTablePtr, 'Version', $pdfVer);
|
|
@@ -2384,8 +2411,8 @@ This module is loaded automatically by Image::ExifTool when required.
|
|
|
2384
2411
|
This code reads meta information from PDF (Adobe Portable Document Format)
|
|
2385
2412
|
files. It supports object streams introduced in PDF-1.5 but only with a
|
|
2386
2413
|
limited set of Filter and Predictor algorithms, however all standard
|
|
2387
|
-
encryption methods through PDF-
|
|
2388
|
-
|
|
2414
|
+
encryption methods through PDF-2.0 are supported, including AESV2 (AES-128)
|
|
2415
|
+
and AESV3 (AES-256).
|
|
2389
2416
|
|
|
2390
2417
|
=head1 AUTHOR
|
|
2391
2418
|
|
|
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
21
21
|
use Image::ExifTool::XMP;
|
|
22
22
|
use Image::ExifTool::GPS;
|
|
23
23
|
|
|
24
|
-
$VERSION = '1.
|
|
24
|
+
$VERSION = '1.11';
|
|
25
25
|
|
|
26
26
|
sub ExtractObject($$;$);
|
|
27
27
|
sub Get24u($$);
|
|
@@ -288,6 +288,12 @@ sub ExtractObject($$;$)
|
|
|
288
288
|
my $obj = ExtractObject($et, $plistInfo, $tag);
|
|
289
289
|
next if not defined $obj;
|
|
290
290
|
unless ($tagTablePtr) {
|
|
291
|
+
# make sure this is a valid structure field name
|
|
292
|
+
if (not defined $key or $key !~ /^[-_a-zA-Z0-9]+$/) {
|
|
293
|
+
$key = "Tag$i"; # (generate fake tag name if it had illegal characters)
|
|
294
|
+
} elsif ($key !~ /^[_a-zA-Z]/) {
|
|
295
|
+
$key = "_$key"; # (must begin with alpha or underline)
|
|
296
|
+
}
|
|
291
297
|
$$val{$key} = $obj if defined $obj;
|
|
292
298
|
next;
|
|
293
299
|
}
|
|
@@ -298,6 +304,7 @@ sub ExtractObject($$;$)
|
|
|
298
304
|
my $name = $tag;
|
|
299
305
|
$name =~ s/([^A-Za-z])([a-z])/$1\u$2/g; # capitalize words
|
|
300
306
|
$name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters
|
|
307
|
+
$name = "Tag$name" if length($name) < 2 or $name =~ /^[-0-9]/;
|
|
301
308
|
$tagInfo = { Name => ucfirst($name), List => 1 };
|
|
302
309
|
if ($$plistInfo{DateFormat}) {
|
|
303
310
|
$$tagInfo{Groups}{2} = 'Time';
|
|
@@ -36,7 +36,7 @@ use strict;
|
|
|
36
36
|
use vars qw($VERSION $AUTOLOAD %stdCase);
|
|
37
37
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
38
38
|
|
|
39
|
-
$VERSION = '1.
|
|
39
|
+
$VERSION = '1.64';
|
|
40
40
|
|
|
41
41
|
sub ProcessPNG_tEXt($$$);
|
|
42
42
|
sub ProcessPNG_iTXt($$$);
|
|
@@ -1374,7 +1374,7 @@ sub ProcessPNG($$)
|
|
|
1374
1374
|
my $datCount = 0;
|
|
1375
1375
|
my $datBytes = 0;
|
|
1376
1376
|
my $fastScan = $et->Options('FastScan');
|
|
1377
|
-
my $
|
|
1377
|
+
my $hash = $$et{ImageDataHash};
|
|
1378
1378
|
my ($n, $sig, $err, $hbuf, $dbuf, $cbuf);
|
|
1379
1379
|
my ($wasHdr, $wasEnd, $wasDat, $doTxt, @txtOffset);
|
|
1380
1380
|
|
|
@@ -1454,7 +1454,7 @@ sub ProcessPNG($$)
|
|
|
1454
1454
|
if ($datCount and $chunk ne $datChunk) {
|
|
1455
1455
|
my $s = $datCount > 1 ? 's' : '';
|
|
1456
1456
|
print $out "$fileType $datChunk ($datCount chunk$s, total $datBytes bytes)\n";
|
|
1457
|
-
print $out "$$et{INDENT}(
|
|
1457
|
+
print $out "$$et{INDENT}(ImageDataHash: $datBytes bytes of $datChunk data)\n" if $hash;
|
|
1458
1458
|
$datCount = $datBytes = 0;
|
|
1459
1459
|
}
|
|
1460
1460
|
}
|
|
@@ -1541,8 +1541,8 @@ sub ProcessPNG($$)
|
|
|
1541
1541
|
}
|
|
1542
1542
|
# skip over data chunks if possible/necessary
|
|
1543
1543
|
} elsif (not $validate or $len > $chunkSizeLimit) {
|
|
1544
|
-
if ($
|
|
1545
|
-
$et->
|
|
1544
|
+
if ($hash) {
|
|
1545
|
+
$et->ImageDataHash($raf, $len);
|
|
1546
1546
|
$raf->Read($cbuf, 4) == 4 or $et->Warn('Truncated data'), last;
|
|
1547
1547
|
} else {
|
|
1548
1548
|
$raf->Seek($len + 4, 1) or $et->Warn('Seek error'), last;
|
|
@@ -1565,7 +1565,7 @@ sub ProcessPNG($$)
|
|
|
1565
1565
|
$et->Warn("Corrupted $fileType image") unless $wasEnd;
|
|
1566
1566
|
last;
|
|
1567
1567
|
}
|
|
1568
|
-
$
|
|
1568
|
+
$hash->add($dbuf) if $hash and $datChunk; # add to hash if necessary
|
|
1569
1569
|
if ($verbose or $validate or ($outfile and not $fastScan)) {
|
|
1570
1570
|
# check CRC when in verbose mode (since we don't care about speed)
|
|
1571
1571
|
my $crc = CalculateCRC(\$hbuf, undef, 4);
|
|
@@ -15,7 +15,7 @@ use vars qw($VERSION);
|
|
|
15
15
|
use Image::ExifTool qw(:DataAccess :Utils);
|
|
16
16
|
use Image::ExifTool::Exif;
|
|
17
17
|
|
|
18
|
-
$VERSION = '1.
|
|
18
|
+
$VERSION = '1.09';
|
|
19
19
|
|
|
20
20
|
sub WritePhaseOne($$$);
|
|
21
21
|
sub ProcessPhaseOne($$$);
|
|
@@ -585,7 +585,7 @@ sub ProcessPhaseOne($$$)
|
|
|
585
585
|
my $dirLen = $$dirInfo{DirLen} || $$dirInfo{DataLen} - $dirStart;
|
|
586
586
|
my $binary = $et->Options('Binary');
|
|
587
587
|
my $verbose = $et->Options('Verbose');
|
|
588
|
-
my $
|
|
588
|
+
my $hash = $$et{ImageDataHash};
|
|
589
589
|
my $htmlDump = $$et{HTML_DUMP};
|
|
590
590
|
|
|
591
591
|
return 0 if $dirLen < 12;
|
|
@@ -678,16 +678,16 @@ sub ProcessPhaseOne($$$)
|
|
|
678
678
|
}
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
|
-
if ($
|
|
681
|
+
if ($hash and $tagInfo and $$tagInfo{IsImageData}) {
|
|
682
682
|
my ($pos, $len) = ($valuePtr, $size);
|
|
683
683
|
while ($len) {
|
|
684
684
|
my $n = $len > 65536 ? 65536 : $len;
|
|
685
685
|
my $tmp = substr($$dataPt, $pos, $n);
|
|
686
|
-
$
|
|
686
|
+
$hash->add($tmp);
|
|
687
687
|
$len -= $n;
|
|
688
688
|
$pos += $n;
|
|
689
689
|
}
|
|
690
|
-
$et->VPrint(0, "$$et{INDENT}(
|
|
690
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: $size bytes of PhaseOne:$$tagInfo{Name})\n");
|
|
691
691
|
}
|
|
692
692
|
my %parms = (
|
|
693
693
|
DirName => $ifdType,
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
# 25) https://cconcolato.github.io/mp4ra/atoms.html
|
|
38
38
|
# 26) https://github.com/SamsungVR/android_upload_sdk/blob/master/SDKLib/src/main/java/com/samsung/msca/samsungvr/sdk/UserVideo.java
|
|
39
39
|
# 27) https://exiftool.org/forum/index.php?topic=11517.0
|
|
40
|
+
# 28) https://docs.mp3tag.de/mapping/
|
|
40
41
|
#------------------------------------------------------------------------------
|
|
41
42
|
|
|
42
43
|
package Image::ExifTool::QuickTime;
|
|
@@ -47,7 +48,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
|
|
|
47
48
|
use Image::ExifTool::Exif;
|
|
48
49
|
use Image::ExifTool::GPS;
|
|
49
50
|
|
|
50
|
-
$VERSION = '2.
|
|
51
|
+
$VERSION = '2.87';
|
|
51
52
|
|
|
52
53
|
sub ProcessMOV($$;$);
|
|
53
54
|
sub ProcessKeys($$$);
|
|
@@ -224,6 +225,9 @@ my %ftypLookup = (
|
|
|
224
225
|
'crx ' => 'Canon Raw (.CRX)', #PH (CR3 or CRM; use Canon CompressorVersion to decide)
|
|
225
226
|
);
|
|
226
227
|
|
|
228
|
+
# use extension to determine file type
|
|
229
|
+
my %useExt = ( GLV => 'MP4' );
|
|
230
|
+
|
|
227
231
|
# information for int32u date/time tags (time zero is Jan 1, 1904)
|
|
228
232
|
my %timeInfo = (
|
|
229
233
|
Notes => 'converted from UTC to local time if the QuickTimeUTC option is set',
|
|
@@ -447,8 +451,8 @@ my %dupDirOK = ( ipco => 1, '----' => 1 );
|
|
|
447
451
|
my %eeStd = ( stco => 'stbl', co64 => 'stbl', stsz => 'stbl', stz2 => 'stbl',
|
|
448
452
|
stsc => 'stbl', stts => 'stbl' );
|
|
449
453
|
|
|
450
|
-
# atoms required for generating
|
|
451
|
-
my %
|
|
454
|
+
# atoms required for generating ImageDataHash
|
|
455
|
+
my %hashBox = ( vide => { %eeStd }, soun => { %eeStd } );
|
|
452
456
|
|
|
453
457
|
# boxes and their containers for the various handler types that we want to save
|
|
454
458
|
# when the ExtractEmbedded is enabled (currently only the 'gps ' container name is
|
|
@@ -470,6 +474,9 @@ my %eeBox2 = (
|
|
|
470
474
|
vide => { avcC => 'stsd' }, # (parses H264 video stream)
|
|
471
475
|
);
|
|
472
476
|
|
|
477
|
+
# image types in AVIF and HEIC files
|
|
478
|
+
my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 );
|
|
479
|
+
|
|
473
480
|
# QuickTime atoms
|
|
474
481
|
%Image::ExifTool::QuickTime::Main = (
|
|
475
482
|
PROCESS_PROC => \&ProcessMOV,
|
|
@@ -1003,7 +1010,8 @@ my %eeBox2 = (
|
|
|
1003
1010
|
0 => 'Monoscopic',
|
|
1004
1011
|
1 => 'Stereoscopic Top-Bottom',
|
|
1005
1012
|
2 => 'Stereoscopic Left-Right',
|
|
1006
|
-
3 => 'Stereoscopic Stereo-Custom',
|
|
1013
|
+
3 => 'Stereoscopic Stereo-Custom',
|
|
1014
|
+
4 => 'Stereoscopic Right-Left',
|
|
1007
1015
|
},
|
|
1008
1016
|
},
|
|
1009
1017
|
sv3d => {
|
|
@@ -2067,8 +2075,8 @@ my %eeBox2 = (
|
|
|
2067
2075
|
ValueConv => 'substr($val, 4)',
|
|
2068
2076
|
ValueConvInv => '"\0\0\0\x01$val"',
|
|
2069
2077
|
},
|
|
2070
|
-
# hmtp - "\0\0\0\x01"
|
|
2071
|
-
# vrin - "\0\0\0\x01" followed by 8 bytes of zero
|
|
2078
|
+
# hmtp - 412 bytes: "\0\0\0\x01" then maybe "\0\0\0\x64" and the rest zeros
|
|
2079
|
+
# vrin - 12 bytes: "\0\0\0\x01" followed by 8 bytes of zero
|
|
2072
2080
|
# ---- GoPro ---- (ref PH)
|
|
2073
2081
|
GoPr => 'GoProType', # (Hero3+)
|
|
2074
2082
|
FIRM => { Name => 'FirmwareVersion', Avoid => 1 }, # (Hero4)
|
|
@@ -2864,6 +2872,25 @@ my %eeBox2 = (
|
|
|
2864
2872
|
Name => 'AV1Configuration',
|
|
2865
2873
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AV1Config' },
|
|
2866
2874
|
},
|
|
2875
|
+
clli => {
|
|
2876
|
+
Name => 'ContentLightLevel',
|
|
2877
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ContentLightLevel' },
|
|
2878
|
+
},
|
|
2879
|
+
# ref https://nokiatech.github.io/heif/technical.html
|
|
2880
|
+
# cclv - Content Color Volume
|
|
2881
|
+
# mdcv - Mastering Display Color Volume
|
|
2882
|
+
# rrtp - Required reference types
|
|
2883
|
+
# crtt - Creation time information
|
|
2884
|
+
# mdft - Modification time information
|
|
2885
|
+
# udes - User description
|
|
2886
|
+
# altt - Accessibility text
|
|
2887
|
+
# aebr - Auto exposure information
|
|
2888
|
+
# wbbr - White balance information
|
|
2889
|
+
# fobr - Focus information
|
|
2890
|
+
# afbr - Flash exposure information
|
|
2891
|
+
# dobr - Depth of field information
|
|
2892
|
+
# pano - Panorama information
|
|
2893
|
+
# iscl - Image Scaling
|
|
2867
2894
|
);
|
|
2868
2895
|
|
|
2869
2896
|
# ref https://aomediacodec.github.io/av1-spec/av1-spec.pdf
|
|
@@ -2884,7 +2911,7 @@ my %eeBox2 = (
|
|
|
2884
2911
|
7 => 'SMPTE 240',
|
|
2885
2912
|
8 => 'Generic film (color filters using illuminant C)',
|
|
2886
2913
|
9 => 'BT.2020, BT.2100',
|
|
2887
|
-
10 => 'SMPTE 428 (CIE
|
|
2914
|
+
10 => 'SMPTE 428 (CIE 1931 XYZ)', #forum14766
|
|
2888
2915
|
11 => 'SMPTE RP 431-2',
|
|
2889
2916
|
12 => 'SMPTE EG 432-1',
|
|
2890
2917
|
22 => 'EBU Tech. 3213-E',
|
|
@@ -2898,8 +2925,8 @@ my %eeBox2 = (
|
|
|
2898
2925
|
1 => 'BT.709',
|
|
2899
2926
|
2 => 'Unspecified',
|
|
2900
2927
|
3 => 'For future use (3)',
|
|
2901
|
-
4 => 'BT.470 System M (historical)',
|
|
2902
|
-
5 => 'BT.470 System B, G (historical)',
|
|
2928
|
+
4 => 'BT.470 System M (historical)', # Gamma 2.2? (ref forum14960)
|
|
2929
|
+
5 => 'BT.470 System B, G (historical)', # Gamma 2.8? (ref forum14960)
|
|
2903
2930
|
6 => 'BT.601',
|
|
2904
2931
|
7 => 'SMPTE 240 M',
|
|
2905
2932
|
8 => 'Linear',
|
|
@@ -3125,6 +3152,16 @@ my %eeBox2 = (
|
|
|
3125
3152
|
},
|
|
3126
3153
|
);
|
|
3127
3154
|
|
|
3155
|
+
# ref https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/MPEG4Writer.cpp
|
|
3156
|
+
%Image::ExifTool::QuickTime::ContentLightLevel = (
|
|
3157
|
+
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
|
3158
|
+
GROUPS => { 2 => 'Video' },
|
|
3159
|
+
FIRST_ENTRY => 0,
|
|
3160
|
+
FORMAT => 'int16u',
|
|
3161
|
+
0 => 'MaxContentLightLevel',
|
|
3162
|
+
1 => 'MaxPicAverageLightLevel',
|
|
3163
|
+
);
|
|
3164
|
+
|
|
3128
3165
|
%Image::ExifTool::QuickTime::ItemRef = (
|
|
3129
3166
|
PROCESS_PROC => \&ProcessMOV,
|
|
3130
3167
|
WRITE_PROC => \&WriteQuickTime,
|
|
@@ -3360,8 +3397,9 @@ my %eeBox2 = (
|
|
|
3360
3397
|
},
|
|
3361
3398
|
albm => { Name => 'Album', Avoid => 1 }, #(ffmpeg source)
|
|
3362
3399
|
apID => 'AppleStoreAccount',
|
|
3363
|
-
atID => {
|
|
3364
|
-
|
|
3400
|
+
atID => {
|
|
3401
|
+
# (ref 10 called this AlbumTitleID or TVSeries)
|
|
3402
|
+
Name => 'ArtistID', #28 (or Track ID ref https://gist.github.com/maf654321/2b44c7b15d798f0c52ee)
|
|
3365
3403
|
Format => 'int32u',
|
|
3366
3404
|
Writable => 'int32s', #27
|
|
3367
3405
|
},
|
|
@@ -3372,6 +3410,7 @@ my %eeBox2 = (
|
|
|
3372
3410
|
Format => 'int32u',
|
|
3373
3411
|
Writable => 'int32s', #27
|
|
3374
3412
|
},
|
|
3413
|
+
cmID => 'ComposerID', #28 (need sample to get format)
|
|
3375
3414
|
cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } },
|
|
3376
3415
|
dscp => { Name => 'Description', Avoid => 1 },
|
|
3377
3416
|
desc => { Name => 'Description', Avoid => 1 }, #7
|
|
@@ -6064,10 +6103,10 @@ my %eeBox2 = (
|
|
|
6064
6103
|
PrintConv => { 0 => 'No', 1 => 'Yes' },
|
|
6065
6104
|
},
|
|
6066
6105
|
perf => 'Performer',
|
|
6067
|
-
plID => {
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6106
|
+
plID => {
|
|
6107
|
+
# (ref 10 called this PlayListID or TVSeason)
|
|
6108
|
+
Name => 'AlbumID', #28
|
|
6109
|
+
Format => 'int64u',
|
|
6071
6110
|
Writable => 'int32s', #27
|
|
6072
6111
|
},
|
|
6073
6112
|
purd => 'PurchaseDate', #7
|
|
@@ -6529,6 +6568,7 @@ my %eeBox2 = (
|
|
|
6529
6568
|
'rating.user' => 'UserRating', # (Canon ELPH 510 HS)
|
|
6530
6569
|
'collection.user' => 'UserCollection', #22
|
|
6531
6570
|
'Encoded_With' => 'EncodedWith',
|
|
6571
|
+
'content.identifier' => 'ContentIdentifier', #forum14874
|
|
6532
6572
|
#
|
|
6533
6573
|
# the following tags aren't in the com.apple.quicktime namespace:
|
|
6534
6574
|
#
|
|
@@ -7184,7 +7224,7 @@ my %eeBox2 = (
|
|
|
7184
7224
|
#
|
|
7185
7225
|
# AudioFormat Offset Child atoms
|
|
7186
7226
|
# ----------- ------ ----------------
|
|
7187
|
-
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max)
|
|
7227
|
+
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max and Garmin VIRB 360)
|
|
7188
7228
|
# in24 52 wave, chan
|
|
7189
7229
|
# "ms\0\x11" 52 wave
|
|
7190
7230
|
# sowt 52 chan
|
|
@@ -7217,11 +7257,14 @@ my %eeBox2 = (
|
|
|
7217
7257
|
chan => {
|
|
7218
7258
|
Name => 'AudioChannelLayout',
|
|
7219
7259
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ChannelLayout' },
|
|
7220
|
-
}
|
|
7260
|
+
},
|
|
7261
|
+
SA3D => { # written by Garmin VIRB360
|
|
7262
|
+
Name => 'SpatialAudio',
|
|
7263
|
+
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SpatialAudio' },
|
|
7264
|
+
},
|
|
7221
7265
|
# alac - 28 bytes
|
|
7222
7266
|
# adrm - AAX DRM atom? 148 bytes
|
|
7223
7267
|
# aabd - AAX unknown 17kB (contains 'aavd' strings)
|
|
7224
|
-
# SA3D - written by Garmin VIRB360
|
|
7225
7268
|
);
|
|
7226
7269
|
|
|
7227
7270
|
# AMR decode config box (ref 3)
|
|
@@ -7569,6 +7612,20 @@ my %eeBox2 = (
|
|
|
7569
7612
|
# (arbitrarily decode only first 8 channels)
|
|
7570
7613
|
);
|
|
7571
7614
|
|
|
7615
|
+
# spatial audio (ref https://github.com/google/spatial-media/blob/master/docs/spatial-audio-rfc.md)
|
|
7616
|
+
%Image::ExifTool::QuickTime::SpatialAudio = (
|
|
7617
|
+
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
|
7618
|
+
GROUPS => { 2 => 'Audio' },
|
|
7619
|
+
NOTES => 'Spatial Audio tags.',
|
|
7620
|
+
0 => 'SpatialAudioVersion',
|
|
7621
|
+
1 => { Name => 'AmbisonicType', PrintConv => { 0 => 'Periphonic' } },
|
|
7622
|
+
2 => { Name => 'AmbisonicOrder', Format => 'int32u' },
|
|
7623
|
+
6 => { Name => 'AmbisonicChannelOrdering', PrintConv => { 0 => 'ACN' } },
|
|
7624
|
+
7 => { Name => 'AmbisonicNormalization', PrintConv => { 0 => 'SN3D' } },
|
|
7625
|
+
8 => { Name => 'AmbisonicChannels', Format => 'int32u' },
|
|
7626
|
+
12 => { Name => 'AmbisonicChannelMap', Format => 'int32u[$val{8}]' },
|
|
7627
|
+
);
|
|
7628
|
+
|
|
7572
7629
|
# scheme type atom
|
|
7573
7630
|
# ref http://xhelmboyx.tripod.com/formats/mp4-layout.txt
|
|
7574
7631
|
%Image::ExifTool::QuickTime::SchemeType = (
|
|
@@ -8784,15 +8841,15 @@ sub HandleItemInfo($)
|
|
|
8784
8841
|
$et->VPrint(0, "$$et{INDENT} [snip $snip bytes]\n") if $snip;
|
|
8785
8842
|
}
|
|
8786
8843
|
}
|
|
8787
|
-
# do
|
|
8788
|
-
if ($type
|
|
8789
|
-
my $
|
|
8844
|
+
# do hash of AVIF "av01" and HEIC image data
|
|
8845
|
+
if ($isImageData{$type} and $$et{ImageDataHash}) {
|
|
8846
|
+
my $hash = $$et{ImageDataHash};
|
|
8790
8847
|
my $tot = 0;
|
|
8791
8848
|
foreach $extent (@{$$item{Extents}}) {
|
|
8792
|
-
$raf->Seek($$extent[1] + $base, 0) or $et->Warn(
|
|
8793
|
-
$tot += $et->
|
|
8849
|
+
$raf->Seek($$extent[1] + $base, 0) or $et->Warn("Seek error in $type image data"), last;
|
|
8850
|
+
$tot += $et->ImageDataHash($raf, $$extent[2], "$type image", 1);
|
|
8794
8851
|
}
|
|
8795
|
-
$et->VPrint(0, "$$et{INDENT}(
|
|
8852
|
+
$et->VPrint(0, "$$et{INDENT}(ImageDataHash: $tot bytes of $type data)\n") if $tot;
|
|
8796
8853
|
}
|
|
8797
8854
|
next unless $name;
|
|
8798
8855
|
# assemble the data for this item
|
|
@@ -9282,6 +9339,9 @@ sub ProcessMOV($$;$)
|
|
|
9282
9339
|
}
|
|
9283
9340
|
}
|
|
9284
9341
|
$fileType or $fileType = 'MP4'; # default to MP4
|
|
9342
|
+
# set file type from extension if appropriate
|
|
9343
|
+
my $ext = $$et{FILE_EXT};
|
|
9344
|
+
$fileType = $ext if $ext and $useExt{$ext} and $fileType eq $useExt{$ext};
|
|
9285
9345
|
$et->SetFileType($fileType, $mimeLookup{$fileType} || 'video/mp4');
|
|
9286
9346
|
# temporarily set ExtractEmbedded option for CRX files
|
|
9287
9347
|
$saveOptions{ExtractEmbedded} = $et->Options(ExtractEmbedded => 1) if $fileType eq 'CRX';
|
|
@@ -9296,8 +9356,8 @@ sub ProcessMOV($$;$)
|
|
|
9296
9356
|
$$raf{NoBuffer} = 1 if $fast; # disable buffering in FastScan mode
|
|
9297
9357
|
|
|
9298
9358
|
my $ee = $$et{OPTIONS}{ExtractEmbedded};
|
|
9299
|
-
my $
|
|
9300
|
-
if ($ee or $
|
|
9359
|
+
my $hash = $$et{ImageDataHash};
|
|
9360
|
+
if ($ee or $hash) {
|
|
9301
9361
|
$unkOpt = $$et{OPTIONS}{Unknown};
|
|
9302
9362
|
require 'Image/ExifTool/QuickTimeStream.pl';
|
|
9303
9363
|
}
|
|
@@ -9379,7 +9439,7 @@ sub ProcessMOV($$;$)
|
|
|
9379
9439
|
# set flag to store additional information for ExtractEmbedded option
|
|
9380
9440
|
my $handlerType = $$et{HandlerType};
|
|
9381
9441
|
if ($eeBox{$handlerType} and $eeBox{$handlerType}{$tag}) {
|
|
9382
|
-
if ($ee or $
|
|
9442
|
+
if ($ee or $hash) {
|
|
9383
9443
|
# (there is another 'gps ' box with a track log that doesn't contain offsets)
|
|
9384
9444
|
if ($tag ne 'gps ' or $eeBox{$handlerType}{$tag} eq $dirID) {
|
|
9385
9445
|
$eeTag = 1;
|
|
@@ -9391,7 +9451,7 @@ sub ProcessMOV($$;$)
|
|
|
9391
9451
|
} elsif ($ee and $ee > 1 and $eeBox2{$handlerType} and $eeBox2{$handlerType}{$tag}) {
|
|
9392
9452
|
$eeTag = 1;
|
|
9393
9453
|
$$et{OPTIONS}{Unknown} = 1;
|
|
9394
|
-
} elsif ($
|
|
9454
|
+
} elsif ($hash and $hashBox{$handlerType} and $hashBox{$handlerType}{$tag}) {
|
|
9395
9455
|
$eeTag = 1;
|
|
9396
9456
|
$$et{OPTIONS}{Unknown} = 1;
|
|
9397
9457
|
}
|
|
@@ -9463,13 +9523,17 @@ sub ProcessMOV($$;$)
|
|
|
9463
9523
|
my $items = $$et{ItemInfo};
|
|
9464
9524
|
my ($id, $prop, $docNum, $lowest);
|
|
9465
9525
|
my $primary = $$et{PrimaryItem} || 0;
|
|
9466
|
-
ItemID: foreach $id (keys %$items) {
|
|
9526
|
+
ItemID: foreach $id (reverse sort { $a <=> $b } keys %$items) {
|
|
9467
9527
|
next unless $$items{$id}{Association};
|
|
9468
9528
|
my $item = $$items{$id};
|
|
9469
9529
|
foreach $prop (@{$$item{Association}}) {
|
|
9470
9530
|
next unless $prop == $index;
|
|
9471
9531
|
if ($id == $primary or (not $dontInherit{$tag} and
|
|
9472
|
-
(
|
|
9532
|
+
(($$item{RefersTo} and $$item{RefersTo}{$primary}) or
|
|
9533
|
+
# hack: assume Item 1 is from the main image (eg. hvc1 data)
|
|
9534
|
+
# to hack the case where the primary item (ie. main image)
|
|
9535
|
+
# doesn't directly reference this property
|
|
9536
|
+
(not $$item{RefersTo} and $id == 1))))
|
|
9473
9537
|
{
|
|
9474
9538
|
# this is associated with the primary item or an item describing
|
|
9475
9539
|
# the primary item, so consider this part of the main document
|
|
@@ -9480,7 +9544,7 @@ ItemID: foreach $id (keys %$items) {
|
|
|
9480
9544
|
# this property is already associated with an item that has
|
|
9481
9545
|
# an ExifTool document number, so use the lowest associated DocNum
|
|
9482
9546
|
$docNum = $$item{DocNum} if not defined $docNum or $docNum > $$item{DocNum};
|
|
9483
|
-
}
|
|
9547
|
+
} else {
|
|
9484
9548
|
# keep track of the lowest associated item ID
|
|
9485
9549
|
$lowest = $id;
|
|
9486
9550
|
}
|
|
@@ -9626,7 +9690,7 @@ ItemID: foreach $id (keys %$items) {
|
|
|
9626
9690
|
}
|
|
9627
9691
|
if ($tag eq 'stbl') {
|
|
9628
9692
|
# process sample data when exiting SampleTable box if extracting embedded
|
|
9629
|
-
ProcessSamples($et) if $ee or $
|
|
9693
|
+
ProcessSamples($et) if $ee or $hash;
|
|
9630
9694
|
} elsif ($tag eq 'minf') {
|
|
9631
9695
|
$$et{HandlerType} = ''; # reset handler type at end of media info box
|
|
9632
9696
|
}
|