line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
2
|
|
|
|
|
|
|
# File: QuickTime.pm |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Description: Read QuickTime and MP4 meta information |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Revisions: 10/04/2005 - P. Harvey Created |
7
|
|
|
|
|
|
|
# 12/19/2005 - P. Harvey Added MP4 support |
8
|
|
|
|
|
|
|
# 09/22/2006 - P. Harvey Added M4A support |
9
|
|
|
|
|
|
|
# 07/27/2010 - P. Harvey Updated to 2010-05-03 QuickTime spec |
10
|
|
|
|
|
|
|
# |
11
|
|
|
|
|
|
|
# References: |
12
|
|
|
|
|
|
|
# |
13
|
|
|
|
|
|
|
# 1) http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html |
14
|
|
|
|
|
|
|
# 2) http://search.cpan.org/dist/MP4-Info-1.04/ |
15
|
|
|
|
|
|
|
# 3) http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt |
16
|
|
|
|
|
|
|
# 4) http://wiki.multimedia.cx/index.php?title=Apple_QuickTime |
17
|
|
|
|
|
|
|
# 5) ISO 14496-12 (http://read.pudn.com/downloads64/ebook/226547/ISO_base_media_file_format.pdf) |
18
|
|
|
|
|
|
|
# 6) ISO 14496-16 (http://www.iec-normen.de/previewpdf/info_isoiec14496-16%7Bed2.0%7Den.pdf) |
19
|
|
|
|
|
|
|
# 7) http://atomicparsley.sourceforge.net/mpeg-4files.html |
20
|
|
|
|
|
|
|
# 8) http://wiki.multimedia.cx/index.php?title=QuickTime_container |
21
|
|
|
|
|
|
|
# 9) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf (Oct 2008) |
22
|
|
|
|
|
|
|
# 10) http://code.google.com/p/mp4v2/wiki/iTunesMetadata |
23
|
|
|
|
|
|
|
# 11) http://www.canieti.com.mx/assets/files/1011/IEC_100_1384_DC.pdf |
24
|
|
|
|
|
|
|
# 12) QuickTime file format specification 2010-05-03 |
25
|
|
|
|
|
|
|
# 13) http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf |
26
|
|
|
|
|
|
|
# 14) http://standards.iso.org/ittf/PubliclyAvailableStandards/c051533_ISO_IEC_14496-12_2008.zip |
27
|
|
|
|
|
|
|
# 15) http://getid3.sourceforge.net/source/module.audio-video.quicktime.phps |
28
|
|
|
|
|
|
|
# 16) http://qtra.apple.com/atoms.html |
29
|
|
|
|
|
|
|
# 17) http://www.etsi.org/deliver/etsi_ts/126200_126299/126244/10.01.00_60/ts_126244v100100p.pdf |
30
|
|
|
|
|
|
|
# 18) https://github.com/appsec-labs/iNalyzer/blob/master/scinfo.m |
31
|
|
|
|
|
|
|
# 19) http://nah6.com/~itsme/cvs-xdadevtools/iphone/tools/decodesinf.pl |
32
|
|
|
|
|
|
|
# 20) https://developer.apple.com/legacy/library/documentation/quicktime/reference/QT7-1_Update_Reference/QT7-1_Update_Reference.pdf |
33
|
|
|
|
|
|
|
# 21) Francois Bonzon private communication |
34
|
|
|
|
|
|
|
# 22) https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html |
35
|
|
|
|
|
|
|
# 23) http://atomicparsley.sourceforge.net/mpeg-4files.html |
36
|
|
|
|
|
|
|
# 24) https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata |
37
|
|
|
|
|
|
|
# 25) https://cconcolato.github.io/mp4ra/atoms.html |
38
|
|
|
|
|
|
|
# 26) https://github.com/SamsungVR/android_upload_sdk/blob/master/SDKLib/src/main/java/com/samsung/msca/samsungvr/sdk/UserVideo.java |
39
|
|
|
|
|
|
|
# 27) https://exiftool.org/forum/index.php?topic=11517.0 |
40
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
package Image::ExifTool::QuickTime; |
43
|
|
|
|
|
|
|
|
44
|
29
|
|
|
29
|
|
4945
|
use strict; |
|
29
|
|
|
|
|
60
|
|
|
29
|
|
|
|
|
969
|
|
45
|
29
|
|
|
29
|
|
140
|
use vars qw($VERSION $AUTOLOAD %stringEncoding); |
|
29
|
|
|
|
|
56
|
|
|
29
|
|
|
|
|
1575
|
|
46
|
29
|
|
|
29
|
|
163
|
use Image::ExifTool qw(:DataAccess :Utils); |
|
29
|
|
|
|
|
59
|
|
|
29
|
|
|
|
|
5289
|
|
47
|
29
|
|
|
29
|
|
2258
|
use Image::ExifTool::Exif; |
|
29
|
|
|
|
|
104
|
|
|
29
|
|
|
|
|
772
|
|
48
|
29
|
|
|
29
|
|
1344
|
use Image::ExifTool::GPS; |
|
29
|
|
|
|
|
57
|
|
|
29
|
|
|
|
|
343856
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
$VERSION = '2.74'; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub ProcessMOV($$;$); |
53
|
|
|
|
|
|
|
sub ProcessKeys($$$); |
54
|
|
|
|
|
|
|
sub ProcessMetaKeys($$$); |
55
|
|
|
|
|
|
|
sub ProcessMetaData($$$); |
56
|
|
|
|
|
|
|
sub ProcessEncodingParams($$$); |
57
|
|
|
|
|
|
|
sub ProcessSampleDesc($$$); |
58
|
|
|
|
|
|
|
sub ProcessHybrid($$$); |
59
|
|
|
|
|
|
|
sub ProcessRights($$$); |
60
|
|
|
|
|
|
|
# ++vvvvvvvvvvvv++ (in QuickTimeStream.pl) |
61
|
|
|
|
|
|
|
sub Process_mebx($$$); |
62
|
|
|
|
|
|
|
sub Process_3gf($$$); |
63
|
|
|
|
|
|
|
sub Process_gps0($$$); |
64
|
|
|
|
|
|
|
sub Process_gsen($$$); |
65
|
|
|
|
|
|
|
sub ProcessRIFFTrailer($$$); |
66
|
|
|
|
|
|
|
sub ProcessTTAD($$$); |
67
|
|
|
|
|
|
|
sub ProcessNMEA($$$); |
68
|
|
|
|
|
|
|
sub ProcessGPSLog($$$); |
69
|
|
|
|
|
|
|
sub SaveMetaKeys($$$); |
70
|
|
|
|
|
|
|
# ++^^^^^^^^^^^^++ |
71
|
|
|
|
|
|
|
sub ParseItemLocation($$); |
72
|
|
|
|
|
|
|
sub ParseContentDescribes($$); |
73
|
|
|
|
|
|
|
sub ParseItemInfoEntry($$); |
74
|
|
|
|
|
|
|
sub ParseItemPropAssoc($$); |
75
|
|
|
|
|
|
|
sub FixWrongFormat($); |
76
|
|
|
|
|
|
|
sub GetMatrixStructure($$); |
77
|
|
|
|
|
|
|
sub ConvertISO6709($); |
78
|
|
|
|
|
|
|
sub ConvInvISO6709($); |
79
|
|
|
|
|
|
|
sub ConvertChapterList($); |
80
|
|
|
|
|
|
|
sub PrintChapter($); |
81
|
|
|
|
|
|
|
sub PrintGPSCoordinates($); |
82
|
|
|
|
|
|
|
sub PrintInvGPSCoordinates($); |
83
|
|
|
|
|
|
|
sub UnpackLang($;$); |
84
|
|
|
|
|
|
|
sub WriteKeys($$$); |
85
|
|
|
|
|
|
|
sub WriteQuickTime($$$); |
86
|
|
|
|
|
|
|
sub WriteMOV($$); |
87
|
|
|
|
|
|
|
sub GetLangInfo($$); |
88
|
|
|
|
|
|
|
sub CheckQTValue($$$); |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# MIME types for all entries in the ftypLookup with file extensions |
91
|
|
|
|
|
|
|
# (defaults to 'video/mp4' if not found in this lookup) |
92
|
|
|
|
|
|
|
my %mimeLookup = ( |
93
|
|
|
|
|
|
|
'3G2' => 'video/3gpp2', |
94
|
|
|
|
|
|
|
'3GP' => 'video/3gpp', |
95
|
|
|
|
|
|
|
AAX => 'audio/vnd.audible.aax', |
96
|
|
|
|
|
|
|
DVB => 'video/vnd.dvb.file', |
97
|
|
|
|
|
|
|
F4A => 'audio/mp4', |
98
|
|
|
|
|
|
|
F4B => 'audio/mp4', |
99
|
|
|
|
|
|
|
JP2 => 'image/jp2', |
100
|
|
|
|
|
|
|
JPM => 'image/jpm', |
101
|
|
|
|
|
|
|
JPX => 'image/jpx', |
102
|
|
|
|
|
|
|
M4A => 'audio/mp4', |
103
|
|
|
|
|
|
|
M4B => 'audio/mp4', |
104
|
|
|
|
|
|
|
M4P => 'audio/mp4', |
105
|
|
|
|
|
|
|
M4V => 'video/x-m4v', |
106
|
|
|
|
|
|
|
MOV => 'video/quicktime', |
107
|
|
|
|
|
|
|
MQV => 'video/quicktime', |
108
|
|
|
|
|
|
|
HEIC => 'image/heic', |
109
|
|
|
|
|
|
|
HEVC => 'image/heic-sequence', |
110
|
|
|
|
|
|
|
HEICS=> 'image/heic-sequence', |
111
|
|
|
|
|
|
|
HEIF => 'image/heif', |
112
|
|
|
|
|
|
|
HEIFS=> 'image/heif-sequence', |
113
|
|
|
|
|
|
|
AVIF => 'image/avif', #PH (NC) |
114
|
|
|
|
|
|
|
CRX => 'video/x-canon-crx', # (will get overridden) |
115
|
|
|
|
|
|
|
); |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# look up file type from ftyp atom type, with MIME type in comment if known |
118
|
|
|
|
|
|
|
# (ref http://www.ftyps.com/) |
119
|
|
|
|
|
|
|
my %ftypLookup = ( |
120
|
|
|
|
|
|
|
'3g2a' => '3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-0 V1.0', # video/3gpp2 |
121
|
|
|
|
|
|
|
'3g2b' => '3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-A V1.0.0', # video/3gpp2 |
122
|
|
|
|
|
|
|
'3g2c' => '3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-B v1.0', # video/3gpp2 |
123
|
|
|
|
|
|
|
'3ge6' => '3GPP (.3GP) Release 6 MBMS Extended Presentations', # video/3gpp |
124
|
|
|
|
|
|
|
'3ge7' => '3GPP (.3GP) Release 7 MBMS Extended Presentations', # video/3gpp |
125
|
|
|
|
|
|
|
'3gg6' => '3GPP Release 6 General Profile', # video/3gpp |
126
|
|
|
|
|
|
|
'3gp1' => '3GPP Media (.3GP) Release 1 (probably non-existent)', # video/3gpp |
127
|
|
|
|
|
|
|
'3gp2' => '3GPP Media (.3GP) Release 2 (probably non-existent)', # video/3gpp |
128
|
|
|
|
|
|
|
'3gp3' => '3GPP Media (.3GP) Release 3 (probably non-existent)', # video/3gpp |
129
|
|
|
|
|
|
|
'3gp4' => '3GPP Media (.3GP) Release 4', # video/3gpp |
130
|
|
|
|
|
|
|
'3gp5' => '3GPP Media (.3GP) Release 5', # video/3gpp |
131
|
|
|
|
|
|
|
'3gp6' => '3GPP Media (.3GP) Release 6 Basic Profile', # video/3gpp |
132
|
|
|
|
|
|
|
'3gp6' => '3GPP Media (.3GP) Release 6 Progressive Download', # video/3gpp |
133
|
|
|
|
|
|
|
'3gp6' => '3GPP Media (.3GP) Release 6 Streaming Servers', # video/3gpp |
134
|
|
|
|
|
|
|
'3gs7' => '3GPP Media (.3GP) Release 7 Streaming Servers', # video/3gpp |
135
|
|
|
|
|
|
|
'aax ' => 'Audible Enhanced Audiobook (.AAX)', #PH |
136
|
|
|
|
|
|
|
'avc1' => 'MP4 Base w/ AVC ext [ISO 14496-12:2005]', # video/mp4 |
137
|
|
|
|
|
|
|
'CAEP' => 'Canon Digital Camera', |
138
|
|
|
|
|
|
|
'caqv' => 'Casio Digital Camera', |
139
|
|
|
|
|
|
|
'CDes' => 'Convergent Design', |
140
|
|
|
|
|
|
|
'da0a' => 'DMB MAF w/ MPEG Layer II aud, MOT slides, DLS, JPG/PNG/MNG images', |
141
|
|
|
|
|
|
|
'da0b' => 'DMB MAF, extending DA0A, with 3GPP timed text, DID, TVA, REL, IPMP', |
142
|
|
|
|
|
|
|
'da1a' => 'DMB MAF audio with ER-BSAC audio, JPG/PNG/MNG images', |
143
|
|
|
|
|
|
|
'da1b' => 'DMB MAF, extending da1a, with 3GPP timed text, DID, TVA, REL, IPMP', |
144
|
|
|
|
|
|
|
'da2a' => 'DMB MAF aud w/ HE-AAC v2 aud, MOT slides, DLS, JPG/PNG/MNG images', |
145
|
|
|
|
|
|
|
'da2b' => 'DMB MAF, extending da2a, with 3GPP timed text, DID, TVA, REL, IPMP', |
146
|
|
|
|
|
|
|
'da3a' => 'DMB MAF aud with HE-AAC aud, JPG/PNG/MNG images', |
147
|
|
|
|
|
|
|
'da3b' => 'DMB MAF, extending da3a w/ BIFS, 3GPP timed text, DID, TVA, REL, IPMP', |
148
|
|
|
|
|
|
|
'dmb1' => 'DMB MAF supporting all the components defined in the specification', |
149
|
|
|
|
|
|
|
'dmpf' => 'Digital Media Project', # various |
150
|
|
|
|
|
|
|
'drc1' => 'Dirac (wavelet compression), encapsulated in ISO base media (MP4)', |
151
|
|
|
|
|
|
|
'dv1a' => 'DMB MAF vid w/ AVC vid, ER-BSAC aud, BIFS, JPG/PNG/MNG images, TS', |
152
|
|
|
|
|
|
|
'dv1b' => 'DMB MAF, extending dv1a, with 3GPP timed text, DID, TVA, REL, IPMP', |
153
|
|
|
|
|
|
|
'dv2a' => 'DMB MAF vid w/ AVC vid, HE-AAC v2 aud, BIFS, JPG/PNG/MNG images, TS', |
154
|
|
|
|
|
|
|
'dv2b' => 'DMB MAF, extending dv2a, with 3GPP timed text, DID, TVA, REL, IPMP', |
155
|
|
|
|
|
|
|
'dv3a' => 'DMB MAF vid w/ AVC vid, HE-AAC aud, BIFS, JPG/PNG/MNG images, TS', |
156
|
|
|
|
|
|
|
'dv3b' => 'DMB MAF, extending dv3a, with 3GPP timed text, DID, TVA, REL, IPMP', |
157
|
|
|
|
|
|
|
'dvr1' => 'DVB (.DVB) over RTP', # video/vnd.dvb.file |
158
|
|
|
|
|
|
|
'dvt1' => 'DVB (.DVB) over MPEG-2 Transport Stream', # video/vnd.dvb.file |
159
|
|
|
|
|
|
|
'F4A ' => 'Audio for Adobe Flash Player 9+ (.F4A)', # audio/mp4 |
160
|
|
|
|
|
|
|
'F4B ' => 'Audio Book for Adobe Flash Player 9+ (.F4B)', # audio/mp4 |
161
|
|
|
|
|
|
|
'F4P ' => 'Protected Video for Adobe Flash Player 9+ (.F4P)', # video/mp4 |
162
|
|
|
|
|
|
|
'F4V ' => 'Video for Adobe Flash Player 9+ (.F4V)', # video/mp4 |
163
|
|
|
|
|
|
|
'isc2' => 'ISMACryp 2.0 Encrypted File', # ?/enc-isoff-generic |
164
|
|
|
|
|
|
|
'iso2' => 'MP4 Base Media v2 [ISO 14496-12:2005]', # video/mp4 (or audio) |
165
|
|
|
|
|
|
|
'iso3' => 'MP4 Base Media v3', # video/mp4 (or audio) |
166
|
|
|
|
|
|
|
'iso4' => 'MP4 Base Media v4', # video/mp4 (or audio) |
167
|
|
|
|
|
|
|
'iso5' => 'MP4 Base Media v5', # video/mp4 (or audio) |
168
|
|
|
|
|
|
|
'iso6' => 'MP4 Base Media v6', # video/mp4 (or audio) |
169
|
|
|
|
|
|
|
'iso7' => 'MP4 Base Media v7', # video/mp4 (or audio) |
170
|
|
|
|
|
|
|
'iso8' => 'MP4 Base Media v8', # video/mp4 (or audio) |
171
|
|
|
|
|
|
|
'iso9' => 'MP4 Base Media v9', # video/mp4 (or audio) |
172
|
|
|
|
|
|
|
'isom' => 'MP4 Base Media v1 [IS0 14496-12:2003]', # video/mp4 (or audio) |
173
|
|
|
|
|
|
|
'JP2 ' => 'JPEG 2000 Image (.JP2) [ISO 15444-1 ?]', # image/jp2 |
174
|
|
|
|
|
|
|
'JP20' => 'Unknown, from GPAC samples (prob non-existent)', |
175
|
|
|
|
|
|
|
'jpm ' => 'JPEG 2000 Compound Image (.JPM) [ISO 15444-6]', # image/jpm |
176
|
|
|
|
|
|
|
'jpx ' => 'JPEG 2000 with extensions (.JPX) [ISO 15444-2]', # image/jpx |
177
|
|
|
|
|
|
|
'KDDI' => '3GPP2 EZmovie for KDDI 3G cellphones', # video/3gpp2 |
178
|
|
|
|
|
|
|
#LCAG => (found in CompatibleBrands of Leica MOV videos) |
179
|
|
|
|
|
|
|
'M4A ' => 'Apple iTunes AAC-LC (.M4A) Audio', # audio/x-m4a |
180
|
|
|
|
|
|
|
'M4B ' => 'Apple iTunes AAC-LC (.M4B) Audio Book', # audio/mp4 |
181
|
|
|
|
|
|
|
'M4P ' => 'Apple iTunes AAC-LC (.M4P) AES Protected Audio', # audio/mp4 |
182
|
|
|
|
|
|
|
'M4V ' => 'Apple iTunes Video (.M4V) Video', # video/x-m4v |
183
|
|
|
|
|
|
|
'M4VH' => 'Apple TV (.M4V)', # video/x-m4v |
184
|
|
|
|
|
|
|
'M4VP' => 'Apple iPhone (.M4V)', # video/x-m4v |
185
|
|
|
|
|
|
|
'mj2s' => 'Motion JPEG 2000 [ISO 15444-3] Simple Profile', # video/mj2 |
186
|
|
|
|
|
|
|
'mjp2' => 'Motion JPEG 2000 [ISO 15444-3] General Profile', # video/mj2 |
187
|
|
|
|
|
|
|
'mmp4' => 'MPEG-4/3GPP Mobile Profile (.MP4/3GP) (for NTT)', # video/mp4 |
188
|
|
|
|
|
|
|
'mp21' => 'MPEG-21 [ISO/IEC 21000-9]', # various |
189
|
|
|
|
|
|
|
'mp41' => 'MP4 v1 [ISO 14496-1:ch13]', # video/mp4 |
190
|
|
|
|
|
|
|
'mp42' => 'MP4 v2 [ISO 14496-14]', # video/mp4 |
191
|
|
|
|
|
|
|
'mp71' => 'MP4 w/ MPEG-7 Metadata [per ISO 14496-12]', # various |
192
|
|
|
|
|
|
|
'MPPI' => 'Photo Player, MAF [ISO/IEC 23000-3]', # various |
193
|
|
|
|
|
|
|
'mqt ' => 'Sony / Mobile QuickTime (.MQV) US Patent 7,477,830 (Sony Corp)', # video/quicktime |
194
|
|
|
|
|
|
|
'MSNV' => 'MPEG-4 (.MP4) for SonyPSP', # audio/mp4 |
195
|
|
|
|
|
|
|
'NDAS' => 'MP4 v2 [ISO 14496-14] Nero Digital AAC Audio', # audio/mp4 |
196
|
|
|
|
|
|
|
'NDSC' => 'MPEG-4 (.MP4) Nero Cinema Profile', # video/mp4 |
197
|
|
|
|
|
|
|
'NDSH' => 'MPEG-4 (.MP4) Nero HDTV Profile', # video/mp4 |
198
|
|
|
|
|
|
|
'NDSM' => 'MPEG-4 (.MP4) Nero Mobile Profile', # video/mp4 |
199
|
|
|
|
|
|
|
'NDSP' => 'MPEG-4 (.MP4) Nero Portable Profile', # video/mp4 |
200
|
|
|
|
|
|
|
'NDSS' => 'MPEG-4 (.MP4) Nero Standard Profile', # video/mp4 |
201
|
|
|
|
|
|
|
'NDXC' => 'H.264/MPEG-4 AVC (.MP4) Nero Cinema Profile', # video/mp4 |
202
|
|
|
|
|
|
|
'NDXH' => 'H.264/MPEG-4 AVC (.MP4) Nero HDTV Profile', # video/mp4 |
203
|
|
|
|
|
|
|
'NDXM' => 'H.264/MPEG-4 AVC (.MP4) Nero Mobile Profile', # video/mp4 |
204
|
|
|
|
|
|
|
'NDXP' => 'H.264/MPEG-4 AVC (.MP4) Nero Portable Profile', # video/mp4 |
205
|
|
|
|
|
|
|
'NDXS' => 'H.264/MPEG-4 AVC (.MP4) Nero Standard Profile', # video/mp4 |
206
|
|
|
|
|
|
|
'odcf' => 'OMA DCF DRM Format 2.0 (OMA-TS-DRM-DCF-V2_0-20060303-A)', # various |
207
|
|
|
|
|
|
|
'opf2' => 'OMA PDCF DRM Format 2.1 (OMA-TS-DRM-DCF-V2_1-20070724-C)', |
208
|
|
|
|
|
|
|
'opx2' => 'OMA PDCF DRM + XBS extensions (OMA-TS-DRM_XBS-V1_0-20070529-C)', |
209
|
|
|
|
|
|
|
'pana' => 'Panasonic Digital Camera', |
210
|
|
|
|
|
|
|
'qt ' => 'Apple QuickTime (.MOV/QT)', # video/quicktime |
211
|
|
|
|
|
|
|
'ROSS' => 'Ross Video', |
212
|
|
|
|
|
|
|
'sdv ' => 'SD Memory Card Video', # various? |
213
|
|
|
|
|
|
|
'ssc1' => 'Samsung stereoscopic, single stream', |
214
|
|
|
|
|
|
|
'ssc2' => 'Samsung stereoscopic, dual stream', |
215
|
|
|
|
|
|
|
'XAVC' => 'Sony XAVC', #PH |
216
|
|
|
|
|
|
|
'heic' => 'High Efficiency Image Format HEVC still image (.HEIC)', # image/heic |
217
|
|
|
|
|
|
|
'hevc' => 'High Efficiency Image Format HEVC sequence (.HEICS)', # image/heic-sequence |
218
|
|
|
|
|
|
|
'mif1' => 'High Efficiency Image Format still image (.HEIF)', # image/heif |
219
|
|
|
|
|
|
|
'msf1' => 'High Efficiency Image Format sequence (.HEIFS)', # image/heif-sequence |
220
|
|
|
|
|
|
|
'heix' => 'High Efficiency Image Format still image (.HEIF)', # image/heif (ref PH, Canon 1DXmkIII) |
221
|
|
|
|
|
|
|
'avif' => 'AV1 Image File Format (.AVIF)', # image/avif |
222
|
|
|
|
|
|
|
'crx ' => 'Canon Raw (.CRX)', #PH (CR3 or CRM; use Canon CompressorVersion to decide) |
223
|
|
|
|
|
|
|
); |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# information for int32u date/time tags (time zero is Jan 1, 1904) |
226
|
|
|
|
|
|
|
my %timeInfo = ( |
227
|
|
|
|
|
|
|
Notes => 'converted from UTC to local time if the QuickTimeUTC option is set', |
228
|
|
|
|
|
|
|
Shift => 'Time', |
229
|
|
|
|
|
|
|
Writable => 1, |
230
|
|
|
|
|
|
|
Permanent => 1, |
231
|
|
|
|
|
|
|
DelValue => 0, |
232
|
|
|
|
|
|
|
# It is not uncommon for brain-dead software to use the wrong time zero, it should be |
233
|
|
|
|
|
|
|
# Jan 1, 1904, so assume a time zero of Jan 1, 1970 if the date is before this |
234
|
|
|
|
|
|
|
# Note: This value will be in UTC if generated by a system that is aware of the time zone |
235
|
|
|
|
|
|
|
# (also note: this code is duplicated for the CreateDate tag) |
236
|
|
|
|
|
|
|
RawConv => q{ |
237
|
|
|
|
|
|
|
my $offset = (66 * 365 + 17) * 24 * 3600; |
238
|
|
|
|
|
|
|
return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC}; |
239
|
|
|
|
|
|
|
if ($val and not $$self{IsWriting}) { |
240
|
|
|
|
|
|
|
$self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
return $val; |
243
|
|
|
|
|
|
|
}, |
244
|
|
|
|
|
|
|
RawConvInv => q{ |
245
|
|
|
|
|
|
|
if ($$self{FileType} eq 'CR3' and not $self->Options('QuickTimeUTC')) { |
246
|
|
|
|
|
|
|
# convert to UTC |
247
|
|
|
|
|
|
|
my $offset = (66 * 365 + 17) * 24 * 3600; |
248
|
|
|
|
|
|
|
$val = ConvertUnixTime($val - $offset); |
249
|
|
|
|
|
|
|
$val = GetUnixTime($val, 1) + $offset; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
return $val; |
252
|
|
|
|
|
|
|
}, |
253
|
|
|
|
|
|
|
# (all CR3 files store UTC times - PH) |
254
|
|
|
|
|
|
|
ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3")', |
255
|
|
|
|
|
|
|
ValueConvInv => q{ |
256
|
|
|
|
|
|
|
$val = GetUnixTime($val, $self->Options("QuickTimeUTC")); |
257
|
|
|
|
|
|
|
return undef unless defined $val; |
258
|
|
|
|
|
|
|
return $val + (66 * 365 + 17) * 24 * 3600; |
259
|
|
|
|
|
|
|
}, |
260
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
261
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val)', |
262
|
|
|
|
|
|
|
# (can't put Groups here because they aren't constant!) |
263
|
|
|
|
|
|
|
); |
264
|
|
|
|
|
|
|
# information for duration tags |
265
|
|
|
|
|
|
|
my %durationInfo = ( |
266
|
|
|
|
|
|
|
ValueConv => '$$self{TimeScale} ? $val / $$self{TimeScale} : $val', |
267
|
|
|
|
|
|
|
PrintConv => '$$self{TimeScale} ? ConvertDuration($val) : $val', |
268
|
|
|
|
|
|
|
); |
269
|
|
|
|
|
|
|
# handle unknown tags |
270
|
|
|
|
|
|
|
my %unknownInfo = ( |
271
|
|
|
|
|
|
|
Unknown => 1, |
272
|
|
|
|
|
|
|
ValueConv => '$val =~ /^([\x20-\x7e]*)\0*$/ ? $1 : \$val', |
273
|
|
|
|
|
|
|
); |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# multi-language text with 6-byte header |
276
|
|
|
|
|
|
|
my %langText = ( IText => 6 ); |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# parsing for most of the 3gp udta language text boxes |
279
|
|
|
|
|
|
|
my %langText3gp = ( |
280
|
|
|
|
|
|
|
Notes => 'used in 3gp videos', |
281
|
|
|
|
|
|
|
Avoid => 1, |
282
|
|
|
|
|
|
|
IText => 6, |
283
|
|
|
|
|
|
|
); |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# 4-character Vendor ID codes (ref PH) |
286
|
|
|
|
|
|
|
my %vendorID = ( |
287
|
|
|
|
|
|
|
appl => 'Apple', |
288
|
|
|
|
|
|
|
fe20 => 'Olympus (fe20)', # (FE200) |
289
|
|
|
|
|
|
|
FFMP => 'FFmpeg', |
290
|
|
|
|
|
|
|
'GIC '=> 'General Imaging Co.', |
291
|
|
|
|
|
|
|
kdak => 'Kodak', |
292
|
|
|
|
|
|
|
KMPI => 'Konica-Minolta', |
293
|
|
|
|
|
|
|
leic => 'Leica', |
294
|
|
|
|
|
|
|
mino => 'Minolta', |
295
|
|
|
|
|
|
|
niko => 'Nikon', |
296
|
|
|
|
|
|
|
NIKO => 'Nikon', |
297
|
|
|
|
|
|
|
olym => 'Olympus', |
298
|
|
|
|
|
|
|
pana => 'Panasonic', |
299
|
|
|
|
|
|
|
pent => 'Pentax', |
300
|
|
|
|
|
|
|
pr01 => 'Olympus (pr01)', # (FE100,FE110,FE115) |
301
|
|
|
|
|
|
|
sany => 'Sanyo', |
302
|
|
|
|
|
|
|
'SMI '=> 'Sorenson Media Inc.', |
303
|
|
|
|
|
|
|
ZORA => 'Zoran Corporation', |
304
|
|
|
|
|
|
|
'AR.D'=> 'Parrot AR.Drone', |
305
|
|
|
|
|
|
|
' KD '=> 'Kodak', # (FZ201) |
306
|
|
|
|
|
|
|
); |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# QuickTime data atom encodings for string types (ref 12) |
309
|
|
|
|
|
|
|
%stringEncoding = ( |
310
|
|
|
|
|
|
|
1 => 'UTF8', |
311
|
|
|
|
|
|
|
2 => 'UTF16', |
312
|
|
|
|
|
|
|
3 => 'ShiftJIS', |
313
|
|
|
|
|
|
|
4 => 'UTF8', |
314
|
|
|
|
|
|
|
5 => 'UTF16', |
315
|
|
|
|
|
|
|
); |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
my %graphicsMode = ( |
318
|
|
|
|
|
|
|
# (ref http://homepage.mac.com/vanhoek/MovieGuts%20docs/64.html) |
319
|
|
|
|
|
|
|
0x00 => 'srcCopy', |
320
|
|
|
|
|
|
|
0x01 => 'srcOr', |
321
|
|
|
|
|
|
|
0x02 => 'srcXor', |
322
|
|
|
|
|
|
|
0x03 => 'srcBic', |
323
|
|
|
|
|
|
|
0x04 => 'notSrcCopy', |
324
|
|
|
|
|
|
|
0x05 => 'notSrcOr', |
325
|
|
|
|
|
|
|
0x06 => 'notSrcXor', |
326
|
|
|
|
|
|
|
0x07 => 'notSrcBic', |
327
|
|
|
|
|
|
|
0x08 => 'patCopy', |
328
|
|
|
|
|
|
|
0x09 => 'patOr', |
329
|
|
|
|
|
|
|
0x0a => 'patXor', |
330
|
|
|
|
|
|
|
0x0b => 'patBic', |
331
|
|
|
|
|
|
|
0x0c => 'notPatCopy', |
332
|
|
|
|
|
|
|
0x0d => 'notPatOr', |
333
|
|
|
|
|
|
|
0x0e => 'notPatXor', |
334
|
|
|
|
|
|
|
0x0f => 'notPatBic', |
335
|
|
|
|
|
|
|
0x20 => 'blend', |
336
|
|
|
|
|
|
|
0x21 => 'addPin', |
337
|
|
|
|
|
|
|
0x22 => 'addOver', |
338
|
|
|
|
|
|
|
0x23 => 'subPin', |
339
|
|
|
|
|
|
|
0x24 => 'transparent', |
340
|
|
|
|
|
|
|
0x25 => 'addMax', |
341
|
|
|
|
|
|
|
0x26 => 'subOver', |
342
|
|
|
|
|
|
|
0x27 => 'addMin', |
343
|
|
|
|
|
|
|
0x31 => 'grayishTextOr', |
344
|
|
|
|
|
|
|
0x32 => 'hilite', |
345
|
|
|
|
|
|
|
0x40 => 'ditherCopy', |
346
|
|
|
|
|
|
|
# the following ref ISO/IEC 15444-3 |
347
|
|
|
|
|
|
|
0x100 => 'Alpha', |
348
|
|
|
|
|
|
|
0x101 => 'White Alpha', |
349
|
|
|
|
|
|
|
0x102 => 'Pre-multiplied Black Alpha', |
350
|
|
|
|
|
|
|
0x110 => 'Component Alpha', |
351
|
|
|
|
|
|
|
); |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
my %channelLabel = ( |
354
|
|
|
|
|
|
|
0xFFFFFFFF => 'Unknown', |
355
|
|
|
|
|
|
|
0 => 'Unused', |
356
|
|
|
|
|
|
|
100 => 'UseCoordinates', |
357
|
|
|
|
|
|
|
1 => 'Left', |
358
|
|
|
|
|
|
|
2 => 'Right', |
359
|
|
|
|
|
|
|
3 => 'Center', |
360
|
|
|
|
|
|
|
4 => 'LFEScreen', |
361
|
|
|
|
|
|
|
5 => 'LeftSurround', |
362
|
|
|
|
|
|
|
6 => 'RightSurround', |
363
|
|
|
|
|
|
|
7 => 'LeftCenter', |
364
|
|
|
|
|
|
|
8 => 'RightCenter', |
365
|
|
|
|
|
|
|
9 => 'CenterSurround', |
366
|
|
|
|
|
|
|
10 => 'LeftSurroundDirect', |
367
|
|
|
|
|
|
|
11 => 'RightSurroundDirect', |
368
|
|
|
|
|
|
|
12 => 'TopCenterSurround', |
369
|
|
|
|
|
|
|
13 => 'VerticalHeightLeft', |
370
|
|
|
|
|
|
|
14 => 'VerticalHeightCenter', |
371
|
|
|
|
|
|
|
15 => 'VerticalHeightRight', |
372
|
|
|
|
|
|
|
16 => 'TopBackLeft', |
373
|
|
|
|
|
|
|
17 => 'TopBackCenter', |
374
|
|
|
|
|
|
|
18 => 'TopBackRight', |
375
|
|
|
|
|
|
|
33 => 'RearSurroundLeft', |
376
|
|
|
|
|
|
|
34 => 'RearSurroundRight', |
377
|
|
|
|
|
|
|
35 => 'LeftWide', |
378
|
|
|
|
|
|
|
36 => 'RightWide', |
379
|
|
|
|
|
|
|
37 => 'LFE2', |
380
|
|
|
|
|
|
|
38 => 'LeftTotal', |
381
|
|
|
|
|
|
|
39 => 'RightTotal', |
382
|
|
|
|
|
|
|
40 => 'HearingImpaired', |
383
|
|
|
|
|
|
|
41 => 'Narration', |
384
|
|
|
|
|
|
|
42 => 'Mono', |
385
|
|
|
|
|
|
|
43 => 'DialogCentricMix', |
386
|
|
|
|
|
|
|
44 => 'CenterSurroundDirect', |
387
|
|
|
|
|
|
|
45 => 'Haptic', |
388
|
|
|
|
|
|
|
200 => 'Ambisonic_W', |
389
|
|
|
|
|
|
|
201 => 'Ambisonic_X', |
390
|
|
|
|
|
|
|
202 => 'Ambisonic_Y', |
391
|
|
|
|
|
|
|
203 => 'Ambisonic_Z', |
392
|
|
|
|
|
|
|
204 => 'MS_Mid', |
393
|
|
|
|
|
|
|
205 => 'MS_Side', |
394
|
|
|
|
|
|
|
206 => 'XY_X', |
395
|
|
|
|
|
|
|
207 => 'XY_Y', |
396
|
|
|
|
|
|
|
301 => 'HeadphonesLeft', |
397
|
|
|
|
|
|
|
302 => 'HeadphonesRight', |
398
|
|
|
|
|
|
|
304 => 'ClickTrack', |
399
|
|
|
|
|
|
|
305 => 'ForeignLanguage', |
400
|
|
|
|
|
|
|
400 => 'Discrete', |
401
|
|
|
|
|
|
|
0x10000 => 'Discrete_0', |
402
|
|
|
|
|
|
|
0x10001 => 'Discrete_1', |
403
|
|
|
|
|
|
|
0x10002 => 'Discrete_2', |
404
|
|
|
|
|
|
|
0x10003 => 'Discrete_3', |
405
|
|
|
|
|
|
|
0x10004 => 'Discrete_4', |
406
|
|
|
|
|
|
|
0x10005 => 'Discrete_5', |
407
|
|
|
|
|
|
|
0x10006 => 'Discrete_6', |
408
|
|
|
|
|
|
|
0x10007 => 'Discrete_7', |
409
|
|
|
|
|
|
|
0x10008 => 'Discrete_8', |
410
|
|
|
|
|
|
|
0x10009 => 'Discrete_9', |
411
|
|
|
|
|
|
|
0x1000a => 'Discrete_10', |
412
|
|
|
|
|
|
|
0x1000b => 'Discrete_11', |
413
|
|
|
|
|
|
|
0x1000c => 'Discrete_12', |
414
|
|
|
|
|
|
|
0x1000d => 'Discrete_13', |
415
|
|
|
|
|
|
|
0x1000e => 'Discrete_14', |
416
|
|
|
|
|
|
|
0x1000f => 'Discrete_15', |
417
|
|
|
|
|
|
|
0x1ffff => 'Discrete_65535', |
418
|
|
|
|
|
|
|
); |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# properties which don't get inherited from the parent |
421
|
|
|
|
|
|
|
my %dontInherit = ( |
422
|
|
|
|
|
|
|
ispe => 1, # size of parent may be different |
423
|
|
|
|
|
|
|
hvcC => 1, # (likely redundant) |
424
|
|
|
|
|
|
|
); |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# tags that may be duplicated and directories that may contain duplicate tags |
427
|
|
|
|
|
|
|
# (used only to avoid warnings when Validate-ing) |
428
|
|
|
|
|
|
|
my %dupTagOK = ( mdat => 1, trak => 1, free => 1, infe => 1, sgpd => 1, dimg => 1, CCDT => 1, |
429
|
|
|
|
|
|
|
sbgp => 1, csgm => 1, uuid => 1, cdsc => 1, maxr => 1, '----' => 1 ); |
430
|
|
|
|
|
|
|
my %dupDirOK = ( ipco => 1, '----' => 1 ); |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
# the usual atoms required to decode timed metadata with the ExtractEmbedded option |
433
|
|
|
|
|
|
|
my %eeStd = ( stco => 'stbl', co64 => 'stbl', stsz => 'stbl', stz2 => 'stbl', |
434
|
|
|
|
|
|
|
stsc => 'stbl', stts => 'stbl' ); |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# boxes and their containers for the various handler types that we want to save |
437
|
|
|
|
|
|
|
# when the ExtractEmbedded is enabled (currently only the 'gps ' container name is |
438
|
|
|
|
|
|
|
# used, but others have been checked against all available sample files and may be |
439
|
|
|
|
|
|
|
# useful in the future if the names are used for different boxes on other locations) |
440
|
|
|
|
|
|
|
my %eeBox = ( |
441
|
|
|
|
|
|
|
# (note: vide is only processed if specific atoms exist in the VideoSampleDesc) |
442
|
|
|
|
|
|
|
vide => { %eeStd, |
443
|
|
|
|
|
|
|
JPEG => 'stsd', |
444
|
|
|
|
|
|
|
}, |
445
|
|
|
|
|
|
|
text => { %eeStd }, |
446
|
|
|
|
|
|
|
meta => { %eeStd }, |
447
|
|
|
|
|
|
|
sbtl => { %eeStd }, |
448
|
|
|
|
|
|
|
data => { %eeStd }, |
449
|
|
|
|
|
|
|
camm => { %eeStd }, # (Insta360) |
450
|
|
|
|
|
|
|
ctbx => { %eeStd }, # (GM cars) |
451
|
|
|
|
|
|
|
'' => { 'gps ' => 'moov', 'GPS ' => 'main' }, # (no handler -- in top level 'moov' box, and main) |
452
|
|
|
|
|
|
|
); |
453
|
|
|
|
|
|
|
# boxes to save when ExtractEmbedded is set to 2 or higher |
454
|
|
|
|
|
|
|
my %eeBox2 = ( |
455
|
|
|
|
|
|
|
vide => { avcC => 'stsd' }, # (parses H264 video stream) |
456
|
|
|
|
|
|
|
); |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# QuickTime atoms |
459
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Main = ( |
460
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
461
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, # (only needs to be defined for directories to process when writing) |
462
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
463
|
|
|
|
|
|
|
meta => { # 'meta' is found here in my Sony ILCE-7S MP4 sample - PH |
464
|
|
|
|
|
|
|
Name => 'Meta', |
465
|
|
|
|
|
|
|
SubDirectory => { |
466
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Meta', |
467
|
|
|
|
|
|
|
Start => 4, # skip 4-byte version number header |
468
|
|
|
|
|
|
|
}, |
469
|
|
|
|
|
|
|
}, |
470
|
|
|
|
|
|
|
meco => { #ISO14496-12:2015 |
471
|
|
|
|
|
|
|
Name => 'OtherMeta', |
472
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::OtherMeta' }, |
473
|
|
|
|
|
|
|
}, |
474
|
|
|
|
|
|
|
free => [ |
475
|
|
|
|
|
|
|
{ |
476
|
|
|
|
|
|
|
Name => 'KodakFree', |
477
|
|
|
|
|
|
|
# (found in Kodak M5370 MP4 videos) |
478
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\0\0\0.Seri/s', |
479
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Kodak::Free' }, |
480
|
|
|
|
|
|
|
},{ |
481
|
|
|
|
|
|
|
Name => 'Pittasoft', |
482
|
|
|
|
|
|
|
# (Pittasoft Blackview dashcam MP4 videos) |
483
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\0\0..(cprt|sttm|ptnm|ptrh|thum|gps |3gf )/s', |
484
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Pittasoft' }, |
485
|
|
|
|
|
|
|
},{ |
486
|
|
|
|
|
|
|
Name => 'ThumbnailImage', |
487
|
|
|
|
|
|
|
# (DJI Zenmuse XT2 thermal camera) |
488
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
489
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^.{4}mdat\xff\xd8\xff/s', |
490
|
|
|
|
|
|
|
RawConv => q{ |
491
|
|
|
|
|
|
|
my $len = unpack('N', $val); |
492
|
|
|
|
|
|
|
return undef if $len <= 8 or $len > length($val); |
493
|
|
|
|
|
|
|
return substr($val, 8, $len-8); |
494
|
|
|
|
|
|
|
}, |
495
|
|
|
|
|
|
|
Binary => 1, |
496
|
|
|
|
|
|
|
},{ |
497
|
|
|
|
|
|
|
Unknown => 1, |
498
|
|
|
|
|
|
|
Binary => 1, |
499
|
|
|
|
|
|
|
}, |
500
|
|
|
|
|
|
|
# (also Samsung WB750 uncompressed thumbnail data starting with "SDIC\0") |
501
|
|
|
|
|
|
|
], |
502
|
|
|
|
|
|
|
# fre1 - 4 bytes: "june" (Kodak PixPro SP360) |
503
|
|
|
|
|
|
|
frea => { |
504
|
|
|
|
|
|
|
Name => 'Kodak_frea', |
505
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Kodak::frea' }, |
506
|
|
|
|
|
|
|
}, |
507
|
|
|
|
|
|
|
skip => [ |
508
|
|
|
|
|
|
|
{ |
509
|
|
|
|
|
|
|
Name => 'CanonSkip', |
510
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\0.{3}(CNDB|CNCV|CNMN|CNFV|CNTH|CNDM)/s', |
511
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Canon::Skip' }, |
512
|
|
|
|
|
|
|
}, |
513
|
|
|
|
|
|
|
{ |
514
|
|
|
|
|
|
|
Name => 'PreviewImage', # (found in DuDuBell M1 dashcam MOV files) |
515
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
516
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^.{12}\xff\xd8\xff/', |
517
|
|
|
|
|
|
|
Binary => 1, |
518
|
|
|
|
|
|
|
RawConv => q{ |
519
|
|
|
|
|
|
|
my $len = Get32u(\$val, 8); |
520
|
|
|
|
|
|
|
return undef unless length($val) >= $len + 12; |
521
|
|
|
|
|
|
|
return substr($val, 12, $len); |
522
|
|
|
|
|
|
|
}, |
523
|
|
|
|
|
|
|
}, |
524
|
|
|
|
|
|
|
{ Name => 'Skip', Unknown => 1, Binary => 1 }, |
525
|
|
|
|
|
|
|
], |
526
|
|
|
|
|
|
|
wide => { Unknown => 1, Binary => 1 }, |
527
|
|
|
|
|
|
|
ftyp => { #MP4 |
528
|
|
|
|
|
|
|
Name => 'FileType', |
529
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::FileType' }, |
530
|
|
|
|
|
|
|
}, |
531
|
|
|
|
|
|
|
pnot => { |
532
|
|
|
|
|
|
|
Name => 'Preview', |
533
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Preview' }, |
534
|
|
|
|
|
|
|
}, |
535
|
|
|
|
|
|
|
PICT => { |
536
|
|
|
|
|
|
|
Name => 'PreviewPICT', |
537
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
538
|
|
|
|
|
|
|
Binary => 1, |
539
|
|
|
|
|
|
|
}, |
540
|
|
|
|
|
|
|
pict => { #8 |
541
|
|
|
|
|
|
|
Name => 'PreviewPICT', |
542
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
543
|
|
|
|
|
|
|
Binary => 1, |
544
|
|
|
|
|
|
|
}, |
545
|
|
|
|
|
|
|
# (note that moov is present for an HEIF sequence) |
546
|
|
|
|
|
|
|
moov => { |
547
|
|
|
|
|
|
|
Name => 'Movie', |
548
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Movie' }, |
549
|
|
|
|
|
|
|
}, |
550
|
|
|
|
|
|
|
moof => { |
551
|
|
|
|
|
|
|
Name => 'MovieFragment', |
552
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MovieFragment' }, |
553
|
|
|
|
|
|
|
}, |
554
|
|
|
|
|
|
|
# mfra - movie fragment random access: contains tfra (track fragment random access), and |
555
|
|
|
|
|
|
|
# mfro (movie fragment random access offset) (ref 5) |
556
|
|
|
|
|
|
|
mdat => { Name => 'MediaData', Unknown => 1, Binary => 1 }, |
557
|
|
|
|
|
|
|
'mdat-size' => { |
558
|
|
|
|
|
|
|
Name => 'MediaDataSize', |
559
|
|
|
|
|
|
|
Notes => q{ |
560
|
|
|
|
|
|
|
not a real tag ID, this tag represents the size of the 'mdat' data in bytes |
561
|
|
|
|
|
|
|
and is used in the AvgBitrate calculation |
562
|
|
|
|
|
|
|
}, |
563
|
|
|
|
|
|
|
}, |
564
|
|
|
|
|
|
|
'mdat-offset' => 'MediaDataOffset', |
565
|
|
|
|
|
|
|
junk => { Unknown => 1, Binary => 1 }, #8 |
566
|
|
|
|
|
|
|
uuid => [ |
567
|
|
|
|
|
|
|
{ #9 (MP4 files) |
568
|
|
|
|
|
|
|
Name => 'XMP', |
569
|
|
|
|
|
|
|
# *** this is where ExifTool writes XMP in MP4 videos (as per XMP spec) *** |
570
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac/', |
571
|
|
|
|
|
|
|
WriteGroup => 'XMP', # (write main XMP tags here) |
572
|
|
|
|
|
|
|
PreservePadding => 1, |
573
|
|
|
|
|
|
|
SubDirectory => { |
574
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::XMP::Main', |
575
|
|
|
|
|
|
|
Start => 16, |
576
|
|
|
|
|
|
|
}, |
577
|
|
|
|
|
|
|
}, |
578
|
|
|
|
|
|
|
{ #11 (MP4 files) |
579
|
|
|
|
|
|
|
Name => 'UUID-PROF', |
580
|
|
|
|
|
|
|
Condition => '$$valPt=~/^PROF!\xd2\x4f\xce\xbb\x88\x69\x5c\xfa\xc9\xc7\x40/', |
581
|
|
|
|
|
|
|
SubDirectory => { |
582
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Profile', |
583
|
|
|
|
|
|
|
Start => 24, # uid(16) + version(1) + flags(3) + count(4) |
584
|
|
|
|
|
|
|
}, |
585
|
|
|
|
|
|
|
}, |
586
|
|
|
|
|
|
|
{ #PH (Flip MP4 files) |
587
|
|
|
|
|
|
|
Name => 'UUID-Flip', |
588
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\x4a\xb0\x3b\x0f\x61\x8d\x40\x75\x82\xb2\xd9\xfa\xce\xd3\x5f\xf5/', |
589
|
|
|
|
|
|
|
SubDirectory => { |
590
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Flip', |
591
|
|
|
|
|
|
|
Start => 16, |
592
|
|
|
|
|
|
|
}, |
593
|
|
|
|
|
|
|
}, |
594
|
|
|
|
|
|
|
# "\x98\x7f\xa3\xdf\x2a\x85\x43\xc0\x8f\x8f\xd9\x7c\x47\x1e\x8e\xea" - unknown data in Flip videos |
595
|
|
|
|
|
|
|
{ #PH (Canon CR3) |
596
|
|
|
|
|
|
|
Name => 'UUID-Canon2', |
597
|
|
|
|
|
|
|
WriteLast => 1, # MUST come after mdat or DPP will drop mdat when writing! |
598
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\x21\x0f\x16\x87\x91\x49\x11\xe4\x81\x11\x00\x24\x21\x31\xfc\xe4/', |
599
|
|
|
|
|
|
|
SubDirectory => { |
600
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Canon::uuid2', |
601
|
|
|
|
|
|
|
Start => 16, |
602
|
|
|
|
|
|
|
}, |
603
|
|
|
|
|
|
|
}, |
604
|
|
|
|
|
|
|
{ # (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php) |
605
|
|
|
|
|
|
|
Name => 'SensorData', # sensor data for the 360Fly |
606
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}', |
607
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' }, |
608
|
|
|
|
|
|
|
}, |
609
|
|
|
|
|
|
|
{ |
610
|
|
|
|
|
|
|
Name => 'SensorData', |
611
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/', |
612
|
|
|
|
|
|
|
Notes => 'raw 360Fly sensor data without ExtractEmbedded option', |
613
|
|
|
|
|
|
|
RawConv => q{ |
614
|
|
|
|
|
|
|
$self->WarnOnce('Use the ExtractEmbedded option to decode timed SensorData',3); |
615
|
|
|
|
|
|
|
return \$val; |
616
|
|
|
|
|
|
|
}, |
617
|
|
|
|
|
|
|
}, |
618
|
|
|
|
|
|
|
{ #PH (Canon CR3) |
619
|
|
|
|
|
|
|
Name => 'PreviewImage', |
620
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/', |
621
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
622
|
|
|
|
|
|
|
PreservePadding => 1, |
623
|
|
|
|
|
|
|
# 0x00 - undef[16]: UUID |
624
|
|
|
|
|
|
|
# 0x10 - int32u[2]: "0 1" (version and/or item count?) |
625
|
|
|
|
|
|
|
# 0x18 - int32u: PRVW atom size |
626
|
|
|
|
|
|
|
# 0x20 - int32u: 'PRVW' |
627
|
|
|
|
|
|
|
# 0x30 - int32u: 0 |
628
|
|
|
|
|
|
|
# 0x34 - int16u: 1 |
629
|
|
|
|
|
|
|
# 0x36 - int16u: image width |
630
|
|
|
|
|
|
|
# 0x38 - int16u: image height |
631
|
|
|
|
|
|
|
# 0x3a - int16u: 1 |
632
|
|
|
|
|
|
|
# 0x3c - int32u: preview length |
633
|
|
|
|
|
|
|
RawConv => '$val = substr($val, 0x30); $self->ValidateImage(\$val, $tag)', |
634
|
|
|
|
|
|
|
}, |
635
|
|
|
|
|
|
|
{ #8 |
636
|
|
|
|
|
|
|
Name => 'UUID-Unknown', |
637
|
|
|
|
|
|
|
%unknownInfo, |
638
|
|
|
|
|
|
|
}, |
639
|
|
|
|
|
|
|
], |
640
|
|
|
|
|
|
|
_htc => { |
641
|
|
|
|
|
|
|
Name => 'HTCInfo', |
642
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HTCInfo' }, |
643
|
|
|
|
|
|
|
}, |
644
|
|
|
|
|
|
|
udta => { |
645
|
|
|
|
|
|
|
Name => 'UserData', |
646
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::FLIR::UserData' }, |
647
|
|
|
|
|
|
|
}, |
648
|
|
|
|
|
|
|
thum => { #PH |
649
|
|
|
|
|
|
|
Name => 'ThumbnailImage', |
650
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
651
|
|
|
|
|
|
|
Binary => 1, |
652
|
|
|
|
|
|
|
}, |
653
|
|
|
|
|
|
|
'thm ' => { #PH (70mai A800) |
654
|
|
|
|
|
|
|
Name => 'ThumbnailImage', |
655
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
656
|
|
|
|
|
|
|
Binary => 1, |
657
|
|
|
|
|
|
|
}, |
658
|
|
|
|
|
|
|
ardt => { #PH |
659
|
|
|
|
|
|
|
Name => 'ARDroneFile', |
660
|
|
|
|
|
|
|
ValueConv => 'length($val) > 4 ? substr($val,4) : $val', # remove length |
661
|
|
|
|
|
|
|
}, |
662
|
|
|
|
|
|
|
prrt => { #PH |
663
|
|
|
|
|
|
|
Name => 'ARDroneTelemetry', |
664
|
|
|
|
|
|
|
Notes => q{ |
665
|
|
|
|
|
|
|
telemetry information for each video frame: status1, status2, time, pitch, |
666
|
|
|
|
|
|
|
roll, yaw, speed, altitude |
667
|
|
|
|
|
|
|
}, |
668
|
|
|
|
|
|
|
ValueConv => q{ |
669
|
|
|
|
|
|
|
my $size = length $val; |
670
|
|
|
|
|
|
|
return \$val if $size < 12 or not $$self{OPTIONS}{Binary}; |
671
|
|
|
|
|
|
|
my $len = Get16u(\$val, 2); |
672
|
|
|
|
|
|
|
my $str = ''; |
673
|
|
|
|
|
|
|
SetByteOrder('II'); |
674
|
|
|
|
|
|
|
my $pos = 12; |
675
|
|
|
|
|
|
|
while ($pos + $len <= $size) { |
676
|
|
|
|
|
|
|
my $s1 = Get16u(\$val, $pos); |
677
|
|
|
|
|
|
|
# s2: 7=take-off?, 3=moving, 4=hovering, 9=landing?, 2=landed |
678
|
|
|
|
|
|
|
my $s2 = Get16u(\$val, $pos + 2); |
679
|
|
|
|
|
|
|
$str .= "$s1 $s2"; |
680
|
|
|
|
|
|
|
my $num = int(($len-4)/4); |
681
|
|
|
|
|
|
|
my ($i, $v); |
682
|
|
|
|
|
|
|
for ($i=0; $i<$num; ++$i) { |
683
|
|
|
|
|
|
|
my $pt = $pos + 4 + $i * 4; |
684
|
|
|
|
|
|
|
if ($i > 0 && $i < 4) { |
685
|
|
|
|
|
|
|
$v = GetFloat(\$val, $pt); # pitch/roll/yaw |
686
|
|
|
|
|
|
|
} else { |
687
|
|
|
|
|
|
|
$v = Get32u(\$val, $pt); |
688
|
|
|
|
|
|
|
# convert time to sec, and speed(NC)/altitude to metres |
689
|
|
|
|
|
|
|
$v /= 1000 if $i <= 5; |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
$str .= " $v"; |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
$str .= "\n"; |
694
|
|
|
|
|
|
|
$pos += $len; |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
SetByteOrder('MM'); |
697
|
|
|
|
|
|
|
return \$str; |
698
|
|
|
|
|
|
|
}, |
699
|
|
|
|
|
|
|
}, |
700
|
|
|
|
|
|
|
udat => { #PH (GPS NMEA-format log written by Datakam Player software) |
701
|
|
|
|
|
|
|
Name => 'GPSLog', |
702
|
|
|
|
|
|
|
Binary => 1, # (actually ASCII, but very lengthy) |
703
|
|
|
|
|
|
|
Notes => 'parsed to extract GPS separately when ExtractEmbedded is used', |
704
|
|
|
|
|
|
|
RawConv => q{ |
705
|
|
|
|
|
|
|
$val =~ s/\0+$//; # remove trailing nulls |
706
|
|
|
|
|
|
|
if (length $val and $$self{OPTIONS}{ExtractEmbedded}) { |
707
|
|
|
|
|
|
|
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream'); |
708
|
|
|
|
|
|
|
Image::ExifTool::QuickTime::ProcessGPSLog($self, { DataPt => \$val }, $tagTbl); |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
return $val; |
711
|
|
|
|
|
|
|
}, |
712
|
|
|
|
|
|
|
}, |
713
|
|
|
|
|
|
|
# meta - proprietary XML information written by some Flip cameras - PH |
714
|
|
|
|
|
|
|
# beam - 16 bytes found in an iPhone video |
715
|
|
|
|
|
|
|
IDIT => { #PH (written by DuDuBell M1, VSYS M6L dashcams) |
716
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
717
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
718
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
719
|
|
|
|
|
|
|
Format => 'string', # (removes trailing "\0") |
720
|
|
|
|
|
|
|
Shift => 'Time', |
721
|
|
|
|
|
|
|
Writable => 1, |
722
|
|
|
|
|
|
|
Permanent => 1, |
723
|
|
|
|
|
|
|
DelValue => '0000-00-00T00:00:00+0000', |
724
|
|
|
|
|
|
|
ValueConv => '$val=~tr/-/:/; $val', |
725
|
|
|
|
|
|
|
ValueConvInv => '$val=~s/(\d+):(\d+):/$1-$2-/; $val', |
726
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
727
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) |
728
|
|
|
|
|
|
|
}, |
729
|
|
|
|
|
|
|
gps0 => { #PH (DuDuBell M1, VSYS M6L) |
730
|
|
|
|
|
|
|
Name => 'GPSTrack', |
731
|
|
|
|
|
|
|
SubDirectory => { |
732
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
733
|
|
|
|
|
|
|
ProcessProc => \&Process_gps0, |
734
|
|
|
|
|
|
|
}, |
735
|
|
|
|
|
|
|
}, |
736
|
|
|
|
|
|
|
gsen => { #PH (DuDuBell M1, VSYS M6L) |
737
|
|
|
|
|
|
|
Name => 'GSensor', |
738
|
|
|
|
|
|
|
SubDirectory => { |
739
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
740
|
|
|
|
|
|
|
ProcessProc => \&Process_gsen, |
741
|
|
|
|
|
|
|
}, |
742
|
|
|
|
|
|
|
}, |
743
|
|
|
|
|
|
|
# gpsa - seen hex "01 20 00 00" (DuDuBell M1, VSYS M6L) |
744
|
|
|
|
|
|
|
# gsea - 20 bytes hex "05 00's..." (DuDuBell M1) "05 08 02 01 ..." (VSYS M6L) |
745
|
|
|
|
|
|
|
'GPS ' => { # GPS data written by 70mai dashcam (parsed in QuickTimeStream.pl) |
746
|
|
|
|
|
|
|
Name => 'GPSDataList2', |
747
|
|
|
|
|
|
|
Unknown => 1, |
748
|
|
|
|
|
|
|
Binary => 1, |
749
|
|
|
|
|
|
|
}, |
750
|
|
|
|
|
|
|
sefd => { |
751
|
|
|
|
|
|
|
Name => 'SamsungTrailer', |
752
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Samsung::Trailer' }, |
753
|
|
|
|
|
|
|
}, |
754
|
|
|
|
|
|
|
# 'samn'? - seen in Vantrue N2S sample video |
755
|
|
|
|
|
|
|
); |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
# MPEG-4 'ftyp' atom |
758
|
|
|
|
|
|
|
# (ref http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html) |
759
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::FileType = ( |
760
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
761
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
762
|
|
|
|
|
|
|
FORMAT => 'int32u', |
763
|
|
|
|
|
|
|
0 => { |
764
|
|
|
|
|
|
|
Name => 'MajorBrand', |
765
|
|
|
|
|
|
|
Format => 'undef[4]', |
766
|
|
|
|
|
|
|
PrintConv => \%ftypLookup, |
767
|
|
|
|
|
|
|
}, |
768
|
|
|
|
|
|
|
1 => { |
769
|
|
|
|
|
|
|
Name => 'MinorVersion', |
770
|
|
|
|
|
|
|
Format => 'undef[4]', |
771
|
|
|
|
|
|
|
ValueConv => 'sprintf("%x.%x.%x", unpack("nCC", $val))', |
772
|
|
|
|
|
|
|
}, |
773
|
|
|
|
|
|
|
2 => { |
774
|
|
|
|
|
|
|
Name => 'CompatibleBrands', |
775
|
|
|
|
|
|
|
Format => 'undef[$size-8]', |
776
|
|
|
|
|
|
|
# ignore any entry with a null, and return others as a list |
777
|
|
|
|
|
|
|
ValueConv => 'my @a=($val=~/.{4}/sg); @a=grep(!/\0/,@a); \@a', |
778
|
|
|
|
|
|
|
}, |
779
|
|
|
|
|
|
|
); |
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
# proprietary HTC atom (HTC One MP4 video) |
782
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::HTCInfo = ( |
783
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
784
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
785
|
|
|
|
|
|
|
NOTES => 'Tags written by some HTC camera phones.', |
786
|
|
|
|
|
|
|
slmt => { |
787
|
|
|
|
|
|
|
Name => 'Unknown_slmt', |
788
|
|
|
|
|
|
|
Unknown => 1, |
789
|
|
|
|
|
|
|
Format => 'int32u', # (observed values: 4) |
790
|
|
|
|
|
|
|
}, |
791
|
|
|
|
|
|
|
); |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
# atoms used in QTIF files |
794
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ImageFile = ( |
795
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
796
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
797
|
|
|
|
|
|
|
NOTES => 'Tags used in QTIF QuickTime Image Files.', |
798
|
|
|
|
|
|
|
idsc => { |
799
|
|
|
|
|
|
|
Name => 'ImageDescription', |
800
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ImageDesc' }, |
801
|
|
|
|
|
|
|
}, |
802
|
|
|
|
|
|
|
idat => { |
803
|
|
|
|
|
|
|
Name => 'ImageData', |
804
|
|
|
|
|
|
|
Binary => 1, |
805
|
|
|
|
|
|
|
}, |
806
|
|
|
|
|
|
|
iicc => { |
807
|
|
|
|
|
|
|
Name => 'ICC_Profile', |
808
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, |
809
|
|
|
|
|
|
|
}, |
810
|
|
|
|
|
|
|
); |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
# image description data block |
813
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ImageDesc = ( |
814
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessHybrid, |
815
|
|
|
|
|
|
|
VARS => { ID_LABEL => 'ID/Index' }, |
816
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
817
|
|
|
|
|
|
|
FORMAT => 'int16u', |
818
|
|
|
|
|
|
|
2 => { |
819
|
|
|
|
|
|
|
Name => 'CompressorID', |
820
|
|
|
|
|
|
|
Format => 'string[4]', |
821
|
|
|
|
|
|
|
# not very useful since this isn't a complete list and name is given below |
822
|
|
|
|
|
|
|
# # ref http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html |
823
|
|
|
|
|
|
|
# PrintConv => { |
824
|
|
|
|
|
|
|
# cvid => 'Cinepak', |
825
|
|
|
|
|
|
|
# jpeg => 'JPEG', |
826
|
|
|
|
|
|
|
# 'smc '=> 'Graphics', |
827
|
|
|
|
|
|
|
# 'rle '=> 'Animation', |
828
|
|
|
|
|
|
|
# rpza => 'Apple Video', |
829
|
|
|
|
|
|
|
# kpcd => 'Kodak Photo CD', |
830
|
|
|
|
|
|
|
# 'png '=> 'Portable Network Graphics', |
831
|
|
|
|
|
|
|
# mjpa => 'Motion-JPEG (format A)', |
832
|
|
|
|
|
|
|
# mjpb => 'Motion-JPEG (format B)', |
833
|
|
|
|
|
|
|
# SVQ1 => 'Sorenson video, version 1', |
834
|
|
|
|
|
|
|
# SVQ3 => 'Sorenson video, version 3', |
835
|
|
|
|
|
|
|
# mp4v => 'MPEG-4 video', |
836
|
|
|
|
|
|
|
# 'dvc '=> 'NTSC DV-25 video', |
837
|
|
|
|
|
|
|
# dvcp => 'PAL DV-25 video', |
838
|
|
|
|
|
|
|
# 'gif '=> 'Compuserve Graphics Interchange Format', |
839
|
|
|
|
|
|
|
# h263 => 'H.263 video', |
840
|
|
|
|
|
|
|
# tiff => 'Tagged Image File Format', |
841
|
|
|
|
|
|
|
# 'raw '=> 'Uncompressed RGB', |
842
|
|
|
|
|
|
|
# '2vuY'=> "Uncompressed Y'CbCr, 3x8-bit 4:2:2 (2vuY)", |
843
|
|
|
|
|
|
|
# 'yuv2'=> "Uncompressed Y'CbCr, 3x8-bit 4:2:2 (yuv2)", |
844
|
|
|
|
|
|
|
# v308 => "Uncompressed Y'CbCr, 8-bit 4:4:4", |
845
|
|
|
|
|
|
|
# v408 => "Uncompressed Y'CbCr, 8-bit 4:4:4:4", |
846
|
|
|
|
|
|
|
# v216 => "Uncompressed Y'CbCr, 10, 12, 14, or 16-bit 4:2:2", |
847
|
|
|
|
|
|
|
# v410 => "Uncompressed Y'CbCr, 10-bit 4:4:4", |
848
|
|
|
|
|
|
|
# v210 => "Uncompressed Y'CbCr, 10-bit 4:2:2", |
849
|
|
|
|
|
|
|
# hvc1 => 'HEVC', #PH |
850
|
|
|
|
|
|
|
# }, |
851
|
|
|
|
|
|
|
}, |
852
|
|
|
|
|
|
|
10 => { |
853
|
|
|
|
|
|
|
Name => 'VendorID', |
854
|
|
|
|
|
|
|
Format => 'string[4]', |
855
|
|
|
|
|
|
|
RawConv => 'length $val ? $val : undef', |
856
|
|
|
|
|
|
|
PrintConv => \%vendorID, |
857
|
|
|
|
|
|
|
SeparateTable => 'VendorID', |
858
|
|
|
|
|
|
|
}, |
859
|
|
|
|
|
|
|
# 14 - ("Quality" in QuickTime docs) ?? |
860
|
|
|
|
|
|
|
16 => 'SourceImageWidth', |
861
|
|
|
|
|
|
|
17 => 'SourceImageHeight', |
862
|
|
|
|
|
|
|
18 => { Name => 'XResolution', Format => 'fixed32u' }, |
863
|
|
|
|
|
|
|
20 => { Name => 'YResolution', Format => 'fixed32u' }, |
864
|
|
|
|
|
|
|
# 24 => 'FrameCount', # always 1 (what good is this?) |
865
|
|
|
|
|
|
|
25 => { |
866
|
|
|
|
|
|
|
Name => 'CompressorName', |
867
|
|
|
|
|
|
|
Format => 'string[32]', |
868
|
|
|
|
|
|
|
# (sometimes this is a Pascal string, and sometimes it is a C string) |
869
|
|
|
|
|
|
|
RawConv => q{ |
870
|
|
|
|
|
|
|
$val=substr($val,1,ord($1)) if $val=~/^([\0-\x1f])/ and ord($1)
|
871
|
|
|
|
|
|
|
length $val ? $val : undef; |
872
|
|
|
|
|
|
|
}, |
873
|
|
|
|
|
|
|
}, |
874
|
|
|
|
|
|
|
41 => 'BitDepth', |
875
|
|
|
|
|
|
|
# |
876
|
|
|
|
|
|
|
# Observed offsets for child atoms of various CompressorID types: |
877
|
|
|
|
|
|
|
# |
878
|
|
|
|
|
|
|
# CompressorID Offset Child atoms |
879
|
|
|
|
|
|
|
# ----------- ------ ---------------- |
880
|
|
|
|
|
|
|
# avc1 86 avcC, btrt, colr, pasp, fiel, clap, svcC |
881
|
|
|
|
|
|
|
# mp4v 86 esds, pasp |
882
|
|
|
|
|
|
|
# s263 86 d263 |
883
|
|
|
|
|
|
|
# |
884
|
|
|
|
|
|
|
btrt => { |
885
|
|
|
|
|
|
|
Name => 'BitrateInfo', |
886
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Bitrate' }, |
887
|
|
|
|
|
|
|
}, |
888
|
|
|
|
|
|
|
# Reference for fiel, colr, pasp, clap: |
889
|
|
|
|
|
|
|
# https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9 |
890
|
|
|
|
|
|
|
fiel => { |
891
|
|
|
|
|
|
|
Name => 'VideoFieldOrder', |
892
|
|
|
|
|
|
|
ValueConv => 'join(" ", unpack("C*",$val))', |
893
|
|
|
|
|
|
|
PrintConv => [{ |
894
|
|
|
|
|
|
|
1 => 'Progressive', |
895
|
|
|
|
|
|
|
2 => '2:1 Interlaced', |
896
|
|
|
|
|
|
|
}], |
897
|
|
|
|
|
|
|
}, |
898
|
|
|
|
|
|
|
colr => { |
899
|
|
|
|
|
|
|
Name => 'ColorRepresentation', |
900
|
|
|
|
|
|
|
ValueConv => 'join(" ", substr($val,0,4), unpack("x4n*",$val))', |
901
|
|
|
|
|
|
|
}, |
902
|
|
|
|
|
|
|
pasp => { |
903
|
|
|
|
|
|
|
Name => 'PixelAspectRatio', |
904
|
|
|
|
|
|
|
ValueConv => 'join(":", unpack("N*",$val))', |
905
|
|
|
|
|
|
|
}, |
906
|
|
|
|
|
|
|
clap => { |
907
|
|
|
|
|
|
|
Name => 'CleanAperture', |
908
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::CleanAperture' }, |
909
|
|
|
|
|
|
|
}, |
910
|
|
|
|
|
|
|
avcC => { |
911
|
|
|
|
|
|
|
# (see http://thompsonng.blogspot.ca/2010/11/mp4-file-format-part-2.html) |
912
|
|
|
|
|
|
|
Name => 'AVCConfiguration', |
913
|
|
|
|
|
|
|
Unknown => 1, |
914
|
|
|
|
|
|
|
Binary => 1, |
915
|
|
|
|
|
|
|
}, |
916
|
|
|
|
|
|
|
JPEG => { # (found in CR3 images; used as a flag to identify JpgFromRaw 'vide' stream) |
917
|
|
|
|
|
|
|
Name => 'JPEGInfo', |
918
|
|
|
|
|
|
|
# (4 bytes all zero) |
919
|
|
|
|
|
|
|
Unknown => 1, |
920
|
|
|
|
|
|
|
Binary => 1, |
921
|
|
|
|
|
|
|
}, |
922
|
|
|
|
|
|
|
# hvcC - HEVC configuration |
923
|
|
|
|
|
|
|
# svcC - 7 bytes: 00 00 00 00 ff e0 00 |
924
|
|
|
|
|
|
|
# esds - elementary stream descriptor |
925
|
|
|
|
|
|
|
# d263 |
926
|
|
|
|
|
|
|
gama => { Name => 'Gamma', Format => 'fixed32u' }, |
927
|
|
|
|
|
|
|
# mjqt - default quantization table for MJPEG |
928
|
|
|
|
|
|
|
# mjht - default Huffman table for MJPEG |
929
|
|
|
|
|
|
|
# csgm ? (seen in hevc video) |
930
|
|
|
|
|
|
|
CMP1 => { # Canon CR3 |
931
|
|
|
|
|
|
|
Name => 'CMP1', |
932
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Canon::CMP1' }, |
933
|
|
|
|
|
|
|
}, |
934
|
|
|
|
|
|
|
CDI1 => { # Canon CR3 |
935
|
|
|
|
|
|
|
Name => 'CDI1', |
936
|
|
|
|
|
|
|
SubDirectory => { |
937
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Canon::CDI1', |
938
|
|
|
|
|
|
|
Start => 4, |
939
|
|
|
|
|
|
|
}, |
940
|
|
|
|
|
|
|
}, |
941
|
|
|
|
|
|
|
# JPEG - 4 bytes all 0 (Canon CR3) |
942
|
|
|
|
|
|
|
# free - (Canon CR3) |
943
|
|
|
|
|
|
|
# |
944
|
|
|
|
|
|
|
# spherical video v2 stuff (untested) |
945
|
|
|
|
|
|
|
# |
946
|
|
|
|
|
|
|
st3d => { |
947
|
|
|
|
|
|
|
Name => 'Stereoscopic3D', |
948
|
|
|
|
|
|
|
Format => 'int8u', |
949
|
|
|
|
|
|
|
ValueConv => '$val =~ s/.* //; $val', # (remove leading version/flags bytes?) |
950
|
|
|
|
|
|
|
PrintConv => { |
951
|
|
|
|
|
|
|
0 => 'Monoscopic', |
952
|
|
|
|
|
|
|
1 => 'Stereoscopic Top-Bottom', |
953
|
|
|
|
|
|
|
2 => 'Stereoscopic Left-Right', |
954
|
|
|
|
|
|
|
3 => 'Stereoscopic Stereo-Custom', # (provisional in spec as of 2017-10-10) |
955
|
|
|
|
|
|
|
}, |
956
|
|
|
|
|
|
|
}, |
957
|
|
|
|
|
|
|
sv3d => { |
958
|
|
|
|
|
|
|
Name => 'SphericalVideo', |
959
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::sv3d' }, |
960
|
|
|
|
|
|
|
}, |
961
|
|
|
|
|
|
|
); |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
# 'sv3d' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) |
964
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::sv3d = ( |
965
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
966
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
967
|
|
|
|
|
|
|
NOTES => q{ |
968
|
|
|
|
|
|
|
Tags defined by the Spherical Video V2 specification. See |
969
|
|
|
|
|
|
|
L |
970
|
|
|
|
|
|
|
for the specification. |
971
|
|
|
|
|
|
|
}, |
972
|
|
|
|
|
|
|
svhd => { |
973
|
|
|
|
|
|
|
Name => 'MetadataSource', |
974
|
|
|
|
|
|
|
Format => 'undef', |
975
|
|
|
|
|
|
|
ValueConv => '$val=~tr/\0//d; $val', # (remove version/flags? and terminator?) |
976
|
|
|
|
|
|
|
}, |
977
|
|
|
|
|
|
|
proj => { |
978
|
|
|
|
|
|
|
Name => 'Projection', |
979
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::proj' }, |
980
|
|
|
|
|
|
|
}, |
981
|
|
|
|
|
|
|
); |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
# 'proj' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) |
984
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::proj = ( |
985
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
986
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
987
|
|
|
|
|
|
|
prhd => { |
988
|
|
|
|
|
|
|
Name => 'ProjectionHeader', |
989
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::prhd' }, |
990
|
|
|
|
|
|
|
}, |
991
|
|
|
|
|
|
|
cbmp => { |
992
|
|
|
|
|
|
|
Name => 'CubemapProj', |
993
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::cbmp' }, |
994
|
|
|
|
|
|
|
}, |
995
|
|
|
|
|
|
|
equi => { |
996
|
|
|
|
|
|
|
Name => 'EquirectangularProj', |
997
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::equi' }, |
998
|
|
|
|
|
|
|
}, |
999
|
|
|
|
|
|
|
# mshp - MeshProjection (P.I.T.A. to decode, for not much reward, see ref) |
1000
|
|
|
|
|
|
|
); |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
# 'prhd' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) |
1003
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::prhd = ( |
1004
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1005
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1006
|
|
|
|
|
|
|
FORMAT => 'fixed32s', |
1007
|
|
|
|
|
|
|
# 0 - version (high 8 bits) / flags (low 24 bits) |
1008
|
|
|
|
|
|
|
1 => 'PoseYawDegrees', |
1009
|
|
|
|
|
|
|
2 => 'PosePitchDegrees', |
1010
|
|
|
|
|
|
|
3 => 'PoseRollDegrees', |
1011
|
|
|
|
|
|
|
); |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
# 'cbmp' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) |
1014
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::cbmp = ( |
1015
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1016
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1017
|
|
|
|
|
|
|
FORMAT => 'int32u', |
1018
|
|
|
|
|
|
|
# 0 - version (high 8 bits) / flags (low 24 bits) |
1019
|
|
|
|
|
|
|
1 => 'Layout', |
1020
|
|
|
|
|
|
|
2 => 'Padding', |
1021
|
|
|
|
|
|
|
); |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
# 'equi' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md) |
1024
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::equi = ( |
1025
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1026
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1027
|
|
|
|
|
|
|
FORMAT => 'int32u', # (actually 0.32 fixed point) |
1028
|
|
|
|
|
|
|
# 0 - version (high 8 bits) / flags (low 24 bits) |
1029
|
|
|
|
|
|
|
1 => { Name => 'ProjectionBoundsTop', ValueConv => '$val / 4294967296' }, |
1030
|
|
|
|
|
|
|
2 => { Name => 'ProjectionBoundsBottom',ValueConv => '$val / 4294967296' }, |
1031
|
|
|
|
|
|
|
3 => { Name => 'ProjectionBoundsLeft', ValueConv => '$val / 4294967296' }, |
1032
|
|
|
|
|
|
|
4 => { Name => 'ProjectionBoundsRight', ValueConv => '$val / 4294967296' }, |
1033
|
|
|
|
|
|
|
); |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
# 'btrt' atom information (ref http://lists.freedesktop.org/archives/gstreamer-commits/2011-October/054459.html) |
1036
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Bitrate = ( |
1037
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1038
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1039
|
|
|
|
|
|
|
FORMAT => 'int32u', |
1040
|
|
|
|
|
|
|
PRIORITY => 0, # often filled with zeros |
1041
|
|
|
|
|
|
|
0 => 'BufferSize', |
1042
|
|
|
|
|
|
|
1 => 'MaxBitrate', |
1043
|
|
|
|
|
|
|
2 => 'AverageBitrate', |
1044
|
|
|
|
|
|
|
); |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
# 'clap' atom information (ref https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9) |
1047
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::CleanAperture = ( |
1048
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1049
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1050
|
|
|
|
|
|
|
FORMAT => 'rational64s', |
1051
|
|
|
|
|
|
|
0 => 'CleanApertureWidth', |
1052
|
|
|
|
|
|
|
1 => 'CleanApertureHeight', |
1053
|
|
|
|
|
|
|
2 => 'CleanApertureOffsetX', |
1054
|
|
|
|
|
|
|
3 => 'CleanApertureOffsetY', |
1055
|
|
|
|
|
|
|
); |
1056
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
# preview data block |
1058
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Preview = ( |
1059
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1060
|
|
|
|
|
|
|
WRITE_PROC => \&Image::ExifTool::WriteBinaryData, |
1061
|
|
|
|
|
|
|
CHECK_PROC => \&Image::ExifTool::CheckBinaryData, |
1062
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
1063
|
|
|
|
|
|
|
FORMAT => 'int16u', |
1064
|
|
|
|
|
|
|
0 => { |
1065
|
|
|
|
|
|
|
Name => 'PreviewDate', |
1066
|
|
|
|
|
|
|
Format => 'int32u', |
1067
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1068
|
|
|
|
|
|
|
%timeInfo, |
1069
|
|
|
|
|
|
|
}, |
1070
|
|
|
|
|
|
|
2 => 'PreviewVersion', |
1071
|
|
|
|
|
|
|
3 => { |
1072
|
|
|
|
|
|
|
Name => 'PreviewAtomType', |
1073
|
|
|
|
|
|
|
Format => 'string[4]', |
1074
|
|
|
|
|
|
|
}, |
1075
|
|
|
|
|
|
|
5 => 'PreviewAtomIndex', |
1076
|
|
|
|
|
|
|
); |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
# movie atoms |
1079
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Movie = ( |
1080
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
1081
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
1082
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1083
|
|
|
|
|
|
|
mvhd => { |
1084
|
|
|
|
|
|
|
Name => 'MovieHeader', |
1085
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MovieHeader' }, |
1086
|
|
|
|
|
|
|
}, |
1087
|
|
|
|
|
|
|
trak => { |
1088
|
|
|
|
|
|
|
Name => 'Track', |
1089
|
|
|
|
|
|
|
CanCreate => 0, # don't create this atom |
1090
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Track' }, |
1091
|
|
|
|
|
|
|
}, |
1092
|
|
|
|
|
|
|
udta => { |
1093
|
|
|
|
|
|
|
Name => 'UserData', |
1094
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::UserData' }, |
1095
|
|
|
|
|
|
|
}, |
1096
|
|
|
|
|
|
|
meta => { # 'meta' is found here in my EX-F1 MOV sample - PH |
1097
|
|
|
|
|
|
|
Name => 'Meta', |
1098
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' }, |
1099
|
|
|
|
|
|
|
}, |
1100
|
|
|
|
|
|
|
iods => { |
1101
|
|
|
|
|
|
|
Name => 'InitialObjectDescriptor', |
1102
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
1103
|
|
|
|
|
|
|
}, |
1104
|
|
|
|
|
|
|
uuid => [ |
1105
|
|
|
|
|
|
|
{ #11 (MP4 files) (also found in QuickTime::Track) |
1106
|
|
|
|
|
|
|
Name => 'UUID-USMT', |
1107
|
|
|
|
|
|
|
Condition => '$$valPt=~/^USMT!\xd2\x4f\xce\xbb\x88\x69\x5c\xfa\xc9\xc7\x40/', |
1108
|
|
|
|
|
|
|
SubDirectory => { |
1109
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::UserMedia', |
1110
|
|
|
|
|
|
|
Start => 16, |
1111
|
|
|
|
|
|
|
}, |
1112
|
|
|
|
|
|
|
}, |
1113
|
|
|
|
|
|
|
{ #PH (Canon SX280) |
1114
|
|
|
|
|
|
|
Name => 'UUID-Canon', |
1115
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/', |
1116
|
|
|
|
|
|
|
SubDirectory => { |
1117
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Canon::uuid', |
1118
|
|
|
|
|
|
|
Start => 16, |
1119
|
|
|
|
|
|
|
}, |
1120
|
|
|
|
|
|
|
}, |
1121
|
|
|
|
|
|
|
{ |
1122
|
|
|
|
|
|
|
Name => 'UUID-Unknown', |
1123
|
|
|
|
|
|
|
%unknownInfo, |
1124
|
|
|
|
|
|
|
}, |
1125
|
|
|
|
|
|
|
], |
1126
|
|
|
|
|
|
|
cmov => { |
1127
|
|
|
|
|
|
|
Name => 'CompressedMovie', |
1128
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::CMovie' }, |
1129
|
|
|
|
|
|
|
}, |
1130
|
|
|
|
|
|
|
htka => { # (written by HTC One M8 in slow-motion 1280x720 video - PH) |
1131
|
|
|
|
|
|
|
Name => 'HTCTrack', |
1132
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Track' }, |
1133
|
|
|
|
|
|
|
}, |
1134
|
|
|
|
|
|
|
'gps ' => { # GPS data written by Novatek cameras (parsed in QuickTimeStream.pl) |
1135
|
|
|
|
|
|
|
Name => 'GPSDataList', |
1136
|
|
|
|
|
|
|
Unknown => 1, |
1137
|
|
|
|
|
|
|
Binary => 1, |
1138
|
|
|
|
|
|
|
}, |
1139
|
|
|
|
|
|
|
meco => { #ISO14496-12:2015 |
1140
|
|
|
|
|
|
|
Name => 'OtherMeta', |
1141
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::OtherMeta' }, |
1142
|
|
|
|
|
|
|
}, |
1143
|
|
|
|
|
|
|
# prfl - Profile (ref 12) |
1144
|
|
|
|
|
|
|
# clip - clipping --> contains crgn (clip region) (ref 12) |
1145
|
|
|
|
|
|
|
# mvex - movie extends --> contains mehd (movie extends header), trex (track extends) (ref 14) |
1146
|
|
|
|
|
|
|
# ICAT - 4 bytes: "6350" (Nikon CoolPix S6900), "6500" (Panasonic FT7) |
1147
|
|
|
|
|
|
|
); |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
# (ref CFFMediaFormat-2_1.pdf) |
1150
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MovieFragment = ( |
1151
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
1152
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
1153
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1154
|
|
|
|
|
|
|
mfhd => { |
1155
|
|
|
|
|
|
|
Name => 'MovieFragmentHeader', |
1156
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MovieFragHdr' }, |
1157
|
|
|
|
|
|
|
}, |
1158
|
|
|
|
|
|
|
traf => { |
1159
|
|
|
|
|
|
|
Name => 'TrackFragment', |
1160
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackFragment' }, |
1161
|
|
|
|
|
|
|
}, |
1162
|
|
|
|
|
|
|
meta => { #ISO14496-12:2015 |
1163
|
|
|
|
|
|
|
Name => 'Meta', |
1164
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' }, |
1165
|
|
|
|
|
|
|
}, |
1166
|
|
|
|
|
|
|
); |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
# (ref CFFMediaFormat-2_1.pdf) |
1169
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MovieFragHdr = ( |
1170
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1171
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1172
|
|
|
|
|
|
|
FORMAT => 'int32u', |
1173
|
|
|
|
|
|
|
1 => 'MovieFragmentSequence', |
1174
|
|
|
|
|
|
|
); |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
# (ref CFFMediaFormat-2_1.pdf) |
1177
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::TrackFragment = ( |
1178
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
1179
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
1180
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1181
|
|
|
|
|
|
|
meta => { #ISO14496-12:2015 |
1182
|
|
|
|
|
|
|
Name => 'Meta', |
1183
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' }, |
1184
|
|
|
|
|
|
|
}, |
1185
|
|
|
|
|
|
|
# tfhd - track fragment header |
1186
|
|
|
|
|
|
|
# edts - edits --> contains elst (edit list) (ref PH) |
1187
|
|
|
|
|
|
|
# tfdt - track fragment base media decode time |
1188
|
|
|
|
|
|
|
# trik - trick play box |
1189
|
|
|
|
|
|
|
# trun - track fragment run box |
1190
|
|
|
|
|
|
|
# avcn - AVC NAL unit storage box |
1191
|
|
|
|
|
|
|
# secn - sample encryption box |
1192
|
|
|
|
|
|
|
# saio - sample auxiliary information offsets box |
1193
|
|
|
|
|
|
|
# sbgp - sample to group box |
1194
|
|
|
|
|
|
|
# sgpd - sample group description box |
1195
|
|
|
|
|
|
|
# sdtp - independent and disposable samples (ref 5) |
1196
|
|
|
|
|
|
|
# subs - sub-sample information (ref 5) |
1197
|
|
|
|
|
|
|
); |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
# movie header data block |
1200
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MovieHeader = ( |
1201
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1202
|
|
|
|
|
|
|
WRITE_PROC => \&Image::ExifTool::WriteBinaryData, |
1203
|
|
|
|
|
|
|
CHECK_PROC => \&Image::ExifTool::CheckBinaryData, |
1204
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
1205
|
|
|
|
|
|
|
FORMAT => 'int32u', |
1206
|
|
|
|
|
|
|
DATAMEMBER => [ 0, 1, 2, 3, 4 ], |
1207
|
|
|
|
|
|
|
0 => { |
1208
|
|
|
|
|
|
|
Name => 'MovieHeaderVersion', |
1209
|
|
|
|
|
|
|
Format => 'int8u', |
1210
|
|
|
|
|
|
|
RawConv => '$$self{MovieHeaderVersion} = $val', |
1211
|
|
|
|
|
|
|
}, |
1212
|
|
|
|
|
|
|
1 => { |
1213
|
|
|
|
|
|
|
Name => 'CreateDate', |
1214
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1215
|
|
|
|
|
|
|
%timeInfo, |
1216
|
|
|
|
|
|
|
RawConv => q{ |
1217
|
|
|
|
|
|
|
my $offset = (66 * 365 + 17) * 24 * 3600; |
1218
|
|
|
|
|
|
|
if ($val >= $offset or $$self{OPTIONS}{QuickTimeUTC}) { |
1219
|
|
|
|
|
|
|
$val -= $offset; |
1220
|
|
|
|
|
|
|
} elsif ($val and not $$self{IsWriting}) { |
1221
|
|
|
|
|
|
|
$self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1); |
1222
|
|
|
|
|
|
|
} |
1223
|
|
|
|
|
|
|
return $$self{CreateDate} = $val; |
1224
|
|
|
|
|
|
|
}, |
1225
|
|
|
|
|
|
|
# this is int64u if MovieHeaderVersion == 1 (ref 13) |
1226
|
|
|
|
|
|
|
Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4', |
1227
|
|
|
|
|
|
|
}, |
1228
|
|
|
|
|
|
|
2 => { |
1229
|
|
|
|
|
|
|
Name => 'ModifyDate', |
1230
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1231
|
|
|
|
|
|
|
%timeInfo, |
1232
|
|
|
|
|
|
|
# this is int64u if MovieHeaderVersion == 1 (ref 13) |
1233
|
|
|
|
|
|
|
Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4', |
1234
|
|
|
|
|
|
|
}, |
1235
|
|
|
|
|
|
|
3 => { |
1236
|
|
|
|
|
|
|
Name => 'TimeScale', |
1237
|
|
|
|
|
|
|
RawConv => '$$self{TimeScale} = $val', |
1238
|
|
|
|
|
|
|
}, |
1239
|
|
|
|
|
|
|
4 => { |
1240
|
|
|
|
|
|
|
Name => 'Duration', |
1241
|
|
|
|
|
|
|
%durationInfo, |
1242
|
|
|
|
|
|
|
# this is int64u if MovieHeaderVersion == 1 (ref 13) |
1243
|
|
|
|
|
|
|
Hook => '$$self{MovieHeaderVersion} and $format = "int64u", $varSize += 4', |
1244
|
|
|
|
|
|
|
}, |
1245
|
|
|
|
|
|
|
5 => { |
1246
|
|
|
|
|
|
|
Name => 'PreferredRate', |
1247
|
|
|
|
|
|
|
ValueConv => '$val / 0x10000', |
1248
|
|
|
|
|
|
|
}, |
1249
|
|
|
|
|
|
|
6 => { |
1250
|
|
|
|
|
|
|
Name => 'PreferredVolume', |
1251
|
|
|
|
|
|
|
Format => 'int16u', |
1252
|
|
|
|
|
|
|
ValueConv => '$val / 256', |
1253
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.2f%%", $val * 100)', |
1254
|
|
|
|
|
|
|
}, |
1255
|
|
|
|
|
|
|
9 => { |
1256
|
|
|
|
|
|
|
Name => 'MatrixStructure', |
1257
|
|
|
|
|
|
|
Format => 'fixed32s[9]', |
1258
|
|
|
|
|
|
|
# (the right column is fixed 2.30 instead of 16.16) |
1259
|
|
|
|
|
|
|
ValueConv => q{ |
1260
|
|
|
|
|
|
|
my @a = split ' ',$val; |
1261
|
|
|
|
|
|
|
$_ /= 0x4000 foreach @a[2,5,8]; |
1262
|
|
|
|
|
|
|
return "@a"; |
1263
|
|
|
|
|
|
|
}, |
1264
|
|
|
|
|
|
|
}, |
1265
|
|
|
|
|
|
|
18 => { Name => 'PreviewTime', %durationInfo }, |
1266
|
|
|
|
|
|
|
19 => { Name => 'PreviewDuration', %durationInfo }, |
1267
|
|
|
|
|
|
|
20 => { Name => 'PosterTime', %durationInfo }, |
1268
|
|
|
|
|
|
|
21 => { Name => 'SelectionTime', %durationInfo }, |
1269
|
|
|
|
|
|
|
22 => { Name => 'SelectionDuration',%durationInfo }, |
1270
|
|
|
|
|
|
|
23 => { Name => 'CurrentTime', %durationInfo }, |
1271
|
|
|
|
|
|
|
24 => 'NextTrackID', |
1272
|
|
|
|
|
|
|
); |
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
# track atoms |
1275
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Track = ( |
1276
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
1277
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
1278
|
|
|
|
|
|
|
GROUPS => { 1 => 'Track#', 2 => 'Video' }, |
1279
|
|
|
|
|
|
|
tkhd => { |
1280
|
|
|
|
|
|
|
Name => 'TrackHeader', |
1281
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackHeader' }, |
1282
|
|
|
|
|
|
|
}, |
1283
|
|
|
|
|
|
|
udta => { |
1284
|
|
|
|
|
|
|
Name => 'UserData', |
1285
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::UserData' }, |
1286
|
|
|
|
|
|
|
}, |
1287
|
|
|
|
|
|
|
mdia => { #MP4 |
1288
|
|
|
|
|
|
|
Name => 'Media', |
1289
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Media' }, |
1290
|
|
|
|
|
|
|
}, |
1291
|
|
|
|
|
|
|
meta => { #PH (MOV) |
1292
|
|
|
|
|
|
|
Name => 'Meta', |
1293
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' }, |
1294
|
|
|
|
|
|
|
}, |
1295
|
|
|
|
|
|
|
tref => { |
1296
|
|
|
|
|
|
|
Name => 'TrackRef', |
1297
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackRef' }, |
1298
|
|
|
|
|
|
|
}, |
1299
|
|
|
|
|
|
|
tapt => { |
1300
|
|
|
|
|
|
|
Name => 'TrackAperture', |
1301
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackAperture' }, |
1302
|
|
|
|
|
|
|
}, |
1303
|
|
|
|
|
|
|
uuid => [ |
1304
|
|
|
|
|
|
|
{ #11 (MP4 files) (also found in QuickTime::Movie) |
1305
|
|
|
|
|
|
|
Name => 'UUID-USMT', |
1306
|
|
|
|
|
|
|
Condition => '$$valPt=~/^USMT!\xd2\x4f\xce\xbb\x88\x69\x5c\xfa\xc9\xc7\x40/', |
1307
|
|
|
|
|
|
|
SubDirectory => { |
1308
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::UserMedia', |
1309
|
|
|
|
|
|
|
Start => 16, |
1310
|
|
|
|
|
|
|
}, |
1311
|
|
|
|
|
|
|
}, |
1312
|
|
|
|
|
|
|
{ #https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md |
1313
|
|
|
|
|
|
|
Name => 'SphericalVideoXML', |
1314
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\xff\xcc\x82\x63\xf8\x55\x4a\x93\x88\x14\x58\x7a\x02\x52\x1f\xdd/', |
1315
|
|
|
|
|
|
|
WriteGroup => 'GSpherical', # write only GSpherical XMP tags here |
1316
|
|
|
|
|
|
|
HandlerType => 'vide', # only write in video tracks |
1317
|
|
|
|
|
|
|
SubDirectory => { |
1318
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::XMP::Main', |
1319
|
|
|
|
|
|
|
Start => 16, |
1320
|
|
|
|
|
|
|
WriteProc => 'Image::ExifTool::XMP::WriteGSpherical', |
1321
|
|
|
|
|
|
|
}, |
1322
|
|
|
|
|
|
|
}, |
1323
|
|
|
|
|
|
|
{ |
1324
|
|
|
|
|
|
|
Name => 'UUID-Unknown', |
1325
|
|
|
|
|
|
|
%unknownInfo, |
1326
|
|
|
|
|
|
|
}, |
1327
|
|
|
|
|
|
|
], |
1328
|
|
|
|
|
|
|
meco => { #ISO14492-12:2015 pg 83 |
1329
|
|
|
|
|
|
|
Name => 'OtherMeta', |
1330
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::OtherMeta' }, |
1331
|
|
|
|
|
|
|
}, |
1332
|
|
|
|
|
|
|
# edts - edits --> contains elst (edit list) |
1333
|
|
|
|
|
|
|
# clip - clipping --> contains crgn (clip region) |
1334
|
|
|
|
|
|
|
# matt - track matt --> contains kmat (compressed matt) |
1335
|
|
|
|
|
|
|
# load - track loading settings |
1336
|
|
|
|
|
|
|
# imap - track input map --> contains ' in' --> contains ' ty', obid |
1337
|
|
|
|
|
|
|
# prfl - Profile (ref 12) |
1338
|
|
|
|
|
|
|
); |
1339
|
|
|
|
|
|
|
|
1340
|
|
|
|
|
|
|
# track header data block |
1341
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::TrackHeader = ( |
1342
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
1343
|
|
|
|
|
|
|
WRITE_PROC => \&Image::ExifTool::WriteBinaryData, |
1344
|
|
|
|
|
|
|
CHECK_PROC => \&Image::ExifTool::CheckBinaryData, |
1345
|
|
|
|
|
|
|
GROUPS => { 1 => 'Track#', 2 => 'Video' }, |
1346
|
|
|
|
|
|
|
FORMAT => 'int32u', |
1347
|
|
|
|
|
|
|
DATAMEMBER => [ 0, 1, 2, 5, 7 ], |
1348
|
|
|
|
|
|
|
0 => { |
1349
|
|
|
|
|
|
|
Name => 'TrackHeaderVersion', |
1350
|
|
|
|
|
|
|
Format => 'int8u', |
1351
|
|
|
|
|
|
|
Priority => 0, |
1352
|
|
|
|
|
|
|
RawConv => '$$self{TrackHeaderVersion} = $val', |
1353
|
|
|
|
|
|
|
}, |
1354
|
|
|
|
|
|
|
1 => { |
1355
|
|
|
|
|
|
|
Name => 'TrackCreateDate', |
1356
|
|
|
|
|
|
|
Priority => 0, |
1357
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1358
|
|
|
|
|
|
|
%timeInfo, |
1359
|
|
|
|
|
|
|
# this is int64u if TrackHeaderVersion == 1 (ref 13) |
1360
|
|
|
|
|
|
|
Hook => '$$self{TrackHeaderVersion} and $format = "int64u", $varSize += 4', |
1361
|
|
|
|
|
|
|
}, |
1362
|
|
|
|
|
|
|
2 => { |
1363
|
|
|
|
|
|
|
Name => 'TrackModifyDate', |
1364
|
|
|
|
|
|
|
Priority => 0, |
1365
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1366
|
|
|
|
|
|
|
%timeInfo, |
1367
|
|
|
|
|
|
|
# this is int64u if TrackHeaderVersion == 1 (ref 13) |
1368
|
|
|
|
|
|
|
Hook => '$$self{TrackHeaderVersion} and $format = "int64u", $varSize += 4', |
1369
|
|
|
|
|
|
|
}, |
1370
|
|
|
|
|
|
|
3 => { |
1371
|
|
|
|
|
|
|
Name => 'TrackID', |
1372
|
|
|
|
|
|
|
Priority => 0, |
1373
|
|
|
|
|
|
|
}, |
1374
|
|
|
|
|
|
|
5 => { |
1375
|
|
|
|
|
|
|
Name => 'TrackDuration', |
1376
|
|
|
|
|
|
|
Priority => 0, |
1377
|
|
|
|
|
|
|
%durationInfo, |
1378
|
|
|
|
|
|
|
# this is int64u if TrackHeaderVersion == 1 (ref 13) |
1379
|
|
|
|
|
|
|
Hook => '$$self{TrackHeaderVersion} and $format = "int64u", $varSize += 4', |
1380
|
|
|
|
|
|
|
}, |
1381
|
|
|
|
|
|
|
7 => { # (used only for writing MatrixStructure) |
1382
|
|
|
|
|
|
|
Name => 'ImageSizeLookahead', |
1383
|
|
|
|
|
|
|
Hidden => 1, |
1384
|
|
|
|
|
|
|
Format => 'int32u[14]', |
1385
|
|
|
|
|
|
|
RawConv => '$$self{ImageSizeLookahead} = $val; undef', |
1386
|
|
|
|
|
|
|
}, |
1387
|
|
|
|
|
|
|
8 => { |
1388
|
|
|
|
|
|
|
Name => 'TrackLayer', |
1389
|
|
|
|
|
|
|
Format => 'int16u', |
1390
|
|
|
|
|
|
|
Priority => 0, |
1391
|
|
|
|
|
|
|
}, |
1392
|
|
|
|
|
|
|
9 => { |
1393
|
|
|
|
|
|
|
Name => 'TrackVolume', |
1394
|
|
|
|
|
|
|
Format => 'int16u', |
1395
|
|
|
|
|
|
|
Priority => 0, |
1396
|
|
|
|
|
|
|
ValueConv => '$val / 256', |
1397
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.2f%%", $val * 100)', |
1398
|
|
|
|
|
|
|
}, |
1399
|
|
|
|
|
|
|
10 => { |
1400
|
|
|
|
|
|
|
Name => 'MatrixStructure', |
1401
|
|
|
|
|
|
|
Format => 'fixed32s[9]', |
1402
|
|
|
|
|
|
|
Notes => 'writable for the video track via the Composite Rotation tag', |
1403
|
|
|
|
|
|
|
Writable => 1, |
1404
|
|
|
|
|
|
|
Protected => 1, |
1405
|
|
|
|
|
|
|
Permanent => 1, |
1406
|
|
|
|
|
|
|
# only set rotation if image size is non-zero |
1407
|
|
|
|
|
|
|
RawConvInv => \&GetMatrixStructure, |
1408
|
|
|
|
|
|
|
# (the right column is fixed 2.30 instead of 16.16) |
1409
|
|
|
|
|
|
|
ValueConv => q{ |
1410
|
|
|
|
|
|
|
my @a = split ' ',$val; |
1411
|
|
|
|
|
|
|
$_ /= 0x4000 foreach @a[2,5,8]; |
1412
|
|
|
|
|
|
|
return "@a"; |
1413
|
|
|
|
|
|
|
}, |
1414
|
|
|
|
|
|
|
ValueConvInv => q{ |
1415
|
|
|
|
|
|
|
my @a = split ' ',$val; |
1416
|
|
|
|
|
|
|
$_ *= 0x4000 foreach @a[2,5,8]; |
1417
|
|
|
|
|
|
|
return "@a"; |
1418
|
|
|
|
|
|
|
}, |
1419
|
|
|
|
|
|
|
}, |
1420
|
|
|
|
|
|
|
19 => { |
1421
|
|
|
|
|
|
|
Name => 'ImageWidth', |
1422
|
|
|
|
|
|
|
Priority => 0, |
1423
|
|
|
|
|
|
|
RawConv => \&FixWrongFormat, |
1424
|
|
|
|
|
|
|
}, |
1425
|
|
|
|
|
|
|
20 => { |
1426
|
|
|
|
|
|
|
Name => 'ImageHeight', |
1427
|
|
|
|
|
|
|
Priority => 0, |
1428
|
|
|
|
|
|
|
RawConv => \&FixWrongFormat, |
1429
|
|
|
|
|
|
|
}, |
1430
|
|
|
|
|
|
|
); |
1431
|
|
|
|
|
|
|
|
1432
|
|
|
|
|
|
|
# user data atoms |
1433
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::UserData = ( |
1434
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
1435
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
1436
|
|
|
|
|
|
|
CHECK_PROC => \&CheckQTValue, |
1437
|
|
|
|
|
|
|
GROUPS => { 1 => 'UserData', 2 => 'Video' }, |
1438
|
|
|
|
|
|
|
WRITABLE => 1, |
1439
|
|
|
|
|
|
|
PREFERRED => 1, # (preferred over Keys tags when writing) |
1440
|
|
|
|
|
|
|
FORMAT => 'string', |
1441
|
|
|
|
|
|
|
WRITE_GROUP => 'UserData', |
1442
|
|
|
|
|
|
|
LANG_INFO => \&GetLangInfo, |
1443
|
|
|
|
|
|
|
NOTES => q{ |
1444
|
|
|
|
|
|
|
Tag ID's beginning with the copyright symbol (hex 0xa9) are multi-language |
1445
|
|
|
|
|
|
|
text. Alternate language tags are accessed by adding a dash followed by a |
1446
|
|
|
|
|
|
|
3-character ISO 639-2 language code to the tag name. ExifTool will extract |
1447
|
|
|
|
|
|
|
any multi-language user data tags found, even if they aren't in this table. |
1448
|
|
|
|
|
|
|
Note when creating new tags, |
1449
|
|
|
|
|
|
|
L tags are |
1450
|
|
|
|
|
|
|
preferred over these, so to create the tag when a same-named ItemList tag |
1451
|
|
|
|
|
|
|
exists, either "UserData" must be specified (eg. C<-UserData:Artist=Monet> |
1452
|
|
|
|
|
|
|
on the command line), or the PREFERRED level must be changed via |
1453
|
|
|
|
|
|
|
L. |
1454
|
|
|
|
|
|
|
}, |
1455
|
|
|
|
|
|
|
"\xa9cpy" => { Name => 'Copyright', Groups => { 2 => 'Author' } }, |
1456
|
|
|
|
|
|
|
"\xa9day" => { |
1457
|
|
|
|
|
|
|
Name => 'ContentCreateDate', |
1458
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1459
|
|
|
|
|
|
|
Shift => 'Time', |
1460
|
|
|
|
|
|
|
# handle values in the form "2010-02-12T13:27:14-0800" (written by Apple iPhone) |
1461
|
|
|
|
|
|
|
ValueConv => q{ |
1462
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
1463
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::ConvertXMPDate($val); |
1464
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary |
1465
|
|
|
|
|
|
|
return $val; |
1466
|
|
|
|
|
|
|
}, |
1467
|
|
|
|
|
|
|
ValueConvInv => q{ |
1468
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
1469
|
|
|
|
|
|
|
my $tmp = Image::ExifTool::XMP::FormatXMPDate($val); |
1470
|
|
|
|
|
|
|
($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon |
1471
|
|
|
|
|
|
|
return $val; |
1472
|
|
|
|
|
|
|
}, |
1473
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
1474
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) |
1475
|
|
|
|
|
|
|
}, |
1476
|
|
|
|
|
|
|
"\xa9ART" => 'Artist', #PH (iTunes 8.0.2) |
1477
|
|
|
|
|
|
|
"\xa9alb" => 'Album', #PH (iTunes 8.0.2) |
1478
|
|
|
|
|
|
|
"\xa9arg" => 'Arranger', #12 |
1479
|
|
|
|
|
|
|
"\xa9ark" => 'ArrangerKeywords', #12 |
1480
|
|
|
|
|
|
|
"\xa9cmt" => 'Comment', #PH (iTunes 8.0.2) |
1481
|
|
|
|
|
|
|
"\xa9cok" => 'ComposerKeywords', #12 |
1482
|
|
|
|
|
|
|
"\xa9com" => 'Composer', #12 |
1483
|
|
|
|
|
|
|
"\xa9dir" => 'Director', #12 |
1484
|
|
|
|
|
|
|
"\xa9ed1" => 'Edit1', |
1485
|
|
|
|
|
|
|
"\xa9ed2" => 'Edit2', |
1486
|
|
|
|
|
|
|
"\xa9ed3" => 'Edit3', |
1487
|
|
|
|
|
|
|
"\xa9ed4" => 'Edit4', |
1488
|
|
|
|
|
|
|
"\xa9ed5" => 'Edit5', |
1489
|
|
|
|
|
|
|
"\xa9ed6" => 'Edit6', |
1490
|
|
|
|
|
|
|
"\xa9ed7" => 'Edit7', |
1491
|
|
|
|
|
|
|
"\xa9ed8" => 'Edit8', |
1492
|
|
|
|
|
|
|
"\xa9ed9" => 'Edit9', |
1493
|
|
|
|
|
|
|
"\xa9fmt" => 'Format', |
1494
|
|
|
|
|
|
|
"\xa9gen" => 'Genre', #PH (iTunes 8.0.2) |
1495
|
|
|
|
|
|
|
"\xa9grp" => 'Grouping', #PH (NC) |
1496
|
|
|
|
|
|
|
"\xa9inf" => 'Information', |
1497
|
|
|
|
|
|
|
"\xa9isr" => 'ISRCCode', #12 |
1498
|
|
|
|
|
|
|
"\xa9lab" => 'RecordLabelName', #12 |
1499
|
|
|
|
|
|
|
"\xa9lal" => 'RecordLabelURL', #12 |
1500
|
|
|
|
|
|
|
"\xa9lyr" => 'Lyrics', #PH (NC) |
1501
|
|
|
|
|
|
|
"\xa9mak" => 'Make', #12 |
1502
|
|
|
|
|
|
|
"\xa9mal" => 'MakerURL', #12 |
1503
|
|
|
|
|
|
|
"\xa9mod" => 'Model', #PH |
1504
|
|
|
|
|
|
|
"\xa9nam" => 'Title', #12 |
1505
|
|
|
|
|
|
|
"\xa9pdk" => 'ProducerKeywords', #12 |
1506
|
|
|
|
|
|
|
"\xa9phg" => 'RecordingCopyright', #12 |
1507
|
|
|
|
|
|
|
"\xa9prd" => 'Producer', |
1508
|
|
|
|
|
|
|
"\xa9prf" => 'Performers', |
1509
|
|
|
|
|
|
|
"\xa9prk" => 'PerformerKeywords', #12 |
1510
|
|
|
|
|
|
|
"\xa9prl" => 'PerformerURL', |
1511
|
|
|
|
|
|
|
"\xa9req" => 'Requirements', |
1512
|
|
|
|
|
|
|
"\xa9snk" => 'SubtitleKeywords', #12 |
1513
|
|
|
|
|
|
|
"\xa9snm" => 'Subtitle', #12 |
1514
|
|
|
|
|
|
|
"\xa9src" => 'SourceCredits', #12 |
1515
|
|
|
|
|
|
|
"\xa9swf" => 'SongWriter', #12 |
1516
|
|
|
|
|
|
|
"\xa9swk" => 'SongWriterKeywords', #12 |
1517
|
|
|
|
|
|
|
"\xa9swr" => 'SoftwareVersion', #12 |
1518
|
|
|
|
|
|
|
"\xa9too" => 'Encoder', #PH (NC) |
1519
|
|
|
|
|
|
|
"\xa9trk" => 'Track', #PH (NC) |
1520
|
|
|
|
|
|
|
"\xa9wrt" => { Name => 'Composer', Avoid => 1 }, # ("\xa9com" is preferred in UserData) |
1521
|
|
|
|
|
|
|
"\xa9xyz" => { #PH (iPhone 3GS) |
1522
|
|
|
|
|
|
|
Name => 'GPSCoordinates', |
1523
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
1524
|
|
|
|
|
|
|
ValueConv => \&ConvertISO6709, |
1525
|
|
|
|
|
|
|
ValueConvInv => \&ConvInvISO6709, |
1526
|
|
|
|
|
|
|
PrintConv => \&PrintGPSCoordinates, |
1527
|
|
|
|
|
|
|
PrintConvInv => \&PrintInvGPSCoordinates, |
1528
|
|
|
|
|
|
|
}, |
1529
|
|
|
|
|
|
|
# \xa9 tags written by DJI Phantom 3: (ref PH) |
1530
|
|
|
|
|
|
|
"\xa9xsp" => 'SpeedX', #PH (guess) |
1531
|
|
|
|
|
|
|
"\xa9ysp" => 'SpeedY', #PH (guess) |
1532
|
|
|
|
|
|
|
"\xa9zsp" => 'SpeedZ', #PH (guess) |
1533
|
|
|
|
|
|
|
"\xa9fpt" => 'Pitch', #PH |
1534
|
|
|
|
|
|
|
"\xa9fyw" => 'Yaw', #PH |
1535
|
|
|
|
|
|
|
"\xa9frl" => 'Roll', #PH |
1536
|
|
|
|
|
|
|
"\xa9gpt" => 'CameraPitch', #PH |
1537
|
|
|
|
|
|
|
"\xa9gyw" => 'CameraYaw', #PH |
1538
|
|
|
|
|
|
|
"\xa9grl" => 'CameraRoll', #PH |
1539
|
|
|
|
|
|
|
"\xa9enc" => 'EncoderID', #PH (forum9271) |
1540
|
|
|
|
|
|
|
# and the following entries don't have the proper 4-byte header for \xa9 tags: |
1541
|
|
|
|
|
|
|
"\xa9dji" => { Name => 'UserData_dji', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 }, |
1542
|
|
|
|
|
|
|
"\xa9res" => { Name => 'UserData_res', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 }, |
1543
|
|
|
|
|
|
|
"\xa9uid" => { Name => 'UserData_uid', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 }, |
1544
|
|
|
|
|
|
|
"\xa9mdl" => { |
1545
|
|
|
|
|
|
|
Name => 'Model', |
1546
|
|
|
|
|
|
|
Notes => 'non-standard-format DJI tag', |
1547
|
|
|
|
|
|
|
Format => 'string', |
1548
|
|
|
|
|
|
|
Avoid => 1, |
1549
|
|
|
|
|
|
|
}, |
1550
|
|
|
|
|
|
|
# end DJI tags |
1551
|
|
|
|
|
|
|
name => 'Name', |
1552
|
|
|
|
|
|
|
WLOC => { |
1553
|
|
|
|
|
|
|
Name => 'WindowLocation', |
1554
|
|
|
|
|
|
|
Format => 'int16u', |
1555
|
|
|
|
|
|
|
}, |
1556
|
|
|
|
|
|
|
LOOP => { |
1557
|
|
|
|
|
|
|
Name => 'LoopStyle', |
1558
|
|
|
|
|
|
|
Format => 'int32u', |
1559
|
|
|
|
|
|
|
PrintConv => { |
1560
|
|
|
|
|
|
|
1 => 'Normal', |
1561
|
|
|
|
|
|
|
2 => 'Palindromic', |
1562
|
|
|
|
|
|
|
}, |
1563
|
|
|
|
|
|
|
}, |
1564
|
|
|
|
|
|
|
SelO => { |
1565
|
|
|
|
|
|
|
Name => 'PlaySelection', |
1566
|
|
|
|
|
|
|
Format => 'int8u', |
1567
|
|
|
|
|
|
|
}, |
1568
|
|
|
|
|
|
|
AllF => { |
1569
|
|
|
|
|
|
|
Name => 'PlayAllFrames', |
1570
|
|
|
|
|
|
|
Format => 'int8u', |
1571
|
|
|
|
|
|
|
}, |
1572
|
|
|
|
|
|
|
meta => { |
1573
|
|
|
|
|
|
|
Name => 'Meta', |
1574
|
|
|
|
|
|
|
SubDirectory => { |
1575
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Meta', |
1576
|
|
|
|
|
|
|
Start => 4, # must skip 4-byte version number header |
1577
|
|
|
|
|
|
|
}, |
1578
|
|
|
|
|
|
|
}, |
1579
|
|
|
|
|
|
|
'ptv '=> { |
1580
|
|
|
|
|
|
|
Name => 'PrintToVideo', |
1581
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Video' }, |
1582
|
|
|
|
|
|
|
}, |
1583
|
|
|
|
|
|
|
hnti => { |
1584
|
|
|
|
|
|
|
Name => 'HintInfo', |
1585
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintInfo' }, |
1586
|
|
|
|
|
|
|
}, |
1587
|
|
|
|
|
|
|
hinf => { |
1588
|
|
|
|
|
|
|
Name => 'HintTrackInfo', |
1589
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintTrackInfo' }, |
1590
|
|
|
|
|
|
|
}, |
1591
|
|
|
|
|
|
|
hinv => 'HintVersion', #PH (guess) |
1592
|
|
|
|
|
|
|
XMP_ => { #PH (Adobe CS3 Bridge) |
1593
|
|
|
|
|
|
|
Name => 'XMP', |
1594
|
|
|
|
|
|
|
WriteGroup => 'XMP', # (write main tags here) |
1595
|
|
|
|
|
|
|
# *** this is where ExifTool writes XMP in MOV videos (as per XMP spec) *** |
1596
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, |
1597
|
|
|
|
|
|
|
}, |
1598
|
|
|
|
|
|
|
# the following are 3gp tags, references: |
1599
|
|
|
|
|
|
|
# http://atomicparsley.sourceforge.net |
1600
|
|
|
|
|
|
|
# http://www.3gpp.org/ftp/tsg_sa/WG4_CODEC/TSGS4_25/Docs/ |
1601
|
|
|
|
|
|
|
# (note that all %langText3gp tags are Avoid => 1) |
1602
|
|
|
|
|
|
|
cprt => { Name => 'Copyright', %langText3gp, Groups => { 2 => 'Author' } }, |
1603
|
|
|
|
|
|
|
auth => { Name => 'Author', %langText3gp, Groups => { 2 => 'Author' } }, |
1604
|
|
|
|
|
|
|
titl => { Name => 'Title', %langText3gp }, |
1605
|
|
|
|
|
|
|
dscp => { Name => 'Description',%langText3gp }, |
1606
|
|
|
|
|
|
|
perf => { Name => 'Performer', %langText3gp }, |
1607
|
|
|
|
|
|
|
gnre => { Name => 'Genre', %langText3gp }, |
1608
|
|
|
|
|
|
|
albm => { Name => 'Album', %langText3gp }, |
1609
|
|
|
|
|
|
|
coll => { Name => 'CollectionName', %langText3gp }, #17 |
1610
|
|
|
|
|
|
|
rtng => { |
1611
|
|
|
|
|
|
|
Name => 'Rating', |
1612
|
|
|
|
|
|
|
Writable => 'undef', |
1613
|
|
|
|
|
|
|
Avoid => 1, |
1614
|
|
|
|
|
|
|
# (4-byte flags, 4-char entity, 4-char criteria, 2-byte lang, string) |
1615
|
|
|
|
|
|
|
IText => 14, # (14 bytes before string) |
1616
|
|
|
|
|
|
|
Notes => 'string in the form "Entity=XXXX Criteria=XXXX XXXXX", used in 3gp videos', |
1617
|
|
|
|
|
|
|
ValueConv => '$val=~s/^(.{4})(.{4})/Entity=$1 Criteria=$2 /i; $val', |
1618
|
|
|
|
|
|
|
ValueConvInv => '$val=~s/Entity=(.{4}) Criteria=(.{4}) ?/$1$2/i; $val', |
1619
|
|
|
|
|
|
|
}, |
1620
|
|
|
|
|
|
|
clsf => { |
1621
|
|
|
|
|
|
|
Name => 'Classification', |
1622
|
|
|
|
|
|
|
Writable => 'undef', |
1623
|
|
|
|
|
|
|
Avoid => 1, |
1624
|
|
|
|
|
|
|
# (4-byte flags, 4-char entity, 2-byte index, 2-byte lang, string) |
1625
|
|
|
|
|
|
|
IText => 12, |
1626
|
|
|
|
|
|
|
Notes => 'string in the form "Entity=XXXX Index=### XXXXX", used in 3gp videos', |
1627
|
|
|
|
|
|
|
ValueConv => '$val=~s/^(.{4})(.{2})/"Entity=$1 Index=".unpack("n",$2)." "/ie; $val', |
1628
|
|
|
|
|
|
|
ValueConvInv => '$val=~s/Entity=(.{4}) Index=(\d+) ?/$1.pack("n",$2)/ie; $val', |
1629
|
|
|
|
|
|
|
}, |
1630
|
|
|
|
|
|
|
kywd => { |
1631
|
|
|
|
|
|
|
Name => 'Keywords', |
1632
|
|
|
|
|
|
|
# (4 byte flags, 2-byte lang, 1-byte count, count x pascal strings, ref 17) |
1633
|
|
|
|
|
|
|
# (but I have also seen a simple string written by iPhone, so don't make writable yet) |
1634
|
|
|
|
|
|
|
Notes => "not writable because Apple doesn't follow the 3gp specification", |
1635
|
|
|
|
|
|
|
RawConv => q{ |
1636
|
|
|
|
|
|
|
my $sep = $self->Options('ListSep'); |
1637
|
|
|
|
|
|
|
return join($sep, split /\0+/, $val) unless $val =~ /^\0/; # (iPhone) |
1638
|
|
|
|
|
|
|
return '' unless length $val >= 7; |
1639
|
|
|
|
|
|
|
my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4)); |
1640
|
|
|
|
|
|
|
$lang = $lang ? "($lang) " : ''; |
1641
|
|
|
|
|
|
|
my $num = Get8u(\$val, 6); |
1642
|
|
|
|
|
|
|
my ($i, @vals); |
1643
|
|
|
|
|
|
|
my $pos = 7; |
1644
|
|
|
|
|
|
|
for ($i=0; $i<$num; ++$i) { |
1645
|
|
|
|
|
|
|
last if $pos >= length $val; |
1646
|
|
|
|
|
|
|
my $len = Get8u(\$val, $pos++); |
1647
|
|
|
|
|
|
|
last if $pos + $len > length $val; |
1648
|
|
|
|
|
|
|
my $v = substr($val, $pos, $len); |
1649
|
|
|
|
|
|
|
$v = $self->Decode($v, 'UCS2') if $v =~ /^\xfe\xff/; |
1650
|
|
|
|
|
|
|
push @vals, $v; |
1651
|
|
|
|
|
|
|
$pos += $len; |
1652
|
|
|
|
|
|
|
} |
1653
|
|
|
|
|
|
|
return $lang . join($sep, @vals); |
1654
|
|
|
|
|
|
|
}, |
1655
|
|
|
|
|
|
|
}, |
1656
|
|
|
|
|
|
|
loci => { |
1657
|
|
|
|
|
|
|
Name => 'LocationInformation', |
1658
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
1659
|
|
|
|
|
|
|
Writable => 'undef', |
1660
|
|
|
|
|
|
|
IText => 6, |
1661
|
|
|
|
|
|
|
Avoid => 1, |
1662
|
|
|
|
|
|
|
NoDecode => 1, # (we'll decode the data ourself) |
1663
|
|
|
|
|
|
|
Notes => q{ |
1664
|
|
|
|
|
|
|
string in the form "XXXXX Role=XXX Lat=XXX Lon=XXX Alt=XXX Body=XXX |
1665
|
|
|
|
|
|
|
Notes=XXX", used in 3gp videos |
1666
|
|
|
|
|
|
|
}, |
1667
|
|
|
|
|
|
|
# (4-byte flags, 2-byte lang, location string, 1-byte role, 4-byte fixed longitude, |
1668
|
|
|
|
|
|
|
# 4-byte fixed latitude, 4-byte fixed altitude, body string, notes string) |
1669
|
|
|
|
|
|
|
RawConv => q{ |
1670
|
|
|
|
|
|
|
my $str; |
1671
|
|
|
|
|
|
|
if ($val =~ /^\xfe\xff/) { |
1672
|
|
|
|
|
|
|
$val =~ s/^(\xfe\xff(.{2})*?)\0\0//s or return ''; |
1673
|
|
|
|
|
|
|
$str = $self->Decode($1, 'UCS2'); |
1674
|
|
|
|
|
|
|
} else { |
1675
|
|
|
|
|
|
|
$val =~ s/^(.*?)\0//s or return ''; |
1676
|
|
|
|
|
|
|
$str = $self->Decode($1, 'UTF8'); |
1677
|
|
|
|
|
|
|
} |
1678
|
|
|
|
|
|
|
$str = '(none)' unless length $str; |
1679
|
|
|
|
|
|
|
return '' if length $val < 13; |
1680
|
|
|
|
|
|
|
my $role = Get8u(\$val, 0); |
1681
|
|
|
|
|
|
|
my $lon = GetFixed32s(\$val, 1); |
1682
|
|
|
|
|
|
|
my $lat = GetFixed32s(\$val, 5); |
1683
|
|
|
|
|
|
|
my $alt = GetFixed32s(\$val, 9); |
1684
|
|
|
|
|
|
|
my $roleStr = {0=>'shooting',1=>'real',2=>'fictional',3=>'reserved'}->{$role}; |
1685
|
|
|
|
|
|
|
$str .= ' Role=' . ($roleStr || "unknown($role)"); |
1686
|
|
|
|
|
|
|
$str .= sprintf(' Lat=%.5f Lon=%.5f Alt=%.2f', $lat, $lon, $alt); |
1687
|
|
|
|
|
|
|
$val = substr($val, 13); |
1688
|
|
|
|
|
|
|
if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) { |
1689
|
|
|
|
|
|
|
$str .= ' Body=' . $self->Decode($1, 'UCS2'); |
1690
|
|
|
|
|
|
|
} elsif ($val =~ s/^(.*?)\0//s) { |
1691
|
|
|
|
|
|
|
$str .= ' Body=' . $self->Decode($1, 'UTF8'); |
1692
|
|
|
|
|
|
|
} |
1693
|
|
|
|
|
|
|
if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) { |
1694
|
|
|
|
|
|
|
$str .= ' Notes=' . $self->Decode($1, 'UCS2'); |
1695
|
|
|
|
|
|
|
} elsif ($val =~ s/^(.*?)\0//s) { |
1696
|
|
|
|
|
|
|
$str .= ' Notes=' . $self->Decode($1, 'UTF8'); |
1697
|
|
|
|
|
|
|
} |
1698
|
|
|
|
|
|
|
return $str; |
1699
|
|
|
|
|
|
|
}, |
1700
|
|
|
|
|
|
|
RawConvInv => q{ |
1701
|
|
|
|
|
|
|
my ($role, $lat, $lon, $alt, $body, $note); |
1702
|
|
|
|
|
|
|
$lat = $1 if $val =~ s/ Lat=([-+]?[.\d]+)//i; |
1703
|
|
|
|
|
|
|
$lon = $1 if $val =~ s/ Lon=([-+]?[.\d]+)//i; |
1704
|
|
|
|
|
|
|
$alt = $1 if $val =~ s/ Alt=([-+]?[.\d]+)//i; |
1705
|
|
|
|
|
|
|
$note = $val =~ s/ Notes=(.*)//i ? $1 : ''; |
1706
|
|
|
|
|
|
|
$body = $val =~ s/ Body=(.*)//i ? $1 : ''; |
1707
|
|
|
|
|
|
|
$role = $val =~ s/ Role=(.*)//i ? $1 : ''; |
1708
|
|
|
|
|
|
|
$val = '' if $val eq '(none)'; |
1709
|
|
|
|
|
|
|
$role = {shooting=>0,real=>1,fictional=>2}->{lc $role} || 0; |
1710
|
|
|
|
|
|
|
return $self->Encode($val, 'UTF8') . "\0" . Set8u($role) . |
1711
|
|
|
|
|
|
|
SetFixed32s(defined $lon ? $lon : 999) . |
1712
|
|
|
|
|
|
|
SetFixed32s(defined $lat ? $lat : 999) . |
1713
|
|
|
|
|
|
|
SetFixed32s(defined $alt ? $alt : 0) . |
1714
|
|
|
|
|
|
|
$self->Encode($body) . "\0" . |
1715
|
|
|
|
|
|
|
$self->Encode($note) . "\0"; |
1716
|
|
|
|
|
|
|
}, |
1717
|
|
|
|
|
|
|
}, |
1718
|
|
|
|
|
|
|
yrrc => { |
1719
|
|
|
|
|
|
|
Name => 'Year', |
1720
|
|
|
|
|
|
|
Writable => 'undef', |
1721
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1722
|
|
|
|
|
|
|
Avoid => 1, |
1723
|
|
|
|
|
|
|
Notes => 'used in 3gp videos', |
1724
|
|
|
|
|
|
|
ValueConv => 'length($val) >= 6 ? unpack("x4n",$val) : ""', |
1725
|
|
|
|
|
|
|
ValueConvInv => 'pack("Nn",0,$val)', |
1726
|
|
|
|
|
|
|
}, |
1727
|
|
|
|
|
|
|
urat => { #17 |
1728
|
|
|
|
|
|
|
Name => 'UserRating', |
1729
|
|
|
|
|
|
|
Writable => 'undef', |
1730
|
|
|
|
|
|
|
Notes => 'used in 3gp videos', |
1731
|
|
|
|
|
|
|
Avoid => 1, |
1732
|
|
|
|
|
|
|
ValueConv => q{ |
1733
|
|
|
|
|
|
|
return '' unless length $val >= 8; |
1734
|
|
|
|
|
|
|
unpack('x7C', $val); |
1735
|
|
|
|
|
|
|
}, |
1736
|
|
|
|
|
|
|
ValueConvInv => 'pack("N2",0,$val)', |
1737
|
|
|
|
|
|
|
}, |
1738
|
|
|
|
|
|
|
# tsel - TrackSelection (ref 17) |
1739
|
|
|
|
|
|
|
# Apple tags (ref 16[dead] -- see ref 25 instead) |
1740
|
|
|
|
|
|
|
angl => { Name => 'CameraAngle', Format => 'string' }, # (NC) |
1741
|
|
|
|
|
|
|
clfn => { Name => 'ClipFileName', Format => 'string' }, # (NC) |
1742
|
|
|
|
|
|
|
clid => { Name => 'ClipID', Format => 'string' }, # (NC) |
1743
|
|
|
|
|
|
|
cmid => { Name => 'CameraID', Format => 'string' }, # (NC) |
1744
|
|
|
|
|
|
|
cmnm => { # (NC) |
1745
|
|
|
|
|
|
|
Name => 'Model', |
1746
|
|
|
|
|
|
|
Description => 'Camera Model Name', |
1747
|
|
|
|
|
|
|
Avoid => 1, |
1748
|
|
|
|
|
|
|
Format => 'string', # (necessary to remove the trailing NULL) |
1749
|
|
|
|
|
|
|
}, |
1750
|
|
|
|
|
|
|
date => { |
1751
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
1752
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
1753
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
1754
|
|
|
|
|
|
|
Notes => q{ |
1755
|
|
|
|
|
|
|
Apple Photos has been reported to show a crazy date/time for some MP4 files |
1756
|
|
|
|
|
|
|
containing this tag, but perhaps only if it is missing a time zone |
1757
|
|
|
|
|
|
|
}, #forum10690/11125 |
1758
|
|
|
|
|
|
|
Shift => 'Time', |
1759
|
|
|
|
|
|
|
ValueConv => q{ |
1760
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
1761
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::ConvertXMPDate($val); |
1762
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary |
1763
|
|
|
|
|
|
|
return $val; |
1764
|
|
|
|
|
|
|
}, |
1765
|
|
|
|
|
|
|
ValueConvInv => q{ |
1766
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
1767
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::FormatXMPDate($val); |
1768
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon |
1769
|
|
|
|
|
|
|
return $val; |
1770
|
|
|
|
|
|
|
}, |
1771
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
1772
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) |
1773
|
|
|
|
|
|
|
}, |
1774
|
|
|
|
|
|
|
manu => { # (SX280) |
1775
|
|
|
|
|
|
|
Name => 'Make', |
1776
|
|
|
|
|
|
|
Avoid => 1, |
1777
|
|
|
|
|
|
|
# (with Canon there are 6 unknown bytes before the model: "\0\0\0\0\x15\xc7") |
1778
|
|
|
|
|
|
|
RawConv => '$val=~s/^\0{4}..//s; $val=~s/\0.*//; $val', |
1779
|
|
|
|
|
|
|
}, |
1780
|
|
|
|
|
|
|
modl => { # (Samsung GT-S8530, Canon SX280) |
1781
|
|
|
|
|
|
|
Name => 'Model', |
1782
|
|
|
|
|
|
|
Description => 'Camera Model Name', |
1783
|
|
|
|
|
|
|
Avoid => 1, |
1784
|
|
|
|
|
|
|
# (with Canon there are 6 unknown bytes before the model: "\0\0\0\0\x15\xc7") |
1785
|
|
|
|
|
|
|
RawConv => '$val=~s/^\0{4}..//s; $val=~s/\0.*//; $val', |
1786
|
|
|
|
|
|
|
}, |
1787
|
|
|
|
|
|
|
reel => { Name => 'ReelName', Format => 'string' }, # (NC) |
1788
|
|
|
|
|
|
|
scen => { Name => 'Scene', Format => 'string' }, # (NC) |
1789
|
|
|
|
|
|
|
shot => { Name => 'ShotName', Format => 'string' }, # (NC) |
1790
|
|
|
|
|
|
|
slno => { Name => 'SerialNumber', Format => 'string' }, # (NC) |
1791
|
|
|
|
|
|
|
apmd => { Name => 'ApertureMode', Format => 'undef' }, #20 |
1792
|
|
|
|
|
|
|
kgtt => { #http://lists.ffmpeg.org/pipermail/ffmpeg-devel-irc/2012-June/000707.html |
1793
|
|
|
|
|
|
|
# 'TrackType' will expand to 'Track#Type' when found inside a track |
1794
|
|
|
|
|
|
|
Name => 'TrackType', |
1795
|
|
|
|
|
|
|
# set flag to process this as international text |
1796
|
|
|
|
|
|
|
# even though the tag ID doesn't start with 0xa9 |
1797
|
|
|
|
|
|
|
IText => 4, # IText with 4-byte header |
1798
|
|
|
|
|
|
|
}, |
1799
|
|
|
|
|
|
|
chpl => { # (Nero chapter list) |
1800
|
|
|
|
|
|
|
Name => 'ChapterList', |
1801
|
|
|
|
|
|
|
ValueConv => \&ConvertChapterList, |
1802
|
|
|
|
|
|
|
PrintConv => \&PrintChapter, |
1803
|
|
|
|
|
|
|
}, |
1804
|
|
|
|
|
|
|
# ndrm - 7 bytes (0 0 0 1 0 0 0) Nero Digital Rights Management? (PH) |
1805
|
|
|
|
|
|
|
# other non-Apple tags (ref 16) |
1806
|
|
|
|
|
|
|
# hpix - HipixRichPicture (ref 16, HIPIX) |
1807
|
|
|
|
|
|
|
# strk - sub-track information (ref 16, ISO) |
1808
|
|
|
|
|
|
|
# |
1809
|
|
|
|
|
|
|
# Manufacturer-specific metadata |
1810
|
|
|
|
|
|
|
# |
1811
|
|
|
|
|
|
|
TAGS => [ #PH |
1812
|
|
|
|
|
|
|
# these tags were initially discovered in a Pentax movie, |
1813
|
|
|
|
|
|
|
# but similar information is found in videos from other manufacturers |
1814
|
|
|
|
|
|
|
{ |
1815
|
|
|
|
|
|
|
Name => 'FujiFilmTags', |
1816
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^FUJIFILM DIGITAL CAMERA\0/', |
1817
|
|
|
|
|
|
|
SubDirectory => { |
1818
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::FujiFilm::MOV', |
1819
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1820
|
|
|
|
|
|
|
}, |
1821
|
|
|
|
|
|
|
}, |
1822
|
|
|
|
|
|
|
{ |
1823
|
|
|
|
|
|
|
Name => 'KodakTags', |
1824
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^EASTMAN KODAK COMPANY/', |
1825
|
|
|
|
|
|
|
SubDirectory => { |
1826
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Kodak::MOV', |
1827
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1828
|
|
|
|
|
|
|
}, |
1829
|
|
|
|
|
|
|
}, |
1830
|
|
|
|
|
|
|
{ |
1831
|
|
|
|
|
|
|
Name => 'KonicaMinoltaTags', |
1832
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^KONICA MINOLTA DIGITAL CAMERA/', |
1833
|
|
|
|
|
|
|
SubDirectory => { |
1834
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Minolta::MOV1', |
1835
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1836
|
|
|
|
|
|
|
}, |
1837
|
|
|
|
|
|
|
}, |
1838
|
|
|
|
|
|
|
{ |
1839
|
|
|
|
|
|
|
Name => 'MinoltaTags', |
1840
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^MINOLTA DIGITAL CAMERA/', |
1841
|
|
|
|
|
|
|
SubDirectory => { |
1842
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Minolta::MOV2', |
1843
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1844
|
|
|
|
|
|
|
}, |
1845
|
|
|
|
|
|
|
}, |
1846
|
|
|
|
|
|
|
{ |
1847
|
|
|
|
|
|
|
Name => 'NikonTags', |
1848
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^NIKON DIGITAL CAMERA\0/', |
1849
|
|
|
|
|
|
|
SubDirectory => { |
1850
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Nikon::MOV', |
1851
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1852
|
|
|
|
|
|
|
}, |
1853
|
|
|
|
|
|
|
}, |
1854
|
|
|
|
|
|
|
{ |
1855
|
|
|
|
|
|
|
Name => 'OlympusTags1', |
1856
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^OLYMPUS DIGITAL CAMERA\0.{9}\x01\0/s', |
1857
|
|
|
|
|
|
|
SubDirectory => { |
1858
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Olympus::MOV1', |
1859
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1860
|
|
|
|
|
|
|
}, |
1861
|
|
|
|
|
|
|
}, |
1862
|
|
|
|
|
|
|
{ |
1863
|
|
|
|
|
|
|
Name => 'OlympusTags2', |
1864
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^OLYMPUS DIGITAL CAMERA(?!\0.{21}\x0a\0{3})/s', |
1865
|
|
|
|
|
|
|
SubDirectory => { |
1866
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Olympus::MOV2', |
1867
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1868
|
|
|
|
|
|
|
}, |
1869
|
|
|
|
|
|
|
}, |
1870
|
|
|
|
|
|
|
{ |
1871
|
|
|
|
|
|
|
Name => 'OlympusTags3', |
1872
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^OLYMPUS DIGITAL CAMERA\0/', |
1873
|
|
|
|
|
|
|
SubDirectory => { |
1874
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Olympus::MP4', |
1875
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1876
|
|
|
|
|
|
|
}, |
1877
|
|
|
|
|
|
|
}, |
1878
|
|
|
|
|
|
|
{ |
1879
|
|
|
|
|
|
|
Name => 'OlympusTags4', |
1880
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^.{16}OLYM\0/s', |
1881
|
|
|
|
|
|
|
SubDirectory => { |
1882
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Olympus::MOV3', |
1883
|
|
|
|
|
|
|
Start => 12, |
1884
|
|
|
|
|
|
|
}, |
1885
|
|
|
|
|
|
|
}, |
1886
|
|
|
|
|
|
|
{ |
1887
|
|
|
|
|
|
|
Name => 'PentaxTags', |
1888
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^PENTAX DIGITAL CAMERA\0/', |
1889
|
|
|
|
|
|
|
SubDirectory => { |
1890
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::MOV', |
1891
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1892
|
|
|
|
|
|
|
}, |
1893
|
|
|
|
|
|
|
}, |
1894
|
|
|
|
|
|
|
{ |
1895
|
|
|
|
|
|
|
Name => 'SamsungTags', |
1896
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^SAMSUNG DIGITAL CAMERA\0/', |
1897
|
|
|
|
|
|
|
SubDirectory => { |
1898
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Samsung::MP4', |
1899
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1900
|
|
|
|
|
|
|
}, |
1901
|
|
|
|
|
|
|
}, |
1902
|
|
|
|
|
|
|
{ |
1903
|
|
|
|
|
|
|
Name => 'SanyoMOV', |
1904
|
|
|
|
|
|
|
Condition => q{ |
1905
|
|
|
|
|
|
|
$$valPt =~ /^SANYO DIGITAL CAMERA\0/ and |
1906
|
|
|
|
|
|
|
$self->{VALUE}->{FileType} eq "MOV" |
1907
|
|
|
|
|
|
|
}, |
1908
|
|
|
|
|
|
|
SubDirectory => { |
1909
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Sanyo::MOV', |
1910
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1911
|
|
|
|
|
|
|
}, |
1912
|
|
|
|
|
|
|
}, |
1913
|
|
|
|
|
|
|
{ |
1914
|
|
|
|
|
|
|
Name => 'SanyoMP4', |
1915
|
|
|
|
|
|
|
Condition => q{ |
1916
|
|
|
|
|
|
|
$$valPt =~ /^SANYO DIGITAL CAMERA\0/ and |
1917
|
|
|
|
|
|
|
$self->{VALUE}->{FileType} eq "MP4" |
1918
|
|
|
|
|
|
|
}, |
1919
|
|
|
|
|
|
|
SubDirectory => { |
1920
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Sanyo::MP4', |
1921
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1922
|
|
|
|
|
|
|
}, |
1923
|
|
|
|
|
|
|
}, |
1924
|
|
|
|
|
|
|
{ |
1925
|
|
|
|
|
|
|
Name => 'UnknownTags', |
1926
|
|
|
|
|
|
|
Unknown => 1, |
1927
|
|
|
|
|
|
|
Binary => 1 |
1928
|
|
|
|
|
|
|
}, |
1929
|
|
|
|
|
|
|
], |
1930
|
|
|
|
|
|
|
# ---- Canon ---- |
1931
|
|
|
|
|
|
|
CNCV => { Name => 'CompressorVersion', Format => 'string' }, #PH (5D Mark II) |
1932
|
|
|
|
|
|
|
CNMN => { |
1933
|
|
|
|
|
|
|
Name => 'Model', #PH (EOS 550D) |
1934
|
|
|
|
|
|
|
Description => 'Camera Model Name', |
1935
|
|
|
|
|
|
|
Avoid => 1, |
1936
|
|
|
|
|
|
|
Format => 'string', # (necessary to remove the trailing NULL) |
1937
|
|
|
|
|
|
|
}, |
1938
|
|
|
|
|
|
|
CNFV => { Name => 'FirmwareVersion', Format => 'string' }, #PH (EOS 550D) |
1939
|
|
|
|
|
|
|
CNTH => { #PH (PowerShot S95) |
1940
|
|
|
|
|
|
|
Name => 'CanonCNTH', |
1941
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNTH' }, |
1942
|
|
|
|
|
|
|
}, |
1943
|
|
|
|
|
|
|
CNOP => { #PH (7DmkII) |
1944
|
|
|
|
|
|
|
Name => 'CanonCNOP', |
1945
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNOP' }, |
1946
|
|
|
|
|
|
|
}, |
1947
|
|
|
|
|
|
|
# CNDB - 2112 bytes (550D) |
1948
|
|
|
|
|
|
|
# CNDM - 4 bytes - 0xff,0xd8,0xff,0xd9 (S95) |
1949
|
|
|
|
|
|
|
# CNDG - 10232 bytes, mostly zeros (N100) |
1950
|
|
|
|
|
|
|
# ---- Casio ---- |
1951
|
|
|
|
|
|
|
QVMI => { #PH |
1952
|
|
|
|
|
|
|
Name => 'CasioQVMI', |
1953
|
|
|
|
|
|
|
# Casio stores standard EXIF-format information in MOV videos (eg. EX-S880) |
1954
|
|
|
|
|
|
|
SubDirectory => { |
1955
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Exif::Main', |
1956
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) |
1957
|
|
|
|
|
|
|
DirName => 'IFD0', |
1958
|
|
|
|
|
|
|
Multi => 0, # (no NextIFD pointer) |
1959
|
|
|
|
|
|
|
Start => 10, |
1960
|
|
|
|
|
|
|
ByteOrder => 'BigEndian', |
1961
|
|
|
|
|
|
|
}, |
1962
|
|
|
|
|
|
|
}, |
1963
|
|
|
|
|
|
|
# ---- FujiFilm ---- |
1964
|
|
|
|
|
|
|
FFMV => { #PH (FinePix HS20EXR) |
1965
|
|
|
|
|
|
|
Name => 'FujiFilmFFMV', |
1966
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::FFMV' }, |
1967
|
|
|
|
|
|
|
}, |
1968
|
|
|
|
|
|
|
MVTG => { #PH (FinePix HS20EXR) |
1969
|
|
|
|
|
|
|
Name => 'FujiFilmMVTG', |
1970
|
|
|
|
|
|
|
SubDirectory => { |
1971
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Exif::Main', |
1972
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) |
1973
|
|
|
|
|
|
|
DirName => 'IFD0', |
1974
|
|
|
|
|
|
|
Start => 16, |
1975
|
|
|
|
|
|
|
Base => '$start', |
1976
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
1977
|
|
|
|
|
|
|
}, |
1978
|
|
|
|
|
|
|
}, |
1979
|
|
|
|
|
|
|
# ---- Garmin ---- (ref PH) |
1980
|
|
|
|
|
|
|
uuid => [{ |
1981
|
|
|
|
|
|
|
Name => 'GarminSoftware', # (NC) |
1982
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^VIRBactioncamera/', |
1983
|
|
|
|
|
|
|
RawConv => 'substr($val, 16)', |
1984
|
|
|
|
|
|
|
RawConvInv => '"VIRBactioncamera$val"', |
1985
|
|
|
|
|
|
|
},{ |
1986
|
|
|
|
|
|
|
# have seen "28 f3 11 e2 b7 91 4f 6f 94 e2 4f 5d ea cb 3c 01" for RicohThetaZ1 accelerometer RADT data (not yet decoded) |
1987
|
|
|
|
|
|
|
Name => 'UUID-Unknown', |
1988
|
|
|
|
|
|
|
Writable => 0, |
1989
|
|
|
|
|
|
|
%unknownInfo, |
1990
|
|
|
|
|
|
|
}], |
1991
|
|
|
|
|
|
|
pmcc => { |
1992
|
|
|
|
|
|
|
Name => 'GarminSettings', |
1993
|
|
|
|
|
|
|
ValueConv => 'substr($val, 4)', |
1994
|
|
|
|
|
|
|
ValueConvInv => '"\0\0\0\x01$val"', |
1995
|
|
|
|
|
|
|
}, |
1996
|
|
|
|
|
|
|
# hmtp - "\0\0\0\x01" followed by 408 bytes of zero |
1997
|
|
|
|
|
|
|
# vrin - "\0\0\0\x01" followed by 8 bytes of zero |
1998
|
|
|
|
|
|
|
# ---- GoPro ---- (ref PH) |
1999
|
|
|
|
|
|
|
GoPr => 'GoProType', # (Hero3+) |
2000
|
|
|
|
|
|
|
FIRM => { Name => 'FirmwareVersion', Avoid => 1 }, # (Hero4) |
2001
|
|
|
|
|
|
|
LENS => 'LensSerialNumber', # (Hero4) |
2002
|
|
|
|
|
|
|
CAME => { # (Hero4) |
2003
|
|
|
|
|
|
|
Name => 'SerialNumberHash', |
2004
|
|
|
|
|
|
|
Description => 'Camera Serial Number Hash', |
2005
|
|
|
|
|
|
|
ValueConv => 'unpack("H*",$val)', |
2006
|
|
|
|
|
|
|
ValueConvInv => 'pack("H*",$val)', |
2007
|
|
|
|
|
|
|
}, |
2008
|
|
|
|
|
|
|
# SETT? 12 bytes (Hero4) |
2009
|
|
|
|
|
|
|
# MUID? 32 bytes (Hero4, starts with serial number hash) |
2010
|
|
|
|
|
|
|
# HMMT? 404 bytes (Hero4, all zero) |
2011
|
|
|
|
|
|
|
# BCID? 26 bytes (Hero5, all zero), 36 bytes GoPro Max |
2012
|
|
|
|
|
|
|
# GUMI? 16 bytes (Hero5) |
2013
|
|
|
|
|
|
|
"FOV\0" => 'FieldOfView', #forum8938 (Hero2) seen: "Wide" |
2014
|
|
|
|
|
|
|
GPMF => { |
2015
|
|
|
|
|
|
|
Name => 'GoProGPMF', |
2016
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' }, |
2017
|
|
|
|
|
|
|
}, |
2018
|
|
|
|
|
|
|
# free (all zero) |
2019
|
|
|
|
|
|
|
"\xa9TSC" => 'StartTimeScale', # (Hero6) |
2020
|
|
|
|
|
|
|
"\xa9TSZ" => 'StartTimeSampleSize', # (Hero6) |
2021
|
|
|
|
|
|
|
"\xa9TIM" => 'StartTimecode', #PH (NC) |
2022
|
|
|
|
|
|
|
# --- HTC ---- |
2023
|
|
|
|
|
|
|
htcb => { |
2024
|
|
|
|
|
|
|
Name => 'HTCBinary', |
2025
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HTCBinary' }, |
2026
|
|
|
|
|
|
|
}, |
2027
|
|
|
|
|
|
|
# ---- Kodak ---- |
2028
|
|
|
|
|
|
|
DcMD => { |
2029
|
|
|
|
|
|
|
Name => 'KodakDcMD', |
2030
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Kodak::DcMD' }, |
2031
|
|
|
|
|
|
|
}, |
2032
|
|
|
|
|
|
|
SNum => { Name => 'SerialNumber', Avoid => 1, Groups => { 2 => 'Camera' } }, |
2033
|
|
|
|
|
|
|
ptch => { Name => 'Pitch', Format => 'rational64s', Avoid => 1 }, # Units?? |
2034
|
|
|
|
|
|
|
_yaw => { Name => 'Yaw', Format => 'rational64s', Avoid => 1 }, # Units?? |
2035
|
|
|
|
|
|
|
roll => { Name => 'Roll', Format => 'rational64s', Avoid => 1 }, # Units?? |
2036
|
|
|
|
|
|
|
_cx_ => { Name => 'CX', Format => 'rational64s', Unknown => 1 }, |
2037
|
|
|
|
|
|
|
_cy_ => { Name => 'CY', Format => 'rational64s', Unknown => 1 }, |
2038
|
|
|
|
|
|
|
rads => { Name => 'Rads', Format => 'rational64s', Unknown => 1 }, |
2039
|
|
|
|
|
|
|
lvlm => { Name => 'LevelMeter', Format => 'rational64s', Unknown => 1 }, # (guess) |
2040
|
|
|
|
|
|
|
Lvlm => { Name => 'LevelMeter', Format => 'rational64s', Unknown => 1 }, # (guess) |
2041
|
|
|
|
|
|
|
pose => { Name => 'pose', SubDirectory => { TagTable => 'Image::ExifTool::Kodak::pose' } }, |
2042
|
|
|
|
|
|
|
# AMBA => Ambarella AVC atom (unknown data written by Kodak Playsport video cam) |
2043
|
|
|
|
|
|
|
# tmlp - 1 byte: 0 (PixPro SP360/4KVR360) |
2044
|
|
|
|
|
|
|
# pivi - 72 bytes (PixPro SP360) |
2045
|
|
|
|
|
|
|
# pive - 12 bytes (PixPro SP360) |
2046
|
|
|
|
|
|
|
# loop - 4 bytes: 0 0 0 0 (PixPro 4KVR360) |
2047
|
|
|
|
|
|
|
# m cm - 2 bytes: 0 0 (PixPro 4KVR360) |
2048
|
|
|
|
|
|
|
# m ev - 2 bytes: 0 0 (PixPro SP360/4KVR360) (exposure comp?) |
2049
|
|
|
|
|
|
|
# m vr - 2 bytes: 0 1 (PixPro 4KVR360) (virtual reality?) |
2050
|
|
|
|
|
|
|
# m wb - 4 bytes: 0 0 0 0 (PixPro SP360/4KVR360) (white balance?) |
2051
|
|
|
|
|
|
|
# mclr - 4 bytes: 0 0 0 0 (PixPro SP360/4KVR360) |
2052
|
|
|
|
|
|
|
# mmtr - 4 bytes: 0,6 0 0 0 (PixPro SP360/4KVR360) |
2053
|
|
|
|
|
|
|
# mflr - 4 bytes: 0 0 0 0 (PixPro SP360) |
2054
|
|
|
|
|
|
|
# lvlm - 24 bytes (PixPro SP360) |
2055
|
|
|
|
|
|
|
# Lvlm - 24 bytes (PixPro 4KVR360) |
2056
|
|
|
|
|
|
|
# ufdm - 4 bytes: 0 0 0 1 (PixPro SP360) |
2057
|
|
|
|
|
|
|
# mtdt - 1 byte: 0 (PixPro SP360/4KVR360) |
2058
|
|
|
|
|
|
|
# gdta - 75240 bytes (PixPro SP360) |
2059
|
|
|
|
|
|
|
# EIS1 - 4 bytes: 03 07 00 00 (PixPro 4KVR360) |
2060
|
|
|
|
|
|
|
# EIS2 - 4 bytes: 04 97 00 00 (PixPro 4KVR360) |
2061
|
|
|
|
|
|
|
# ---- LG ---- |
2062
|
|
|
|
|
|
|
adzc => { Name => 'Unknown_adzc', Unknown => 1, Hidden => 1, %langText }, # "false\0/","true\0/" |
2063
|
|
|
|
|
|
|
adze => { Name => 'Unknown_adze', Unknown => 1, Hidden => 1, %langText }, # "false\0/" |
2064
|
|
|
|
|
|
|
adzm => { Name => 'Unknown_adzm', Unknown => 1, Hidden => 1, %langText }, # "\x0e\x04/","\x10\x06" |
2065
|
|
|
|
|
|
|
# ---- Microsoft ---- |
2066
|
|
|
|
|
|
|
Xtra => { #PH (microsoft) |
2067
|
|
|
|
|
|
|
Name => 'MicrosoftXtra', |
2068
|
|
|
|
|
|
|
WriteGroup => 'Microsoft', |
2069
|
|
|
|
|
|
|
SubDirectory => { |
2070
|
|
|
|
|
|
|
DirName => 'Microsoft', |
2071
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Microsoft::Xtra', |
2072
|
|
|
|
|
|
|
}, |
2073
|
|
|
|
|
|
|
}, |
2074
|
|
|
|
|
|
|
# ---- Minolta ---- |
2075
|
|
|
|
|
|
|
MMA0 => { #PH (DiMage 7Hi) |
2076
|
|
|
|
|
|
|
Name => 'MinoltaMMA0', |
2077
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' }, |
2078
|
|
|
|
|
|
|
}, |
2079
|
|
|
|
|
|
|
MMA1 => { #PH (Dimage A2) |
2080
|
|
|
|
|
|
|
Name => 'MinoltaMMA1', |
2081
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' }, |
2082
|
|
|
|
|
|
|
}, |
2083
|
|
|
|
|
|
|
# ---- Nikon ---- |
2084
|
|
|
|
|
|
|
NCDT => { #PH |
2085
|
|
|
|
|
|
|
Name => 'NikonNCDT', |
2086
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Nikon::NCDT' }, |
2087
|
|
|
|
|
|
|
}, |
2088
|
|
|
|
|
|
|
# ---- Olympus ---- |
2089
|
|
|
|
|
|
|
scrn => { #PH (TG-810) |
2090
|
|
|
|
|
|
|
Name => 'OlympusPreview', |
2091
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^.{4}\xff\xd8\xff\xdb/s', |
2092
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Olympus::scrn' }, |
2093
|
|
|
|
|
|
|
}, |
2094
|
|
|
|
|
|
|
# ---- Panasonic/Leica ---- |
2095
|
|
|
|
|
|
|
PANA => { #PH |
2096
|
|
|
|
|
|
|
Name => 'PanasonicPANA', |
2097
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::PANA' }, |
2098
|
|
|
|
|
|
|
}, |
2099
|
|
|
|
|
|
|
LEIC => { #PH |
2100
|
|
|
|
|
|
|
Name => 'LeicaLEIC', |
2101
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::PANA' }, |
2102
|
|
|
|
|
|
|
}, |
2103
|
|
|
|
|
|
|
# ---- Pentax ---- |
2104
|
|
|
|
|
|
|
thmb => [ # (apparently defined by 3gpp, ref 16) |
2105
|
|
|
|
|
|
|
{ #PH (Pentax Q) |
2106
|
|
|
|
|
|
|
Name => 'MakerNotePentax5a', |
2107
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^PENTAX \0II/', |
2108
|
|
|
|
|
|
|
SubDirectory => { |
2109
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::Main', |
2110
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) |
2111
|
|
|
|
|
|
|
Start => 10, |
2112
|
|
|
|
|
|
|
Base => '$start - 10', |
2113
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
2114
|
|
|
|
|
|
|
}, |
2115
|
|
|
|
|
|
|
},{ #PH (TG-810) |
2116
|
|
|
|
|
|
|
Name => 'OlympusThumbnail', |
2117
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^.{4}\xff\xd8\xff\xdb/s', |
2118
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Olympus::thmb' }, |
2119
|
|
|
|
|
|
|
},{ #17 (format is in bytes 3-7) |
2120
|
|
|
|
|
|
|
Name => 'ThumbnailImage', |
2121
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^.{8}\xff\xd8\xff[\xdb\xe0]/s', |
2122
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
2123
|
|
|
|
|
|
|
RawConv => 'substr($val, 8)', |
2124
|
|
|
|
|
|
|
Binary => 1, |
2125
|
|
|
|
|
|
|
},{ #17 (format is in bytes 3-7) |
2126
|
|
|
|
|
|
|
Name => 'ThumbnailPNG', |
2127
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^.{8}\x89PNG\r\n\x1a\n/s', |
2128
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
2129
|
|
|
|
|
|
|
RawConv => 'substr($val, 8)', |
2130
|
|
|
|
|
|
|
Binary => 1, |
2131
|
|
|
|
|
|
|
},{ |
2132
|
|
|
|
|
|
|
Name => 'UnknownThumbnail', |
2133
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
2134
|
|
|
|
|
|
|
Binary => 1, |
2135
|
|
|
|
|
|
|
}, |
2136
|
|
|
|
|
|
|
], |
2137
|
|
|
|
|
|
|
PENT => { #PH |
2138
|
|
|
|
|
|
|
Name => 'PentaxPENT', |
2139
|
|
|
|
|
|
|
SubDirectory => { |
2140
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::PENT', |
2141
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
2142
|
|
|
|
|
|
|
}, |
2143
|
|
|
|
|
|
|
}, |
2144
|
|
|
|
|
|
|
PXTH => { #PH (Pentax K-01) |
2145
|
|
|
|
|
|
|
Name => 'PentaxPreview', |
2146
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Pentax::PXTH' }, |
2147
|
|
|
|
|
|
|
}, |
2148
|
|
|
|
|
|
|
PXMN => [{ #PH (Pentax K-01) |
2149
|
|
|
|
|
|
|
Name => 'MakerNotePentax5b', |
2150
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^PENTAX \0MM/', |
2151
|
|
|
|
|
|
|
SubDirectory => { |
2152
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::Main', |
2153
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) |
2154
|
|
|
|
|
|
|
Start => 10, |
2155
|
|
|
|
|
|
|
Base => '$start - 10', |
2156
|
|
|
|
|
|
|
ByteOrder => 'BigEndian', |
2157
|
|
|
|
|
|
|
}, |
2158
|
|
|
|
|
|
|
},{ #PH (Pentax 645Z) |
2159
|
|
|
|
|
|
|
Name => 'MakerNotePentax5c', |
2160
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^PENTAX \0II/', |
2161
|
|
|
|
|
|
|
SubDirectory => { |
2162
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::Main', |
2163
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default) |
2164
|
|
|
|
|
|
|
Start => 10, |
2165
|
|
|
|
|
|
|
Base => '$start - 10', |
2166
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
2167
|
|
|
|
|
|
|
}, |
2168
|
|
|
|
|
|
|
},{ |
2169
|
|
|
|
|
|
|
Name => 'MakerNotePentaxUnknown', |
2170
|
|
|
|
|
|
|
Binary => 1, |
2171
|
|
|
|
|
|
|
}], |
2172
|
|
|
|
|
|
|
# ---- Ricoh ---- |
2173
|
|
|
|
|
|
|
RTHU => { #PH (GR) |
2174
|
|
|
|
|
|
|
Name => 'PreviewImage', |
2175
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
2176
|
|
|
|
|
|
|
RawConv => '$self->ValidateImage(\$val, $tag)', |
2177
|
|
|
|
|
|
|
}, |
2178
|
|
|
|
|
|
|
RMKN => { #PH (GR) |
2179
|
|
|
|
|
|
|
Name => 'RicohRMKN', |
2180
|
|
|
|
|
|
|
SubDirectory => { |
2181
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Exif::Main', |
2182
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::ProcessTIFF, # (because ProcessMOV is default) |
2183
|
|
|
|
|
|
|
}, |
2184
|
|
|
|
|
|
|
}, |
2185
|
|
|
|
|
|
|
'@mak' => { Name => 'Make', Avoid => 1 }, |
2186
|
|
|
|
|
|
|
'@mod' => { Name => 'Model', Avoid => 1 }, |
2187
|
|
|
|
|
|
|
'@swr' => { Name => 'SoftwareVersion', Avoid => 1 }, |
2188
|
|
|
|
|
|
|
'@day' => { |
2189
|
|
|
|
|
|
|
Name => 'ContentCreateDate', |
2190
|
|
|
|
|
|
|
Notes => q{ |
2191
|
|
|
|
|
|
|
some stupid Ricoh programmer used the '@' symbol instead of the copyright |
2192
|
|
|
|
|
|
|
symbol in these tag ID's for the Ricoh Theta Z1 and maybe other models |
2193
|
|
|
|
|
|
|
}, |
2194
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2195
|
|
|
|
|
|
|
Shift => 'Time', |
2196
|
|
|
|
|
|
|
Avoid => 1, |
2197
|
|
|
|
|
|
|
# handle values in the form "2010-02-12T13:27:14-0800" |
2198
|
|
|
|
|
|
|
ValueConv => q{ |
2199
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
2200
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::ConvertXMPDate($val); |
2201
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary |
2202
|
|
|
|
|
|
|
return $val; |
2203
|
|
|
|
|
|
|
}, |
2204
|
|
|
|
|
|
|
ValueConvInv => q{ |
2205
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
2206
|
|
|
|
|
|
|
my $tmp = Image::ExifTool::XMP::FormatXMPDate($val); |
2207
|
|
|
|
|
|
|
($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon |
2208
|
|
|
|
|
|
|
return $val; |
2209
|
|
|
|
|
|
|
}, |
2210
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
2211
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) |
2212
|
|
|
|
|
|
|
}, |
2213
|
|
|
|
|
|
|
'@xyz' => { #PH (iPhone 3GS) |
2214
|
|
|
|
|
|
|
Name => 'GPSCoordinates', |
2215
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
2216
|
|
|
|
|
|
|
Avoid => 1, |
2217
|
|
|
|
|
|
|
ValueConv => \&ConvertISO6709, |
2218
|
|
|
|
|
|
|
ValueConvInv => \&ConvInvISO6709, |
2219
|
|
|
|
|
|
|
PrintConv => \&PrintGPSCoordinates, |
2220
|
|
|
|
|
|
|
PrintConvInv => \&PrintInvGPSCoordinates, |
2221
|
|
|
|
|
|
|
}, |
2222
|
|
|
|
|
|
|
# RDT1 - pairs of int32u_BE, starting at byte 8: "458275 471846" |
2223
|
|
|
|
|
|
|
# RDT2 - pairs of int32u_BE, starting at byte 8: "472276 468526" |
2224
|
|
|
|
|
|
|
# RDT3 - pairs of int32u_BE, starting at byte 8: "876603 482191" |
2225
|
|
|
|
|
|
|
# RDT4 - pairs of int32u_BE, starting at byte 8: "1955 484612" |
2226
|
|
|
|
|
|
|
# RDT6 - empty |
2227
|
|
|
|
|
|
|
# RDT7 - empty |
2228
|
|
|
|
|
|
|
# RDT8 - empty |
2229
|
|
|
|
|
|
|
# RDT9 - only 16-byte header? |
2230
|
|
|
|
|
|
|
# the boxes below all have a similar header (little-endian): |
2231
|
|
|
|
|
|
|
# 0 int32u - number of records |
2232
|
|
|
|
|
|
|
# 4 ? - "1e 00" |
2233
|
|
|
|
|
|
|
# 6 int16u - record length in bytes |
2234
|
|
|
|
|
|
|
# 8 ? - "23 01 00 00 00 00 00 00" |
2235
|
|
|
|
|
|
|
# 16 - start of records (each record ends in an int64u timestamp "ts" in ns) |
2236
|
|
|
|
|
|
|
# RDTA - float[4],ts: "-0.31289672 -0.2245330 11.303817 0 775.780" |
2237
|
|
|
|
|
|
|
# RDTB - float[4],ts: "-0.04841613 -0.2166595 0.0724792 0 775.780" |
2238
|
|
|
|
|
|
|
# RDTC - float[4],ts: "27.60925 -27.10037 -13.27285 0 775.829" |
2239
|
|
|
|
|
|
|
# RDTD - int16s[3],ts: "353 -914 16354 0 775.829" |
2240
|
|
|
|
|
|
|
# RDTG - ts: "775.825" |
2241
|
|
|
|
|
|
|
# RDTI - float[4],ts: "0.00165951 0.005770059 0.06838259 0.1744695 775.862" |
2242
|
|
|
|
|
|
|
# ---- Samsung ---- |
2243
|
|
|
|
|
|
|
vndr => 'Vendor', #PH (Samsung PL70) |
2244
|
|
|
|
|
|
|
SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY") |
2245
|
|
|
|
|
|
|
INFO => { |
2246
|
|
|
|
|
|
|
Name => 'SamsungINFO', |
2247
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Samsung::INFO' }, |
2248
|
|
|
|
|
|
|
}, |
2249
|
|
|
|
|
|
|
'@sec' => { #PH (Samsung WB30F) |
2250
|
|
|
|
|
|
|
Name => 'SamsungSec', |
2251
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Samsung::sec' }, |
2252
|
|
|
|
|
|
|
}, |
2253
|
|
|
|
|
|
|
'smta' => { #PH (Samsung SM-C101) |
2254
|
|
|
|
|
|
|
Name => 'SamsungSmta', |
2255
|
|
|
|
|
|
|
SubDirectory => { |
2256
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Samsung::smta', |
2257
|
|
|
|
|
|
|
Start => 4, |
2258
|
|
|
|
|
|
|
}, |
2259
|
|
|
|
|
|
|
}, |
2260
|
|
|
|
|
|
|
cver => 'CodeVersion', #PH (guess, Samsung MV900F) |
2261
|
|
|
|
|
|
|
# ducp - 4 bytes all zero (Samsung ST96,WB750), 52 bytes all zero (Samsung WB30F) |
2262
|
|
|
|
|
|
|
# edli - 52 bytes all zero (Samsung WB30F) |
2263
|
|
|
|
|
|
|
# @etc - 4 bytes all zero (Samsung WB30F) |
2264
|
|
|
|
|
|
|
# saut - 4 bytes all zero (Samsung SM-N900T) |
2265
|
|
|
|
|
|
|
# smrd - string "TRUEBLUE" (Samsung SM-C101) |
2266
|
|
|
|
|
|
|
# ---- TomTom Bandit Action Cam ---- |
2267
|
|
|
|
|
|
|
TTMD => { |
2268
|
|
|
|
|
|
|
Name => 'TomTomMetaData', |
2269
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TomTom' }, |
2270
|
|
|
|
|
|
|
}, |
2271
|
|
|
|
|
|
|
# ---- Samsung Gear 360 ---- |
2272
|
|
|
|
|
|
|
vrot => { |
2273
|
|
|
|
|
|
|
Name => 'AccelerometerData', |
2274
|
|
|
|
|
|
|
Notes => q{ |
2275
|
|
|
|
|
|
|
accelerometer readings for each frame of the video, expressed as sets of |
2276
|
|
|
|
|
|
|
yaw, pitch and roll angles in degrees |
2277
|
|
|
|
|
|
|
}, |
2278
|
|
|
|
|
|
|
Format => 'rational64s', |
2279
|
|
|
|
|
|
|
ValueConv => '$val =~ s/^-?\d+ //; \$val', # (ignore leading version/size words) |
2280
|
|
|
|
|
|
|
}, |
2281
|
|
|
|
|
|
|
# m360 - 8 bytes "0 0 0 0 0 0 0 1" |
2282
|
|
|
|
|
|
|
# opax - 164 bytes unknown (center and affine arrays? ref 26) |
2283
|
|
|
|
|
|
|
# opai - 32 bytes (maybe contains a serial number starting at byte 16? - PH) (rgb gains, degamma, gamma? ref 26) |
2284
|
|
|
|
|
|
|
# intv - 16 bytes all zero |
2285
|
|
|
|
|
|
|
# ---- Xaiomi ---- |
2286
|
|
|
|
|
|
|
mcvr => { |
2287
|
|
|
|
|
|
|
Name => 'PreviewImage', |
2288
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
2289
|
|
|
|
|
|
|
Binary => 1, |
2290
|
|
|
|
|
|
|
}, |
2291
|
|
|
|
|
|
|
# ---- Unknown ---- |
2292
|
|
|
|
|
|
|
# CDET - 128 bytes (unknown origin) |
2293
|
|
|
|
|
|
|
# mtyp - 4 bytes all zero (some drone video) |
2294
|
|
|
|
|
|
|
# kgrf - 8 bytes all zero ? (in udta inside trak atom) |
2295
|
|
|
|
|
|
|
# kgcg - 128 bytes 0's and 1's |
2296
|
|
|
|
|
|
|
# kgsi - 4 bytes "00 00 00 80" |
2297
|
|
|
|
|
|
|
# FIEL - 18 bytes "FIEL\0\x01\0\0\0..." |
2298
|
|
|
|
|
|
|
# |
2299
|
|
|
|
|
|
|
# other 3rd-party tags |
2300
|
|
|
|
|
|
|
# (ref http://code.google.com/p/mp4parser/source/browse/trunk/isoparser/src/main/resources/isoparser-default.properties?r=814) |
2301
|
|
|
|
|
|
|
# |
2302
|
|
|
|
|
|
|
ccid => 'ContentID', |
2303
|
|
|
|
|
|
|
icnu => 'IconURI', |
2304
|
|
|
|
|
|
|
infu => 'InfoURL', |
2305
|
|
|
|
|
|
|
cdis => 'ContentDistributorID', |
2306
|
|
|
|
|
|
|
albr => { Name => 'AlbumArtist', Groups => { 2 => 'Author' } }, |
2307
|
|
|
|
|
|
|
cvru => 'CoverURI', |
2308
|
|
|
|
|
|
|
lrcu => 'LyricsURI', |
2309
|
|
|
|
|
|
|
|
2310
|
|
|
|
|
|
|
tags => { # found in Audible .m4b audio books (ref PH) |
2311
|
|
|
|
|
|
|
Name => 'Audible_tags', |
2312
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Audible::tags' }, |
2313
|
|
|
|
|
|
|
}, |
2314
|
|
|
|
|
|
|
); |
2315
|
|
|
|
|
|
|
|
2316
|
|
|
|
|
|
|
# Unknown information stored in HTC One (M8) videos - PH |
2317
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::HTCBinary = ( |
2318
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
2319
|
|
|
|
|
|
|
GROUPS => { 0 => 'MakerNotes', 1 => 'HTC', 2 => 'Video' }, |
2320
|
|
|
|
|
|
|
TAG_PREFIX => 'HTCBinary', |
2321
|
|
|
|
|
|
|
FORMAT => 'int32u', |
2322
|
|
|
|
|
|
|
FIRST_ENTRY => 0, |
2323
|
|
|
|
|
|
|
# 0 - values: 1 |
2324
|
|
|
|
|
|
|
# 1 - values: 0 |
2325
|
|
|
|
|
|
|
# 2 - values: 0 |
2326
|
|
|
|
|
|
|
# 3 - values: FileSize minus 12 (why?) |
2327
|
|
|
|
|
|
|
# 4 - values: 12 |
2328
|
|
|
|
|
|
|
); |
2329
|
|
|
|
|
|
|
|
2330
|
|
|
|
|
|
|
# TomTom Bandit Action Cam metadata (ref PH) |
2331
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::TomTom = ( |
2332
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2333
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2334
|
|
|
|
|
|
|
NOTES => 'Tags found in TomTom Bandit Action Cam MP4 videos.', |
2335
|
|
|
|
|
|
|
TTAD => { |
2336
|
|
|
|
|
|
|
Name => 'TomTomAD', |
2337
|
|
|
|
|
|
|
SubDirectory => { |
2338
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
2339
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::QuickTime::ProcessTTAD, |
2340
|
|
|
|
|
|
|
}, |
2341
|
|
|
|
|
|
|
}, |
2342
|
|
|
|
|
|
|
TTHL => { Name => 'TomTomHL', Binary => 1, Unknown => 1 }, # (mostly zeros) |
2343
|
|
|
|
|
|
|
# (TTID values are different for each video) |
2344
|
|
|
|
|
|
|
TTID => { Name => 'TomTomID', ValueConv => 'unpack("x4H*",$val)' }, |
2345
|
|
|
|
|
|
|
TTVI => { Name => 'TomTomVI', Format => 'int32u', Unknown => 1 }, # seen: "0 1 61 508 508" |
2346
|
|
|
|
|
|
|
# TTVD seen: "normal 720p 60fps 60fps 16/9 wide 1x" |
2347
|
|
|
|
|
|
|
TTVD => { Name => 'TomTomVD', ValueConv => 'my @a = ($val =~ /[\x20-\x7f]+/g); "@a"' }, |
2348
|
|
|
|
|
|
|
); |
2349
|
|
|
|
|
|
|
|
2350
|
|
|
|
|
|
|
# User-specific media data atoms (ref 11) |
2351
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::UserMedia = ( |
2352
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2353
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2354
|
|
|
|
|
|
|
MTDT => { |
2355
|
|
|
|
|
|
|
Name => 'MetaData', |
2356
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MetaData' }, |
2357
|
|
|
|
|
|
|
}, |
2358
|
|
|
|
|
|
|
); |
2359
|
|
|
|
|
|
|
|
2360
|
|
|
|
|
|
|
# User-specific media data atoms (ref 11) |
2361
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MetaData = ( |
2362
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMetaData, |
2363
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2364
|
|
|
|
|
|
|
TAG_PREFIX => 'MetaData', |
2365
|
|
|
|
|
|
|
0x01 => 'Title', |
2366
|
|
|
|
|
|
|
0x03 => { |
2367
|
|
|
|
|
|
|
Name => 'ProductionDate', |
2368
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2369
|
|
|
|
|
|
|
Shift => 'Time', |
2370
|
|
|
|
|
|
|
Writable => 1, |
2371
|
|
|
|
|
|
|
Permanent => 1, |
2372
|
|
|
|
|
|
|
DelValue => '0000/00/00 00:00:00', |
2373
|
|
|
|
|
|
|
# translate from format "YYYY/mm/dd HH:MM:SS" |
2374
|
|
|
|
|
|
|
ValueConv => '$val=~tr{/}{:}; $val', |
2375
|
|
|
|
|
|
|
ValueConvInv => '$val=~s[^(\d{4}):(\d{2}):][$1/$2/]; $val', |
2376
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
2377
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val)', |
2378
|
|
|
|
|
|
|
}, |
2379
|
|
|
|
|
|
|
0x04 => 'Software', |
2380
|
|
|
|
|
|
|
0x05 => 'Product', |
2381
|
|
|
|
|
|
|
0x0a => { |
2382
|
|
|
|
|
|
|
Name => 'TrackProperty', |
2383
|
|
|
|
|
|
|
RawConv => 'my @a=unpack("Nnn",$val); "@a"', |
2384
|
|
|
|
|
|
|
PrintConv => [ |
2385
|
|
|
|
|
|
|
{ 0 => 'No presentation', BITMASK => { 0 => 'Main track' } }, |
2386
|
|
|
|
|
|
|
{ 0 => 'No attributes', BITMASK => { 15 => 'Read only' } }, |
2387
|
|
|
|
|
|
|
'"Priority $val"', |
2388
|
|
|
|
|
|
|
], |
2389
|
|
|
|
|
|
|
}, |
2390
|
|
|
|
|
|
|
0x0b => { |
2391
|
|
|
|
|
|
|
Name => 'TimeZone', |
2392
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2393
|
|
|
|
|
|
|
Writable => 1, |
2394
|
|
|
|
|
|
|
Permanent => 1, |
2395
|
|
|
|
|
|
|
DelValue => 0, |
2396
|
|
|
|
|
|
|
RawConv => 'Get16s(\$val,0)', |
2397
|
|
|
|
|
|
|
RawConvInv => 'Set16s($val)', |
2398
|
|
|
|
|
|
|
PrintConv => 'TimeZoneString($val)', |
2399
|
|
|
|
|
|
|
PrintConvInv => q{ |
2400
|
|
|
|
|
|
|
return undef unless $val =~ /^([-+])(\d{1,2}):?(\d{2})$/' |
2401
|
|
|
|
|
|
|
my $tzmin = $2 * 60 + $3; |
2402
|
|
|
|
|
|
|
$tzmin = -$tzmin if $1 eq '-'; |
2403
|
|
|
|
|
|
|
return $tzmin; |
2404
|
|
|
|
|
|
|
} |
2405
|
|
|
|
|
|
|
}, |
2406
|
|
|
|
|
|
|
0x0c => { |
2407
|
|
|
|
|
|
|
Name => 'ModifyDate', |
2408
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
2409
|
|
|
|
|
|
|
Shift => 'Time', |
2410
|
|
|
|
|
|
|
Writable => 1, |
2411
|
|
|
|
|
|
|
Permanent => 1, |
2412
|
|
|
|
|
|
|
DelValue => '0000/00/00 00:00:00', |
2413
|
|
|
|
|
|
|
# translate from format "YYYY/mm/dd HH:MM:SS" |
2414
|
|
|
|
|
|
|
ValueConv => '$val=~tr{/}{:}; $val', |
2415
|
|
|
|
|
|
|
ValueConvInv => '$val=~s[^(\d{4}):(\d{2}):][$1/$2/]; $val', |
2416
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
2417
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val)', |
2418
|
|
|
|
|
|
|
}, |
2419
|
|
|
|
|
|
|
); |
2420
|
|
|
|
|
|
|
|
2421
|
|
|
|
|
|
|
# compressed movie atoms (ref http://wiki.multimedia.cx/index.php?title=QuickTime_container#cmov) |
2422
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::CMovie = ( |
2423
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2424
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2425
|
|
|
|
|
|
|
dcom => 'Compression', |
2426
|
|
|
|
|
|
|
# cmvd - compressed moov atom data |
2427
|
|
|
|
|
|
|
); |
2428
|
|
|
|
|
|
|
|
2429
|
|
|
|
|
|
|
# Profile atoms (ref 11) |
2430
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Profile = ( |
2431
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2432
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2433
|
|
|
|
|
|
|
FPRF => { |
2434
|
|
|
|
|
|
|
Name => 'FileGlobalProfile', |
2435
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::FileProf' }, |
2436
|
|
|
|
|
|
|
}, |
2437
|
|
|
|
|
|
|
APRF => { |
2438
|
|
|
|
|
|
|
Name => 'AudioProfile', |
2439
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AudioProf' }, |
2440
|
|
|
|
|
|
|
}, |
2441
|
|
|
|
|
|
|
VPRF => { |
2442
|
|
|
|
|
|
|
Name => 'VideoProfile', |
2443
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::VideoProf' }, |
2444
|
|
|
|
|
|
|
}, |
2445
|
|
|
|
|
|
|
OLYM => { #PH |
2446
|
|
|
|
|
|
|
Name => 'OlympusOLYM', |
2447
|
|
|
|
|
|
|
SubDirectory => { |
2448
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Olympus::OLYM', |
2449
|
|
|
|
|
|
|
ByteOrder => 'BigEndian', |
2450
|
|
|
|
|
|
|
}, |
2451
|
|
|
|
|
|
|
}, |
2452
|
|
|
|
|
|
|
); |
2453
|
|
|
|
|
|
|
|
2454
|
|
|
|
|
|
|
# FPRF atom information (ref 11) |
2455
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::FileProf = ( |
2456
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
2457
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2458
|
|
|
|
|
|
|
FORMAT => 'int32u', |
2459
|
|
|
|
|
|
|
0 => { Name => 'FileProfileVersion', Unknown => 1 }, # unknown = uninteresting |
2460
|
|
|
|
|
|
|
1 => { |
2461
|
|
|
|
|
|
|
Name => 'FileFunctionFlags', |
2462
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
2463
|
|
|
|
|
|
|
28 => 'Fragmented', |
2464
|
|
|
|
|
|
|
29 => 'Additional tracks', |
2465
|
|
|
|
|
|
|
30 => 'Edited', # (main AV track is edited) |
2466
|
|
|
|
|
|
|
}}, |
2467
|
|
|
|
|
|
|
}, |
2468
|
|
|
|
|
|
|
# 2 - reserved |
2469
|
|
|
|
|
|
|
); |
2470
|
|
|
|
|
|
|
|
2471
|
|
|
|
|
|
|
# APRF atom information (ref 11) |
2472
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::AudioProf = ( |
2473
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
2474
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
2475
|
|
|
|
|
|
|
FORMAT => 'int32u', |
2476
|
|
|
|
|
|
|
0 => { Name => 'AudioProfileVersion', Unknown => 1 }, |
2477
|
|
|
|
|
|
|
1 => 'AudioTrackID', |
2478
|
|
|
|
|
|
|
2 => { |
2479
|
|
|
|
|
|
|
Name => 'AudioCodec', |
2480
|
|
|
|
|
|
|
Format => 'undef[4]', |
2481
|
|
|
|
|
|
|
}, |
2482
|
|
|
|
|
|
|
3 => { |
2483
|
|
|
|
|
|
|
Name => 'AudioCodecInfo', |
2484
|
|
|
|
|
|
|
Unknown => 1, |
2485
|
|
|
|
|
|
|
PrintConv => 'sprintf("0x%.4x", $val)', |
2486
|
|
|
|
|
|
|
}, |
2487
|
|
|
|
|
|
|
4 => { |
2488
|
|
|
|
|
|
|
Name => 'AudioAttributes', |
2489
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
2490
|
|
|
|
|
|
|
0 => 'Encrypted', |
2491
|
|
|
|
|
|
|
1 => 'Variable bitrate', |
2492
|
|
|
|
|
|
|
2 => 'Dual mono', |
2493
|
|
|
|
|
|
|
}}, |
2494
|
|
|
|
|
|
|
}, |
2495
|
|
|
|
|
|
|
5 => { |
2496
|
|
|
|
|
|
|
Name => 'AudioAvgBitrate', |
2497
|
|
|
|
|
|
|
ValueConv => '$val * 1000', |
2498
|
|
|
|
|
|
|
PrintConv => 'ConvertBitrate($val)', |
2499
|
|
|
|
|
|
|
}, |
2500
|
|
|
|
|
|
|
6 => { |
2501
|
|
|
|
|
|
|
Name => 'AudioMaxBitrate', |
2502
|
|
|
|
|
|
|
ValueConv => '$val * 1000', |
2503
|
|
|
|
|
|
|
PrintConv => 'ConvertBitrate($val)', |
2504
|
|
|
|
|
|
|
}, |
2505
|
|
|
|
|
|
|
7 => 'AudioSampleRate', |
2506
|
|
|
|
|
|
|
8 => 'AudioChannels', |
2507
|
|
|
|
|
|
|
); |
2508
|
|
|
|
|
|
|
|
2509
|
|
|
|
|
|
|
# VPRF atom information (ref 11) |
2510
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::VideoProf = ( |
2511
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
2512
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2513
|
|
|
|
|
|
|
FORMAT => 'int32u', |
2514
|
|
|
|
|
|
|
0 => { Name => 'VideoProfileVersion', Unknown => 1 }, |
2515
|
|
|
|
|
|
|
1 => 'VideoTrackID', |
2516
|
|
|
|
|
|
|
2 => { |
2517
|
|
|
|
|
|
|
Name => 'VideoCodec', |
2518
|
|
|
|
|
|
|
Format => 'undef[4]', |
2519
|
|
|
|
|
|
|
}, |
2520
|
|
|
|
|
|
|
3 => { |
2521
|
|
|
|
|
|
|
Name => 'VideoCodecInfo', |
2522
|
|
|
|
|
|
|
Unknown => 1, |
2523
|
|
|
|
|
|
|
PrintConv => 'sprintf("0x%.4x", $val)', |
2524
|
|
|
|
|
|
|
}, |
2525
|
|
|
|
|
|
|
4 => { |
2526
|
|
|
|
|
|
|
Name => 'VideoAttributes', |
2527
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
2528
|
|
|
|
|
|
|
0 => 'Encrypted', |
2529
|
|
|
|
|
|
|
1 => 'Variable bitrate', |
2530
|
|
|
|
|
|
|
2 => 'Variable frame rate', |
2531
|
|
|
|
|
|
|
3 => 'Interlaced', |
2532
|
|
|
|
|
|
|
}}, |
2533
|
|
|
|
|
|
|
}, |
2534
|
|
|
|
|
|
|
5 => { |
2535
|
|
|
|
|
|
|
Name => 'VideoAvgBitrate', |
2536
|
|
|
|
|
|
|
ValueConv => '$val * 1000', |
2537
|
|
|
|
|
|
|
PrintConv => 'ConvertBitrate($val)', |
2538
|
|
|
|
|
|
|
}, |
2539
|
|
|
|
|
|
|
6 => { |
2540
|
|
|
|
|
|
|
Name => 'VideoMaxBitrate', |
2541
|
|
|
|
|
|
|
ValueConv => '$val * 1000', |
2542
|
|
|
|
|
|
|
PrintConv => 'ConvertBitrate($val)', |
2543
|
|
|
|
|
|
|
}, |
2544
|
|
|
|
|
|
|
7 => { |
2545
|
|
|
|
|
|
|
Name => 'VideoAvgFrameRate', |
2546
|
|
|
|
|
|
|
Format => 'fixed32u', |
2547
|
|
|
|
|
|
|
PrintConv => 'int($val * 1000 + 0.5) / 1000', |
2548
|
|
|
|
|
|
|
}, |
2549
|
|
|
|
|
|
|
8 => { |
2550
|
|
|
|
|
|
|
Name => 'VideoMaxFrameRate', |
2551
|
|
|
|
|
|
|
Format => 'fixed32u', |
2552
|
|
|
|
|
|
|
PrintConv => 'int($val * 1000 + 0.5) / 1000', |
2553
|
|
|
|
|
|
|
}, |
2554
|
|
|
|
|
|
|
9 => { |
2555
|
|
|
|
|
|
|
Name => 'VideoSize', |
2556
|
|
|
|
|
|
|
Format => 'int16u[2]', |
2557
|
|
|
|
|
|
|
PrintConv => '$val=~tr/ /x/; $val', |
2558
|
|
|
|
|
|
|
}, |
2559
|
|
|
|
|
|
|
10 => { |
2560
|
|
|
|
|
|
|
Name => 'PixelAspectRatio', |
2561
|
|
|
|
|
|
|
Format => 'int16u[2]', |
2562
|
|
|
|
|
|
|
PrintConv => '$val=~tr/ /:/; $val', |
2563
|
|
|
|
|
|
|
}, |
2564
|
|
|
|
|
|
|
); |
2565
|
|
|
|
|
|
|
|
2566
|
|
|
|
|
|
|
# meta atoms |
2567
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Meta = ( |
2568
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2569
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
2570
|
|
|
|
|
|
|
GROUPS => { 1 => 'Meta', 2 => 'Video' }, |
2571
|
|
|
|
|
|
|
ilst => { |
2572
|
|
|
|
|
|
|
Name => 'ItemList', |
2573
|
|
|
|
|
|
|
SubDirectory => { |
2574
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::ItemList', |
2575
|
|
|
|
|
|
|
HasData => 1, # process atoms as containers with 'data' elements |
2576
|
|
|
|
|
|
|
}, |
2577
|
|
|
|
|
|
|
}, |
2578
|
|
|
|
|
|
|
# MP4 tags (ref 5) |
2579
|
|
|
|
|
|
|
hdlr => { |
2580
|
|
|
|
|
|
|
Name => 'Handler', |
2581
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Handler' }, |
2582
|
|
|
|
|
|
|
}, |
2583
|
|
|
|
|
|
|
dinf => { |
2584
|
|
|
|
|
|
|
Name => 'DataInfo', # (don't change this name -- used to recognize directory when writing) |
2585
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DataInfo' }, |
2586
|
|
|
|
|
|
|
}, |
2587
|
|
|
|
|
|
|
ipmc => { |
2588
|
|
|
|
|
|
|
Name => 'IPMPControl', |
2589
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
2590
|
|
|
|
|
|
|
}, |
2591
|
|
|
|
|
|
|
iloc => { |
2592
|
|
|
|
|
|
|
Name => 'ItemLocation', |
2593
|
|
|
|
|
|
|
RawConv => \&ParseItemLocation, |
2594
|
|
|
|
|
|
|
WriteHook => \&ParseItemLocation, |
2595
|
|
|
|
|
|
|
Notes => 'parsed, but not extracted as a tag', |
2596
|
|
|
|
|
|
|
}, |
2597
|
|
|
|
|
|
|
ipro => { |
2598
|
|
|
|
|
|
|
Name => 'ItemProtection', |
2599
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
2600
|
|
|
|
|
|
|
}, |
2601
|
|
|
|
|
|
|
iinf => [{ |
2602
|
|
|
|
|
|
|
Name => 'ItemInformation', |
2603
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\0/', # (check for version 0) |
2604
|
|
|
|
|
|
|
SubDirectory => { |
2605
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::ItemInfo', |
2606
|
|
|
|
|
|
|
Start => 6, # (4-byte version/flags + 2-byte count) |
2607
|
|
|
|
|
|
|
}, |
2608
|
|
|
|
|
|
|
},{ |
2609
|
|
|
|
|
|
|
Name => 'ItemInformation', |
2610
|
|
|
|
|
|
|
SubDirectory => { |
2611
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::ItemInfo', |
2612
|
|
|
|
|
|
|
Start => 8, # (4-byte version/flags + 4-byte count) |
2613
|
|
|
|
|
|
|
}, |
2614
|
|
|
|
|
|
|
}], |
2615
|
|
|
|
|
|
|
'xml ' => { |
2616
|
|
|
|
|
|
|
Name => 'XML', |
2617
|
|
|
|
|
|
|
Flags => [ 'Binary', 'Protected' ], |
2618
|
|
|
|
|
|
|
SubDirectory => { |
2619
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::XMP::XML', |
2620
|
|
|
|
|
|
|
IgnoreProp => { NonRealTimeMeta => 1 }, # ignore container for Sony 'nrtm' |
2621
|
|
|
|
|
|
|
}, |
2622
|
|
|
|
|
|
|
}, |
2623
|
|
|
|
|
|
|
'keys' => { |
2624
|
|
|
|
|
|
|
Name => 'Keys', |
2625
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Keys' }, |
2626
|
|
|
|
|
|
|
}, |
2627
|
|
|
|
|
|
|
bxml => { |
2628
|
|
|
|
|
|
|
Name => 'BinaryXML', |
2629
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
2630
|
|
|
|
|
|
|
}, |
2631
|
|
|
|
|
|
|
pitm => [{ |
2632
|
|
|
|
|
|
|
Name => 'PrimaryItemReference', |
2633
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\0/', # (version 0?) |
2634
|
|
|
|
|
|
|
RawConv => '$$self{PrimaryItem} = unpack("x4n",$val)', |
2635
|
|
|
|
|
|
|
WriteHook => sub { my ($val,$et) = @_; $$et{PrimaryItem} = unpack("x4n",$val); }, |
2636
|
|
|
|
|
|
|
},{ |
2637
|
|
|
|
|
|
|
Name => 'PrimaryItemReference', |
2638
|
|
|
|
|
|
|
RawConv => '$$self{PrimaryItem} = unpack("x4N",$val)', |
2639
|
|
|
|
|
|
|
WriteHook => sub { my ($val,$et) = @_; $$et{PrimaryItem} = unpack("x4N",$val); }, |
2640
|
|
|
|
|
|
|
}], |
2641
|
|
|
|
|
|
|
free => { #PH |
2642
|
|
|
|
|
|
|
Name => 'Free', |
2643
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
2644
|
|
|
|
|
|
|
}, |
2645
|
|
|
|
|
|
|
iprp => { |
2646
|
|
|
|
|
|
|
Name => 'ItemProperties', |
2647
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ItemProp' }, |
2648
|
|
|
|
|
|
|
}, |
2649
|
|
|
|
|
|
|
iref => { |
2650
|
|
|
|
|
|
|
Name => 'ItemReference', |
2651
|
|
|
|
|
|
|
# the version is needed to parse some of the item references |
2652
|
|
|
|
|
|
|
Condition => '$$self{ItemRefVersion} = ord($$valPt); 1', |
2653
|
|
|
|
|
|
|
SubDirectory => { |
2654
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::ItemRef', |
2655
|
|
|
|
|
|
|
Start => 4, |
2656
|
|
|
|
|
|
|
}, |
2657
|
|
|
|
|
|
|
}, |
2658
|
|
|
|
|
|
|
idat => { |
2659
|
|
|
|
|
|
|
Name => 'MetaImageSize', #PH (NC) |
2660
|
|
|
|
|
|
|
Format => 'int16u', |
2661
|
|
|
|
|
|
|
# (don't know what the first two numbers are for) |
2662
|
|
|
|
|
|
|
PrintConv => '$val =~ s/^(\d+) (\d+) (\d+) (\d+)/${3}x$4/; $val', |
2663
|
|
|
|
|
|
|
}, |
2664
|
|
|
|
|
|
|
uuid => [ |
2665
|
|
|
|
|
|
|
{ #PH (Canon R5/R6 HIF) |
2666
|
|
|
|
|
|
|
Name => 'MetaVersion', # (NC) |
2667
|
|
|
|
|
|
|
Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/', |
2668
|
|
|
|
|
|
|
RawConv => 'substr($val, 0x14)', |
2669
|
|
|
|
|
|
|
}, |
2670
|
|
|
|
|
|
|
{ |
2671
|
|
|
|
|
|
|
Name => 'UUID-Unknown', |
2672
|
|
|
|
|
|
|
%unknownInfo, |
2673
|
|
|
|
|
|
|
}, |
2674
|
|
|
|
|
|
|
], |
2675
|
|
|
|
|
|
|
); |
2676
|
|
|
|
|
|
|
|
2677
|
|
|
|
|
|
|
# additional metadata container (ref ISO14496-12:2015) |
2678
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::OtherMeta = ( |
2679
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2680
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
2681
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2682
|
|
|
|
|
|
|
mere => { |
2683
|
|
|
|
|
|
|
Name => 'MetaRelation', |
2684
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MetaRelation' }, |
2685
|
|
|
|
|
|
|
}, |
2686
|
|
|
|
|
|
|
meta => { |
2687
|
|
|
|
|
|
|
Name => 'Meta', |
2688
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' }, |
2689
|
|
|
|
|
|
|
}, |
2690
|
|
|
|
|
|
|
); |
2691
|
|
|
|
|
|
|
|
2692
|
|
|
|
|
|
|
# metabox relation (ref ISO14496-12:2015) |
2693
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MetaRelation = ( |
2694
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
2695
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2696
|
|
|
|
|
|
|
FORMAT => 'int32u', |
2697
|
|
|
|
|
|
|
# 0 => 'MetaRelationVersion', |
2698
|
|
|
|
|
|
|
# 1 => 'FirstMetaboxHandlerType', |
2699
|
|
|
|
|
|
|
# 2 => 'FirstMetaboxHandlerType', |
2700
|
|
|
|
|
|
|
# 3 => { Name => 'MetaboxRelation', Format => 'int8u' }, |
2701
|
|
|
|
|
|
|
); |
2702
|
|
|
|
|
|
|
|
2703
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ItemProp = ( |
2704
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2705
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
2706
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
2707
|
|
|
|
|
|
|
ipco => { |
2708
|
|
|
|
|
|
|
Name => 'ItemPropertyContainer', |
2709
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ItemPropCont' }, |
2710
|
|
|
|
|
|
|
}, |
2711
|
|
|
|
|
|
|
ipma => { |
2712
|
|
|
|
|
|
|
Name => 'ItemPropertyAssociation', |
2713
|
|
|
|
|
|
|
RawConv => \&ParseItemPropAssoc, |
2714
|
|
|
|
|
|
|
WriteHook => \&ParseItemPropAssoc, |
2715
|
|
|
|
|
|
|
Notes => 'parsed, but not extracted as a tag', |
2716
|
|
|
|
|
|
|
}, |
2717
|
|
|
|
|
|
|
); |
2718
|
|
|
|
|
|
|
|
2719
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ItemPropCont = ( |
2720
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2721
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
2722
|
|
|
|
|
|
|
PERMANENT => 1, # (can't be deleted) |
2723
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
2724
|
|
|
|
|
|
|
VARS => { START_INDEX => 1 }, # show verbose indices starting at 1 |
2725
|
|
|
|
|
|
|
colr => [{ |
2726
|
|
|
|
|
|
|
Name => 'ICC_Profile', |
2727
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^(prof|rICC)/', |
2728
|
|
|
|
|
|
|
Permanent => 0, # (in QuickTime, this writes a zero-length box instead of deleting) |
2729
|
|
|
|
|
|
|
SubDirectory => { |
2730
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::ICC_Profile::Main', |
2731
|
|
|
|
|
|
|
Start => 4, |
2732
|
|
|
|
|
|
|
}, |
2733
|
|
|
|
|
|
|
},{ |
2734
|
|
|
|
|
|
|
Name => 'ColorRepresentation', |
2735
|
|
|
|
|
|
|
ValueConv => 'join(" ", substr($val,0,4), unpack("x4n*",$val))', |
2736
|
|
|
|
|
|
|
}], |
2737
|
|
|
|
|
|
|
irot => { |
2738
|
|
|
|
|
|
|
Name => 'Rotation', |
2739
|
|
|
|
|
|
|
Format => 'int8u', |
2740
|
|
|
|
|
|
|
Writable => 'int8u', |
2741
|
|
|
|
|
|
|
Protected => 1, |
2742
|
|
|
|
|
|
|
ValueConv => '$val * 90', |
2743
|
|
|
|
|
|
|
ValueConvInv => 'int($val / 90 + 0.5)', |
2744
|
|
|
|
|
|
|
}, |
2745
|
|
|
|
|
|
|
ispe => { |
2746
|
|
|
|
|
|
|
Name => 'ImageSpatialExtent', |
2747
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\0{4}/', # (version/flags == 0/0) |
2748
|
|
|
|
|
|
|
RawConv => q{ |
2749
|
|
|
|
|
|
|
my @dim = unpack("x4N*", $val); |
2750
|
|
|
|
|
|
|
return undef if @dim < 2; |
2751
|
|
|
|
|
|
|
unless ($$self{DOC_NUM}) { |
2752
|
|
|
|
|
|
|
$self->FoundTag(ImageWidth => $dim[0]); |
2753
|
|
|
|
|
|
|
$self->FoundTag(ImageHeight => $dim[1]); |
2754
|
|
|
|
|
|
|
} |
2755
|
|
|
|
|
|
|
return join ' ', @dim; |
2756
|
|
|
|
|
|
|
}, |
2757
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /x/; $val', |
2758
|
|
|
|
|
|
|
}, |
2759
|
|
|
|
|
|
|
pixi => { |
2760
|
|
|
|
|
|
|
Name => 'ImagePixelDepth', |
2761
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\0{4}./s', # (version/flags == 0/0 and count) |
2762
|
|
|
|
|
|
|
RawConv => 'join " ", unpack("x5C*", $val)', |
2763
|
|
|
|
|
|
|
}, |
2764
|
|
|
|
|
|
|
auxC => { |
2765
|
|
|
|
|
|
|
Name => 'AuxiliaryImageType', |
2766
|
|
|
|
|
|
|
Format => 'undef', |
2767
|
|
|
|
|
|
|
RawConv => '$val = substr($val, 4); $val =~ s/\0.*//s; $val', |
2768
|
|
|
|
|
|
|
}, |
2769
|
|
|
|
|
|
|
pasp => { |
2770
|
|
|
|
|
|
|
Name => 'PixelAspectRatio', |
2771
|
|
|
|
|
|
|
Format => 'int32u', |
2772
|
|
|
|
|
|
|
Writable => 'int32u', |
2773
|
|
|
|
|
|
|
Protected => 1, |
2774
|
|
|
|
|
|
|
}, |
2775
|
|
|
|
|
|
|
rloc => { |
2776
|
|
|
|
|
|
|
Name => 'RelativeLocation', |
2777
|
|
|
|
|
|
|
Format => 'int32u', |
2778
|
|
|
|
|
|
|
RawConv => '$val =~ s/^\S+\s+//; $val', # remove version/flags |
2779
|
|
|
|
|
|
|
}, |
2780
|
|
|
|
|
|
|
clap => { |
2781
|
|
|
|
|
|
|
Name => 'CleanAperture', |
2782
|
|
|
|
|
|
|
Format => 'rational64s', |
2783
|
|
|
|
|
|
|
Notes => '4 numbers: width, height, left and top', |
2784
|
|
|
|
|
|
|
}, |
2785
|
|
|
|
|
|
|
hvcC => { |
2786
|
|
|
|
|
|
|
Name => 'HEVCConfiguration', |
2787
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HEVCConfig' }, |
2788
|
|
|
|
|
|
|
}, |
2789
|
|
|
|
|
|
|
av1C => { |
2790
|
|
|
|
|
|
|
Name => 'AV1Configuration', |
2791
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AV1Config' }, |
2792
|
|
|
|
|
|
|
}, |
2793
|
|
|
|
|
|
|
); |
2794
|
|
|
|
|
|
|
|
2795
|
|
|
|
|
|
|
# HEVC configuration (ref https://github.com/MPEGGroup/isobmff/blob/master/IsoLib/libisomediafile/src/HEVCConfigAtom.c) |
2796
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::HEVCConfig = ( |
2797
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
2798
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2799
|
|
|
|
|
|
|
FIRST_ENTRY => 0, |
2800
|
|
|
|
|
|
|
0 => 'HEVCConfigurationVersion', |
2801
|
|
|
|
|
|
|
1 => { |
2802
|
|
|
|
|
|
|
Name => 'GeneralProfileSpace', |
2803
|
|
|
|
|
|
|
Mask => 0xc0, |
2804
|
|
|
|
|
|
|
PrintConv => { 0 => 'Conforming' }, |
2805
|
|
|
|
|
|
|
}, |
2806
|
|
|
|
|
|
|
1.1 => { |
2807
|
|
|
|
|
|
|
Name => 'GeneralTierFlag', |
2808
|
|
|
|
|
|
|
Mask => 0x20, |
2809
|
|
|
|
|
|
|
PrintConv => { |
2810
|
|
|
|
|
|
|
0 => 'Main Tier', |
2811
|
|
|
|
|
|
|
1 => 'High Tier', |
2812
|
|
|
|
|
|
|
}, |
2813
|
|
|
|
|
|
|
}, |
2814
|
|
|
|
|
|
|
1.2 => { |
2815
|
|
|
|
|
|
|
Name => 'GeneralProfileIDC', |
2816
|
|
|
|
|
|
|
Mask => 0x1f, |
2817
|
|
|
|
|
|
|
PrintConv => { |
2818
|
|
|
|
|
|
|
0 => 'No Profile', |
2819
|
|
|
|
|
|
|
1 => 'Main', |
2820
|
|
|
|
|
|
|
2 => 'Main 10', |
2821
|
|
|
|
|
|
|
3 => 'Main Still Picture', |
2822
|
|
|
|
|
|
|
4 => 'Format Range Extensions', |
2823
|
|
|
|
|
|
|
5 => 'High Throughput', |
2824
|
|
|
|
|
|
|
6 => 'Multiview Main', |
2825
|
|
|
|
|
|
|
7 => 'Scalable Main', |
2826
|
|
|
|
|
|
|
8 => '3D Main', |
2827
|
|
|
|
|
|
|
9 => 'Screen Content Coding Extensions', |
2828
|
|
|
|
|
|
|
10 => 'Scalable Format Range Extensions', |
2829
|
|
|
|
|
|
|
11 => 'High Throughput Screen Content Coding Extensions', |
2830
|
|
|
|
|
|
|
}, |
2831
|
|
|
|
|
|
|
}, |
2832
|
|
|
|
|
|
|
2 => { |
2833
|
|
|
|
|
|
|
Name => 'GenProfileCompatibilityFlags', |
2834
|
|
|
|
|
|
|
Format => 'int32u', |
2835
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
2836
|
|
|
|
|
|
|
31 => 'No Profile', # (bit 0 in stream) |
2837
|
|
|
|
|
|
|
30 => 'Main', # (bit 1 in stream) |
2838
|
|
|
|
|
|
|
29 => 'Main 10', # (bit 2 in stream) |
2839
|
|
|
|
|
|
|
28 => 'Main Still Picture', # (bit 3 in stream) |
2840
|
|
|
|
|
|
|
27 => 'Format Range Extensions',# (...) |
2841
|
|
|
|
|
|
|
26 => 'High Throughput', |
2842
|
|
|
|
|
|
|
25 => 'Multiview Main', |
2843
|
|
|
|
|
|
|
24 => 'Scalable Main', |
2844
|
|
|
|
|
|
|
23 => '3D Main', |
2845
|
|
|
|
|
|
|
22 => 'Screen Content Coding Extensions', |
2846
|
|
|
|
|
|
|
21 => 'Scalable Format Range Extensions', |
2847
|
|
|
|
|
|
|
20 => 'High Throughput Screen Content Coding Extensions', |
2848
|
|
|
|
|
|
|
}}, |
2849
|
|
|
|
|
|
|
}, |
2850
|
|
|
|
|
|
|
6 => { |
2851
|
|
|
|
|
|
|
Name => 'ConstraintIndicatorFlags', |
2852
|
|
|
|
|
|
|
Format => 'int8u[6]', |
2853
|
|
|
|
|
|
|
}, |
2854
|
|
|
|
|
|
|
12 => { |
2855
|
|
|
|
|
|
|
Name => 'GeneralLevelIDC', |
2856
|
|
|
|
|
|
|
PrintConv => 'sprintf("%d (level %.1f)", $val, $val/30)', |
2857
|
|
|
|
|
|
|
}, |
2858
|
|
|
|
|
|
|
13 => { |
2859
|
|
|
|
|
|
|
Name => 'MinSpatialSegmentationIDC', |
2860
|
|
|
|
|
|
|
Format => 'int16u', |
2861
|
|
|
|
|
|
|
Mask => 0x0fff, |
2862
|
|
|
|
|
|
|
}, |
2863
|
|
|
|
|
|
|
15 => { |
2864
|
|
|
|
|
|
|
Name => 'ParallelismType', |
2865
|
|
|
|
|
|
|
Mask => 0x03, |
2866
|
|
|
|
|
|
|
}, |
2867
|
|
|
|
|
|
|
16 => { |
2868
|
|
|
|
|
|
|
Name => 'ChromaFormat', |
2869
|
|
|
|
|
|
|
Mask => 0x03, |
2870
|
|
|
|
|
|
|
PrintConv => { |
2871
|
|
|
|
|
|
|
0 => 'Monochrome', |
2872
|
|
|
|
|
|
|
1 => '4:2:0', |
2873
|
|
|
|
|
|
|
2 => '4:2:2', |
2874
|
|
|
|
|
|
|
3 => '4:4:4', |
2875
|
|
|
|
|
|
|
}, |
2876
|
|
|
|
|
|
|
}, |
2877
|
|
|
|
|
|
|
17 => { |
2878
|
|
|
|
|
|
|
Name => 'BitDepthLuma', |
2879
|
|
|
|
|
|
|
Mask => 0x07, |
2880
|
|
|
|
|
|
|
ValueConv => '$val + 8', |
2881
|
|
|
|
|
|
|
}, |
2882
|
|
|
|
|
|
|
18 => { |
2883
|
|
|
|
|
|
|
Name => 'BitDepthChroma', |
2884
|
|
|
|
|
|
|
Mask => 0x07, |
2885
|
|
|
|
|
|
|
ValueConv => '$val + 8', |
2886
|
|
|
|
|
|
|
}, |
2887
|
|
|
|
|
|
|
19 => { |
2888
|
|
|
|
|
|
|
Name => 'AverageFrameRate', |
2889
|
|
|
|
|
|
|
Format => 'int16u', |
2890
|
|
|
|
|
|
|
ValueConv => '$val / 256', |
2891
|
|
|
|
|
|
|
}, |
2892
|
|
|
|
|
|
|
21 => { |
2893
|
|
|
|
|
|
|
Name => 'ConstantFrameRate', |
2894
|
|
|
|
|
|
|
Mask => 0xc0, |
2895
|
|
|
|
|
|
|
PrintConv => { |
2896
|
|
|
|
|
|
|
0 => 'Unknown', |
2897
|
|
|
|
|
|
|
1 => 'Constant Frame Rate', |
2898
|
|
|
|
|
|
|
2 => 'Each Temporal Layer is Constant Frame Rate', |
2899
|
|
|
|
|
|
|
}, |
2900
|
|
|
|
|
|
|
}, |
2901
|
|
|
|
|
|
|
21.1 => { |
2902
|
|
|
|
|
|
|
Name => 'NumTemporalLayers', |
2903
|
|
|
|
|
|
|
Mask => 0x38, |
2904
|
|
|
|
|
|
|
}, |
2905
|
|
|
|
|
|
|
21.2 => { |
2906
|
|
|
|
|
|
|
Name => 'TemporalIDNested', |
2907
|
|
|
|
|
|
|
Mask => 0x04, |
2908
|
|
|
|
|
|
|
PrintConv => { 0 => 'No', 1 => 'Yes' }, |
2909
|
|
|
|
|
|
|
}, |
2910
|
|
|
|
|
|
|
#21.3 => { |
2911
|
|
|
|
|
|
|
# Name => 'NALUnitLengthSize', |
2912
|
|
|
|
|
|
|
# Mask => 0x03, |
2913
|
|
|
|
|
|
|
# ValueConv => '$val + 1', |
2914
|
|
|
|
|
|
|
# PrintConv => { 1 => '8-bit', 2 => '16-bit', 4 => '32-bit' }, |
2915
|
|
|
|
|
|
|
#}, |
2916
|
|
|
|
|
|
|
#22 => 'NumberOfNALUnitArrays', |
2917
|
|
|
|
|
|
|
# (don't decode the NAL unit arrays) |
2918
|
|
|
|
|
|
|
); |
2919
|
|
|
|
|
|
|
|
2920
|
|
|
|
|
|
|
# HEVC configuration (ref https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox) |
2921
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::AV1Config = ( |
2922
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
2923
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
2924
|
|
|
|
|
|
|
FIRST_ENTRY => 0, |
2925
|
|
|
|
|
|
|
0 => { |
2926
|
|
|
|
|
|
|
Name => 'AV1ConfigurationVersion', |
2927
|
|
|
|
|
|
|
Mask => 0x7f, |
2928
|
|
|
|
|
|
|
}, |
2929
|
|
|
|
|
|
|
1.0 => { |
2930
|
|
|
|
|
|
|
Name => 'SeqProfile', |
2931
|
|
|
|
|
|
|
Mask => 0xe0, |
2932
|
|
|
|
|
|
|
Unknown => 1, |
2933
|
|
|
|
|
|
|
}, |
2934
|
|
|
|
|
|
|
1.1 => { |
2935
|
|
|
|
|
|
|
Name => 'SeqLevelIdx0', |
2936
|
|
|
|
|
|
|
Mask => 0x1f, |
2937
|
|
|
|
|
|
|
Unknown => 1, |
2938
|
|
|
|
|
|
|
}, |
2939
|
|
|
|
|
|
|
2.0 => { |
2940
|
|
|
|
|
|
|
Name => 'SeqTier0', |
2941
|
|
|
|
|
|
|
Mask => 0x80, |
2942
|
|
|
|
|
|
|
Unknown => 1, |
2943
|
|
|
|
|
|
|
}, |
2944
|
|
|
|
|
|
|
2.1 => { |
2945
|
|
|
|
|
|
|
Name => 'HighBitDepth', |
2946
|
|
|
|
|
|
|
Mask => 0x40, |
2947
|
|
|
|
|
|
|
Unknown => 1, |
2948
|
|
|
|
|
|
|
}, |
2949
|
|
|
|
|
|
|
2.2 => { |
2950
|
|
|
|
|
|
|
Name => 'TwelveBit', |
2951
|
|
|
|
|
|
|
Mask => 0x20, |
2952
|
|
|
|
|
|
|
Unknown => 1, |
2953
|
|
|
|
|
|
|
}, |
2954
|
|
|
|
|
|
|
2.3 => { |
2955
|
|
|
|
|
|
|
Name => 'ChromaFormat', # (Monochrome+SubSamplingX+SubSamplingY) |
2956
|
|
|
|
|
|
|
Notes => 'bits: 0x04 = Monochrome, 0x02 = SubSamplingX, 0x01 = SubSamplingY', |
2957
|
|
|
|
|
|
|
Mask => 0x1c, |
2958
|
|
|
|
|
|
|
PrintConv => { |
2959
|
|
|
|
|
|
|
0x00 => 'YUV 4:4:4', |
2960
|
|
|
|
|
|
|
0x02 => 'YUV 4:2:2', |
2961
|
|
|
|
|
|
|
0x03 => 'YUV 4:2:0', |
2962
|
|
|
|
|
|
|
0x07 => 'Monochrome 4:0:0', |
2963
|
|
|
|
|
|
|
}, |
2964
|
|
|
|
|
|
|
}, |
2965
|
|
|
|
|
|
|
2.4 => { |
2966
|
|
|
|
|
|
|
Name => 'ChromaSamplePosition', |
2967
|
|
|
|
|
|
|
Mask => 0x03, |
2968
|
|
|
|
|
|
|
PrintConv => { |
2969
|
|
|
|
|
|
|
0 => 'Unknown', |
2970
|
|
|
|
|
|
|
1 => 'Vertical', |
2971
|
|
|
|
|
|
|
2 => 'Colocated', |
2972
|
|
|
|
|
|
|
3 => '(reserved)', |
2973
|
|
|
|
|
|
|
}, |
2974
|
|
|
|
|
|
|
}, |
2975
|
|
|
|
|
|
|
3 => { |
2976
|
|
|
|
|
|
|
Name => 'InitialDelaySamples', |
2977
|
|
|
|
|
|
|
RawConv => '$val & 0x10 ? undef : ($val & 0x0f) + 1', |
2978
|
|
|
|
|
|
|
Unknown => 1, |
2979
|
|
|
|
|
|
|
}, |
2980
|
|
|
|
|
|
|
); |
2981
|
|
|
|
|
|
|
|
2982
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ItemRef = ( |
2983
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
2984
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
2985
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
2986
|
|
|
|
|
|
|
# (Note: ExifTool's ItemRefVersion may be used to test the iref version number) |
2987
|
|
|
|
|
|
|
NOTES => q{ |
2988
|
|
|
|
|
|
|
The Item reference entries listed in the table below contain information about |
2989
|
|
|
|
|
|
|
the associations between items in the file. This information is used by |
2990
|
|
|
|
|
|
|
ExifTool, but these entries are not extracted as tags. |
2991
|
|
|
|
|
|
|
}, |
2992
|
|
|
|
|
|
|
dimg => { Name => 'DerivedImageRef', RawConv => 'undef' }, |
2993
|
|
|
|
|
|
|
thmb => { Name => 'ThumbnailRef', RawConv => 'undef' }, |
2994
|
|
|
|
|
|
|
auxl => { Name => 'AuxiliaryImageRef', RawConv => 'undef' }, |
2995
|
|
|
|
|
|
|
cdsc => { |
2996
|
|
|
|
|
|
|
Name => 'ContentDescribes', |
2997
|
|
|
|
|
|
|
RawConv => \&ParseContentDescribes, |
2998
|
|
|
|
|
|
|
WriteHook => \&ParseContentDescribes, |
2999
|
|
|
|
|
|
|
}, |
3000
|
|
|
|
|
|
|
); |
3001
|
|
|
|
|
|
|
|
3002
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ItemInfo = ( |
3003
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
3004
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
3005
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
3006
|
|
|
|
|
|
|
# avc1 - AVC image |
3007
|
|
|
|
|
|
|
# hvc1 - HEVC image |
3008
|
|
|
|
|
|
|
# lhv1 - L-HEVC image |
3009
|
|
|
|
|
|
|
# infe - ItemInformationEntry |
3010
|
|
|
|
|
|
|
# infe types: avc1,hvc1,lhv1,Exif,xml1,iovl(overlay image),grid,mime,hvt1(tile image) |
3011
|
|
|
|
|
|
|
infe => { |
3012
|
|
|
|
|
|
|
Name => 'ItemInfoEntry', |
3013
|
|
|
|
|
|
|
RawConv => \&ParseItemInfoEntry, |
3014
|
|
|
|
|
|
|
WriteHook => \&ParseItemInfoEntry, |
3015
|
|
|
|
|
|
|
Notes => 'parsed, but not extracted as a tag', |
3016
|
|
|
|
|
|
|
}, |
3017
|
|
|
|
|
|
|
); |
3018
|
|
|
|
|
|
|
|
3019
|
|
|
|
|
|
|
# track reference atoms |
3020
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::TrackRef = ( |
3021
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
3022
|
|
|
|
|
|
|
GROUPS => { 1 => 'Track#', 2 => 'Video' }, |
3023
|
|
|
|
|
|
|
chap => { Name => 'ChapterListTrackID', Format => 'int32u' }, |
3024
|
|
|
|
|
|
|
tmcd => { Name => 'TimeCode', Format => 'int32u' }, |
3025
|
|
|
|
|
|
|
mpod => { #PH (FLIR MP4) |
3026
|
|
|
|
|
|
|
Name => 'ElementaryStreamTrack', |
3027
|
|
|
|
|
|
|
Format => 'int32u', |
3028
|
|
|
|
|
|
|
ValueConv => '$val =~ s/^1 //; $val', # (why 2 numbers? -- ignore the first if "1") |
3029
|
|
|
|
|
|
|
}, |
3030
|
|
|
|
|
|
|
# also: sync, scpt, ssrc, iTunesInfo |
3031
|
|
|
|
|
|
|
cdsc => { |
3032
|
|
|
|
|
|
|
Name => 'ContentDescribes', |
3033
|
|
|
|
|
|
|
Format => 'int32u', |
3034
|
|
|
|
|
|
|
PrintConv => '"Track $val"', |
3035
|
|
|
|
|
|
|
}, |
3036
|
|
|
|
|
|
|
# cdep (Structural Dependency QT tag?) |
3037
|
|
|
|
|
|
|
); |
3038
|
|
|
|
|
|
|
|
3039
|
|
|
|
|
|
|
# track aperture mode dimensions atoms |
3040
|
|
|
|
|
|
|
# (ref https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html) |
3041
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::TrackAperture = ( |
3042
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
3043
|
|
|
|
|
|
|
GROUPS => { 1 => 'Track#', 2 => 'Video' }, |
3044
|
|
|
|
|
|
|
clef => { |
3045
|
|
|
|
|
|
|
Name => 'CleanApertureDimensions', |
3046
|
|
|
|
|
|
|
Format => 'fixed32u', |
3047
|
|
|
|
|
|
|
Count => 3, |
3048
|
|
|
|
|
|
|
ValueConv => '$val =~ s/^.*? //; $val', # remove flags word |
3049
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /x/; $val', |
3050
|
|
|
|
|
|
|
}, |
3051
|
|
|
|
|
|
|
prof => { |
3052
|
|
|
|
|
|
|
Name => 'ProductionApertureDimensions', |
3053
|
|
|
|
|
|
|
Format => 'fixed32u', |
3054
|
|
|
|
|
|
|
Count => 3, |
3055
|
|
|
|
|
|
|
ValueConv => '$val =~ s/^.*? //; $val', |
3056
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /x/; $val', |
3057
|
|
|
|
|
|
|
}, |
3058
|
|
|
|
|
|
|
enof => { |
3059
|
|
|
|
|
|
|
Name => 'EncodedPixelsDimensions', |
3060
|
|
|
|
|
|
|
Format => 'fixed32u', |
3061
|
|
|
|
|
|
|
Count => 3, |
3062
|
|
|
|
|
|
|
ValueConv => '$val =~ s/^.*? //; $val', |
3063
|
|
|
|
|
|
|
PrintConv => '$val =~ tr/ /x/; $val', |
3064
|
|
|
|
|
|
|
}, |
3065
|
|
|
|
|
|
|
); |
3066
|
|
|
|
|
|
|
|
3067
|
|
|
|
|
|
|
# item list atoms |
3068
|
|
|
|
|
|
|
# -> these atoms are unique, and contain one or more 'data' atoms |
3069
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ItemList = ( |
3070
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
3071
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
3072
|
|
|
|
|
|
|
CHECK_PROC => \&CheckQTValue, |
3073
|
|
|
|
|
|
|
WRITABLE => 1, |
3074
|
|
|
|
|
|
|
PREFERRED => 2, # (preferred over UserData and Keys tags when writing) |
3075
|
|
|
|
|
|
|
FORMAT => 'string', |
3076
|
|
|
|
|
|
|
GROUPS => { 1 => 'ItemList', 2 => 'Audio' }, |
3077
|
|
|
|
|
|
|
WRITE_GROUP => 'ItemList', |
3078
|
|
|
|
|
|
|
LANG_INFO => \&GetLangInfo, |
3079
|
|
|
|
|
|
|
NOTES => q{ |
3080
|
|
|
|
|
|
|
This is the preferred location for creating new QuickTime tags. Tags in |
3081
|
|
|
|
|
|
|
this table support alternate languages which are accessed by adding a |
3082
|
|
|
|
|
|
|
3-character ISO 639-2 language code and an optional ISO 3166-1 alpha 2 |
3083
|
|
|
|
|
|
|
country code to the tag name (eg. "ItemList:Title-fra" or |
3084
|
|
|
|
|
|
|
"ItemList::Title-fra-FR"). When creating a new Meta box to contain the |
3085
|
|
|
|
|
|
|
ItemList directory, by default ExifTool adds an 'mdir' (Metadata) Handler |
3086
|
|
|
|
|
|
|
box because Apple software may ignore ItemList tags otherwise, but the API |
3087
|
|
|
|
|
|
|
L option may be set to 0 to avoid this. |
3088
|
|
|
|
|
|
|
}, |
3089
|
|
|
|
|
|
|
# in this table, binary 1 and 2-byte "data"-type tags are interpreted as |
3090
|
|
|
|
|
|
|
# int8u and int16u. Multi-byte binary "data" tags are extracted as binary data. |
3091
|
|
|
|
|
|
|
# (Note that the Preferred property is set to 0 for some tags to prevent them |
3092
|
|
|
|
|
|
|
# from being created when a same-named tag already exists in the table) |
3093
|
|
|
|
|
|
|
"\xa9ART" => 'Artist', |
3094
|
|
|
|
|
|
|
"\xa9alb" => 'Album', |
3095
|
|
|
|
|
|
|
"\xa9aut" => { Name => 'Author', Avoid => 1, Groups => { 2 => 'Author' } }, #forum10091 ('auth' is preferred) |
3096
|
|
|
|
|
|
|
"\xa9cmt" => 'Comment', |
3097
|
|
|
|
|
|
|
"\xa9com" => { Name => 'Composer', Avoid => 1, }, # ("\xa9wrt" is preferred in ItemList) |
3098
|
|
|
|
|
|
|
"\xa9day" => { |
3099
|
|
|
|
|
|
|
Name => 'ContentCreateDate', |
3100
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
3101
|
|
|
|
|
|
|
Shift => 'Time', |
3102
|
|
|
|
|
|
|
# handle values in the form "2010-02-12T13:27:14-0800" |
3103
|
|
|
|
|
|
|
ValueConv => q{ |
3104
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
3105
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::ConvertXMPDate($val); |
3106
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary |
3107
|
|
|
|
|
|
|
return $val; |
3108
|
|
|
|
|
|
|
}, |
3109
|
|
|
|
|
|
|
ValueConvInv => q{ |
3110
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
3111
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::FormatXMPDate($val); |
3112
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon |
3113
|
|
|
|
|
|
|
return $val; |
3114
|
|
|
|
|
|
|
}, |
3115
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
3116
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) |
3117
|
|
|
|
|
|
|
}, |
3118
|
|
|
|
|
|
|
"\xa9des" => 'Description', #4 |
3119
|
|
|
|
|
|
|
"\xa9enc" => 'EncodedBy', #10 |
3120
|
|
|
|
|
|
|
"\xa9gen" => 'Genre', |
3121
|
|
|
|
|
|
|
"\xa9grp" => 'Grouping', |
3122
|
|
|
|
|
|
|
"\xa9lyr" => 'Lyrics', |
3123
|
|
|
|
|
|
|
"\xa9nam" => 'Title', |
3124
|
|
|
|
|
|
|
"\xa9too" => 'Encoder', |
3125
|
|
|
|
|
|
|
"\xa9trk" => 'Track', |
3126
|
|
|
|
|
|
|
"\xa9wrt" => 'Composer', |
3127
|
|
|
|
|
|
|
# |
3128
|
|
|
|
|
|
|
# the following tags written by AtomicParsley 0.9.6 |
3129
|
|
|
|
|
|
|
# (ref https://exiftool.org/forum/index.php?topic=11455.0) |
3130
|
|
|
|
|
|
|
# |
3131
|
|
|
|
|
|
|
"\xa9st3" => 'Subtitle', |
3132
|
|
|
|
|
|
|
"\xa9con" => 'Conductor', |
3133
|
|
|
|
|
|
|
"\xa9sol" => 'Soloist', |
3134
|
|
|
|
|
|
|
"\xa9arg" => 'Arranger', |
3135
|
|
|
|
|
|
|
"\xa9ope" => 'OriginalArtist', |
3136
|
|
|
|
|
|
|
"\xa9dir" => 'Director', |
3137
|
|
|
|
|
|
|
"\xa9ard" => 'ArtDirector', |
3138
|
|
|
|
|
|
|
"\xa9sne" => 'SoundEngineer', |
3139
|
|
|
|
|
|
|
"\xa9prd" => 'Producer', |
3140
|
|
|
|
|
|
|
"\xa9xpd" => 'ExecutiveProducer', |
3141
|
|
|
|
|
|
|
sdes => 'StoreDescription', |
3142
|
|
|
|
|
|
|
# |
3143
|
|
|
|
|
|
|
'----' => { |
3144
|
|
|
|
|
|
|
Name => 'iTunesInfo', |
3145
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::iTunesInfo' }, |
3146
|
|
|
|
|
|
|
}, |
3147
|
|
|
|
|
|
|
aART => { Name => 'AlbumArtist', Groups => { 2 => 'Author' } }, |
3148
|
|
|
|
|
|
|
covr => { Name => 'CoverArt', Groups => { 2 => 'Preview' } }, |
3149
|
|
|
|
|
|
|
cpil => { #10 |
3150
|
|
|
|
|
|
|
Name => 'Compilation', |
3151
|
|
|
|
|
|
|
Format => 'int8u', #27 (ref 23 contradicts what AtomicParsley actually writes, which is int8s) |
3152
|
|
|
|
|
|
|
Writable => 'int8s', |
3153
|
|
|
|
|
|
|
PrintConv => { 0 => 'No', 1 => 'Yes' }, |
3154
|
|
|
|
|
|
|
}, |
3155
|
|
|
|
|
|
|
disk => { |
3156
|
|
|
|
|
|
|
Name => 'DiskNumber', |
3157
|
|
|
|
|
|
|
Format => 'undef', # (necessary to prevent decoding as string!) |
3158
|
|
|
|
|
|
|
ValueConv => q{ |
3159
|
|
|
|
|
|
|
return \$val unless length($val) >= 6; |
3160
|
|
|
|
|
|
|
my @a = unpack 'x2nn', $val; |
3161
|
|
|
|
|
|
|
return $a[1] ? join(' of ', @a) : $a[0]; |
3162
|
|
|
|
|
|
|
}, |
3163
|
|
|
|
|
|
|
ValueConvInv => q{ |
3164
|
|
|
|
|
|
|
my @a = $val =~ /\d+/g; |
3165
|
|
|
|
|
|
|
return undef if @a == 0 or @a > 2; |
3166
|
|
|
|
|
|
|
push @a, 0 if @a == 1; |
3167
|
|
|
|
|
|
|
return pack('n3', 0, @a); |
3168
|
|
|
|
|
|
|
}, |
3169
|
|
|
|
|
|
|
}, |
3170
|
|
|
|
|
|
|
pgap => { #10 |
3171
|
|
|
|
|
|
|
Name => 'PlayGap', |
3172
|
|
|
|
|
|
|
Format => 'int8u', #23 |
3173
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
3174
|
|
|
|
|
|
|
PrintConv => { |
3175
|
|
|
|
|
|
|
0 => 'Insert Gap', |
3176
|
|
|
|
|
|
|
1 => 'No Gap', |
3177
|
|
|
|
|
|
|
}, |
3178
|
|
|
|
|
|
|
}, |
3179
|
|
|
|
|
|
|
tmpo => { |
3180
|
|
|
|
|
|
|
Name => 'BeatsPerMinute', |
3181
|
|
|
|
|
|
|
# marked as boolean but really int16u in my sample |
3182
|
|
|
|
|
|
|
# (but written as int16s by iTunes and AtomicParsley, ref forum11506) |
3183
|
|
|
|
|
|
|
Format => 'int16u', |
3184
|
|
|
|
|
|
|
Writable => 'int16s', |
3185
|
|
|
|
|
|
|
}, |
3186
|
|
|
|
|
|
|
trkn => { |
3187
|
|
|
|
|
|
|
Name => 'TrackNumber', |
3188
|
|
|
|
|
|
|
Format => 'undef', # (necessary to prevent decoding as string!) |
3189
|
|
|
|
|
|
|
ValueConv => q{ |
3190
|
|
|
|
|
|
|
return \$val unless length($val) >= 6; |
3191
|
|
|
|
|
|
|
my @a = unpack 'x2nn', $val; |
3192
|
|
|
|
|
|
|
return $a[1] ? join(' of ', @a) : $a[0]; |
3193
|
|
|
|
|
|
|
}, |
3194
|
|
|
|
|
|
|
# (see forum11501 for discussion about the format used) |
3195
|
|
|
|
|
|
|
ValueConvInv => q{ |
3196
|
|
|
|
|
|
|
my @a = $val =~ /\d+/g; |
3197
|
|
|
|
|
|
|
return undef if @a == 0 or @a > 2; |
3198
|
|
|
|
|
|
|
push @a, 0 if @a == 1; |
3199
|
|
|
|
|
|
|
return pack('n4', 0, @a, 0); |
3200
|
|
|
|
|
|
|
}, |
3201
|
|
|
|
|
|
|
}, |
3202
|
|
|
|
|
|
|
# |
3203
|
|
|
|
|
|
|
# Note: it is possible that the tags below are not being decoded properly |
3204
|
|
|
|
|
|
|
# because I don't have samples to verify many of these - PH |
3205
|
|
|
|
|
|
|
# |
3206
|
|
|
|
|
|
|
akID => { #10 |
3207
|
|
|
|
|
|
|
Name => 'AppleStoreAccountType', |
3208
|
|
|
|
|
|
|
Format => 'int8u', #24 |
3209
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
3210
|
|
|
|
|
|
|
PrintConv => { |
3211
|
|
|
|
|
|
|
0 => 'iTunes', |
3212
|
|
|
|
|
|
|
1 => 'AOL', |
3213
|
|
|
|
|
|
|
}, |
3214
|
|
|
|
|
|
|
}, |
3215
|
|
|
|
|
|
|
albm => { Name => 'Album', Avoid => 1 }, #(ffmpeg source) |
3216
|
|
|
|
|
|
|
apID => 'AppleStoreAccount', |
3217
|
|
|
|
|
|
|
atID => { #10 (or TV series) |
3218
|
|
|
|
|
|
|
Name => 'AlbumTitleID', |
3219
|
|
|
|
|
|
|
Format => 'int32u', |
3220
|
|
|
|
|
|
|
Writable => 'int32s', #27 |
3221
|
|
|
|
|
|
|
}, |
3222
|
|
|
|
|
|
|
auth => { Name => 'Author', Groups => { 2 => 'Author' } }, |
3223
|
|
|
|
|
|
|
catg => 'Category', #7 |
3224
|
|
|
|
|
|
|
cnID => { #10 |
3225
|
|
|
|
|
|
|
Name => 'AppleStoreCatalogID', |
3226
|
|
|
|
|
|
|
Format => 'int32u', |
3227
|
|
|
|
|
|
|
Writable => 'int32s', #27 |
3228
|
|
|
|
|
|
|
}, |
3229
|
|
|
|
|
|
|
cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } }, |
3230
|
|
|
|
|
|
|
dscp => { Name => 'Description', Avoid => 1 }, |
3231
|
|
|
|
|
|
|
desc => { Name => 'Description', Avoid => 1 }, #7 |
3232
|
|
|
|
|
|
|
gnre => { #10 |
3233
|
|
|
|
|
|
|
Name => 'Genre', |
3234
|
|
|
|
|
|
|
Avoid => 1, |
3235
|
|
|
|
|
|
|
# (Note: see https://exiftool.org/forum/index.php?topic=11537.0) |
3236
|
|
|
|
|
|
|
Format => 'undef', |
3237
|
|
|
|
|
|
|
ValueConv => 'unpack("n",$val)', |
3238
|
|
|
|
|
|
|
ValueConvInv => '$val =~ /^\d+$/ ? pack("n",$val) : undef', |
3239
|
|
|
|
|
|
|
PrintConv => q{ |
3240
|
|
|
|
|
|
|
return $val unless $val =~ /^\d+$/; |
3241
|
|
|
|
|
|
|
require Image::ExifTool::ID3; |
3242
|
|
|
|
|
|
|
Image::ExifTool::ID3::PrintGenre($val - 1); # note the "- 1" |
3243
|
|
|
|
|
|
|
}, |
3244
|
|
|
|
|
|
|
PrintConvInv => q{ |
3245
|
|
|
|
|
|
|
return $val if $val =~ /^[0-9]+$/; |
3246
|
|
|
|
|
|
|
require Image::ExifTool::ID3; |
3247
|
|
|
|
|
|
|
my $id = Image::ExifTool::ID3::GetGenreID($val); |
3248
|
|
|
|
|
|
|
return unless defined $id and $id =~ /^\d+$/; |
3249
|
|
|
|
|
|
|
return $id + 1; |
3250
|
|
|
|
|
|
|
}, |
3251
|
|
|
|
|
|
|
}, |
3252
|
|
|
|
|
|
|
egid => 'EpisodeGlobalUniqueID', #7 |
3253
|
|
|
|
|
|
|
geID => { #10 |
3254
|
|
|
|
|
|
|
Name => 'GenreID', |
3255
|
|
|
|
|
|
|
Format => 'int32u', |
3256
|
|
|
|
|
|
|
Writable => 'int32s', #27 |
3257
|
|
|
|
|
|
|
SeparateTable => 1, |
3258
|
|
|
|
|
|
|
# the following lookup is based on http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres |
3259
|
|
|
|
|
|
|
# (see scripts/parse_genre to parse genre JSON file from above) |
3260
|
|
|
|
|
|
|
PrintConv => { #21/PH |
3261
|
|
|
|
|
|
|
2 => 'Music|Blues', |
3262
|
|
|
|
|
|
|
3 => 'Music|Comedy', |
3263
|
|
|
|
|
|
|
4 => "Music|Children's Music", |
3264
|
|
|
|
|
|
|
5 => 'Music|Classical', |
3265
|
|
|
|
|
|
|
6 => 'Music|Country', |
3266
|
|
|
|
|
|
|
7 => 'Music|Electronic', |
3267
|
|
|
|
|
|
|
8 => 'Music|Holiday', |
3268
|
|
|
|
|
|
|
9 => 'Music|Classical|Opera', |
3269
|
|
|
|
|
|
|
10 => 'Music|Singer/Songwriter', |
3270
|
|
|
|
|
|
|
11 => 'Music|Jazz', |
3271
|
|
|
|
|
|
|
12 => 'Music|Latino', |
3272
|
|
|
|
|
|
|
13 => 'Music|New Age', |
3273
|
|
|
|
|
|
|
14 => 'Music|Pop', |
3274
|
|
|
|
|
|
|
15 => 'Music|R&B/Soul', |
3275
|
|
|
|
|
|
|
16 => 'Music|Soundtrack', |
3276
|
|
|
|
|
|
|
17 => 'Music|Dance', |
3277
|
|
|
|
|
|
|
18 => 'Music|Hip-Hop/Rap', |
3278
|
|
|
|
|
|
|
19 => 'Music|World', |
3279
|
|
|
|
|
|
|
20 => 'Music|Alternative', |
3280
|
|
|
|
|
|
|
21 => 'Music|Rock', |
3281
|
|
|
|
|
|
|
22 => 'Music|Christian & Gospel', |
3282
|
|
|
|
|
|
|
23 => 'Music|Vocal', |
3283
|
|
|
|
|
|
|
24 => 'Music|Reggae', |
3284
|
|
|
|
|
|
|
25 => 'Music|Easy Listening', |
3285
|
|
|
|
|
|
|
26 => 'Podcasts', |
3286
|
|
|
|
|
|
|
27 => 'Music|J-Pop', |
3287
|
|
|
|
|
|
|
28 => 'Music|Enka', |
3288
|
|
|
|
|
|
|
29 => 'Music|Anime', |
3289
|
|
|
|
|
|
|
30 => 'Music|Kayokyoku', |
3290
|
|
|
|
|
|
|
31 => 'Music Videos', |
3291
|
|
|
|
|
|
|
32 => 'TV Shows', |
3292
|
|
|
|
|
|
|
33 => 'Movies', |
3293
|
|
|
|
|
|
|
34 => 'Music', |
3294
|
|
|
|
|
|
|
35 => 'iPod Games', |
3295
|
|
|
|
|
|
|
36 => 'App Store', |
3296
|
|
|
|
|
|
|
37 => 'Tones', |
3297
|
|
|
|
|
|
|
38 => 'Books', |
3298
|
|
|
|
|
|
|
39 => 'Mac App Store', |
3299
|
|
|
|
|
|
|
40 => 'Textbooks', |
3300
|
|
|
|
|
|
|
50 => 'Music|Fitness & Workout', |
3301
|
|
|
|
|
|
|
51 => 'Music|Pop|K-Pop', |
3302
|
|
|
|
|
|
|
52 => 'Music|Karaoke', |
3303
|
|
|
|
|
|
|
53 => 'Music|Instrumental', |
3304
|
|
|
|
|
|
|
74 => 'Audiobooks|News', |
3305
|
|
|
|
|
|
|
75 => 'Audiobooks|Programs & Performances', |
3306
|
|
|
|
|
|
|
500 => 'Fitness Music', |
3307
|
|
|
|
|
|
|
501 => 'Fitness Music|Pop', |
3308
|
|
|
|
|
|
|
502 => 'Fitness Music|Dance', |
3309
|
|
|
|
|
|
|
503 => 'Fitness Music|Hip-Hop', |
3310
|
|
|
|
|
|
|
504 => 'Fitness Music|Rock', |
3311
|
|
|
|
|
|
|
505 => 'Fitness Music|Alt/Indie', |
3312
|
|
|
|
|
|
|
506 => 'Fitness Music|Latino', |
3313
|
|
|
|
|
|
|
507 => 'Fitness Music|Country', |
3314
|
|
|
|
|
|
|
508 => 'Fitness Music|World', |
3315
|
|
|
|
|
|
|
509 => 'Fitness Music|New Age', |
3316
|
|
|
|
|
|
|
510 => 'Fitness Music|Classical', |
3317
|
|
|
|
|
|
|
1001 => 'Music|Alternative|College Rock', |
3318
|
|
|
|
|
|
|
1002 => 'Music|Alternative|Goth Rock', |
3319
|
|
|
|
|
|
|
1003 => 'Music|Alternative|Grunge', |
3320
|
|
|
|
|
|
|
1004 => 'Music|Alternative|Indie Rock', |
3321
|
|
|
|
|
|
|
1005 => 'Music|Alternative|New Wave', |
3322
|
|
|
|
|
|
|
1006 => 'Music|Alternative|Punk', |
3323
|
|
|
|
|
|
|
1007 => 'Music|Blues|Chicago Blues', |
3324
|
|
|
|
|
|
|
1009 => 'Music|Blues|Classic Blues', |
3325
|
|
|
|
|
|
|
1010 => 'Music|Blues|Contemporary Blues', |
3326
|
|
|
|
|
|
|
1011 => 'Music|Blues|Country Blues', |
3327
|
|
|
|
|
|
|
1012 => 'Music|Blues|Delta Blues', |
3328
|
|
|
|
|
|
|
1013 => 'Music|Blues|Electric Blues', |
3329
|
|
|
|
|
|
|
1014 => "Music|Children's Music|Lullabies", |
3330
|
|
|
|
|
|
|
1015 => "Music|Children's Music|Sing-Along", |
3331
|
|
|
|
|
|
|
1016 => "Music|Children's Music|Stories", |
3332
|
|
|
|
|
|
|
1017 => 'Music|Classical|Avant-Garde', |
3333
|
|
|
|
|
|
|
1018 => 'Music|Classical|Baroque Era', |
3334
|
|
|
|
|
|
|
1019 => 'Music|Classical|Chamber Music', |
3335
|
|
|
|
|
|
|
1020 => 'Music|Classical|Chant', |
3336
|
|
|
|
|
|
|
1021 => 'Music|Classical|Choral', |
3337
|
|
|
|
|
|
|
1022 => 'Music|Classical|Classical Crossover', |
3338
|
|
|
|
|
|
|
1023 => 'Music|Classical|Early Music', |
3339
|
|
|
|
|
|
|
1024 => 'Music|Classical|Impressionist', |
3340
|
|
|
|
|
|
|
1025 => 'Music|Classical|Medieval Era', |
3341
|
|
|
|
|
|
|
1026 => 'Music|Classical|Minimalism', |
3342
|
|
|
|
|
|
|
1027 => 'Music|Classical|Modern Era', |
3343
|
|
|
|
|
|
|
1028 => 'Music|Classical|Opera', |
3344
|
|
|
|
|
|
|
1029 => 'Music|Classical|Orchestral', |
3345
|
|
|
|
|
|
|
1030 => 'Music|Classical|Renaissance', |
3346
|
|
|
|
|
|
|
1031 => 'Music|Classical|Romantic Era', |
3347
|
|
|
|
|
|
|
1032 => 'Music|Classical|Wedding Music', |
3348
|
|
|
|
|
|
|
1033 => 'Music|Country|Alternative Country', |
3349
|
|
|
|
|
|
|
1034 => 'Music|Country|Americana', |
3350
|
|
|
|
|
|
|
1035 => 'Music|Country|Bluegrass', |
3351
|
|
|
|
|
|
|
1036 => 'Music|Country|Contemporary Bluegrass', |
3352
|
|
|
|
|
|
|
1037 => 'Music|Country|Contemporary Country', |
3353
|
|
|
|
|
|
|
1038 => 'Music|Country|Country Gospel', |
3354
|
|
|
|
|
|
|
1039 => 'Music|Country|Honky Tonk', |
3355
|
|
|
|
|
|
|
1040 => 'Music|Country|Outlaw Country', |
3356
|
|
|
|
|
|
|
1041 => 'Music|Country|Traditional Bluegrass', |
3357
|
|
|
|
|
|
|
1042 => 'Music|Country|Traditional Country', |
3358
|
|
|
|
|
|
|
1043 => 'Music|Country|Urban Cowboy', |
3359
|
|
|
|
|
|
|
1044 => 'Music|Dance|Breakbeat', |
3360
|
|
|
|
|
|
|
1045 => 'Music|Dance|Exercise', |
3361
|
|
|
|
|
|
|
1046 => 'Music|Dance|Garage', |
3362
|
|
|
|
|
|
|
1047 => 'Music|Dance|Hardcore', |
3363
|
|
|
|
|
|
|
1048 => 'Music|Dance|House', |
3364
|
|
|
|
|
|
|
1049 => "Music|Dance|Jungle/Drum'n'bass", |
3365
|
|
|
|
|
|
|
1050 => 'Music|Dance|Techno', |
3366
|
|
|
|
|
|
|
1051 => 'Music|Dance|Trance', |
3367
|
|
|
|
|
|
|
1052 => 'Music|Jazz|Big Band', |
3368
|
|
|
|
|
|
|
1053 => 'Music|Jazz|Bop', |
3369
|
|
|
|
|
|
|
1054 => 'Music|Easy Listening|Lounge', |
3370
|
|
|
|
|
|
|
1055 => 'Music|Easy Listening|Swing', |
3371
|
|
|
|
|
|
|
1056 => 'Music|Electronic|Ambient', |
3372
|
|
|
|
|
|
|
1057 => 'Music|Electronic|Downtempo', |
3373
|
|
|
|
|
|
|
1058 => 'Music|Electronic|Electronica', |
3374
|
|
|
|
|
|
|
1060 => 'Music|Electronic|IDM/Experimental', |
3375
|
|
|
|
|
|
|
1061 => 'Music|Electronic|Industrial', |
3376
|
|
|
|
|
|
|
1062 => 'Music|Singer/Songwriter|Alternative Folk', |
3377
|
|
|
|
|
|
|
1063 => 'Music|Singer/Songwriter|Contemporary Folk', |
3378
|
|
|
|
|
|
|
1064 => 'Music|Singer/Songwriter|Contemporary Singer/Songwriter', |
3379
|
|
|
|
|
|
|
1065 => 'Music|Singer/Songwriter|Folk-Rock', |
3380
|
|
|
|
|
|
|
1066 => 'Music|Singer/Songwriter|New Acoustic', |
3381
|
|
|
|
|
|
|
1067 => 'Music|Singer/Songwriter|Traditional Folk', |
3382
|
|
|
|
|
|
|
1068 => 'Music|Hip-Hop/Rap|Alternative Rap', |
3383
|
|
|
|
|
|
|
1069 => 'Music|Hip-Hop/Rap|Dirty South', |
3384
|
|
|
|
|
|
|
1070 => 'Music|Hip-Hop/Rap|East Coast Rap', |
3385
|
|
|
|
|
|
|
1071 => 'Music|Hip-Hop/Rap|Gangsta Rap', |
3386
|
|
|
|
|
|
|
1072 => 'Music|Hip-Hop/Rap|Hardcore Rap', |
3387
|
|
|
|
|
|
|
1073 => 'Music|Hip-Hop/Rap|Hip-Hop', |
3388
|
|
|
|
|
|
|
1074 => 'Music|Hip-Hop/Rap|Latin Rap', |
3389
|
|
|
|
|
|
|
1075 => 'Music|Hip-Hop/Rap|Old School Rap', |
3390
|
|
|
|
|
|
|
1076 => 'Music|Hip-Hop/Rap|Rap', |
3391
|
|
|
|
|
|
|
1077 => 'Music|Hip-Hop/Rap|Underground Rap', |
3392
|
|
|
|
|
|
|
1078 => 'Music|Hip-Hop/Rap|West Coast Rap', |
3393
|
|
|
|
|
|
|
1079 => 'Music|Holiday|Chanukah', |
3394
|
|
|
|
|
|
|
1080 => 'Music|Holiday|Christmas', |
3395
|
|
|
|
|
|
|
1081 => "Music|Holiday|Christmas: Children's", |
3396
|
|
|
|
|
|
|
1082 => 'Music|Holiday|Christmas: Classic', |
3397
|
|
|
|
|
|
|
1083 => 'Music|Holiday|Christmas: Classical', |
3398
|
|
|
|
|
|
|
1084 => 'Music|Holiday|Christmas: Jazz', |
3399
|
|
|
|
|
|
|
1085 => 'Music|Holiday|Christmas: Modern', |
3400
|
|
|
|
|
|
|
1086 => 'Music|Holiday|Christmas: Pop', |
3401
|
|
|
|
|
|
|
1087 => 'Music|Holiday|Christmas: R&B', |
3402
|
|
|
|
|
|
|
1088 => 'Music|Holiday|Christmas: Religious', |
3403
|
|
|
|
|
|
|
1089 => 'Music|Holiday|Christmas: Rock', |
3404
|
|
|
|
|
|
|
1090 => 'Music|Holiday|Easter', |
3405
|
|
|
|
|
|
|
1091 => 'Music|Holiday|Halloween', |
3406
|
|
|
|
|
|
|
1092 => 'Music|Holiday|Holiday: Other', |
3407
|
|
|
|
|
|
|
1093 => 'Music|Holiday|Thanksgiving', |
3408
|
|
|
|
|
|
|
1094 => 'Music|Christian & Gospel|CCM', |
3409
|
|
|
|
|
|
|
1095 => 'Music|Christian & Gospel|Christian Metal', |
3410
|
|
|
|
|
|
|
1096 => 'Music|Christian & Gospel|Christian Pop', |
3411
|
|
|
|
|
|
|
1097 => 'Music|Christian & Gospel|Christian Rap', |
3412
|
|
|
|
|
|
|
1098 => 'Music|Christian & Gospel|Christian Rock', |
3413
|
|
|
|
|
|
|
1099 => 'Music|Christian & Gospel|Classic Christian', |
3414
|
|
|
|
|
|
|
1100 => 'Music|Christian & Gospel|Contemporary Gospel', |
3415
|
|
|
|
|
|
|
1101 => 'Music|Christian & Gospel|Gospel', |
3416
|
|
|
|
|
|
|
1103 => 'Music|Christian & Gospel|Praise & Worship', |
3417
|
|
|
|
|
|
|
1104 => 'Music|Christian & Gospel|Southern Gospel', |
3418
|
|
|
|
|
|
|
1105 => 'Music|Christian & Gospel|Traditional Gospel', |
3419
|
|
|
|
|
|
|
1106 => 'Music|Jazz|Avant-Garde Jazz', |
3420
|
|
|
|
|
|
|
1107 => 'Music|Jazz|Contemporary Jazz', |
3421
|
|
|
|
|
|
|
1108 => 'Music|Jazz|Crossover Jazz', |
3422
|
|
|
|
|
|
|
1109 => 'Music|Jazz|Dixieland', |
3423
|
|
|
|
|
|
|
1110 => 'Music|Jazz|Fusion', |
3424
|
|
|
|
|
|
|
1111 => 'Music|Jazz|Latin Jazz', |
3425
|
|
|
|
|
|
|
1112 => 'Music|Jazz|Mainstream Jazz', |
3426
|
|
|
|
|
|
|
1113 => 'Music|Jazz|Ragtime', |
3427
|
|
|
|
|
|
|
1114 => 'Music|Jazz|Smooth Jazz', |
3428
|
|
|
|
|
|
|
1115 => 'Music|Latino|Latin Jazz', |
3429
|
|
|
|
|
|
|
1116 => 'Music|Latino|Contemporary Latin', |
3430
|
|
|
|
|
|
|
1117 => 'Music|Latino|Pop Latino', |
3431
|
|
|
|
|
|
|
1118 => 'Music|Latino|Raices', # (Raíces) |
3432
|
|
|
|
|
|
|
1119 => 'Music|Latino|Urbano latino', |
3433
|
|
|
|
|
|
|
1120 => 'Music|Latino|Baladas y Boleros', |
3434
|
|
|
|
|
|
|
1121 => 'Music|Latino|Rock y Alternativo', |
3435
|
|
|
|
|
|
|
1122 => 'Music|Brazilian', |
3436
|
|
|
|
|
|
|
1123 => 'Music|Latino|Musica Mexicana', # (Música Mexicana) |
3437
|
|
|
|
|
|
|
1124 => 'Music|Latino|Musica tropical', # (Música tropical) |
3438
|
|
|
|
|
|
|
1125 => 'Music|New Age|Environmental', |
3439
|
|
|
|
|
|
|
1126 => 'Music|New Age|Healing', |
3440
|
|
|
|
|
|
|
1127 => 'Music|New Age|Meditation', |
3441
|
|
|
|
|
|
|
1128 => 'Music|New Age|Nature', |
3442
|
|
|
|
|
|
|
1129 => 'Music|New Age|Relaxation', |
3443
|
|
|
|
|
|
|
1130 => 'Music|New Age|Travel', |
3444
|
|
|
|
|
|
|
1131 => 'Music|Pop|Adult Contemporary', |
3445
|
|
|
|
|
|
|
1132 => 'Music|Pop|Britpop', |
3446
|
|
|
|
|
|
|
1133 => 'Music|Pop|Pop/Rock', |
3447
|
|
|
|
|
|
|
1134 => 'Music|Pop|Soft Rock', |
3448
|
|
|
|
|
|
|
1135 => 'Music|Pop|Teen Pop', |
3449
|
|
|
|
|
|
|
1136 => 'Music|R&B/Soul|Contemporary R&B', |
3450
|
|
|
|
|
|
|
1137 => 'Music|R&B/Soul|Disco', |
3451
|
|
|
|
|
|
|
1138 => 'Music|R&B/Soul|Doo Wop', |
3452
|
|
|
|
|
|
|
1139 => 'Music|R&B/Soul|Funk', |
3453
|
|
|
|
|
|
|
1140 => 'Music|R&B/Soul|Motown', |
3454
|
|
|
|
|
|
|
1141 => 'Music|R&B/Soul|Neo-Soul', |
3455
|
|
|
|
|
|
|
1142 => 'Music|R&B/Soul|Quiet Storm', |
3456
|
|
|
|
|
|
|
1143 => 'Music|R&B/Soul|Soul', |
3457
|
|
|
|
|
|
|
1144 => 'Music|Rock|Adult Alternative', |
3458
|
|
|
|
|
|
|
1145 => 'Music|Rock|American Trad Rock', |
3459
|
|
|
|
|
|
|
1146 => 'Music|Rock|Arena Rock', |
3460
|
|
|
|
|
|
|
1147 => 'Music|Rock|Blues-Rock', |
3461
|
|
|
|
|
|
|
1148 => 'Music|Rock|British Invasion', |
3462
|
|
|
|
|
|
|
1149 => 'Music|Rock|Death Metal/Black Metal', |
3463
|
|
|
|
|
|
|
1150 => 'Music|Rock|Glam Rock', |
3464
|
|
|
|
|
|
|
1151 => 'Music|Rock|Hair Metal', |
3465
|
|
|
|
|
|
|
1152 => 'Music|Rock|Hard Rock', |
3466
|
|
|
|
|
|
|
1153 => 'Music|Rock|Metal', |
3467
|
|
|
|
|
|
|
1154 => 'Music|Rock|Jam Bands', |
3468
|
|
|
|
|
|
|
1155 => 'Music|Rock|Prog-Rock/Art Rock', |
3469
|
|
|
|
|
|
|
1156 => 'Music|Rock|Psychedelic', |
3470
|
|
|
|
|
|
|
1157 => 'Music|Rock|Rock & Roll', |
3471
|
|
|
|
|
|
|
1158 => 'Music|Rock|Rockabilly', |
3472
|
|
|
|
|
|
|
1159 => 'Music|Rock|Roots Rock', |
3473
|
|
|
|
|
|
|
1160 => 'Music|Rock|Singer/Songwriter', |
3474
|
|
|
|
|
|
|
1161 => 'Music|Rock|Southern Rock', |
3475
|
|
|
|
|
|
|
1162 => 'Music|Rock|Surf', |
3476
|
|
|
|
|
|
|
1163 => 'Music|Rock|Tex-Mex', |
3477
|
|
|
|
|
|
|
1165 => 'Music|Soundtrack|Foreign Cinema', |
3478
|
|
|
|
|
|
|
1166 => 'Music|Soundtrack|Musicals', |
3479
|
|
|
|
|
|
|
1167 => 'Music|Comedy|Novelty', |
3480
|
|
|
|
|
|
|
1168 => 'Music|Soundtrack|Original Score', |
3481
|
|
|
|
|
|
|
1169 => 'Music|Soundtrack|Soundtrack', |
3482
|
|
|
|
|
|
|
1171 => 'Music|Comedy|Standup Comedy', |
3483
|
|
|
|
|
|
|
1172 => 'Music|Soundtrack|TV Soundtrack', |
3484
|
|
|
|
|
|
|
1173 => 'Music|Vocal|Standards', |
3485
|
|
|
|
|
|
|
1174 => 'Music|Vocal|Traditional Pop', |
3486
|
|
|
|
|
|
|
1175 => 'Music|Jazz|Vocal Jazz', |
3487
|
|
|
|
|
|
|
1176 => 'Music|Vocal|Vocal Pop', |
3488
|
|
|
|
|
|
|
1177 => 'Music|African|Afro-Beat', |
3489
|
|
|
|
|
|
|
1178 => 'Music|African|Afro-Pop', |
3490
|
|
|
|
|
|
|
1179 => 'Music|World|Cajun', |
3491
|
|
|
|
|
|
|
1180 => 'Music|World|Celtic', |
3492
|
|
|
|
|
|
|
1181 => 'Music|World|Celtic Folk', |
3493
|
|
|
|
|
|
|
1182 => 'Music|World|Contemporary Celtic', |
3494
|
|
|
|
|
|
|
1183 => 'Music|Reggae|Modern Dancehall', |
3495
|
|
|
|
|
|
|
1184 => 'Music|World|Drinking Songs', |
3496
|
|
|
|
|
|
|
1185 => 'Music|Indian|Indian Pop', |
3497
|
|
|
|
|
|
|
1186 => 'Music|World|Japanese Pop', |
3498
|
|
|
|
|
|
|
1187 => 'Music|World|Klezmer', |
3499
|
|
|
|
|
|
|
1188 => 'Music|World|Polka', |
3500
|
|
|
|
|
|
|
1189 => 'Music|World|Traditional Celtic', |
3501
|
|
|
|
|
|
|
1190 => 'Music|World|Worldbeat', |
3502
|
|
|
|
|
|
|
1191 => 'Music|World|Zydeco', |
3503
|
|
|
|
|
|
|
1192 => 'Music|Reggae|Roots Reggae', |
3504
|
|
|
|
|
|
|
1193 => 'Music|Reggae|Dub', |
3505
|
|
|
|
|
|
|
1194 => 'Music|Reggae|Ska', |
3506
|
|
|
|
|
|
|
1195 => 'Music|World|Caribbean', |
3507
|
|
|
|
|
|
|
1196 => 'Music|World|South America', |
3508
|
|
|
|
|
|
|
1197 => 'Music|Arabic', |
3509
|
|
|
|
|
|
|
1198 => 'Music|World|North America', |
3510
|
|
|
|
|
|
|
1199 => 'Music|World|Hawaii', |
3511
|
|
|
|
|
|
|
1200 => 'Music|World|Australia', |
3512
|
|
|
|
|
|
|
1201 => 'Music|World|Japan', |
3513
|
|
|
|
|
|
|
1202 => 'Music|World|France', |
3514
|
|
|
|
|
|
|
1203 => 'Music|African', |
3515
|
|
|
|
|
|
|
1204 => 'Music|World|Asia', |
3516
|
|
|
|
|
|
|
1205 => 'Music|World|Europe', |
3517
|
|
|
|
|
|
|
1206 => 'Music|World|South Africa', |
3518
|
|
|
|
|
|
|
1207 => 'Music|Jazz|Hard Bop', |
3519
|
|
|
|
|
|
|
1208 => 'Music|Jazz|Trad Jazz', |
3520
|
|
|
|
|
|
|
1209 => 'Music|Jazz|Cool Jazz', |
3521
|
|
|
|
|
|
|
1210 => 'Music|Blues|Acoustic Blues', |
3522
|
|
|
|
|
|
|
1211 => 'Music|Classical|High Classical', |
3523
|
|
|
|
|
|
|
1220 => 'Music|Brazilian|Axe', # (Axé) |
3524
|
|
|
|
|
|
|
1221 => 'Music|Brazilian|Bossa Nova', |
3525
|
|
|
|
|
|
|
1222 => 'Music|Brazilian|Choro', |
3526
|
|
|
|
|
|
|
1223 => 'Music|Brazilian|Forro', # (Forró) |
3527
|
|
|
|
|
|
|
1224 => 'Music|Brazilian|Frevo', |
3528
|
|
|
|
|
|
|
1225 => 'Music|Brazilian|MPB', |
3529
|
|
|
|
|
|
|
1226 => 'Music|Brazilian|Pagode', |
3530
|
|
|
|
|
|
|
1227 => 'Music|Brazilian|Samba', |
3531
|
|
|
|
|
|
|
1228 => 'Music|Brazilian|Sertanejo', |
3532
|
|
|
|
|
|
|
1229 => 'Music|Brazilian|Baile Funk', |
3533
|
|
|
|
|
|
|
1230 => 'Music|Alternative|Chinese Alt', |
3534
|
|
|
|
|
|
|
1231 => 'Music|Alternative|Korean Indie', |
3535
|
|
|
|
|
|
|
1232 => 'Music|Chinese', |
3536
|
|
|
|
|
|
|
1233 => 'Music|Chinese|Chinese Classical', |
3537
|
|
|
|
|
|
|
1234 => 'Music|Chinese|Chinese Flute', |
3538
|
|
|
|
|
|
|
1235 => 'Music|Chinese|Chinese Opera', |
3539
|
|
|
|
|
|
|
1236 => 'Music|Chinese|Chinese Orchestral', |
3540
|
|
|
|
|
|
|
1237 => 'Music|Chinese|Chinese Regional Folk', |
3541
|
|
|
|
|
|
|
1238 => 'Music|Chinese|Chinese Strings', |
3542
|
|
|
|
|
|
|
1239 => 'Music|Chinese|Taiwanese Folk', |
3543
|
|
|
|
|
|
|
1240 => 'Music|Chinese|Tibetan Native Music', |
3544
|
|
|
|
|
|
|
1241 => 'Music|Hip-Hop/Rap|Chinese Hip-Hop', |
3545
|
|
|
|
|
|
|
1242 => 'Music|Hip-Hop/Rap|Korean Hip-Hop', |
3546
|
|
|
|
|
|
|
1243 => 'Music|Korean', |
3547
|
|
|
|
|
|
|
1244 => 'Music|Korean|Korean Classical', |
3548
|
|
|
|
|
|
|
1245 => 'Music|Korean|Korean Trad Song', |
3549
|
|
|
|
|
|
|
1246 => 'Music|Korean|Korean Trad Instrumental', |
3550
|
|
|
|
|
|
|
1247 => 'Music|Korean|Korean Trad Theater', |
3551
|
|
|
|
|
|
|
1248 => 'Music|Rock|Chinese Rock', |
3552
|
|
|
|
|
|
|
1249 => 'Music|Rock|Korean Rock', |
3553
|
|
|
|
|
|
|
1250 => 'Music|Pop|C-Pop', |
3554
|
|
|
|
|
|
|
1251 => 'Music|Pop|Cantopop/HK-Pop', |
3555
|
|
|
|
|
|
|
1252 => 'Music|Pop|Korean Folk-Pop', |
3556
|
|
|
|
|
|
|
1253 => 'Music|Pop|Mandopop', |
3557
|
|
|
|
|
|
|
1254 => 'Music|Pop|Tai-Pop', |
3558
|
|
|
|
|
|
|
1255 => 'Music|Pop|Malaysian Pop', |
3559
|
|
|
|
|
|
|
1256 => 'Music|Pop|Pinoy Pop', |
3560
|
|
|
|
|
|
|
1257 => 'Music|Pop|Original Pilipino Music', |
3561
|
|
|
|
|
|
|
1258 => 'Music|Pop|Manilla Sound', |
3562
|
|
|
|
|
|
|
1259 => 'Music|Pop|Indo Pop', |
3563
|
|
|
|
|
|
|
1260 => 'Music|Pop|Thai Pop', |
3564
|
|
|
|
|
|
|
1261 => 'Music|Vocal|Trot', |
3565
|
|
|
|
|
|
|
1262 => 'Music|Indian', |
3566
|
|
|
|
|
|
|
1263 => 'Music|Indian|Bollywood', |
3567
|
|
|
|
|
|
|
1264 => 'Music|Indian|Regional Indian|Tamil', |
3568
|
|
|
|
|
|
|
1265 => 'Music|Indian|Regional Indian|Telugu', |
3569
|
|
|
|
|
|
|
1266 => 'Music|Indian|Regional Indian', |
3570
|
|
|
|
|
|
|
1267 => 'Music|Indian|Devotional & Spiritual', |
3571
|
|
|
|
|
|
|
1268 => 'Music|Indian|Sufi', |
3572
|
|
|
|
|
|
|
1269 => 'Music|Indian|Indian Classical', |
3573
|
|
|
|
|
|
|
1270 => 'Music|Russian|Russian Chanson', |
3574
|
|
|
|
|
|
|
1271 => 'Music|World|Dini', |
3575
|
|
|
|
|
|
|
1272 => 'Music|Turkish|Halk', |
3576
|
|
|
|
|
|
|
1273 => 'Music|Turkish|Sanat', |
3577
|
|
|
|
|
|
|
1274 => 'Music|World|Dangdut', |
3578
|
|
|
|
|
|
|
1275 => 'Music|World|Indonesian Religious', |
3579
|
|
|
|
|
|
|
1276 => 'Music|World|Calypso', |
3580
|
|
|
|
|
|
|
1277 => 'Music|World|Soca', |
3581
|
|
|
|
|
|
|
1278 => 'Music|Indian|Ghazals', |
3582
|
|
|
|
|
|
|
1279 => 'Music|Indian|Indian Folk', |
3583
|
|
|
|
|
|
|
1280 => 'Music|Turkish|Arabesque', |
3584
|
|
|
|
|
|
|
1281 => 'Music|African|Afrikaans', |
3585
|
|
|
|
|
|
|
1282 => 'Music|World|Farsi', |
3586
|
|
|
|
|
|
|
1283 => 'Music|World|Israeli', |
3587
|
|
|
|
|
|
|
1284 => 'Music|Arabic|Khaleeji', |
3588
|
|
|
|
|
|
|
1285 => 'Music|Arabic|North African', |
3589
|
|
|
|
|
|
|
1286 => 'Music|Arabic|Arabic Pop', |
3590
|
|
|
|
|
|
|
1287 => 'Music|Arabic|Islamic', |
3591
|
|
|
|
|
|
|
1288 => 'Music|Soundtrack|Sound Effects', |
3592
|
|
|
|
|
|
|
1289 => 'Music|Folk', |
3593
|
|
|
|
|
|
|
1290 => 'Music|Orchestral', |
3594
|
|
|
|
|
|
|
1291 => 'Music|Marching', |
3595
|
|
|
|
|
|
|
1293 => 'Music|Pop|Oldies', |
3596
|
|
|
|
|
|
|
1294 => 'Music|Country|Thai Country', |
3597
|
|
|
|
|
|
|
1295 => 'Music|World|Flamenco', |
3598
|
|
|
|
|
|
|
1296 => 'Music|World|Tango', |
3599
|
|
|
|
|
|
|
1297 => 'Music|World|Fado', |
3600
|
|
|
|
|
|
|
1298 => 'Music|World|Iberia', |
3601
|
|
|
|
|
|
|
1299 => 'Music|Russian', |
3602
|
|
|
|
|
|
|
1300 => 'Music|Turkish', |
3603
|
|
|
|
|
|
|
1301 => 'Podcasts|Arts', |
3604
|
|
|
|
|
|
|
1302 => 'Podcasts|Society & Culture|Personal Journals', |
3605
|
|
|
|
|
|
|
1303 => 'Podcasts|Comedy', |
3606
|
|
|
|
|
|
|
1304 => 'Podcasts|Education', |
3607
|
|
|
|
|
|
|
1305 => 'Podcasts|Kids & Family', |
3608
|
|
|
|
|
|
|
1306 => 'Podcasts|Arts|Food', |
3609
|
|
|
|
|
|
|
1307 => 'Podcasts|Health', |
3610
|
|
|
|
|
|
|
1309 => 'Podcasts|TV & Film', |
3611
|
|
|
|
|
|
|
1310 => 'Podcasts|Music', |
3612
|
|
|
|
|
|
|
1311 => 'Podcasts|News & Politics', |
3613
|
|
|
|
|
|
|
1314 => 'Podcasts|Religion & Spirituality', |
3614
|
|
|
|
|
|
|
1315 => 'Podcasts|Science & Medicine', |
3615
|
|
|
|
|
|
|
1316 => 'Podcasts|Sports & Recreation', |
3616
|
|
|
|
|
|
|
1318 => 'Podcasts|Technology', |
3617
|
|
|
|
|
|
|
1320 => 'Podcasts|Society & Culture|Places & Travel', |
3618
|
|
|
|
|
|
|
1321 => 'Podcasts|Business', |
3619
|
|
|
|
|
|
|
1323 => 'Podcasts|Games & Hobbies', |
3620
|
|
|
|
|
|
|
1324 => 'Podcasts|Society & Culture', |
3621
|
|
|
|
|
|
|
1325 => 'Podcasts|Government & Organizations', |
3622
|
|
|
|
|
|
|
1337 => 'Music Videos|Classical|Piano', |
3623
|
|
|
|
|
|
|
1401 => 'Podcasts|Arts|Literature', |
3624
|
|
|
|
|
|
|
1402 => 'Podcasts|Arts|Design', |
3625
|
|
|
|
|
|
|
1404 => 'Podcasts|Games & Hobbies|Video Games', |
3626
|
|
|
|
|
|
|
1405 => 'Podcasts|Arts|Performing Arts', |
3627
|
|
|
|
|
|
|
1406 => 'Podcasts|Arts|Visual Arts', |
3628
|
|
|
|
|
|
|
1410 => 'Podcasts|Business|Careers', |
3629
|
|
|
|
|
|
|
1412 => 'Podcasts|Business|Investing', |
3630
|
|
|
|
|
|
|
1413 => 'Podcasts|Business|Management & Marketing', |
3631
|
|
|
|
|
|
|
1415 => 'Podcasts|Education|K-12', |
3632
|
|
|
|
|
|
|
1416 => 'Podcasts|Education|Higher Education', |
3633
|
|
|
|
|
|
|
1417 => 'Podcasts|Health|Fitness & Nutrition', |
3634
|
|
|
|
|
|
|
1420 => 'Podcasts|Health|Self-Help', |
3635
|
|
|
|
|
|
|
1421 => 'Podcasts|Health|Sexuality', |
3636
|
|
|
|
|
|
|
1438 => 'Podcasts|Religion & Spirituality|Buddhism', |
3637
|
|
|
|
|
|
|
1439 => 'Podcasts|Religion & Spirituality|Christianity', |
3638
|
|
|
|
|
|
|
1440 => 'Podcasts|Religion & Spirituality|Islam', |
3639
|
|
|
|
|
|
|
1441 => 'Podcasts|Religion & Spirituality|Judaism', |
3640
|
|
|
|
|
|
|
1443 => 'Podcasts|Society & Culture|Philosophy', |
3641
|
|
|
|
|
|
|
1444 => 'Podcasts|Religion & Spirituality|Spirituality', |
3642
|
|
|
|
|
|
|
1446 => 'Podcasts|Technology|Gadgets', |
3643
|
|
|
|
|
|
|
1448 => 'Podcasts|Technology|Tech News', |
3644
|
|
|
|
|
|
|
1450 => 'Podcasts|Technology|Podcasting', |
3645
|
|
|
|
|
|
|
1454 => 'Podcasts|Games & Hobbies|Automotive', |
3646
|
|
|
|
|
|
|
1455 => 'Podcasts|Games & Hobbies|Aviation', |
3647
|
|
|
|
|
|
|
1456 => 'Podcasts|Sports & Recreation|Outdoor', |
3648
|
|
|
|
|
|
|
1459 => 'Podcasts|Arts|Fashion & Beauty', |
3649
|
|
|
|
|
|
|
1460 => 'Podcasts|Games & Hobbies|Hobbies', |
3650
|
|
|
|
|
|
|
1461 => 'Podcasts|Games & Hobbies|Other Games', |
3651
|
|
|
|
|
|
|
1462 => 'Podcasts|Society & Culture|History', |
3652
|
|
|
|
|
|
|
1463 => 'Podcasts|Religion & Spirituality|Hinduism', |
3653
|
|
|
|
|
|
|
1464 => 'Podcasts|Religion & Spirituality|Other', |
3654
|
|
|
|
|
|
|
1465 => 'Podcasts|Sports & Recreation|Professional', |
3655
|
|
|
|
|
|
|
1466 => 'Podcasts|Sports & Recreation|College & High School', |
3656
|
|
|
|
|
|
|
1467 => 'Podcasts|Sports & Recreation|Amateur', |
3657
|
|
|
|
|
|
|
1468 => 'Podcasts|Education|Educational Technology', |
3658
|
|
|
|
|
|
|
1469 => 'Podcasts|Education|Language Courses', |
3659
|
|
|
|
|
|
|
1470 => 'Podcasts|Education|Training', |
3660
|
|
|
|
|
|
|
1471 => 'Podcasts|Business|Business News', |
3661
|
|
|
|
|
|
|
1472 => 'Podcasts|Business|Shopping', |
3662
|
|
|
|
|
|
|
1473 => 'Podcasts|Government & Organizations|National', |
3663
|
|
|
|
|
|
|
1474 => 'Podcasts|Government & Organizations|Regional', |
3664
|
|
|
|
|
|
|
1475 => 'Podcasts|Government & Organizations|Local', |
3665
|
|
|
|
|
|
|
1476 => 'Podcasts|Government & Organizations|Non-Profit', |
3666
|
|
|
|
|
|
|
1477 => 'Podcasts|Science & Medicine|Natural Sciences', |
3667
|
|
|
|
|
|
|
1478 => 'Podcasts|Science & Medicine|Medicine', |
3668
|
|
|
|
|
|
|
1479 => 'Podcasts|Science & Medicine|Social Sciences', |
3669
|
|
|
|
|
|
|
1480 => 'Podcasts|Technology|Software How-To', |
3670
|
|
|
|
|
|
|
1481 => 'Podcasts|Health|Alternative Health', |
3671
|
|
|
|
|
|
|
1482 => 'Podcasts|Arts|Books', |
3672
|
|
|
|
|
|
|
1483 => 'Podcasts|Fiction', |
3673
|
|
|
|
|
|
|
1484 => 'Podcasts|Fiction|Drama', |
3674
|
|
|
|
|
|
|
1485 => 'Podcasts|Fiction|Science Fiction', |
3675
|
|
|
|
|
|
|
1486 => 'Podcasts|Fiction|Comedy Fiction', |
3676
|
|
|
|
|
|
|
1487 => 'Podcasts|History', |
3677
|
|
|
|
|
|
|
1488 => 'Podcasts|True Crime', |
3678
|
|
|
|
|
|
|
1489 => 'Podcasts|News', |
3679
|
|
|
|
|
|
|
1490 => 'Podcasts|News|Business News', |
3680
|
|
|
|
|
|
|
1491 => 'Podcasts|Business|Management', |
3681
|
|
|
|
|
|
|
1492 => 'Podcasts|Business|Marketing', |
3682
|
|
|
|
|
|
|
1493 => 'Podcasts|Business|Entrepreneurship', |
3683
|
|
|
|
|
|
|
1494 => 'Podcasts|Business|Non-Profit', |
3684
|
|
|
|
|
|
|
1495 => 'Podcasts|Comedy|Improv', |
3685
|
|
|
|
|
|
|
1496 => 'Podcasts|Comedy|Comedy Interviews', |
3686
|
|
|
|
|
|
|
1497 => 'Podcasts|Comedy|Stand-Up', |
3687
|
|
|
|
|
|
|
1498 => 'Podcasts|Education|Language Learning', |
3688
|
|
|
|
|
|
|
1499 => 'Podcasts|Education|How To', |
3689
|
|
|
|
|
|
|
1500 => 'Podcasts|Education|Self-Improvement', |
3690
|
|
|
|
|
|
|
1501 => 'Podcasts|Education|Courses', |
3691
|
|
|
|
|
|
|
1502 => 'Podcasts|Leisure', |
3692
|
|
|
|
|
|
|
1503 => 'Podcasts|Leisure|Automotive', |
3693
|
|
|
|
|
|
|
1504 => 'Podcasts|Leisure|Aviation', |
3694
|
|
|
|
|
|
|
1505 => 'Podcasts|Leisure|Hobbies', |
3695
|
|
|
|
|
|
|
1506 => 'Podcasts|Leisure|Crafts', |
3696
|
|
|
|
|
|
|
1507 => 'Podcasts|Leisure|Games', |
3697
|
|
|
|
|
|
|
1508 => 'Podcasts|Leisure|Home & Garden', |
3698
|
|
|
|
|
|
|
1509 => 'Podcasts|Leisure|Video Games', |
3699
|
|
|
|
|
|
|
1510 => 'Podcasts|Leisure|Animation & Manga', |
3700
|
|
|
|
|
|
|
1511 => 'Podcasts|Government', |
3701
|
|
|
|
|
|
|
1512 => 'Podcasts|Health & Fitness', |
3702
|
|
|
|
|
|
|
1513 => 'Podcasts|Health & Fitness|Alternative Health', |
3703
|
|
|
|
|
|
|
1514 => 'Podcasts|Health & Fitness|Fitness', |
3704
|
|
|
|
|
|
|
1515 => 'Podcasts|Health & Fitness|Nutrition', |
3705
|
|
|
|
|
|
|
1516 => 'Podcasts|Health & Fitness|Sexuality', |
3706
|
|
|
|
|
|
|
1517 => 'Podcasts|Health & Fitness|Mental Health', |
3707
|
|
|
|
|
|
|
1518 => 'Podcasts|Health & Fitness|Medicine', |
3708
|
|
|
|
|
|
|
1519 => 'Podcasts|Kids & Family|Education for Kids', |
3709
|
|
|
|
|
|
|
1520 => 'Podcasts|Kids & Family|Stories for Kids', |
3710
|
|
|
|
|
|
|
1521 => 'Podcasts|Kids & Family|Parenting', |
3711
|
|
|
|
|
|
|
1522 => 'Podcasts|Kids & Family|Pets & Animals', |
3712
|
|
|
|
|
|
|
1523 => 'Podcasts|Music|Music Commentary', |
3713
|
|
|
|
|
|
|
1524 => 'Podcasts|Music|Music History', |
3714
|
|
|
|
|
|
|
1525 => 'Podcasts|Music|Music Interviews', |
3715
|
|
|
|
|
|
|
1526 => 'Podcasts|News|Daily News', |
3716
|
|
|
|
|
|
|
1527 => 'Podcasts|News|Politics', |
3717
|
|
|
|
|
|
|
1528 => 'Podcasts|News|Tech News', |
3718
|
|
|
|
|
|
|
1529 => 'Podcasts|News|Sports News', |
3719
|
|
|
|
|
|
|
1530 => 'Podcasts|News|News Commentary', |
3720
|
|
|
|
|
|
|
1531 => 'Podcasts|News|Entertainment News', |
3721
|
|
|
|
|
|
|
1532 => 'Podcasts|Religion & Spirituality|Religion', |
3722
|
|
|
|
|
|
|
1533 => 'Podcasts|Science', |
3723
|
|
|
|
|
|
|
1534 => 'Podcasts|Science|Natural Sciences', |
3724
|
|
|
|
|
|
|
1535 => 'Podcasts|Science|Social Sciences', |
3725
|
|
|
|
|
|
|
1536 => 'Podcasts|Science|Mathematics', |
3726
|
|
|
|
|
|
|
1537 => 'Podcasts|Science|Nature', |
3727
|
|
|
|
|
|
|
1538 => 'Podcasts|Science|Astronomy', |
3728
|
|
|
|
|
|
|
1539 => 'Podcasts|Science|Chemistry', |
3729
|
|
|
|
|
|
|
1540 => 'Podcasts|Science|Earth Sciences', |
3730
|
|
|
|
|
|
|
1541 => 'Podcasts|Science|Life Sciences', |
3731
|
|
|
|
|
|
|
1542 => 'Podcasts|Science|Physics', |
3732
|
|
|
|
|
|
|
1543 => 'Podcasts|Society & Culture|Documentary', |
3733
|
|
|
|
|
|
|
1544 => 'Podcasts|Society & Culture|Relationships', |
3734
|
|
|
|
|
|
|
1545 => 'Podcasts|Sports', |
3735
|
|
|
|
|
|
|
1546 => 'Podcasts|Sports|Soccer', |
3736
|
|
|
|
|
|
|
1547 => 'Podcasts|Sports|Football', |
3737
|
|
|
|
|
|
|
1548 => 'Podcasts|Sports|Basketball', |
3738
|
|
|
|
|
|
|
1549 => 'Podcasts|Sports|Baseball', |
3739
|
|
|
|
|
|
|
1550 => 'Podcasts|Sports|Hockey', |
3740
|
|
|
|
|
|
|
1551 => 'Podcasts|Sports|Running', |
3741
|
|
|
|
|
|
|
1552 => 'Podcasts|Sports|Rugby', |
3742
|
|
|
|
|
|
|
1553 => 'Podcasts|Sports|Golf', |
3743
|
|
|
|
|
|
|
1554 => 'Podcasts|Sports|Cricket', |
3744
|
|
|
|
|
|
|
1555 => 'Podcasts|Sports|Wrestling', |
3745
|
|
|
|
|
|
|
1556 => 'Podcasts|Sports|Tennis', |
3746
|
|
|
|
|
|
|
1557 => 'Podcasts|Sports|Volleyball', |
3747
|
|
|
|
|
|
|
1558 => 'Podcasts|Sports|Swimming', |
3748
|
|
|
|
|
|
|
1559 => 'Podcasts|Sports|Wilderness', |
3749
|
|
|
|
|
|
|
1560 => 'Podcasts|Sports|Fantasy Sports', |
3750
|
|
|
|
|
|
|
1561 => 'Podcasts|TV & Film|TV Reviews', |
3751
|
|
|
|
|
|
|
1562 => 'Podcasts|TV & Film|After Shows', |
3752
|
|
|
|
|
|
|
1563 => 'Podcasts|TV & Film|Film Reviews', |
3753
|
|
|
|
|
|
|
1564 => 'Podcasts|TV & Film|Film History', |
3754
|
|
|
|
|
|
|
1565 => 'Podcasts|TV & Film|Film Interviews', |
3755
|
|
|
|
|
|
|
1602 => 'Music Videos|Blues', |
3756
|
|
|
|
|
|
|
1603 => 'Music Videos|Comedy', |
3757
|
|
|
|
|
|
|
1604 => "Music Videos|Children's Music", |
3758
|
|
|
|
|
|
|
1605 => 'Music Videos|Classical', |
3759
|
|
|
|
|
|
|
1606 => 'Music Videos|Country', |
3760
|
|
|
|
|
|
|
1607 => 'Music Videos|Electronic', |
3761
|
|
|
|
|
|
|
1608 => 'Music Videos|Holiday', |
3762
|
|
|
|
|
|
|
1609 => 'Music Videos|Classical|Opera', |
3763
|
|
|
|
|
|
|
1610 => 'Music Videos|Singer/Songwriter', |
3764
|
|
|
|
|
|
|
1611 => 'Music Videos|Jazz', |
3765
|
|
|
|
|
|
|
1612 => 'Music Videos|Latin', |
3766
|
|
|
|
|
|
|
1613 => 'Music Videos|New Age', |
3767
|
|
|
|
|
|
|
1614 => 'Music Videos|Pop', |
3768
|
|
|
|
|
|
|
1615 => 'Music Videos|R&B/Soul', |
3769
|
|
|
|
|
|
|
1616 => 'Music Videos|Soundtrack', |
3770
|
|
|
|
|
|
|
1617 => 'Music Videos|Dance', |
3771
|
|
|
|
|
|
|
1618 => 'Music Videos|Hip-Hop/Rap', |
3772
|
|
|
|
|
|
|
1619 => 'Music Videos|World', |
3773
|
|
|
|
|
|
|
1620 => 'Music Videos|Alternative', |
3774
|
|
|
|
|
|
|
1621 => 'Music Videos|Rock', |
3775
|
|
|
|
|
|
|
1622 => 'Music Videos|Christian & Gospel', |
3776
|
|
|
|
|
|
|
1623 => 'Music Videos|Vocal', |
3777
|
|
|
|
|
|
|
1624 => 'Music Videos|Reggae', |
3778
|
|
|
|
|
|
|
1625 => 'Music Videos|Easy Listening', |
3779
|
|
|
|
|
|
|
1626 => 'Music Videos|Podcasts', |
3780
|
|
|
|
|
|
|
1627 => 'Music Videos|J-Pop', |
3781
|
|
|
|
|
|
|
1628 => 'Music Videos|Enka', |
3782
|
|
|
|
|
|
|
1629 => 'Music Videos|Anime', |
3783
|
|
|
|
|
|
|
1630 => 'Music Videos|Kayokyoku', |
3784
|
|
|
|
|
|
|
1631 => 'Music Videos|Disney', |
3785
|
|
|
|
|
|
|
1632 => 'Music Videos|French Pop', |
3786
|
|
|
|
|
|
|
1633 => 'Music Videos|German Pop', |
3787
|
|
|
|
|
|
|
1634 => 'Music Videos|German Folk', |
3788
|
|
|
|
|
|
|
1635 => 'Music Videos|Alternative|Chinese Alt', |
3789
|
|
|
|
|
|
|
1636 => 'Music Videos|Alternative|Korean Indie', |
3790
|
|
|
|
|
|
|
1637 => 'Music Videos|Chinese', |
3791
|
|
|
|
|
|
|
1638 => 'Music Videos|Chinese|Chinese Classical', |
3792
|
|
|
|
|
|
|
1639 => 'Music Videos|Chinese|Chinese Flute', |
3793
|
|
|
|
|
|
|
1640 => 'Music Videos|Chinese|Chinese Opera', |
3794
|
|
|
|
|
|
|
1641 => 'Music Videos|Chinese|Chinese Orchestral', |
3795
|
|
|
|
|
|
|
1642 => 'Music Videos|Chinese|Chinese Regional Folk', |
3796
|
|
|
|
|
|
|
1643 => 'Music Videos|Chinese|Chinese Strings', |
3797
|
|
|
|
|
|
|
1644 => 'Music Videos|Chinese|Taiwanese Folk', |
3798
|
|
|
|
|
|
|
1645 => 'Music Videos|Chinese|Tibetan Native Music', |
3799
|
|
|
|
|
|
|
1646 => 'Music Videos|Hip-Hop/Rap|Chinese Hip-Hop', |
3800
|
|
|
|
|
|
|
1647 => 'Music Videos|Hip-Hop/Rap|Korean Hip-Hop', |
3801
|
|
|
|
|
|
|
1648 => 'Music Videos|Korean', |
3802
|
|
|
|
|
|
|
1649 => 'Music Videos|Korean|Korean Classical', |
3803
|
|
|
|
|
|
|
1650 => 'Music Videos|Korean|Korean Trad Song', |
3804
|
|
|
|
|
|
|
1651 => 'Music Videos|Korean|Korean Trad Instrumental', |
3805
|
|
|
|
|
|
|
1652 => 'Music Videos|Korean|Korean Trad Theater', |
3806
|
|
|
|
|
|
|
1653 => 'Music Videos|Rock|Chinese Rock', |
3807
|
|
|
|
|
|
|
1654 => 'Music Videos|Rock|Korean Rock', |
3808
|
|
|
|
|
|
|
1655 => 'Music Videos|Pop|C-Pop', |
3809
|
|
|
|
|
|
|
1656 => 'Music Videos|Pop|Cantopop/HK-Pop', |
3810
|
|
|
|
|
|
|
1657 => 'Music Videos|Pop|Korean Folk-Pop', |
3811
|
|
|
|
|
|
|
1658 => 'Music Videos|Pop|Mandopop', |
3812
|
|
|
|
|
|
|
1659 => 'Music Videos|Pop|Tai-Pop', |
3813
|
|
|
|
|
|
|
1660 => 'Music Videos|Pop|Malaysian Pop', |
3814
|
|
|
|
|
|
|
1661 => 'Music Videos|Pop|Pinoy Pop', |
3815
|
|
|
|
|
|
|
1662 => 'Music Videos|Pop|Original Pilipino Music', |
3816
|
|
|
|
|
|
|
1663 => 'Music Videos|Pop|Manilla Sound', |
3817
|
|
|
|
|
|
|
1664 => 'Music Videos|Pop|Indo Pop', |
3818
|
|
|
|
|
|
|
1665 => 'Music Videos|Pop|Thai Pop', |
3819
|
|
|
|
|
|
|
1666 => 'Music Videos|Vocal|Trot', |
3820
|
|
|
|
|
|
|
1671 => 'Music Videos|Brazilian', |
3821
|
|
|
|
|
|
|
1672 => 'Music Videos|Brazilian|Axe', # (Axé) |
3822
|
|
|
|
|
|
|
1673 => 'Music Videos|Brazilian|Baile Funk', |
3823
|
|
|
|
|
|
|
1674 => 'Music Videos|Brazilian|Bossa Nova', |
3824
|
|
|
|
|
|
|
1675 => 'Music Videos|Brazilian|Choro', |
3825
|
|
|
|
|
|
|
1676 => 'Music Videos|Brazilian|Forro', |
3826
|
|
|
|
|
|
|
1677 => 'Music Videos|Brazilian|Frevo', |
3827
|
|
|
|
|
|
|
1678 => 'Music Videos|Brazilian|MPB', |
3828
|
|
|
|
|
|
|
1679 => 'Music Videos|Brazilian|Pagode', |
3829
|
|
|
|
|
|
|
1680 => 'Music Videos|Brazilian|Samba', |
3830
|
|
|
|
|
|
|
1681 => 'Music Videos|Brazilian|Sertanejo', |
3831
|
|
|
|
|
|
|
1682 => 'Music Videos|Classical|High Classical', |
3832
|
|
|
|
|
|
|
1683 => 'Music Videos|Fitness & Workout', |
3833
|
|
|
|
|
|
|
1684 => 'Music Videos|Instrumental', |
3834
|
|
|
|
|
|
|
1685 => 'Music Videos|Jazz|Big Band', |
3835
|
|
|
|
|
|
|
1686 => 'Music Videos|Pop|K-Pop', |
3836
|
|
|
|
|
|
|
1687 => 'Music Videos|Karaoke', |
3837
|
|
|
|
|
|
|
1688 => 'Music Videos|Rock|Heavy Metal', |
3838
|
|
|
|
|
|
|
1689 => 'Music Videos|Spoken Word', |
3839
|
|
|
|
|
|
|
1690 => 'Music Videos|Indian', |
3840
|
|
|
|
|
|
|
1691 => 'Music Videos|Indian|Bollywood', |
3841
|
|
|
|
|
|
|
1692 => 'Music Videos|Indian|Regional Indian|Tamil', |
3842
|
|
|
|
|
|
|
1693 => 'Music Videos|Indian|Regional Indian|Telugu', |
3843
|
|
|
|
|
|
|
1694 => 'Music Videos|Indian|Regional Indian', |
3844
|
|
|
|
|
|
|
1695 => 'Music Videos|Indian|Devotional & Spiritual', |
3845
|
|
|
|
|
|
|
1696 => 'Music Videos|Indian|Sufi', |
3846
|
|
|
|
|
|
|
1697 => 'Music Videos|Indian|Indian Classical', |
3847
|
|
|
|
|
|
|
1698 => 'Music Videos|Russian|Russian Chanson', |
3848
|
|
|
|
|
|
|
1699 => 'Music Videos|World|Dini', |
3849
|
|
|
|
|
|
|
1700 => 'Music Videos|Turkish|Halk', |
3850
|
|
|
|
|
|
|
1701 => 'Music Videos|Turkish|Sanat', |
3851
|
|
|
|
|
|
|
1702 => 'Music Videos|World|Dangdut', |
3852
|
|
|
|
|
|
|
1703 => 'Music Videos|World|Indonesian Religious', |
3853
|
|
|
|
|
|
|
1704 => 'Music Videos|Indian|Indian Pop', |
3854
|
|
|
|
|
|
|
1705 => 'Music Videos|World|Calypso', |
3855
|
|
|
|
|
|
|
1706 => 'Music Videos|World|Soca', |
3856
|
|
|
|
|
|
|
1707 => 'Music Videos|Indian|Ghazals', |
3857
|
|
|
|
|
|
|
1708 => 'Music Videos|Indian|Indian Folk', |
3858
|
|
|
|
|
|
|
1709 => 'Music Videos|Turkish|Arabesque', |
3859
|
|
|
|
|
|
|
1710 => 'Music Videos|African|Afrikaans', |
3860
|
|
|
|
|
|
|
1711 => 'Music Videos|World|Farsi', |
3861
|
|
|
|
|
|
|
1712 => 'Music Videos|World|Israeli', |
3862
|
|
|
|
|
|
|
1713 => 'Music Videos|Arabic', |
3863
|
|
|
|
|
|
|
1714 => 'Music Videos|Arabic|Khaleeji', |
3864
|
|
|
|
|
|
|
1715 => 'Music Videos|Arabic|North African', |
3865
|
|
|
|
|
|
|
1716 => 'Music Videos|Arabic|Arabic Pop', |
3866
|
|
|
|
|
|
|
1717 => 'Music Videos|Arabic|Islamic', |
3867
|
|
|
|
|
|
|
1718 => 'Music Videos|Soundtrack|Sound Effects', |
3868
|
|
|
|
|
|
|
1719 => 'Music Videos|Folk', |
3869
|
|
|
|
|
|
|
1720 => 'Music Videos|Orchestral', |
3870
|
|
|
|
|
|
|
1721 => 'Music Videos|Marching', |
3871
|
|
|
|
|
|
|
1723 => 'Music Videos|Pop|Oldies', |
3872
|
|
|
|
|
|
|
1724 => 'Music Videos|Country|Thai Country', |
3873
|
|
|
|
|
|
|
1725 => 'Music Videos|World|Flamenco', |
3874
|
|
|
|
|
|
|
1726 => 'Music Videos|World|Tango', |
3875
|
|
|
|
|
|
|
1727 => 'Music Videos|World|Fado', |
3876
|
|
|
|
|
|
|
1728 => 'Music Videos|World|Iberia', |
3877
|
|
|
|
|
|
|
1729 => 'Music Videos|Russian', |
3878
|
|
|
|
|
|
|
1730 => 'Music Videos|Turkish', |
3879
|
|
|
|
|
|
|
1731 => 'Music Videos|Alternative|College Rock', |
3880
|
|
|
|
|
|
|
1732 => 'Music Videos|Alternative|Goth Rock', |
3881
|
|
|
|
|
|
|
1733 => 'Music Videos|Alternative|Grunge', |
3882
|
|
|
|
|
|
|
1734 => 'Music Videos|Alternative|Indie Rock', |
3883
|
|
|
|
|
|
|
1735 => 'Music Videos|Alternative|New Wave', |
3884
|
|
|
|
|
|
|
1736 => 'Music Videos|Alternative|Punk', |
3885
|
|
|
|
|
|
|
1737 => 'Music Videos|Blues|Acoustic Blues', |
3886
|
|
|
|
|
|
|
1738 => 'Music Videos|Blues|Chicago Blues', |
3887
|
|
|
|
|
|
|
1739 => 'Music Videos|Blues|Classic Blues', |
3888
|
|
|
|
|
|
|
1740 => 'Music Videos|Blues|Contemporary Blues', |
3889
|
|
|
|
|
|
|
1741 => 'Music Videos|Blues|Country Blues', |
3890
|
|
|
|
|
|
|
1742 => 'Music Videos|Blues|Delta Blues', |
3891
|
|
|
|
|
|
|
1743 => 'Music Videos|Blues|Electric Blues', |
3892
|
|
|
|
|
|
|
1744 => "Music Videos|Children's Music|Lullabies", |
3893
|
|
|
|
|
|
|
1745 => "Music Videos|Children's Music|Sing-Along", |
3894
|
|
|
|
|
|
|
1746 => "Music Videos|Children's Music|Stories", |
3895
|
|
|
|
|
|
|
1747 => 'Music Videos|Christian & Gospel|CCM', |
3896
|
|
|
|
|
|
|
1748 => 'Music Videos|Christian & Gospel|Christian Metal', |
3897
|
|
|
|
|
|
|
1749 => 'Music Videos|Christian & Gospel|Christian Pop', |
3898
|
|
|
|
|
|
|
1750 => 'Music Videos|Christian & Gospel|Christian Rap', |
3899
|
|
|
|
|
|
|
1751 => 'Music Videos|Christian & Gospel|Christian Rock', |
3900
|
|
|
|
|
|
|
1752 => 'Music Videos|Christian & Gospel|Classic Christian', |
3901
|
|
|
|
|
|
|
1753 => 'Music Videos|Christian & Gospel|Contemporary Gospel', |
3902
|
|
|
|
|
|
|
1754 => 'Music Videos|Christian & Gospel|Gospel', |
3903
|
|
|
|
|
|
|
1755 => 'Music Videos|Christian & Gospel|Praise & Worship', |
3904
|
|
|
|
|
|
|
1756 => 'Music Videos|Christian & Gospel|Southern Gospel', |
3905
|
|
|
|
|
|
|
1757 => 'Music Videos|Christian & Gospel|Traditional Gospel', |
3906
|
|
|
|
|
|
|
1758 => 'Music Videos|Classical|Avant-Garde', |
3907
|
|
|
|
|
|
|
1759 => 'Music Videos|Classical|Baroque Era', |
3908
|
|
|
|
|
|
|
1760 => 'Music Videos|Classical|Chamber Music', |
3909
|
|
|
|
|
|
|
1761 => 'Music Videos|Classical|Chant', |
3910
|
|
|
|
|
|
|
1762 => 'Music Videos|Classical|Choral', |
3911
|
|
|
|
|
|
|
1763 => 'Music Videos|Classical|Classical Crossover', |
3912
|
|
|
|
|
|
|
1764 => 'Music Videos|Classical|Early Music', |
3913
|
|
|
|
|
|
|
1765 => 'Music Videos|Classical|Impressionist', |
3914
|
|
|
|
|
|
|
1766 => 'Music Videos|Classical|Medieval Era', |
3915
|
|
|
|
|
|
|
1767 => 'Music Videos|Classical|Minimalism', |
3916
|
|
|
|
|
|
|
1768 => 'Music Videos|Classical|Modern Era', |
3917
|
|
|
|
|
|
|
1769 => 'Music Videos|Classical|Orchestral', |
3918
|
|
|
|
|
|
|
1770 => 'Music Videos|Classical|Renaissance', |
3919
|
|
|
|
|
|
|
1771 => 'Music Videos|Classical|Romantic Era', |
3920
|
|
|
|
|
|
|
1772 => 'Music Videos|Classical|Wedding Music', |
3921
|
|
|
|
|
|
|
1773 => 'Music Videos|Comedy|Novelty', |
3922
|
|
|
|
|
|
|
1774 => 'Music Videos|Comedy|Standup Comedy', |
3923
|
|
|
|
|
|
|
1775 => 'Music Videos|Country|Alternative Country', |
3924
|
|
|
|
|
|
|
1776 => 'Music Videos|Country|Americana', |
3925
|
|
|
|
|
|
|
1777 => 'Music Videos|Country|Bluegrass', |
3926
|
|
|
|
|
|
|
1778 => 'Music Videos|Country|Contemporary Bluegrass', |
3927
|
|
|
|
|
|
|
1779 => 'Music Videos|Country|Contemporary Country', |
3928
|
|
|
|
|
|
|
1780 => 'Music Videos|Country|Country Gospel', |
3929
|
|
|
|
|
|
|
1781 => 'Music Videos|Country|Honky Tonk', |
3930
|
|
|
|
|
|
|
1782 => 'Music Videos|Country|Outlaw Country', |
3931
|
|
|
|
|
|
|
1783 => 'Music Videos|Country|Traditional Bluegrass', |
3932
|
|
|
|
|
|
|
1784 => 'Music Videos|Country|Traditional Country', |
3933
|
|
|
|
|
|
|
1785 => 'Music Videos|Country|Urban Cowboy', |
3934
|
|
|
|
|
|
|
1786 => 'Music Videos|Dance|Breakbeat', |
3935
|
|
|
|
|
|
|
1787 => 'Music Videos|Dance|Exercise', |
3936
|
|
|
|
|
|
|
1788 => 'Music Videos|Dance|Garage', |
3937
|
|
|
|
|
|
|
1789 => 'Music Videos|Dance|Hardcore', |
3938
|
|
|
|
|
|
|
1790 => 'Music Videos|Dance|House', |
3939
|
|
|
|
|
|
|
1791 => "Music Videos|Dance|Jungle/Drum'n'bass", |
3940
|
|
|
|
|
|
|
1792 => 'Music Videos|Dance|Techno', |
3941
|
|
|
|
|
|
|
1793 => 'Music Videos|Dance|Trance', |
3942
|
|
|
|
|
|
|
1794 => 'Music Videos|Easy Listening|Lounge', |
3943
|
|
|
|
|
|
|
1795 => 'Music Videos|Easy Listening|Swing', |
3944
|
|
|
|
|
|
|
1796 => 'Music Videos|Electronic|Ambient', |
3945
|
|
|
|
|
|
|
1797 => 'Music Videos|Electronic|Downtempo', |
3946
|
|
|
|
|
|
|
1798 => 'Music Videos|Electronic|Electronica', |
3947
|
|
|
|
|
|
|
1799 => 'Music Videos|Electronic|IDM/Experimental', |
3948
|
|
|
|
|
|
|
1800 => 'Music Videos|Electronic|Industrial', |
3949
|
|
|
|
|
|
|
1801 => 'Music Videos|Hip-Hop/Rap|Alternative Rap', |
3950
|
|
|
|
|
|
|
1802 => 'Music Videos|Hip-Hop/Rap|Dirty South', |
3951
|
|
|
|
|
|
|
1803 => 'Music Videos|Hip-Hop/Rap|East Coast Rap', |
3952
|
|
|
|
|
|
|
1804 => 'Music Videos|Hip-Hop/Rap|Gangsta Rap', |
3953
|
|
|
|
|
|
|
1805 => 'Music Videos|Hip-Hop/Rap|Hardcore Rap', |
3954
|
|
|
|
|
|
|
1806 => 'Music Videos|Hip-Hop/Rap|Hip-Hop', |
3955
|
|
|
|
|
|
|
1807 => 'Music Videos|Hip-Hop/Rap|Latin Rap', |
3956
|
|
|
|
|
|
|
1808 => 'Music Videos|Hip-Hop/Rap|Old School Rap', |
3957
|
|
|
|
|
|
|
1809 => 'Music Videos|Hip-Hop/Rap|Rap', |
3958
|
|
|
|
|
|
|
1810 => 'Music Videos|Hip-Hop/Rap|Underground Rap', |
3959
|
|
|
|
|
|
|
1811 => 'Music Videos|Hip-Hop/Rap|West Coast Rap', |
3960
|
|
|
|
|
|
|
1812 => 'Music Videos|Holiday|Chanukah', |
3961
|
|
|
|
|
|
|
1813 => 'Music Videos|Holiday|Christmas', |
3962
|
|
|
|
|
|
|
1814 => "Music Videos|Holiday|Christmas: Children's", |
3963
|
|
|
|
|
|
|
1815 => 'Music Videos|Holiday|Christmas: Classic', |
3964
|
|
|
|
|
|
|
1816 => 'Music Videos|Holiday|Christmas: Classical', |
3965
|
|
|
|
|
|
|
1817 => 'Music Videos|Holiday|Christmas: Jazz', |
3966
|
|
|
|
|
|
|
1818 => 'Music Videos|Holiday|Christmas: Modern', |
3967
|
|
|
|
|
|
|
1819 => 'Music Videos|Holiday|Christmas: Pop', |
3968
|
|
|
|
|
|
|
1820 => 'Music Videos|Holiday|Christmas: R&B', |
3969
|
|
|
|
|
|
|
1821 => 'Music Videos|Holiday|Christmas: Religious', |
3970
|
|
|
|
|
|
|
1822 => 'Music Videos|Holiday|Christmas: Rock', |
3971
|
|
|
|
|
|
|
1823 => 'Music Videos|Holiday|Easter', |
3972
|
|
|
|
|
|
|
1824 => 'Music Videos|Holiday|Halloween', |
3973
|
|
|
|
|
|
|
1825 => 'Music Videos|Holiday|Thanksgiving', |
3974
|
|
|
|
|
|
|
1826 => 'Music Videos|Jazz|Avant-Garde Jazz', |
3975
|
|
|
|
|
|
|
1828 => 'Music Videos|Jazz|Bop', |
3976
|
|
|
|
|
|
|
1829 => 'Music Videos|Jazz|Contemporary Jazz', |
3977
|
|
|
|
|
|
|
1830 => 'Music Videos|Jazz|Cool Jazz', |
3978
|
|
|
|
|
|
|
1831 => 'Music Videos|Jazz|Crossover Jazz', |
3979
|
|
|
|
|
|
|
1832 => 'Music Videos|Jazz|Dixieland', |
3980
|
|
|
|
|
|
|
1833 => 'Music Videos|Jazz|Fusion', |
3981
|
|
|
|
|
|
|
1834 => 'Music Videos|Jazz|Hard Bop', |
3982
|
|
|
|
|
|
|
1835 => 'Music Videos|Jazz|Latin Jazz', |
3983
|
|
|
|
|
|
|
1836 => 'Music Videos|Jazz|Mainstream Jazz', |
3984
|
|
|
|
|
|
|
1837 => 'Music Videos|Jazz|Ragtime', |
3985
|
|
|
|
|
|
|
1838 => 'Music Videos|Jazz|Smooth Jazz', |
3986
|
|
|
|
|
|
|
1839 => 'Music Videos|Jazz|Trad Jazz', |
3987
|
|
|
|
|
|
|
1840 => 'Music Videos|Latin|Alternative & Rock in Spanish', |
3988
|
|
|
|
|
|
|
1841 => 'Music Videos|Latin|Baladas y Boleros', |
3989
|
|
|
|
|
|
|
1842 => 'Music Videos|Latin|Contemporary Latin', |
3990
|
|
|
|
|
|
|
1843 => 'Music Videos|Latin|Latin Jazz', |
3991
|
|
|
|
|
|
|
1844 => 'Music Videos|Latin|Latin Urban', |
3992
|
|
|
|
|
|
|
1845 => 'Music Videos|Latin|Pop in Spanish', |
3993
|
|
|
|
|
|
|
1846 => 'Music Videos|Latin|Raices', |
3994
|
|
|
|
|
|
|
1847 => 'Music Videos|Latin|Musica Mexicana', # (Música Mexicana) |
3995
|
|
|
|
|
|
|
1848 => 'Music Videos|Latin|Salsa y Tropical', |
3996
|
|
|
|
|
|
|
1849 => 'Music Videos|New Age|Healing', |
3997
|
|
|
|
|
|
|
1850 => 'Music Videos|New Age|Meditation', |
3998
|
|
|
|
|
|
|
1851 => 'Music Videos|New Age|Nature', |
3999
|
|
|
|
|
|
|
1852 => 'Music Videos|New Age|Relaxation', |
4000
|
|
|
|
|
|
|
1853 => 'Music Videos|New Age|Travel', |
4001
|
|
|
|
|
|
|
1854 => 'Music Videos|Pop|Adult Contemporary', |
4002
|
|
|
|
|
|
|
1855 => 'Music Videos|Pop|Britpop', |
4003
|
|
|
|
|
|
|
1856 => 'Music Videos|Pop|Pop/Rock', |
4004
|
|
|
|
|
|
|
1857 => 'Music Videos|Pop|Soft Rock', |
4005
|
|
|
|
|
|
|
1858 => 'Music Videos|Pop|Teen Pop', |
4006
|
|
|
|
|
|
|
1859 => 'Music Videos|R&B/Soul|Contemporary R&B', |
4007
|
|
|
|
|
|
|
1860 => 'Music Videos|R&B/Soul|Disco', |
4008
|
|
|
|
|
|
|
1861 => 'Music Videos|R&B/Soul|Doo Wop', |
4009
|
|
|
|
|
|
|
1862 => 'Music Videos|R&B/Soul|Funk', |
4010
|
|
|
|
|
|
|
1863 => 'Music Videos|R&B/Soul|Motown', |
4011
|
|
|
|
|
|
|
1864 => 'Music Videos|R&B/Soul|Neo-Soul', |
4012
|
|
|
|
|
|
|
1865 => 'Music Videos|R&B/Soul|Soul', |
4013
|
|
|
|
|
|
|
1866 => 'Music Videos|Reggae|Modern Dancehall', |
4014
|
|
|
|
|
|
|
1867 => 'Music Videos|Reggae|Dub', |
4015
|
|
|
|
|
|
|
1868 => 'Music Videos|Reggae|Roots Reggae', |
4016
|
|
|
|
|
|
|
1869 => 'Music Videos|Reggae|Ska', |
4017
|
|
|
|
|
|
|
1870 => 'Music Videos|Rock|Adult Alternative', |
4018
|
|
|
|
|
|
|
1871 => 'Music Videos|Rock|American Trad Rock', |
4019
|
|
|
|
|
|
|
1872 => 'Music Videos|Rock|Arena Rock', |
4020
|
|
|
|
|
|
|
1873 => 'Music Videos|Rock|Blues-Rock', |
4021
|
|
|
|
|
|
|
1874 => 'Music Videos|Rock|British Invasion', |
4022
|
|
|
|
|
|
|
1875 => 'Music Videos|Rock|Death Metal/Black Metal', |
4023
|
|
|
|
|
|
|
1876 => 'Music Videos|Rock|Glam Rock', |
4024
|
|
|
|
|
|
|
1877 => 'Music Videos|Rock|Hair Metal', |
4025
|
|
|
|
|
|
|
1878 => 'Music Videos|Rock|Hard Rock', |
4026
|
|
|
|
|
|
|
1879 => 'Music Videos|Rock|Jam Bands', |
4027
|
|
|
|
|
|
|
1880 => 'Music Videos|Rock|Prog-Rock/Art Rock', |
4028
|
|
|
|
|
|
|
1881 => 'Music Videos|Rock|Psychedelic', |
4029
|
|
|
|
|
|
|
1882 => 'Music Videos|Rock|Rock & Roll', |
4030
|
|
|
|
|
|
|
1883 => 'Music Videos|Rock|Rockabilly', |
4031
|
|
|
|
|
|
|
1884 => 'Music Videos|Rock|Roots Rock', |
4032
|
|
|
|
|
|
|
1885 => 'Music Videos|Rock|Singer/Songwriter', |
4033
|
|
|
|
|
|
|
1886 => 'Music Videos|Rock|Southern Rock', |
4034
|
|
|
|
|
|
|
1887 => 'Music Videos|Rock|Surf', |
4035
|
|
|
|
|
|
|
1888 => 'Music Videos|Rock|Tex-Mex', |
4036
|
|
|
|
|
|
|
1889 => 'Music Videos|Singer/Songwriter|Alternative Folk', |
4037
|
|
|
|
|
|
|
1890 => 'Music Videos|Singer/Songwriter|Contemporary Folk', |
4038
|
|
|
|
|
|
|
1891 => 'Music Videos|Singer/Songwriter|Contemporary Singer/Songwriter', |
4039
|
|
|
|
|
|
|
1892 => 'Music Videos|Singer/Songwriter|Folk-Rock', |
4040
|
|
|
|
|
|
|
1893 => 'Music Videos|Singer/Songwriter|New Acoustic', |
4041
|
|
|
|
|
|
|
1894 => 'Music Videos|Singer/Songwriter|Traditional Folk', |
4042
|
|
|
|
|
|
|
1895 => 'Music Videos|Soundtrack|Foreign Cinema', |
4043
|
|
|
|
|
|
|
1896 => 'Music Videos|Soundtrack|Musicals', |
4044
|
|
|
|
|
|
|
1897 => 'Music Videos|Soundtrack|Original Score', |
4045
|
|
|
|
|
|
|
1898 => 'Music Videos|Soundtrack|Soundtrack', |
4046
|
|
|
|
|
|
|
1899 => 'Music Videos|Soundtrack|TV Soundtrack', |
4047
|
|
|
|
|
|
|
1900 => 'Music Videos|Vocal|Standards', |
4048
|
|
|
|
|
|
|
1901 => 'Music Videos|Vocal|Traditional Pop', |
4049
|
|
|
|
|
|
|
1902 => 'Music Videos|Jazz|Vocal Jazz', |
4050
|
|
|
|
|
|
|
1903 => 'Music Videos|Vocal|Vocal Pop', |
4051
|
|
|
|
|
|
|
1904 => 'Music Videos|African', |
4052
|
|
|
|
|
|
|
1905 => 'Music Videos|African|Afro-Beat', |
4053
|
|
|
|
|
|
|
1906 => 'Music Videos|African|Afro-Pop', |
4054
|
|
|
|
|
|
|
1907 => 'Music Videos|World|Asia', |
4055
|
|
|
|
|
|
|
1908 => 'Music Videos|World|Australia', |
4056
|
|
|
|
|
|
|
1909 => 'Music Videos|World|Cajun', |
4057
|
|
|
|
|
|
|
1910 => 'Music Videos|World|Caribbean', |
4058
|
|
|
|
|
|
|
1911 => 'Music Videos|World|Celtic', |
4059
|
|
|
|
|
|
|
1912 => 'Music Videos|World|Celtic Folk', |
4060
|
|
|
|
|
|
|
1913 => 'Music Videos|World|Contemporary Celtic', |
4061
|
|
|
|
|
|
|
1914 => 'Music Videos|World|Europe', |
4062
|
|
|
|
|
|
|
1915 => 'Music Videos|World|France', |
4063
|
|
|
|
|
|
|
1916 => 'Music Videos|World|Hawaii', |
4064
|
|
|
|
|
|
|
1917 => 'Music Videos|World|Japan', |
4065
|
|
|
|
|
|
|
1918 => 'Music Videos|World|Klezmer', |
4066
|
|
|
|
|
|
|
1919 => 'Music Videos|World|North America', |
4067
|
|
|
|
|
|
|
1920 => 'Music Videos|World|Polka', |
4068
|
|
|
|
|
|
|
1921 => 'Music Videos|World|South Africa', |
4069
|
|
|
|
|
|
|
1922 => 'Music Videos|World|South America', |
4070
|
|
|
|
|
|
|
1923 => 'Music Videos|World|Traditional Celtic', |
4071
|
|
|
|
|
|
|
1924 => 'Music Videos|World|Worldbeat', |
4072
|
|
|
|
|
|
|
1925 => 'Music Videos|World|Zydeco', |
4073
|
|
|
|
|
|
|
1926 => 'Music Videos|Christian & Gospel', |
4074
|
|
|
|
|
|
|
1928 => 'Music Videos|Classical|Art Song', |
4075
|
|
|
|
|
|
|
1929 => 'Music Videos|Classical|Brass & Woodwinds', |
4076
|
|
|
|
|
|
|
1930 => 'Music Videos|Classical|Solo Instrumental', |
4077
|
|
|
|
|
|
|
1931 => 'Music Videos|Classical|Contemporary Era', |
4078
|
|
|
|
|
|
|
1932 => 'Music Videos|Classical|Oratorio', |
4079
|
|
|
|
|
|
|
1933 => 'Music Videos|Classical|Cantata', |
4080
|
|
|
|
|
|
|
1934 => 'Music Videos|Classical|Electronic', |
4081
|
|
|
|
|
|
|
1935 => 'Music Videos|Classical|Sacred', |
4082
|
|
|
|
|
|
|
1936 => 'Music Videos|Classical|Guitar', |
4083
|
|
|
|
|
|
|
1938 => 'Music Videos|Classical|Violin', |
4084
|
|
|
|
|
|
|
1939 => 'Music Videos|Classical|Cello', |
4085
|
|
|
|
|
|
|
1940 => 'Music Videos|Classical|Percussion', |
4086
|
|
|
|
|
|
|
1941 => 'Music Videos|Electronic|Dubstep', |
4087
|
|
|
|
|
|
|
1942 => 'Music Videos|Electronic|Bass', |
4088
|
|
|
|
|
|
|
1943 => 'Music Videos|Hip-Hop/Rap|UK Hip-Hop', |
4089
|
|
|
|
|
|
|
1944 => 'Music Videos|Reggae|Lovers Rock', |
4090
|
|
|
|
|
|
|
1945 => 'Music Videos|Alternative|EMO', |
4091
|
|
|
|
|
|
|
1946 => 'Music Videos|Alternative|Pop Punk', |
4092
|
|
|
|
|
|
|
1947 => 'Music Videos|Alternative|Indie Pop', |
4093
|
|
|
|
|
|
|
1948 => 'Music Videos|New Age|Yoga', |
4094
|
|
|
|
|
|
|
1949 => 'Music Videos|Pop|Tribute', |
4095
|
|
|
|
|
|
|
1950 => 'Music Videos|Pop|Shows', |
4096
|
|
|
|
|
|
|
1951 => 'Music Videos|Cuban', |
4097
|
|
|
|
|
|
|
1952 => 'Music Videos|Cuban|Mambo', |
4098
|
|
|
|
|
|
|
1953 => 'Music Videos|Cuban|Chachacha', |
4099
|
|
|
|
|
|
|
1954 => 'Music Videos|Cuban|Guajira', |
4100
|
|
|
|
|
|
|
1955 => 'Music Videos|Cuban|Son', |
4101
|
|
|
|
|
|
|
1956 => 'Music Videos|Cuban|Bolero', |
4102
|
|
|
|
|
|
|
1957 => 'Music Videos|Cuban|Guaracha', |
4103
|
|
|
|
|
|
|
1958 => 'Music Videos|Cuban|Timba', |
4104
|
|
|
|
|
|
|
1959 => 'Music Videos|Soundtrack|Video Game', |
4105
|
|
|
|
|
|
|
1960 => 'Music Videos|Indian|Regional Indian|Punjabi|Punjabi Pop', |
4106
|
|
|
|
|
|
|
1961 => 'Music Videos|Indian|Regional Indian|Bengali|Rabindra Sangeet', |
4107
|
|
|
|
|
|
|
1962 => 'Music Videos|Indian|Regional Indian|Malayalam', |
4108
|
|
|
|
|
|
|
1963 => 'Music Videos|Indian|Regional Indian|Kannada', |
4109
|
|
|
|
|
|
|
1964 => 'Music Videos|Indian|Regional Indian|Marathi', |
4110
|
|
|
|
|
|
|
1965 => 'Music Videos|Indian|Regional Indian|Gujarati', |
4111
|
|
|
|
|
|
|
1966 => 'Music Videos|Indian|Regional Indian|Assamese', |
4112
|
|
|
|
|
|
|
1967 => 'Music Videos|Indian|Regional Indian|Bhojpuri', |
4113
|
|
|
|
|
|
|
1968 => 'Music Videos|Indian|Regional Indian|Haryanvi', |
4114
|
|
|
|
|
|
|
1969 => 'Music Videos|Indian|Regional Indian|Odia', |
4115
|
|
|
|
|
|
|
1970 => 'Music Videos|Indian|Regional Indian|Rajasthani', |
4116
|
|
|
|
|
|
|
1971 => 'Music Videos|Indian|Regional Indian|Urdu', |
4117
|
|
|
|
|
|
|
1972 => 'Music Videos|Indian|Regional Indian|Punjabi', |
4118
|
|
|
|
|
|
|
1973 => 'Music Videos|Indian|Regional Indian|Bengali', |
4119
|
|
|
|
|
|
|
1974 => 'Music Videos|Indian|Indian Classical|Carnatic Classical', |
4120
|
|
|
|
|
|
|
1975 => 'Music Videos|Indian|Indian Classical|Hindustani Classical', |
4121
|
|
|
|
|
|
|
1976 => 'Music Videos|African|Afro House', |
4122
|
|
|
|
|
|
|
1977 => 'Music Videos|African|Afro Soul', |
4123
|
|
|
|
|
|
|
1978 => 'Music Videos|African|Afrobeats', |
4124
|
|
|
|
|
|
|
1979 => 'Music Videos|African|Benga', |
4125
|
|
|
|
|
|
|
1980 => 'Music Videos|African|Bongo-Flava', |
4126
|
|
|
|
|
|
|
1981 => 'Music Videos|African|Coupe-Decale', |
4127
|
|
|
|
|
|
|
1982 => 'Music Videos|African|Gqom', |
4128
|
|
|
|
|
|
|
1983 => 'Music Videos|African|Highlife', |
4129
|
|
|
|
|
|
|
1984 => 'Music Videos|African|Kuduro', |
4130
|
|
|
|
|
|
|
1985 => 'Music Videos|African|Kizomba', |
4131
|
|
|
|
|
|
|
1986 => 'Music Videos|African|Kwaito', |
4132
|
|
|
|
|
|
|
1987 => 'Music Videos|African|Mbalax', |
4133
|
|
|
|
|
|
|
1988 => 'Music Videos|African|Ndombolo', |
4134
|
|
|
|
|
|
|
1989 => 'Music Videos|African|Shangaan Electro', |
4135
|
|
|
|
|
|
|
1990 => 'Music Videos|African|Soukous', |
4136
|
|
|
|
|
|
|
1991 => 'Music Videos|African|Taarab', |
4137
|
|
|
|
|
|
|
1992 => 'Music Videos|African|Zouglou', |
4138
|
|
|
|
|
|
|
1993 => 'Music Videos|Turkish|Ozgun', |
4139
|
|
|
|
|
|
|
1994 => 'Music Videos|Turkish|Fantezi', |
4140
|
|
|
|
|
|
|
1995 => 'Music Videos|Turkish|Religious', |
4141
|
|
|
|
|
|
|
1996 => 'Music Videos|Pop|Turkish Pop', |
4142
|
|
|
|
|
|
|
1997 => 'Music Videos|Rock|Turkish Rock', |
4143
|
|
|
|
|
|
|
1998 => 'Music Videos|Alternative|Turkish Alternative', |
4144
|
|
|
|
|
|
|
1999 => 'Music Videos|Hip-Hop/Rap|Turkish Hip-Hop/Rap', |
4145
|
|
|
|
|
|
|
2000 => 'Music Videos|African|Maskandi', |
4146
|
|
|
|
|
|
|
2001 => 'Music Videos|Russian|Russian Romance', |
4147
|
|
|
|
|
|
|
2002 => 'Music Videos|Russian|Russian Bard', |
4148
|
|
|
|
|
|
|
2003 => 'Music Videos|Russian|Russian Pop', |
4149
|
|
|
|
|
|
|
2004 => 'Music Videos|Russian|Russian Rock', |
4150
|
|
|
|
|
|
|
2005 => 'Music Videos|Russian|Russian Hip-Hop', |
4151
|
|
|
|
|
|
|
2006 => 'Music Videos|Arabic|Levant', |
4152
|
|
|
|
|
|
|
2007 => 'Music Videos|Arabic|Levant|Dabke', |
4153
|
|
|
|
|
|
|
2008 => 'Music Videos|Arabic|Maghreb Rai', |
4154
|
|
|
|
|
|
|
2009 => 'Music Videos|Arabic|Khaleeji|Khaleeji Jalsat', |
4155
|
|
|
|
|
|
|
2010 => 'Music Videos|Arabic|Khaleeji|Khaleeji Shailat', |
4156
|
|
|
|
|
|
|
2011 => 'Music Videos|Tarab', |
4157
|
|
|
|
|
|
|
2012 => 'Music Videos|Tarab|Iraqi Tarab', |
4158
|
|
|
|
|
|
|
2013 => 'Music Videos|Tarab|Egyptian Tarab', |
4159
|
|
|
|
|
|
|
2014 => 'Music Videos|Tarab|Khaleeji Tarab', |
4160
|
|
|
|
|
|
|
2015 => 'Music Videos|Pop|Levant Pop', |
4161
|
|
|
|
|
|
|
2016 => 'Music Videos|Pop|Iraqi Pop', |
4162
|
|
|
|
|
|
|
2017 => 'Music Videos|Pop|Egyptian Pop', |
4163
|
|
|
|
|
|
|
2018 => 'Music Videos|Pop|Maghreb Pop', |
4164
|
|
|
|
|
|
|
2019 => 'Music Videos|Pop|Khaleeji Pop', |
4165
|
|
|
|
|
|
|
2020 => 'Music Videos|Hip-Hop/Rap|Levant Hip-Hop', |
4166
|
|
|
|
|
|
|
2021 => 'Music Videos|Hip-Hop/Rap|Egyptian Hip-Hop', |
4167
|
|
|
|
|
|
|
2022 => 'Music Videos|Hip-Hop/Rap|Maghreb Hip-Hop', |
4168
|
|
|
|
|
|
|
2023 => 'Music Videos|Hip-Hop/Rap|Khaleeji Hip-Hop', |
4169
|
|
|
|
|
|
|
2024 => 'Music Videos|Alternative|Indie Levant', |
4170
|
|
|
|
|
|
|
2025 => 'Music Videos|Alternative|Indie Egyptian', |
4171
|
|
|
|
|
|
|
2026 => 'Music Videos|Alternative|Indie Maghreb', |
4172
|
|
|
|
|
|
|
2027 => 'Music Videos|Electronic|Levant Electronic', |
4173
|
|
|
|
|
|
|
2028 => "Music Videos|Electronic|Electro-Cha'abi", |
4174
|
|
|
|
|
|
|
2029 => 'Music Videos|Electronic|Maghreb Electronic', |
4175
|
|
|
|
|
|
|
2030 => 'Music Videos|Folk|Iraqi Folk', |
4176
|
|
|
|
|
|
|
2031 => 'Music Videos|Folk|Khaleeji Folk', |
4177
|
|
|
|
|
|
|
2032 => 'Music Videos|Dance|Maghreb Dance', |
4178
|
|
|
|
|
|
|
4000 => 'TV Shows|Comedy', |
4179
|
|
|
|
|
|
|
4001 => 'TV Shows|Drama', |
4180
|
|
|
|
|
|
|
4002 => 'TV Shows|Animation', |
4181
|
|
|
|
|
|
|
4003 => 'TV Shows|Action & Adventure', |
4182
|
|
|
|
|
|
|
4004 => 'TV Shows|Classics', |
4183
|
|
|
|
|
|
|
4005 => 'TV Shows|Kids & Family', |
4184
|
|
|
|
|
|
|
4006 => 'TV Shows|Nonfiction', |
4185
|
|
|
|
|
|
|
4007 => 'TV Shows|Reality TV', |
4186
|
|
|
|
|
|
|
4008 => 'TV Shows|Sci-Fi & Fantasy', |
4187
|
|
|
|
|
|
|
4009 => 'TV Shows|Sports', |
4188
|
|
|
|
|
|
|
4010 => 'TV Shows|Teens', |
4189
|
|
|
|
|
|
|
4011 => 'TV Shows|Latino TV', |
4190
|
|
|
|
|
|
|
4401 => 'Movies|Action & Adventure', |
4191
|
|
|
|
|
|
|
4402 => 'Movies|Anime', |
4192
|
|
|
|
|
|
|
4403 => 'Movies|Classics', |
4193
|
|
|
|
|
|
|
4404 => 'Movies|Comedy', |
4194
|
|
|
|
|
|
|
4405 => 'Movies|Documentary', |
4195
|
|
|
|
|
|
|
4406 => 'Movies|Drama', |
4196
|
|
|
|
|
|
|
4407 => 'Movies|Foreign', |
4197
|
|
|
|
|
|
|
4408 => 'Movies|Horror', |
4198
|
|
|
|
|
|
|
4409 => 'Movies|Independent', |
4199
|
|
|
|
|
|
|
4410 => 'Movies|Kids & Family', |
4200
|
|
|
|
|
|
|
4411 => 'Movies|Musicals', |
4201
|
|
|
|
|
|
|
4412 => 'Movies|Romance', |
4202
|
|
|
|
|
|
|
4413 => 'Movies|Sci-Fi & Fantasy', |
4203
|
|
|
|
|
|
|
4414 => 'Movies|Short Films', |
4204
|
|
|
|
|
|
|
4415 => 'Movies|Special Interest', |
4205
|
|
|
|
|
|
|
4416 => 'Movies|Thriller', |
4206
|
|
|
|
|
|
|
4417 => 'Movies|Sports', |
4207
|
|
|
|
|
|
|
4418 => 'Movies|Western', |
4208
|
|
|
|
|
|
|
4419 => 'Movies|Urban', |
4209
|
|
|
|
|
|
|
4420 => 'Movies|Holiday', |
4210
|
|
|
|
|
|
|
4421 => 'Movies|Made for TV', |
4211
|
|
|
|
|
|
|
4422 => 'Movies|Concert Films', |
4212
|
|
|
|
|
|
|
4423 => 'Movies|Music Documentaries', |
4213
|
|
|
|
|
|
|
4424 => 'Movies|Music Feature Films', |
4214
|
|
|
|
|
|
|
4425 => 'Movies|Japanese Cinema', |
4215
|
|
|
|
|
|
|
4426 => 'Movies|Jidaigeki', |
4216
|
|
|
|
|
|
|
4427 => 'Movies|Tokusatsu', |
4217
|
|
|
|
|
|
|
4428 => 'Movies|Korean Cinema', |
4218
|
|
|
|
|
|
|
4429 => 'Movies|Russian', |
4219
|
|
|
|
|
|
|
4430 => 'Movies|Turkish', |
4220
|
|
|
|
|
|
|
4431 => 'Movies|Bollywood', |
4221
|
|
|
|
|
|
|
4432 => 'Movies|Regional Indian', |
4222
|
|
|
|
|
|
|
4433 => 'Movies|Middle Eastern', |
4223
|
|
|
|
|
|
|
4434 => 'Movies|African', |
4224
|
|
|
|
|
|
|
6000 => 'App Store|Business', |
4225
|
|
|
|
|
|
|
6001 => 'App Store|Weather', |
4226
|
|
|
|
|
|
|
6002 => 'App Store|Utilities', |
4227
|
|
|
|
|
|
|
6003 => 'App Store|Travel', |
4228
|
|
|
|
|
|
|
6004 => 'App Store|Sports', |
4229
|
|
|
|
|
|
|
6005 => 'App Store|Social Networking', |
4230
|
|
|
|
|
|
|
6006 => 'App Store|Reference', |
4231
|
|
|
|
|
|
|
6007 => 'App Store|Productivity', |
4232
|
|
|
|
|
|
|
6008 => 'App Store|Photo & Video', |
4233
|
|
|
|
|
|
|
6009 => 'App Store|News', |
4234
|
|
|
|
|
|
|
6010 => 'App Store|Navigation', |
4235
|
|
|
|
|
|
|
6011 => 'App Store|Music', |
4236
|
|
|
|
|
|
|
6012 => 'App Store|Lifestyle', |
4237
|
|
|
|
|
|
|
6013 => 'App Store|Health & Fitness', |
4238
|
|
|
|
|
|
|
6014 => 'App Store|Games', |
4239
|
|
|
|
|
|
|
6015 => 'App Store|Finance', |
4240
|
|
|
|
|
|
|
6016 => 'App Store|Entertainment', |
4241
|
|
|
|
|
|
|
6017 => 'App Store|Education', |
4242
|
|
|
|
|
|
|
6018 => 'App Store|Books', |
4243
|
|
|
|
|
|
|
6020 => 'App Store|Medical', |
4244
|
|
|
|
|
|
|
6021 => 'App Store|Magazines & Newspapers', |
4245
|
|
|
|
|
|
|
6022 => 'App Store|Catalogs', |
4246
|
|
|
|
|
|
|
6023 => 'App Store|Food & Drink', |
4247
|
|
|
|
|
|
|
6024 => 'App Store|Shopping', |
4248
|
|
|
|
|
|
|
6025 => 'App Store|Stickers', |
4249
|
|
|
|
|
|
|
6026 => 'App Store|Developer Tools', |
4250
|
|
|
|
|
|
|
6027 => 'App Store|Graphics & Design', |
4251
|
|
|
|
|
|
|
7001 => 'App Store|Games|Action', |
4252
|
|
|
|
|
|
|
7002 => 'App Store|Games|Adventure', |
4253
|
|
|
|
|
|
|
7003 => 'App Store|Games|Casual', |
4254
|
|
|
|
|
|
|
7004 => 'App Store|Games|Board', |
4255
|
|
|
|
|
|
|
7005 => 'App Store|Games|Card', |
4256
|
|
|
|
|
|
|
7006 => 'App Store|Games|Casino', |
4257
|
|
|
|
|
|
|
7007 => 'App Store|Games|Dice', |
4258
|
|
|
|
|
|
|
7008 => 'App Store|Games|Educational', |
4259
|
|
|
|
|
|
|
7009 => 'App Store|Games|Family', |
4260
|
|
|
|
|
|
|
7011 => 'App Store|Games|Music', |
4261
|
|
|
|
|
|
|
7012 => 'App Store|Games|Puzzle', |
4262
|
|
|
|
|
|
|
7013 => 'App Store|Games|Racing', |
4263
|
|
|
|
|
|
|
7014 => 'App Store|Games|Role Playing', |
4264
|
|
|
|
|
|
|
7015 => 'App Store|Games|Simulation', |
4265
|
|
|
|
|
|
|
7016 => 'App Store|Games|Sports', |
4266
|
|
|
|
|
|
|
7017 => 'App Store|Games|Strategy', |
4267
|
|
|
|
|
|
|
7018 => 'App Store|Games|Trivia', |
4268
|
|
|
|
|
|
|
7019 => 'App Store|Games|Word', |
4269
|
|
|
|
|
|
|
8001 => 'Tones|Ringtones|Alternative', |
4270
|
|
|
|
|
|
|
8002 => 'Tones|Ringtones|Blues', |
4271
|
|
|
|
|
|
|
8003 => "Tones|Ringtones|Children's Music", |
4272
|
|
|
|
|
|
|
8004 => 'Tones|Ringtones|Classical', |
4273
|
|
|
|
|
|
|
8005 => 'Tones|Ringtones|Comedy', |
4274
|
|
|
|
|
|
|
8006 => 'Tones|Ringtones|Country', |
4275
|
|
|
|
|
|
|
8007 => 'Tones|Ringtones|Dance', |
4276
|
|
|
|
|
|
|
8008 => 'Tones|Ringtones|Electronic', |
4277
|
|
|
|
|
|
|
8009 => 'Tones|Ringtones|Enka', |
4278
|
|
|
|
|
|
|
8010 => 'Tones|Ringtones|French Pop', |
4279
|
|
|
|
|
|
|
8011 => 'Tones|Ringtones|German Folk', |
4280
|
|
|
|
|
|
|
8012 => 'Tones|Ringtones|German Pop', |
4281
|
|
|
|
|
|
|
8013 => 'Tones|Ringtones|Hip-Hop/Rap', |
4282
|
|
|
|
|
|
|
8014 => 'Tones|Ringtones|Holiday', |
4283
|
|
|
|
|
|
|
8015 => 'Tones|Ringtones|Inspirational', |
4284
|
|
|
|
|
|
|
8016 => 'Tones|Ringtones|J-Pop', |
4285
|
|
|
|
|
|
|
8017 => 'Tones|Ringtones|Jazz', |
4286
|
|
|
|
|
|
|
8018 => 'Tones|Ringtones|Kayokyoku', |
4287
|
|
|
|
|
|
|
8019 => 'Tones|Ringtones|Latin', |
4288
|
|
|
|
|
|
|
8020 => 'Tones|Ringtones|New Age', |
4289
|
|
|
|
|
|
|
8021 => 'Tones|Ringtones|Classical|Opera', |
4290
|
|
|
|
|
|
|
8022 => 'Tones|Ringtones|Pop', |
4291
|
|
|
|
|
|
|
8023 => 'Tones|Ringtones|R&B/Soul', |
4292
|
|
|
|
|
|
|
8024 => 'Tones|Ringtones|Reggae', |
4293
|
|
|
|
|
|
|
8025 => 'Tones|Ringtones|Rock', |
4294
|
|
|
|
|
|
|
8026 => 'Tones|Ringtones|Singer/Songwriter', |
4295
|
|
|
|
|
|
|
8027 => 'Tones|Ringtones|Soundtrack', |
4296
|
|
|
|
|
|
|
8028 => 'Tones|Ringtones|Spoken Word', |
4297
|
|
|
|
|
|
|
8029 => 'Tones|Ringtones|Vocal', |
4298
|
|
|
|
|
|
|
8030 => 'Tones|Ringtones|World', |
4299
|
|
|
|
|
|
|
8050 => 'Tones|Alert Tones|Sound Effects', |
4300
|
|
|
|
|
|
|
8051 => 'Tones|Alert Tones|Dialogue', |
4301
|
|
|
|
|
|
|
8052 => 'Tones|Alert Tones|Music', |
4302
|
|
|
|
|
|
|
8053 => 'Tones|Ringtones', |
4303
|
|
|
|
|
|
|
8054 => 'Tones|Alert Tones', |
4304
|
|
|
|
|
|
|
8055 => 'Tones|Ringtones|Alternative|Chinese Alt', |
4305
|
|
|
|
|
|
|
8056 => 'Tones|Ringtones|Alternative|College Rock', |
4306
|
|
|
|
|
|
|
8057 => 'Tones|Ringtones|Alternative|Goth Rock', |
4307
|
|
|
|
|
|
|
8058 => 'Tones|Ringtones|Alternative|Grunge', |
4308
|
|
|
|
|
|
|
8059 => 'Tones|Ringtones|Alternative|Indie Rock', |
4309
|
|
|
|
|
|
|
8060 => 'Tones|Ringtones|Alternative|Korean Indie', |
4310
|
|
|
|
|
|
|
8061 => 'Tones|Ringtones|Alternative|New Wave', |
4311
|
|
|
|
|
|
|
8062 => 'Tones|Ringtones|Alternative|Punk', |
4312
|
|
|
|
|
|
|
8063 => 'Tones|Ringtones|Anime', |
4313
|
|
|
|
|
|
|
8064 => 'Tones|Ringtones|Arabic', |
4314
|
|
|
|
|
|
|
8065 => 'Tones|Ringtones|Arabic|Arabic Pop', |
4315
|
|
|
|
|
|
|
8066 => 'Tones|Ringtones|Arabic|Islamic', |
4316
|
|
|
|
|
|
|
8067 => 'Tones|Ringtones|Arabic|Khaleeji', |
4317
|
|
|
|
|
|
|
8068 => 'Tones|Ringtones|Arabic|North African', |
4318
|
|
|
|
|
|
|
8069 => 'Tones|Ringtones|Blues|Acoustic Blues', |
4319
|
|
|
|
|
|
|
8070 => 'Tones|Ringtones|Blues|Chicago Blues', |
4320
|
|
|
|
|
|
|
8071 => 'Tones|Ringtones|Blues|Classic Blues', |
4321
|
|
|
|
|
|
|
8072 => 'Tones|Ringtones|Blues|Contemporary Blues', |
4322
|
|
|
|
|
|
|
8073 => 'Tones|Ringtones|Blues|Country Blues', |
4323
|
|
|
|
|
|
|
8074 => 'Tones|Ringtones|Blues|Delta Blues', |
4324
|
|
|
|
|
|
|
8075 => 'Tones|Ringtones|Blues|Electric Blues', |
4325
|
|
|
|
|
|
|
8076 => 'Tones|Ringtones|Brazilian', |
4326
|
|
|
|
|
|
|
8077 => 'Tones|Ringtones|Brazilian|Axe', # (Axé) |
4327
|
|
|
|
|
|
|
8078 => 'Tones|Ringtones|Brazilian|Baile Funk', |
4328
|
|
|
|
|
|
|
8079 => 'Tones|Ringtones|Brazilian|Bossa Nova', |
4329
|
|
|
|
|
|
|
8080 => 'Tones|Ringtones|Brazilian|Choro', |
4330
|
|
|
|
|
|
|
8081 => 'Tones|Ringtones|Brazilian|Forro', # (Forró) |
4331
|
|
|
|
|
|
|
8082 => 'Tones|Ringtones|Brazilian|Frevo', |
4332
|
|
|
|
|
|
|
8083 => 'Tones|Ringtones|Brazilian|MPB', |
4333
|
|
|
|
|
|
|
8084 => 'Tones|Ringtones|Brazilian|Pagode', |
4334
|
|
|
|
|
|
|
8085 => 'Tones|Ringtones|Brazilian|Samba', |
4335
|
|
|
|
|
|
|
8086 => 'Tones|Ringtones|Brazilian|Sertanejo', |
4336
|
|
|
|
|
|
|
8087 => "Tones|Ringtones|Children's Music|Lullabies", |
4337
|
|
|
|
|
|
|
8088 => "Tones|Ringtones|Children's Music|Sing-Along", |
4338
|
|
|
|
|
|
|
8089 => "Tones|Ringtones|Children's Music|Stories", |
4339
|
|
|
|
|
|
|
8090 => 'Tones|Ringtones|Chinese', |
4340
|
|
|
|
|
|
|
8091 => 'Tones|Ringtones|Chinese|Chinese Classical', |
4341
|
|
|
|
|
|
|
8092 => 'Tones|Ringtones|Chinese|Chinese Flute', |
4342
|
|
|
|
|
|
|
8093 => 'Tones|Ringtones|Chinese|Chinese Opera', |
4343
|
|
|
|
|
|
|
8094 => 'Tones|Ringtones|Chinese|Chinese Orchestral', |
4344
|
|
|
|
|
|
|
8095 => 'Tones|Ringtones|Chinese|Chinese Regional Folk', |
4345
|
|
|
|
|
|
|
8096 => 'Tones|Ringtones|Chinese|Chinese Strings', |
4346
|
|
|
|
|
|
|
8097 => 'Tones|Ringtones|Chinese|Taiwanese Folk', |
4347
|
|
|
|
|
|
|
8098 => 'Tones|Ringtones|Chinese|Tibetan Native Music', |
4348
|
|
|
|
|
|
|
8099 => 'Tones|Ringtones|Christian & Gospel', |
4349
|
|
|
|
|
|
|
8100 => 'Tones|Ringtones|Christian & Gospel|CCM', |
4350
|
|
|
|
|
|
|
8101 => 'Tones|Ringtones|Christian & Gospel|Christian Metal', |
4351
|
|
|
|
|
|
|
8102 => 'Tones|Ringtones|Christian & Gospel|Christian Pop', |
4352
|
|
|
|
|
|
|
8103 => 'Tones|Ringtones|Christian & Gospel|Christian Rap', |
4353
|
|
|
|
|
|
|
8104 => 'Tones|Ringtones|Christian & Gospel|Christian Rock', |
4354
|
|
|
|
|
|
|
8105 => 'Tones|Ringtones|Christian & Gospel|Classic Christian', |
4355
|
|
|
|
|
|
|
8106 => 'Tones|Ringtones|Christian & Gospel|Contemporary Gospel', |
4356
|
|
|
|
|
|
|
8107 => 'Tones|Ringtones|Christian & Gospel|Gospel', |
4357
|
|
|
|
|
|
|
8108 => 'Tones|Ringtones|Christian & Gospel|Praise & Worship', |
4358
|
|
|
|
|
|
|
8109 => 'Tones|Ringtones|Christian & Gospel|Southern Gospel', |
4359
|
|
|
|
|
|
|
8110 => 'Tones|Ringtones|Christian & Gospel|Traditional Gospel', |
4360
|
|
|
|
|
|
|
8111 => 'Tones|Ringtones|Classical|Avant-Garde', |
4361
|
|
|
|
|
|
|
8112 => 'Tones|Ringtones|Classical|Baroque Era', |
4362
|
|
|
|
|
|
|
8113 => 'Tones|Ringtones|Classical|Chamber Music', |
4363
|
|
|
|
|
|
|
8114 => 'Tones|Ringtones|Classical|Chant', |
4364
|
|
|
|
|
|
|
8115 => 'Tones|Ringtones|Classical|Choral', |
4365
|
|
|
|
|
|
|
8116 => 'Tones|Ringtones|Classical|Classical Crossover', |
4366
|
|
|
|
|
|
|
8117 => 'Tones|Ringtones|Classical|Early Music', |
4367
|
|
|
|
|
|
|
8118 => 'Tones|Ringtones|Classical|High Classical', |
4368
|
|
|
|
|
|
|
8119 => 'Tones|Ringtones|Classical|Impressionist', |
4369
|
|
|
|
|
|
|
8120 => 'Tones|Ringtones|Classical|Medieval Era', |
4370
|
|
|
|
|
|
|
8121 => 'Tones|Ringtones|Classical|Minimalism', |
4371
|
|
|
|
|
|
|
8122 => 'Tones|Ringtones|Classical|Modern Era', |
4372
|
|
|
|
|
|
|
8123 => 'Tones|Ringtones|Classical|Orchestral', |
4373
|
|
|
|
|
|
|
8124 => 'Tones|Ringtones|Classical|Renaissance', |
4374
|
|
|
|
|
|
|
8125 => 'Tones|Ringtones|Classical|Romantic Era', |
4375
|
|
|
|
|
|
|
8126 => 'Tones|Ringtones|Classical|Wedding Music', |
4376
|
|
|
|
|
|
|
8127 => 'Tones|Ringtones|Comedy|Novelty', |
4377
|
|
|
|
|
|
|
8128 => 'Tones|Ringtones|Comedy|Standup Comedy', |
4378
|
|
|
|
|
|
|
8129 => 'Tones|Ringtones|Country|Alternative Country', |
4379
|
|
|
|
|
|
|
8130 => 'Tones|Ringtones|Country|Americana', |
4380
|
|
|
|
|
|
|
8131 => 'Tones|Ringtones|Country|Bluegrass', |
4381
|
|
|
|
|
|
|
8132 => 'Tones|Ringtones|Country|Contemporary Bluegrass', |
4382
|
|
|
|
|
|
|
8133 => 'Tones|Ringtones|Country|Contemporary Country', |
4383
|
|
|
|
|
|
|
8134 => 'Tones|Ringtones|Country|Country Gospel', |
4384
|
|
|
|
|
|
|
8135 => 'Tones|Ringtones|Country|Honky Tonk', |
4385
|
|
|
|
|
|
|
8136 => 'Tones|Ringtones|Country|Outlaw Country', |
4386
|
|
|
|
|
|
|
8137 => 'Tones|Ringtones|Country|Thai Country', |
4387
|
|
|
|
|
|
|
8138 => 'Tones|Ringtones|Country|Traditional Bluegrass', |
4388
|
|
|
|
|
|
|
8139 => 'Tones|Ringtones|Country|Traditional Country', |
4389
|
|
|
|
|
|
|
8140 => 'Tones|Ringtones|Country|Urban Cowboy', |
4390
|
|
|
|
|
|
|
8141 => 'Tones|Ringtones|Dance|Breakbeat', |
4391
|
|
|
|
|
|
|
8142 => 'Tones|Ringtones|Dance|Exercise', |
4392
|
|
|
|
|
|
|
8143 => 'Tones|Ringtones|Dance|Garage', |
4393
|
|
|
|
|
|
|
8144 => 'Tones|Ringtones|Dance|Hardcore', |
4394
|
|
|
|
|
|
|
8145 => 'Tones|Ringtones|Dance|House', |
4395
|
|
|
|
|
|
|
8146 => "Tones|Ringtones|Dance|Jungle/Drum'n'bass", |
4396
|
|
|
|
|
|
|
8147 => 'Tones|Ringtones|Dance|Techno', |
4397
|
|
|
|
|
|
|
8148 => 'Tones|Ringtones|Dance|Trance', |
4398
|
|
|
|
|
|
|
8149 => 'Tones|Ringtones|Disney', |
4399
|
|
|
|
|
|
|
8150 => 'Tones|Ringtones|Easy Listening', |
4400
|
|
|
|
|
|
|
8151 => 'Tones|Ringtones|Easy Listening|Lounge', |
4401
|
|
|
|
|
|
|
8152 => 'Tones|Ringtones|Easy Listening|Swing', |
4402
|
|
|
|
|
|
|
8153 => 'Tones|Ringtones|Electronic|Ambient', |
4403
|
|
|
|
|
|
|
8154 => 'Tones|Ringtones|Electronic|Downtempo', |
4404
|
|
|
|
|
|
|
8155 => 'Tones|Ringtones|Electronic|Electronica', |
4405
|
|
|
|
|
|
|
8156 => 'Tones|Ringtones|Electronic|IDM/Experimental', |
4406
|
|
|
|
|
|
|
8157 => 'Tones|Ringtones|Electronic|Industrial', |
4407
|
|
|
|
|
|
|
8158 => 'Tones|Ringtones|Fitness & Workout', |
4408
|
|
|
|
|
|
|
8159 => 'Tones|Ringtones|Folk', |
4409
|
|
|
|
|
|
|
8160 => 'Tones|Ringtones|Hip-Hop/Rap|Alternative Rap', |
4410
|
|
|
|
|
|
|
8161 => 'Tones|Ringtones|Hip-Hop/Rap|Chinese Hip-Hop', |
4411
|
|
|
|
|
|
|
8162 => 'Tones|Ringtones|Hip-Hop/Rap|Dirty South', |
4412
|
|
|
|
|
|
|
8163 => 'Tones|Ringtones|Hip-Hop/Rap|East Coast Rap', |
4413
|
|
|
|
|
|
|
8164 => 'Tones|Ringtones|Hip-Hop/Rap|Gangsta Rap', |
4414
|
|
|
|
|
|
|
8165 => 'Tones|Ringtones|Hip-Hop/Rap|Hardcore Rap', |
4415
|
|
|
|
|
|
|
8166 => 'Tones|Ringtones|Hip-Hop/Rap|Hip-Hop', |
4416
|
|
|
|
|
|
|
8167 => 'Tones|Ringtones|Hip-Hop/Rap|Korean Hip-Hop', |
4417
|
|
|
|
|
|
|
8168 => 'Tones|Ringtones|Hip-Hop/Rap|Latin Rap', |
4418
|
|
|
|
|
|
|
8169 => 'Tones|Ringtones|Hip-Hop/Rap|Old School Rap', |
4419
|
|
|
|
|
|
|
8170 => 'Tones|Ringtones|Hip-Hop/Rap|Rap', |
4420
|
|
|
|
|
|
|
8171 => 'Tones|Ringtones|Hip-Hop/Rap|Underground Rap', |
4421
|
|
|
|
|
|
|
8172 => 'Tones|Ringtones|Hip-Hop/Rap|West Coast Rap', |
4422
|
|
|
|
|
|
|
8173 => 'Tones|Ringtones|Holiday|Chanukah', |
4423
|
|
|
|
|
|
|
8174 => 'Tones|Ringtones|Holiday|Christmas', |
4424
|
|
|
|
|
|
|
8175 => "Tones|Ringtones|Holiday|Christmas: Children's", |
4425
|
|
|
|
|
|
|
8176 => 'Tones|Ringtones|Holiday|Christmas: Classic', |
4426
|
|
|
|
|
|
|
8177 => 'Tones|Ringtones|Holiday|Christmas: Classical', |
4427
|
|
|
|
|
|
|
8178 => 'Tones|Ringtones|Holiday|Christmas: Jazz', |
4428
|
|
|
|
|
|
|
8179 => 'Tones|Ringtones|Holiday|Christmas: Modern', |
4429
|
|
|
|
|
|
|
8180 => 'Tones|Ringtones|Holiday|Christmas: Pop', |
4430
|
|
|
|
|
|
|
8181 => 'Tones|Ringtones|Holiday|Christmas: R&B', |
4431
|
|
|
|
|
|
|
8182 => 'Tones|Ringtones|Holiday|Christmas: Religious', |
4432
|
|
|
|
|
|
|
8183 => 'Tones|Ringtones|Holiday|Christmas: Rock', |
4433
|
|
|
|
|
|
|
8184 => 'Tones|Ringtones|Holiday|Easter', |
4434
|
|
|
|
|
|
|
8185 => 'Tones|Ringtones|Holiday|Halloween', |
4435
|
|
|
|
|
|
|
8186 => 'Tones|Ringtones|Holiday|Thanksgiving', |
4436
|
|
|
|
|
|
|
8187 => 'Tones|Ringtones|Indian', |
4437
|
|
|
|
|
|
|
8188 => 'Tones|Ringtones|Indian|Bollywood', |
4438
|
|
|
|
|
|
|
8189 => 'Tones|Ringtones|Indian|Devotional & Spiritual', |
4439
|
|
|
|
|
|
|
8190 => 'Tones|Ringtones|Indian|Ghazals', |
4440
|
|
|
|
|
|
|
8191 => 'Tones|Ringtones|Indian|Indian Classical', |
4441
|
|
|
|
|
|
|
8192 => 'Tones|Ringtones|Indian|Indian Folk', |
4442
|
|
|
|
|
|
|
8193 => 'Tones|Ringtones|Indian|Indian Pop', |
4443
|
|
|
|
|
|
|
8194 => 'Tones|Ringtones|Indian|Regional Indian', |
4444
|
|
|
|
|
|
|
8195 => 'Tones|Ringtones|Indian|Sufi', |
4445
|
|
|
|
|
|
|
8196 => 'Tones|Ringtones|Indian|Regional Indian|Tamil', |
4446
|
|
|
|
|
|
|
8197 => 'Tones|Ringtones|Indian|Regional Indian|Telugu', |
4447
|
|
|
|
|
|
|
8198 => 'Tones|Ringtones|Instrumental', |
4448
|
|
|
|
|
|
|
8199 => 'Tones|Ringtones|Jazz|Avant-Garde Jazz', |
4449
|
|
|
|
|
|
|
8201 => 'Tones|Ringtones|Jazz|Big Band', |
4450
|
|
|
|
|
|
|
8202 => 'Tones|Ringtones|Jazz|Bop', |
4451
|
|
|
|
|
|
|
8203 => 'Tones|Ringtones|Jazz|Contemporary Jazz', |
4452
|
|
|
|
|
|
|
8204 => 'Tones|Ringtones|Jazz|Cool Jazz', |
4453
|
|
|
|
|
|
|
8205 => 'Tones|Ringtones|Jazz|Crossover Jazz', |
4454
|
|
|
|
|
|
|
8206 => 'Tones|Ringtones|Jazz|Dixieland', |
4455
|
|
|
|
|
|
|
8207 => 'Tones|Ringtones|Jazz|Fusion', |
4456
|
|
|
|
|
|
|
8208 => 'Tones|Ringtones|Jazz|Hard Bop', |
4457
|
|
|
|
|
|
|
8209 => 'Tones|Ringtones|Jazz|Latin Jazz', |
4458
|
|
|
|
|
|
|
8210 => 'Tones|Ringtones|Jazz|Mainstream Jazz', |
4459
|
|
|
|
|
|
|
8211 => 'Tones|Ringtones|Jazz|Ragtime', |
4460
|
|
|
|
|
|
|
8212 => 'Tones|Ringtones|Jazz|Smooth Jazz', |
4461
|
|
|
|
|
|
|
8213 => 'Tones|Ringtones|Jazz|Trad Jazz', |
4462
|
|
|
|
|
|
|
8214 => 'Tones|Ringtones|Pop|K-Pop', |
4463
|
|
|
|
|
|
|
8215 => 'Tones|Ringtones|Karaoke', |
4464
|
|
|
|
|
|
|
8216 => 'Tones|Ringtones|Korean', |
4465
|
|
|
|
|
|
|
8217 => 'Tones|Ringtones|Korean|Korean Classical', |
4466
|
|
|
|
|
|
|
8218 => 'Tones|Ringtones|Korean|Korean Trad Instrumental', |
4467
|
|
|
|
|
|
|
8219 => 'Tones|Ringtones|Korean|Korean Trad Song', |
4468
|
|
|
|
|
|
|
8220 => 'Tones|Ringtones|Korean|Korean Trad Theater', |
4469
|
|
|
|
|
|
|
8221 => 'Tones|Ringtones|Latin|Alternative & Rock in Spanish', |
4470
|
|
|
|
|
|
|
8222 => 'Tones|Ringtones|Latin|Baladas y Boleros', |
4471
|
|
|
|
|
|
|
8223 => 'Tones|Ringtones|Latin|Contemporary Latin', |
4472
|
|
|
|
|
|
|
8224 => 'Tones|Ringtones|Latin|Latin Jazz', |
4473
|
|
|
|
|
|
|
8225 => 'Tones|Ringtones|Latin|Latin Urban', |
4474
|
|
|
|
|
|
|
8226 => 'Tones|Ringtones|Latin|Pop in Spanish', |
4475
|
|
|
|
|
|
|
8227 => 'Tones|Ringtones|Latin|Raices', |
4476
|
|
|
|
|
|
|
8228 => 'Tones|Ringtones|Latin|Musica Mexicana', # (Música Mexicana) |
4477
|
|
|
|
|
|
|
8229 => 'Tones|Ringtones|Latin|Salsa y Tropical', |
4478
|
|
|
|
|
|
|
8230 => 'Tones|Ringtones|Marching Bands', |
4479
|
|
|
|
|
|
|
8231 => 'Tones|Ringtones|New Age|Healing', |
4480
|
|
|
|
|
|
|
8232 => 'Tones|Ringtones|New Age|Meditation', |
4481
|
|
|
|
|
|
|
8233 => 'Tones|Ringtones|New Age|Nature', |
4482
|
|
|
|
|
|
|
8234 => 'Tones|Ringtones|New Age|Relaxation', |
4483
|
|
|
|
|
|
|
8235 => 'Tones|Ringtones|New Age|Travel', |
4484
|
|
|
|
|
|
|
8236 => 'Tones|Ringtones|Orchestral', |
4485
|
|
|
|
|
|
|
8237 => 'Tones|Ringtones|Pop|Adult Contemporary', |
4486
|
|
|
|
|
|
|
8238 => 'Tones|Ringtones|Pop|Britpop', |
4487
|
|
|
|
|
|
|
8239 => 'Tones|Ringtones|Pop|C-Pop', |
4488
|
|
|
|
|
|
|
8240 => 'Tones|Ringtones|Pop|Cantopop/HK-Pop', |
4489
|
|
|
|
|
|
|
8241 => 'Tones|Ringtones|Pop|Indo Pop', |
4490
|
|
|
|
|
|
|
8242 => 'Tones|Ringtones|Pop|Korean Folk-Pop', |
4491
|
|
|
|
|
|
|
8243 => 'Tones|Ringtones|Pop|Malaysian Pop', |
4492
|
|
|
|
|
|
|
8244 => 'Tones|Ringtones|Pop|Mandopop', |
4493
|
|
|
|
|
|
|
8245 => 'Tones|Ringtones|Pop|Manilla Sound', |
4494
|
|
|
|
|
|
|
8246 => 'Tones|Ringtones|Pop|Oldies', |
4495
|
|
|
|
|
|
|
8247 => 'Tones|Ringtones|Pop|Original Pilipino Music', |
4496
|
|
|
|
|
|
|
8248 => 'Tones|Ringtones|Pop|Pinoy Pop', |
4497
|
|
|
|
|
|
|
8249 => 'Tones|Ringtones|Pop|Pop/Rock', |
4498
|
|
|
|
|
|
|
8250 => 'Tones|Ringtones|Pop|Soft Rock', |
4499
|
|
|
|
|
|
|
8251 => 'Tones|Ringtones|Pop|Tai-Pop', |
4500
|
|
|
|
|
|
|
8252 => 'Tones|Ringtones|Pop|Teen Pop', |
4501
|
|
|
|
|
|
|
8253 => 'Tones|Ringtones|Pop|Thai Pop', |
4502
|
|
|
|
|
|
|
8254 => 'Tones|Ringtones|R&B/Soul|Contemporary R&B', |
4503
|
|
|
|
|
|
|
8255 => 'Tones|Ringtones|R&B/Soul|Disco', |
4504
|
|
|
|
|
|
|
8256 => 'Tones|Ringtones|R&B/Soul|Doo Wop', |
4505
|
|
|
|
|
|
|
8257 => 'Tones|Ringtones|R&B/Soul|Funk', |
4506
|
|
|
|
|
|
|
8258 => 'Tones|Ringtones|R&B/Soul|Motown', |
4507
|
|
|
|
|
|
|
8259 => 'Tones|Ringtones|R&B/Soul|Neo-Soul', |
4508
|
|
|
|
|
|
|
8260 => 'Tones|Ringtones|R&B/Soul|Soul', |
4509
|
|
|
|
|
|
|
8261 => 'Tones|Ringtones|Reggae|Modern Dancehall', |
4510
|
|
|
|
|
|
|
8262 => 'Tones|Ringtones|Reggae|Dub', |
4511
|
|
|
|
|
|
|
8263 => 'Tones|Ringtones|Reggae|Roots Reggae', |
4512
|
|
|
|
|
|
|
8264 => 'Tones|Ringtones|Reggae|Ska', |
4513
|
|
|
|
|
|
|
8265 => 'Tones|Ringtones|Rock|Adult Alternative', |
4514
|
|
|
|
|
|
|
8266 => 'Tones|Ringtones|Rock|American Trad Rock', |
4515
|
|
|
|
|
|
|
8267 => 'Tones|Ringtones|Rock|Arena Rock', |
4516
|
|
|
|
|
|
|
8268 => 'Tones|Ringtones|Rock|Blues-Rock', |
4517
|
|
|
|
|
|
|
8269 => 'Tones|Ringtones|Rock|British Invasion', |
4518
|
|
|
|
|
|
|
8270 => 'Tones|Ringtones|Rock|Chinese Rock', |
4519
|
|
|
|
|
|
|
8271 => 'Tones|Ringtones|Rock|Death Metal/Black Metal', |
4520
|
|
|
|
|
|
|
8272 => 'Tones|Ringtones|Rock|Glam Rock', |
4521
|
|
|
|
|
|
|
8273 => 'Tones|Ringtones|Rock|Hair Metal', |
4522
|
|
|
|
|
|
|
8274 => 'Tones|Ringtones|Rock|Hard Rock', |
4523
|
|
|
|
|
|
|
8275 => 'Tones|Ringtones|Rock|Metal', |
4524
|
|
|
|
|
|
|
8276 => 'Tones|Ringtones|Rock|Jam Bands', |
4525
|
|
|
|
|
|
|
8277 => 'Tones|Ringtones|Rock|Korean Rock', |
4526
|
|
|
|
|
|
|
8278 => 'Tones|Ringtones|Rock|Prog-Rock/Art Rock', |
4527
|
|
|
|
|
|
|
8279 => 'Tones|Ringtones|Rock|Psychedelic', |
4528
|
|
|
|
|
|
|
8280 => 'Tones|Ringtones|Rock|Rock & Roll', |
4529
|
|
|
|
|
|
|
8281 => 'Tones|Ringtones|Rock|Rockabilly', |
4530
|
|
|
|
|
|
|
8282 => 'Tones|Ringtones|Rock|Roots Rock', |
4531
|
|
|
|
|
|
|
8283 => 'Tones|Ringtones|Rock|Singer/Songwriter', |
4532
|
|
|
|
|
|
|
8284 => 'Tones|Ringtones|Rock|Southern Rock', |
4533
|
|
|
|
|
|
|
8285 => 'Tones|Ringtones|Rock|Surf', |
4534
|
|
|
|
|
|
|
8286 => 'Tones|Ringtones|Rock|Tex-Mex', |
4535
|
|
|
|
|
|
|
8287 => 'Tones|Ringtones|Singer/Songwriter|Alternative Folk', |
4536
|
|
|
|
|
|
|
8288 => 'Tones|Ringtones|Singer/Songwriter|Contemporary Folk', |
4537
|
|
|
|
|
|
|
8289 => 'Tones|Ringtones|Singer/Songwriter|Contemporary Singer/Songwriter', |
4538
|
|
|
|
|
|
|
8290 => 'Tones|Ringtones|Singer/Songwriter|Folk-Rock', |
4539
|
|
|
|
|
|
|
8291 => 'Tones|Ringtones|Singer/Songwriter|New Acoustic', |
4540
|
|
|
|
|
|
|
8292 => 'Tones|Ringtones|Singer/Songwriter|Traditional Folk', |
4541
|
|
|
|
|
|
|
8293 => 'Tones|Ringtones|Soundtrack|Foreign Cinema', |
4542
|
|
|
|
|
|
|
8294 => 'Tones|Ringtones|Soundtrack|Musicals', |
4543
|
|
|
|
|
|
|
8295 => 'Tones|Ringtones|Soundtrack|Original Score', |
4544
|
|
|
|
|
|
|
8296 => 'Tones|Ringtones|Soundtrack|Sound Effects', |
4545
|
|
|
|
|
|
|
8297 => 'Tones|Ringtones|Soundtrack|Soundtrack', |
4546
|
|
|
|
|
|
|
8298 => 'Tones|Ringtones|Soundtrack|TV Soundtrack', |
4547
|
|
|
|
|
|
|
8299 => 'Tones|Ringtones|Vocal|Standards', |
4548
|
|
|
|
|
|
|
8300 => 'Tones|Ringtones|Vocal|Traditional Pop', |
4549
|
|
|
|
|
|
|
8301 => 'Tones|Ringtones|Vocal|Trot', |
4550
|
|
|
|
|
|
|
8302 => 'Tones|Ringtones|Jazz|Vocal Jazz', |
4551
|
|
|
|
|
|
|
8303 => 'Tones|Ringtones|Vocal|Vocal Pop', |
4552
|
|
|
|
|
|
|
8304 => 'Tones|Ringtones|African', |
4553
|
|
|
|
|
|
|
8305 => 'Tones|Ringtones|African|Afrikaans', |
4554
|
|
|
|
|
|
|
8306 => 'Tones|Ringtones|African|Afro-Beat', |
4555
|
|
|
|
|
|
|
8307 => 'Tones|Ringtones|African|Afro-Pop', |
4556
|
|
|
|
|
|
|
8308 => 'Tones|Ringtones|Turkish|Arabesque', |
4557
|
|
|
|
|
|
|
8309 => 'Tones|Ringtones|World|Asia', |
4558
|
|
|
|
|
|
|
8310 => 'Tones|Ringtones|World|Australia', |
4559
|
|
|
|
|
|
|
8311 => 'Tones|Ringtones|World|Cajun', |
4560
|
|
|
|
|
|
|
8312 => 'Tones|Ringtones|World|Calypso', |
4561
|
|
|
|
|
|
|
8313 => 'Tones|Ringtones|World|Caribbean', |
4562
|
|
|
|
|
|
|
8314 => 'Tones|Ringtones|World|Celtic', |
4563
|
|
|
|
|
|
|
8315 => 'Tones|Ringtones|World|Celtic Folk', |
4564
|
|
|
|
|
|
|
8316 => 'Tones|Ringtones|World|Contemporary Celtic', |
4565
|
|
|
|
|
|
|
8317 => 'Tones|Ringtones|World|Dangdut', |
4566
|
|
|
|
|
|
|
8318 => 'Tones|Ringtones|World|Dini', |
4567
|
|
|
|
|
|
|
8319 => 'Tones|Ringtones|World|Europe', |
4568
|
|
|
|
|
|
|
8320 => 'Tones|Ringtones|World|Fado', |
4569
|
|
|
|
|
|
|
8321 => 'Tones|Ringtones|World|Farsi', |
4570
|
|
|
|
|
|
|
8322 => 'Tones|Ringtones|World|Flamenco', |
4571
|
|
|
|
|
|
|
8323 => 'Tones|Ringtones|World|France', |
4572
|
|
|
|
|
|
|
8324 => 'Tones|Ringtones|Turkish|Halk', |
4573
|
|
|
|
|
|
|
8325 => 'Tones|Ringtones|World|Hawaii', |
4574
|
|
|
|
|
|
|
8326 => 'Tones|Ringtones|World|Iberia', |
4575
|
|
|
|
|
|
|
8327 => 'Tones|Ringtones|World|Indonesian Religious', |
4576
|
|
|
|
|
|
|
8328 => 'Tones|Ringtones|World|Israeli', |
4577
|
|
|
|
|
|
|
8329 => 'Tones|Ringtones|World|Japan', |
4578
|
|
|
|
|
|
|
8330 => 'Tones|Ringtones|World|Klezmer', |
4579
|
|
|
|
|
|
|
8331 => 'Tones|Ringtones|World|North America', |
4580
|
|
|
|
|
|
|
8332 => 'Tones|Ringtones|World|Polka', |
4581
|
|
|
|
|
|
|
8333 => 'Tones|Ringtones|Russian', |
4582
|
|
|
|
|
|
|
8334 => 'Tones|Ringtones|Russian|Russian Chanson', |
4583
|
|
|
|
|
|
|
8335 => 'Tones|Ringtones|Turkish|Sanat', |
4584
|
|
|
|
|
|
|
8336 => 'Tones|Ringtones|World|Soca', |
4585
|
|
|
|
|
|
|
8337 => 'Tones|Ringtones|World|South Africa', |
4586
|
|
|
|
|
|
|
8338 => 'Tones|Ringtones|World|South America', |
4587
|
|
|
|
|
|
|
8339 => 'Tones|Ringtones|World|Tango', |
4588
|
|
|
|
|
|
|
8340 => 'Tones|Ringtones|World|Traditional Celtic', |
4589
|
|
|
|
|
|
|
8341 => 'Tones|Ringtones|Turkish', |
4590
|
|
|
|
|
|
|
8342 => 'Tones|Ringtones|World|Worldbeat', |
4591
|
|
|
|
|
|
|
8343 => 'Tones|Ringtones|World|Zydeco', |
4592
|
|
|
|
|
|
|
8345 => 'Tones|Ringtones|Classical|Art Song', |
4593
|
|
|
|
|
|
|
8346 => 'Tones|Ringtones|Classical|Brass & Woodwinds', |
4594
|
|
|
|
|
|
|
8347 => 'Tones|Ringtones|Classical|Solo Instrumental', |
4595
|
|
|
|
|
|
|
8348 => 'Tones|Ringtones|Classical|Contemporary Era', |
4596
|
|
|
|
|
|
|
8349 => 'Tones|Ringtones|Classical|Oratorio', |
4597
|
|
|
|
|
|
|
8350 => 'Tones|Ringtones|Classical|Cantata', |
4598
|
|
|
|
|
|
|
8351 => 'Tones|Ringtones|Classical|Electronic', |
4599
|
|
|
|
|
|
|
8352 => 'Tones|Ringtones|Classical|Sacred', |
4600
|
|
|
|
|
|
|
8353 => 'Tones|Ringtones|Classical|Guitar', |
4601
|
|
|
|
|
|
|
8354 => 'Tones|Ringtones|Classical|Piano', |
4602
|
|
|
|
|
|
|
8355 => 'Tones|Ringtones|Classical|Violin', |
4603
|
|
|
|
|
|
|
8356 => 'Tones|Ringtones|Classical|Cello', |
4604
|
|
|
|
|
|
|
8357 => 'Tones|Ringtones|Classical|Percussion', |
4605
|
|
|
|
|
|
|
8358 => 'Tones|Ringtones|Electronic|Dubstep', |
4606
|
|
|
|
|
|
|
8359 => 'Tones|Ringtones|Electronic|Bass', |
4607
|
|
|
|
|
|
|
8360 => 'Tones|Ringtones|Hip-Hop/Rap|UK Hip Hop', |
4608
|
|
|
|
|
|
|
8361 => 'Tones|Ringtones|Reggae|Lovers Rock', |
4609
|
|
|
|
|
|
|
8362 => 'Tones|Ringtones|Alternative|EMO', |
4610
|
|
|
|
|
|
|
8363 => 'Tones|Ringtones|Alternative|Pop Punk', |
4611
|
|
|
|
|
|
|
8364 => 'Tones|Ringtones|Alternative|Indie Pop', |
4612
|
|
|
|
|
|
|
8365 => 'Tones|Ringtones|New Age|Yoga', |
4613
|
|
|
|
|
|
|
8366 => 'Tones|Ringtones|Pop|Tribute', |
4614
|
|
|
|
|
|
|
8367 => 'Tones|Ringtones|Pop|Shows', |
4615
|
|
|
|
|
|
|
8368 => 'Tones|Ringtones|Cuban', |
4616
|
|
|
|
|
|
|
8369 => 'Tones|Ringtones|Cuban|Mambo', |
4617
|
|
|
|
|
|
|
8370 => 'Tones|Ringtones|Cuban|Chachacha', |
4618
|
|
|
|
|
|
|
8371 => 'Tones|Ringtones|Cuban|Guajira', |
4619
|
|
|
|
|
|
|
8372 => 'Tones|Ringtones|Cuban|Son', |
4620
|
|
|
|
|
|
|
8373 => 'Tones|Ringtones|Cuban|Bolero', |
4621
|
|
|
|
|
|
|
8374 => 'Tones|Ringtones|Cuban|Guaracha', |
4622
|
|
|
|
|
|
|
8375 => 'Tones|Ringtones|Cuban|Timba', |
4623
|
|
|
|
|
|
|
8376 => 'Tones|Ringtones|Soundtrack|Video Game', |
4624
|
|
|
|
|
|
|
8377 => 'Tones|Ringtones|Indian|Regional Indian|Punjabi|Punjabi Pop', |
4625
|
|
|
|
|
|
|
8378 => 'Tones|Ringtones|Indian|Regional Indian|Bengali|Rabindra Sangeet', |
4626
|
|
|
|
|
|
|
8379 => 'Tones|Ringtones|Indian|Regional Indian|Malayalam', |
4627
|
|
|
|
|
|
|
8380 => 'Tones|Ringtones|Indian|Regional Indian|Kannada', |
4628
|
|
|
|
|
|
|
8381 => 'Tones|Ringtones|Indian|Regional Indian|Marathi', |
4629
|
|
|
|
|
|
|
8382 => 'Tones|Ringtones|Indian|Regional Indian|Gujarati', |
4630
|
|
|
|
|
|
|
8383 => 'Tones|Ringtones|Indian|Regional Indian|Assamese', |
4631
|
|
|
|
|
|
|
8384 => 'Tones|Ringtones|Indian|Regional Indian|Bhojpuri', |
4632
|
|
|
|
|
|
|
8385 => 'Tones|Ringtones|Indian|Regional Indian|Haryanvi', |
4633
|
|
|
|
|
|
|
8386 => 'Tones|Ringtones|Indian|Regional Indian|Odia', |
4634
|
|
|
|
|
|
|
8387 => 'Tones|Ringtones|Indian|Regional Indian|Rajasthani', |
4635
|
|
|
|
|
|
|
8388 => 'Tones|Ringtones|Indian|Regional Indian|Urdu', |
4636
|
|
|
|
|
|
|
8389 => 'Tones|Ringtones|Indian|Regional Indian|Punjabi', |
4637
|
|
|
|
|
|
|
8390 => 'Tones|Ringtones|Indian|Regional Indian|Bengali', |
4638
|
|
|
|
|
|
|
8391 => 'Tones|Ringtones|Indian|Indian Classical|Carnatic Classical', |
4639
|
|
|
|
|
|
|
8392 => 'Tones|Ringtones|Indian|Indian Classical|Hindustani Classical', |
4640
|
|
|
|
|
|
|
8393 => 'Tones|Ringtones|African|Afro House', |
4641
|
|
|
|
|
|
|
8394 => 'Tones|Ringtones|African|Afro Soul', |
4642
|
|
|
|
|
|
|
8395 => 'Tones|Ringtones|African|Afrobeats', |
4643
|
|
|
|
|
|
|
8396 => 'Tones|Ringtones|African|Benga', |
4644
|
|
|
|
|
|
|
8397 => 'Tones|Ringtones|African|Bongo-Flava', |
4645
|
|
|
|
|
|
|
8398 => 'Tones|Ringtones|African|Coupe-Decale', |
4646
|
|
|
|
|
|
|
8399 => 'Tones|Ringtones|African|Gqom', |
4647
|
|
|
|
|
|
|
8400 => 'Tones|Ringtones|African|Highlife', |
4648
|
|
|
|
|
|
|
8401 => 'Tones|Ringtones|African|Kuduro', |
4649
|
|
|
|
|
|
|
8402 => 'Tones|Ringtones|African|Kizomba', |
4650
|
|
|
|
|
|
|
8403 => 'Tones|Ringtones|African|Kwaito', |
4651
|
|
|
|
|
|
|
8404 => 'Tones|Ringtones|African|Mbalax', |
4652
|
|
|
|
|
|
|
8405 => 'Tones|Ringtones|African|Ndombolo', |
4653
|
|
|
|
|
|
|
8406 => 'Tones|Ringtones|African|Shangaan Electro', |
4654
|
|
|
|
|
|
|
8407 => 'Tones|Ringtones|African|Soukous', |
4655
|
|
|
|
|
|
|
8408 => 'Tones|Ringtones|African|Taarab', |
4656
|
|
|
|
|
|
|
8409 => 'Tones|Ringtones|African|Zouglou', |
4657
|
|
|
|
|
|
|
8410 => 'Tones|Ringtones|Turkish|Ozgun', |
4658
|
|
|
|
|
|
|
8411 => 'Tones|Ringtones|Turkish|Fantezi', |
4659
|
|
|
|
|
|
|
8412 => 'Tones|Ringtones|Turkish|Religious', |
4660
|
|
|
|
|
|
|
8413 => 'Tones|Ringtones|Pop|Turkish Pop', |
4661
|
|
|
|
|
|
|
8414 => 'Tones|Ringtones|Rock|Turkish Rock', |
4662
|
|
|
|
|
|
|
8415 => 'Tones|Ringtones|Alternative|Turkish Alternative', |
4663
|
|
|
|
|
|
|
8416 => 'Tones|Ringtones|Hip-Hop/Rap|Turkish Hip-Hop/Rap', |
4664
|
|
|
|
|
|
|
8417 => 'Tones|Ringtones|African|Maskandi', |
4665
|
|
|
|
|
|
|
8418 => 'Tones|Ringtones|Russian|Russian Romance', |
4666
|
|
|
|
|
|
|
8419 => 'Tones|Ringtones|Russian|Russian Bard', |
4667
|
|
|
|
|
|
|
8420 => 'Tones|Ringtones|Russian|Russian Pop', |
4668
|
|
|
|
|
|
|
8421 => 'Tones|Ringtones|Russian|Russian Rock', |
4669
|
|
|
|
|
|
|
8422 => 'Tones|Ringtones|Russian|Russian Hip-Hop', |
4670
|
|
|
|
|
|
|
8423 => 'Tones|Ringtones|Arabic|Levant', |
4671
|
|
|
|
|
|
|
8424 => 'Tones|Ringtones|Arabic|Levant|Dabke', |
4672
|
|
|
|
|
|
|
8425 => 'Tones|Ringtones|Arabic|Maghreb Rai', |
4673
|
|
|
|
|
|
|
8426 => 'Tones|Ringtones|Arabic|Khaleeji|Khaleeji Jalsat', |
4674
|
|
|
|
|
|
|
8427 => 'Tones|Ringtones|Arabic|Khaleeji|Khaleeji Shailat', |
4675
|
|
|
|
|
|
|
8428 => 'Tones|Ringtones|Tarab', |
4676
|
|
|
|
|
|
|
8429 => 'Tones|Ringtones|Tarab|Iraqi Tarab', |
4677
|
|
|
|
|
|
|
8430 => 'Tones|Ringtones|Tarab|Egyptian Tarab', |
4678
|
|
|
|
|
|
|
8431 => 'Tones|Ringtones|Tarab|Khaleeji Tarab', |
4679
|
|
|
|
|
|
|
8432 => 'Tones|Ringtones|Pop|Levant Pop', |
4680
|
|
|
|
|
|
|
8433 => 'Tones|Ringtones|Pop|Iraqi Pop', |
4681
|
|
|
|
|
|
|
8434 => 'Tones|Ringtones|Pop|Egyptian Pop', |
4682
|
|
|
|
|
|
|
8435 => 'Tones|Ringtones|Pop|Maghreb Pop', |
4683
|
|
|
|
|
|
|
8436 => 'Tones|Ringtones|Pop|Khaleeji Pop', |
4684
|
|
|
|
|
|
|
8437 => 'Tones|Ringtones|Hip-Hop/Rap|Levant Hip-Hop', |
4685
|
|
|
|
|
|
|
8438 => 'Tones|Ringtones|Hip-Hop/Rap|Egyptian Hip-Hop', |
4686
|
|
|
|
|
|
|
8439 => 'Tones|Ringtones|Hip-Hop/Rap|Maghreb Hip-Hop', |
4687
|
|
|
|
|
|
|
8440 => 'Tones|Ringtones|Hip-Hop/Rap|Khaleeji Hip-Hop', |
4688
|
|
|
|
|
|
|
8441 => 'Tones|Ringtones|Alternative|Indie Levant', |
4689
|
|
|
|
|
|
|
8442 => 'Tones|Ringtones|Alternative|Indie Egyptian', |
4690
|
|
|
|
|
|
|
8443 => 'Tones|Ringtones|Alternative|Indie Maghreb', |
4691
|
|
|
|
|
|
|
8444 => 'Tones|Ringtones|Electronic|Levant Electronic', |
4692
|
|
|
|
|
|
|
8445 => "Tones|Ringtones|Electronic|Electro-Cha'abi", |
4693
|
|
|
|
|
|
|
8446 => 'Tones|Ringtones|Electronic|Maghreb Electronic', |
4694
|
|
|
|
|
|
|
8447 => 'Tones|Ringtones|Folk|Iraqi Folk', |
4695
|
|
|
|
|
|
|
8448 => 'Tones|Ringtones|Folk|Khaleeji Folk', |
4696
|
|
|
|
|
|
|
8449 => 'Tones|Ringtones|Dance|Maghreb Dance', |
4697
|
|
|
|
|
|
|
9002 => 'Books|Nonfiction', |
4698
|
|
|
|
|
|
|
9003 => 'Books|Romance', |
4699
|
|
|
|
|
|
|
9004 => 'Books|Travel & Adventure', |
4700
|
|
|
|
|
|
|
9007 => 'Books|Arts & Entertainment', |
4701
|
|
|
|
|
|
|
9008 => 'Books|Biographies & Memoirs', |
4702
|
|
|
|
|
|
|
9009 => 'Books|Business & Personal Finance', |
4703
|
|
|
|
|
|
|
9010 => 'Books|Children & Teens', |
4704
|
|
|
|
|
|
|
9012 => 'Books|Humor', |
4705
|
|
|
|
|
|
|
9015 => 'Books|History', |
4706
|
|
|
|
|
|
|
9018 => 'Books|Religion & Spirituality', |
4707
|
|
|
|
|
|
|
9019 => 'Books|Science & Nature', |
4708
|
|
|
|
|
|
|
9020 => 'Books|Sci-Fi & Fantasy', |
4709
|
|
|
|
|
|
|
9024 => 'Books|Lifestyle & Home', |
4710
|
|
|
|
|
|
|
9025 => 'Books|Self-Development', |
4711
|
|
|
|
|
|
|
9026 => 'Books|Comics & Graphic Novels', |
4712
|
|
|
|
|
|
|
9027 => 'Books|Computers & Internet', |
4713
|
|
|
|
|
|
|
9028 => 'Books|Cookbooks, Food & Wine', |
4714
|
|
|
|
|
|
|
9029 => 'Books|Professional & Technical', |
4715
|
|
|
|
|
|
|
9030 => 'Books|Parenting', |
4716
|
|
|
|
|
|
|
9031 => 'Books|Fiction & Literature', |
4717
|
|
|
|
|
|
|
9032 => 'Books|Mysteries & Thrillers', |
4718
|
|
|
|
|
|
|
9033 => 'Books|Reference', |
4719
|
|
|
|
|
|
|
9034 => 'Books|Politics & Current Events', |
4720
|
|
|
|
|
|
|
9035 => 'Books|Sports & Outdoors', |
4721
|
|
|
|
|
|
|
10001 => 'Books|Lifestyle & Home|Antiques & Collectibles', |
4722
|
|
|
|
|
|
|
10002 => 'Books|Arts & Entertainment|Art & Architecture', |
4723
|
|
|
|
|
|
|
10003 => 'Books|Religion & Spirituality|Bibles', |
4724
|
|
|
|
|
|
|
10004 => 'Books|Self-Development|Spirituality', |
4725
|
|
|
|
|
|
|
10005 => 'Books|Business & Personal Finance|Industries & Professions', |
4726
|
|
|
|
|
|
|
10006 => 'Books|Business & Personal Finance|Marketing & Sales', |
4727
|
|
|
|
|
|
|
10007 => 'Books|Business & Personal Finance|Small Business & Entrepreneurship', |
4728
|
|
|
|
|
|
|
10008 => 'Books|Business & Personal Finance|Personal Finance', |
4729
|
|
|
|
|
|
|
10009 => 'Books|Business & Personal Finance|Reference', |
4730
|
|
|
|
|
|
|
10010 => 'Books|Business & Personal Finance|Careers', |
4731
|
|
|
|
|
|
|
10011 => 'Books|Business & Personal Finance|Economics', |
4732
|
|
|
|
|
|
|
10012 => 'Books|Business & Personal Finance|Investing', |
4733
|
|
|
|
|
|
|
10013 => 'Books|Business & Personal Finance|Finance', |
4734
|
|
|
|
|
|
|
10014 => 'Books|Business & Personal Finance|Management & Leadership', |
4735
|
|
|
|
|
|
|
10015 => 'Books|Comics & Graphic Novels|Graphic Novels', |
4736
|
|
|
|
|
|
|
10016 => 'Books|Comics & Graphic Novels|Manga', |
4737
|
|
|
|
|
|
|
10017 => 'Books|Computers & Internet|Computers', |
4738
|
|
|
|
|
|
|
10018 => 'Books|Computers & Internet|Databases', |
4739
|
|
|
|
|
|
|
10019 => 'Books|Computers & Internet|Digital Media', |
4740
|
|
|
|
|
|
|
10020 => 'Books|Computers & Internet|Internet', |
4741
|
|
|
|
|
|
|
10021 => 'Books|Computers & Internet|Network', |
4742
|
|
|
|
|
|
|
10022 => 'Books|Computers & Internet|Operating Systems', |
4743
|
|
|
|
|
|
|
10023 => 'Books|Computers & Internet|Programming', |
4744
|
|
|
|
|
|
|
10024 => 'Books|Computers & Internet|Software', |
4745
|
|
|
|
|
|
|
10025 => 'Books|Computers & Internet|System Administration', |
4746
|
|
|
|
|
|
|
10026 => 'Books|Cookbooks, Food & Wine|Beverages', |
4747
|
|
|
|
|
|
|
10027 => 'Books|Cookbooks, Food & Wine|Courses & Dishes', |
4748
|
|
|
|
|
|
|
10028 => 'Books|Cookbooks, Food & Wine|Special Diet', |
4749
|
|
|
|
|
|
|
10029 => 'Books|Cookbooks, Food & Wine|Special Occasions', |
4750
|
|
|
|
|
|
|
10030 => 'Books|Cookbooks, Food & Wine|Methods', |
4751
|
|
|
|
|
|
|
10031 => 'Books|Cookbooks, Food & Wine|Reference', |
4752
|
|
|
|
|
|
|
10032 => 'Books|Cookbooks, Food & Wine|Regional & Ethnic', |
4753
|
|
|
|
|
|
|
10033 => 'Books|Cookbooks, Food & Wine|Specific Ingredients', |
4754
|
|
|
|
|
|
|
10034 => 'Books|Lifestyle & Home|Crafts & Hobbies', |
4755
|
|
|
|
|
|
|
10035 => 'Books|Professional & Technical|Design', |
4756
|
|
|
|
|
|
|
10036 => 'Books|Arts & Entertainment|Theater', |
4757
|
|
|
|
|
|
|
10037 => 'Books|Professional & Technical|Education', |
4758
|
|
|
|
|
|
|
10038 => 'Books|Nonfiction|Family & Relationships', |
4759
|
|
|
|
|
|
|
10039 => 'Books|Fiction & Literature|Action & Adventure', |
4760
|
|
|
|
|
|
|
10040 => 'Books|Fiction & Literature|African American', |
4761
|
|
|
|
|
|
|
10041 => 'Books|Fiction & Literature|Religious', |
4762
|
|
|
|
|
|
|
10042 => 'Books|Fiction & Literature|Classics', |
4763
|
|
|
|
|
|
|
10043 => 'Books|Fiction & Literature|Erotica', |
4764
|
|
|
|
|
|
|
10044 => 'Books|Sci-Fi & Fantasy|Fantasy', |
4765
|
|
|
|
|
|
|
10045 => 'Books|Fiction & Literature|Gay', |
4766
|
|
|
|
|
|
|
10046 => 'Books|Fiction & Literature|Ghost', |
4767
|
|
|
|
|
|
|
10047 => 'Books|Fiction & Literature|Historical', |
4768
|
|
|
|
|
|
|
10048 => 'Books|Fiction & Literature|Horror', |
4769
|
|
|
|
|
|
|
10049 => 'Books|Fiction & Literature|Literary', |
4770
|
|
|
|
|
|
|
10050 => 'Books|Mysteries & Thrillers|Hard-Boiled', |
4771
|
|
|
|
|
|
|
10051 => 'Books|Mysteries & Thrillers|Historical', |
4772
|
|
|
|
|
|
|
10052 => 'Books|Mysteries & Thrillers|Police Procedural', |
4773
|
|
|
|
|
|
|
10053 => 'Books|Mysteries & Thrillers|Short Stories', |
4774
|
|
|
|
|
|
|
10054 => 'Books|Mysteries & Thrillers|British Detectives', |
4775
|
|
|
|
|
|
|
10055 => 'Books|Mysteries & Thrillers|Women Sleuths', |
4776
|
|
|
|
|
|
|
10056 => 'Books|Romance|Erotic Romance', |
4777
|
|
|
|
|
|
|
10057 => 'Books|Romance|Contemporary', |
4778
|
|
|
|
|
|
|
10058 => 'Books|Romance|Paranormal', |
4779
|
|
|
|
|
|
|
10059 => 'Books|Romance|Historical', |
4780
|
|
|
|
|
|
|
10060 => 'Books|Romance|Short Stories', |
4781
|
|
|
|
|
|
|
10061 => 'Books|Romance|Suspense', |
4782
|
|
|
|
|
|
|
10062 => 'Books|Romance|Western', |
4783
|
|
|
|
|
|
|
10063 => 'Books|Sci-Fi & Fantasy|Science Fiction', |
4784
|
|
|
|
|
|
|
10064 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature', |
4785
|
|
|
|
|
|
|
10065 => 'Books|Fiction & Literature|Short Stories', |
4786
|
|
|
|
|
|
|
10066 => 'Books|Reference|Foreign Languages', |
4787
|
|
|
|
|
|
|
10067 => 'Books|Arts & Entertainment|Games', |
4788
|
|
|
|
|
|
|
10068 => 'Books|Lifestyle & Home|Gardening', |
4789
|
|
|
|
|
|
|
10069 => 'Books|Self-Development|Health & Fitness', |
4790
|
|
|
|
|
|
|
10070 => 'Books|History|Africa', |
4791
|
|
|
|
|
|
|
10071 => 'Books|History|Americas', |
4792
|
|
|
|
|
|
|
10072 => 'Books|History|Ancient', |
4793
|
|
|
|
|
|
|
10073 => 'Books|History|Asia', |
4794
|
|
|
|
|
|
|
10074 => 'Books|History|Australia & Oceania', |
4795
|
|
|
|
|
|
|
10075 => 'Books|History|Europe', |
4796
|
|
|
|
|
|
|
10076 => 'Books|History|Latin America', |
4797
|
|
|
|
|
|
|
10077 => 'Books|History|Middle East', |
4798
|
|
|
|
|
|
|
10078 => 'Books|History|Military', |
4799
|
|
|
|
|
|
|
10079 => 'Books|History|United States', |
4800
|
|
|
|
|
|
|
10080 => 'Books|History|World', |
4801
|
|
|
|
|
|
|
10081 => "Books|Children & Teens|Children's Fiction", |
4802
|
|
|
|
|
|
|
10082 => "Books|Children & Teens|Children's Nonfiction", |
4803
|
|
|
|
|
|
|
10083 => 'Books|Professional & Technical|Law', |
4804
|
|
|
|
|
|
|
10084 => 'Books|Fiction & Literature|Literary Criticism', |
4805
|
|
|
|
|
|
|
10085 => 'Books|Science & Nature|Mathematics', |
4806
|
|
|
|
|
|
|
10086 => 'Books|Professional & Technical|Medical', |
4807
|
|
|
|
|
|
|
10087 => 'Books|Arts & Entertainment|Music', |
4808
|
|
|
|
|
|
|
10088 => 'Books|Science & Nature|Nature', |
4809
|
|
|
|
|
|
|
10089 => 'Books|Arts & Entertainment|Performing Arts', |
4810
|
|
|
|
|
|
|
10090 => 'Books|Lifestyle & Home|Pets', |
4811
|
|
|
|
|
|
|
10091 => 'Books|Nonfiction|Philosophy', |
4812
|
|
|
|
|
|
|
10092 => 'Books|Arts & Entertainment|Photography', |
4813
|
|
|
|
|
|
|
10093 => 'Books|Fiction & Literature|Poetry', |
4814
|
|
|
|
|
|
|
10094 => 'Books|Self-Development|Psychology', |
4815
|
|
|
|
|
|
|
10095 => 'Books|Reference|Almanacs & Yearbooks', |
4816
|
|
|
|
|
|
|
10096 => 'Books|Reference|Atlases & Maps', |
4817
|
|
|
|
|
|
|
10097 => 'Books|Reference|Catalogs & Directories', |
4818
|
|
|
|
|
|
|
10098 => 'Books|Reference|Consumer Guides', |
4819
|
|
|
|
|
|
|
10099 => 'Books|Reference|Dictionaries & Thesauruses', |
4820
|
|
|
|
|
|
|
10100 => 'Books|Reference|Encyclopedias', |
4821
|
|
|
|
|
|
|
10101 => 'Books|Reference|Etiquette', |
4822
|
|
|
|
|
|
|
10102 => 'Books|Reference|Quotations', |
4823
|
|
|
|
|
|
|
10103 => 'Books|Reference|Words & Language', |
4824
|
|
|
|
|
|
|
10104 => 'Books|Reference|Writing', |
4825
|
|
|
|
|
|
|
10105 => 'Books|Religion & Spirituality|Bible Studies', |
4826
|
|
|
|
|
|
|
10106 => 'Books|Religion & Spirituality|Buddhism', |
4827
|
|
|
|
|
|
|
10107 => 'Books|Religion & Spirituality|Christianity', |
4828
|
|
|
|
|
|
|
10108 => 'Books|Religion & Spirituality|Hinduism', |
4829
|
|
|
|
|
|
|
10109 => 'Books|Religion & Spirituality|Islam', |
4830
|
|
|
|
|
|
|
10110 => 'Books|Religion & Spirituality|Judaism', |
4831
|
|
|
|
|
|
|
10111 => 'Books|Science & Nature|Astronomy', |
4832
|
|
|
|
|
|
|
10112 => 'Books|Science & Nature|Chemistry', |
4833
|
|
|
|
|
|
|
10113 => 'Books|Science & Nature|Earth Sciences', |
4834
|
|
|
|
|
|
|
10114 => 'Books|Science & Nature|Essays', |
4835
|
|
|
|
|
|
|
10115 => 'Books|Science & Nature|History', |
4836
|
|
|
|
|
|
|
10116 => 'Books|Science & Nature|Life Sciences', |
4837
|
|
|
|
|
|
|
10117 => 'Books|Science & Nature|Physics', |
4838
|
|
|
|
|
|
|
10118 => 'Books|Science & Nature|Reference', |
4839
|
|
|
|
|
|
|
10119 => 'Books|Self-Development|Self-Improvement', |
4840
|
|
|
|
|
|
|
10120 => 'Books|Nonfiction|Social Science', |
4841
|
|
|
|
|
|
|
10121 => 'Books|Sports & Outdoors|Baseball', |
4842
|
|
|
|
|
|
|
10122 => 'Books|Sports & Outdoors|Basketball', |
4843
|
|
|
|
|
|
|
10123 => 'Books|Sports & Outdoors|Coaching', |
4844
|
|
|
|
|
|
|
10124 => 'Books|Sports & Outdoors|Extreme Sports', |
4845
|
|
|
|
|
|
|
10125 => 'Books|Sports & Outdoors|Football', |
4846
|
|
|
|
|
|
|
10126 => 'Books|Sports & Outdoors|Golf', |
4847
|
|
|
|
|
|
|
10127 => 'Books|Sports & Outdoors|Hockey', |
4848
|
|
|
|
|
|
|
10128 => 'Books|Sports & Outdoors|Mountaineering', |
4849
|
|
|
|
|
|
|
10129 => 'Books|Sports & Outdoors|Outdoors', |
4850
|
|
|
|
|
|
|
10130 => 'Books|Sports & Outdoors|Racket Sports', |
4851
|
|
|
|
|
|
|
10131 => 'Books|Sports & Outdoors|Reference', |
4852
|
|
|
|
|
|
|
10132 => 'Books|Sports & Outdoors|Soccer', |
4853
|
|
|
|
|
|
|
10133 => 'Books|Sports & Outdoors|Training', |
4854
|
|
|
|
|
|
|
10134 => 'Books|Sports & Outdoors|Water Sports', |
4855
|
|
|
|
|
|
|
10135 => 'Books|Sports & Outdoors|Winter Sports', |
4856
|
|
|
|
|
|
|
10136 => 'Books|Reference|Study Aids', |
4857
|
|
|
|
|
|
|
10137 => 'Books|Professional & Technical|Engineering', |
4858
|
|
|
|
|
|
|
10138 => 'Books|Nonfiction|Transportation', |
4859
|
|
|
|
|
|
|
10139 => 'Books|Travel & Adventure|Africa', |
4860
|
|
|
|
|
|
|
10140 => 'Books|Travel & Adventure|Asia', |
4861
|
|
|
|
|
|
|
10141 => 'Books|Travel & Adventure|Specialty Travel', |
4862
|
|
|
|
|
|
|
10142 => 'Books|Travel & Adventure|Canada', |
4863
|
|
|
|
|
|
|
10143 => 'Books|Travel & Adventure|Caribbean', |
4864
|
|
|
|
|
|
|
10144 => 'Books|Travel & Adventure|Latin America', |
4865
|
|
|
|
|
|
|
10145 => 'Books|Travel & Adventure|Essays & Memoirs', |
4866
|
|
|
|
|
|
|
10146 => 'Books|Travel & Adventure|Europe', |
4867
|
|
|
|
|
|
|
10147 => 'Books|Travel & Adventure|Middle East', |
4868
|
|
|
|
|
|
|
10148 => 'Books|Travel & Adventure|United States', |
4869
|
|
|
|
|
|
|
10149 => 'Books|Nonfiction|True Crime', |
4870
|
|
|
|
|
|
|
11001 => 'Books|Sci-Fi & Fantasy|Fantasy|Contemporary', |
4871
|
|
|
|
|
|
|
11002 => 'Books|Sci-Fi & Fantasy|Fantasy|Epic', |
4872
|
|
|
|
|
|
|
11003 => 'Books|Sci-Fi & Fantasy|Fantasy|Historical', |
4873
|
|
|
|
|
|
|
11004 => 'Books|Sci-Fi & Fantasy|Fantasy|Paranormal', |
4874
|
|
|
|
|
|
|
11005 => 'Books|Sci-Fi & Fantasy|Fantasy|Short Stories', |
4875
|
|
|
|
|
|
|
11006 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|Adventure', |
4876
|
|
|
|
|
|
|
11007 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|High Tech', |
4877
|
|
|
|
|
|
|
11008 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|Short Stories', |
4878
|
|
|
|
|
|
|
11009 => 'Books|Professional & Technical|Education|Language Arts & Disciplines', |
4879
|
|
|
|
|
|
|
11010 => 'Books|Communications & Media', |
4880
|
|
|
|
|
|
|
11011 => 'Books|Communications & Media|Broadcasting', |
4881
|
|
|
|
|
|
|
11012 => 'Books|Communications & Media|Digital Media', |
4882
|
|
|
|
|
|
|
11013 => 'Books|Communications & Media|Journalism', |
4883
|
|
|
|
|
|
|
11014 => 'Books|Communications & Media|Photojournalism', |
4884
|
|
|
|
|
|
|
11015 => 'Books|Communications & Media|Print', |
4885
|
|
|
|
|
|
|
11016 => 'Books|Communications & Media|Speech', |
4886
|
|
|
|
|
|
|
11017 => 'Books|Communications & Media|Writing', |
4887
|
|
|
|
|
|
|
11018 => 'Books|Arts & Entertainment|Art & Architecture|Urban Planning', |
4888
|
|
|
|
|
|
|
11019 => 'Books|Arts & Entertainment|Dance', |
4889
|
|
|
|
|
|
|
11020 => 'Books|Arts & Entertainment|Fashion', |
4890
|
|
|
|
|
|
|
11021 => 'Books|Arts & Entertainment|Film', |
4891
|
|
|
|
|
|
|
11022 => 'Books|Arts & Entertainment|Interior Design', |
4892
|
|
|
|
|
|
|
11023 => 'Books|Arts & Entertainment|Media Arts', |
4893
|
|
|
|
|
|
|
11024 => 'Books|Arts & Entertainment|Radio', |
4894
|
|
|
|
|
|
|
11025 => 'Books|Arts & Entertainment|TV', |
4895
|
|
|
|
|
|
|
11026 => 'Books|Arts & Entertainment|Visual Arts', |
4896
|
|
|
|
|
|
|
11027 => 'Books|Biographies & Memoirs|Arts & Entertainment', |
4897
|
|
|
|
|
|
|
11028 => 'Books|Biographies & Memoirs|Business', |
4898
|
|
|
|
|
|
|
11029 => 'Books|Biographies & Memoirs|Culinary', |
4899
|
|
|
|
|
|
|
11030 => 'Books|Biographies & Memoirs|Gay & Lesbian', |
4900
|
|
|
|
|
|
|
11031 => 'Books|Biographies & Memoirs|Historical', |
4901
|
|
|
|
|
|
|
11032 => 'Books|Biographies & Memoirs|Literary', |
4902
|
|
|
|
|
|
|
11033 => 'Books|Biographies & Memoirs|Media & Journalism', |
4903
|
|
|
|
|
|
|
11034 => 'Books|Biographies & Memoirs|Military', |
4904
|
|
|
|
|
|
|
11035 => 'Books|Biographies & Memoirs|Politics', |
4905
|
|
|
|
|
|
|
11036 => 'Books|Biographies & Memoirs|Religious', |
4906
|
|
|
|
|
|
|
11037 => 'Books|Biographies & Memoirs|Science & Technology', |
4907
|
|
|
|
|
|
|
11038 => 'Books|Biographies & Memoirs|Sports', |
4908
|
|
|
|
|
|
|
11039 => 'Books|Biographies & Memoirs|Women', |
4909
|
|
|
|
|
|
|
11040 => 'Books|Romance|New Adult', |
4910
|
|
|
|
|
|
|
11042 => 'Books|Romance|Romantic Comedy', |
4911
|
|
|
|
|
|
|
11043 => 'Books|Romance|Gay & Lesbian', |
4912
|
|
|
|
|
|
|
11044 => 'Books|Fiction & Literature|Essays', |
4913
|
|
|
|
|
|
|
11045 => 'Books|Fiction & Literature|Anthologies', |
4914
|
|
|
|
|
|
|
11046 => 'Books|Fiction & Literature|Comparative Literature', |
4915
|
|
|
|
|
|
|
11047 => 'Books|Fiction & Literature|Drama', |
4916
|
|
|
|
|
|
|
11049 => 'Books|Fiction & Literature|Fairy Tales, Myths & Fables', |
4917
|
|
|
|
|
|
|
11050 => 'Books|Fiction & Literature|Family', |
4918
|
|
|
|
|
|
|
11051 => 'Books|Comics & Graphic Novels|Manga|School Drama', |
4919
|
|
|
|
|
|
|
11052 => 'Books|Comics & Graphic Novels|Manga|Human Drama', |
4920
|
|
|
|
|
|
|
11053 => 'Books|Comics & Graphic Novels|Manga|Family Drama', |
4921
|
|
|
|
|
|
|
11054 => 'Books|Sports & Outdoors|Boxing', |
4922
|
|
|
|
|
|
|
11055 => 'Books|Sports & Outdoors|Cricket', |
4923
|
|
|
|
|
|
|
11056 => 'Books|Sports & Outdoors|Cycling', |
4924
|
|
|
|
|
|
|
11057 => 'Books|Sports & Outdoors|Equestrian', |
4925
|
|
|
|
|
|
|
11058 => 'Books|Sports & Outdoors|Martial Arts & Self Defense', |
4926
|
|
|
|
|
|
|
11059 => 'Books|Sports & Outdoors|Motor Sports', |
4927
|
|
|
|
|
|
|
11060 => 'Books|Sports & Outdoors|Rugby', |
4928
|
|
|
|
|
|
|
11061 => 'Books|Sports & Outdoors|Running', |
4929
|
|
|
|
|
|
|
11062 => 'Books|Self-Development|Diet & Nutrition', |
4930
|
|
|
|
|
|
|
11063 => 'Books|Science & Nature|Agriculture', |
4931
|
|
|
|
|
|
|
11064 => 'Books|Science & Nature|Atmosphere', |
4932
|
|
|
|
|
|
|
11065 => 'Books|Science & Nature|Biology', |
4933
|
|
|
|
|
|
|
11066 => 'Books|Science & Nature|Ecology', |
4934
|
|
|
|
|
|
|
11067 => 'Books|Science & Nature|Environment', |
4935
|
|
|
|
|
|
|
11068 => 'Books|Science & Nature|Geography', |
4936
|
|
|
|
|
|
|
11069 => 'Books|Science & Nature|Geology', |
4937
|
|
|
|
|
|
|
11070 => 'Books|Nonfiction|Social Science|Anthropology', |
4938
|
|
|
|
|
|
|
11071 => 'Books|Nonfiction|Social Science|Archaeology', |
4939
|
|
|
|
|
|
|
11072 => 'Books|Nonfiction|Social Science|Civics', |
4940
|
|
|
|
|
|
|
11073 => 'Books|Nonfiction|Social Science|Government', |
4941
|
|
|
|
|
|
|
11074 => 'Books|Nonfiction|Social Science|Social Studies', |
4942
|
|
|
|
|
|
|
11075 => 'Books|Nonfiction|Social Science|Social Welfare', |
4943
|
|
|
|
|
|
|
11076 => 'Books|Nonfiction|Social Science|Society', |
4944
|
|
|
|
|
|
|
11077 => 'Books|Nonfiction|Philosophy|Aesthetics', |
4945
|
|
|
|
|
|
|
11078 => 'Books|Nonfiction|Philosophy|Epistemology', |
4946
|
|
|
|
|
|
|
11079 => 'Books|Nonfiction|Philosophy|Ethics', |
4947
|
|
|
|
|
|
|
11080 => 'Books|Nonfiction|Philosophy|Language', |
4948
|
|
|
|
|
|
|
11081 => 'Books|Nonfiction|Philosophy|Logic', |
4949
|
|
|
|
|
|
|
11082 => 'Books|Nonfiction|Philosophy|Metaphysics', |
4950
|
|
|
|
|
|
|
11083 => 'Books|Nonfiction|Philosophy|Political', |
4951
|
|
|
|
|
|
|
11084 => 'Books|Nonfiction|Philosophy|Religion', |
4952
|
|
|
|
|
|
|
11085 => 'Books|Reference|Manuals', |
4953
|
|
|
|
|
|
|
11086 => 'Books|Kids', |
4954
|
|
|
|
|
|
|
11087 => 'Books|Kids|Animals', |
4955
|
|
|
|
|
|
|
11088 => 'Books|Kids|Basic Concepts', |
4956
|
|
|
|
|
|
|
11089 => 'Books|Kids|Basic Concepts|Alphabet', |
4957
|
|
|
|
|
|
|
11090 => 'Books|Kids|Basic Concepts|Body', |
4958
|
|
|
|
|
|
|
11091 => 'Books|Kids|Basic Concepts|Colors', |
4959
|
|
|
|
|
|
|
11092 => 'Books|Kids|Basic Concepts|Counting & Numbers', |
4960
|
|
|
|
|
|
|
11093 => 'Books|Kids|Basic Concepts|Date & Time', |
4961
|
|
|
|
|
|
|
11094 => 'Books|Kids|Basic Concepts|General', |
4962
|
|
|
|
|
|
|
11095 => 'Books|Kids|Basic Concepts|Money', |
4963
|
|
|
|
|
|
|
11096 => 'Books|Kids|Basic Concepts|Opposites', |
4964
|
|
|
|
|
|
|
11097 => 'Books|Kids|Basic Concepts|Seasons', |
4965
|
|
|
|
|
|
|
11098 => 'Books|Kids|Basic Concepts|Senses & Sensation', |
4966
|
|
|
|
|
|
|
11099 => 'Books|Kids|Basic Concepts|Size & Shape', |
4967
|
|
|
|
|
|
|
11100 => 'Books|Kids|Basic Concepts|Sounds', |
4968
|
|
|
|
|
|
|
11101 => 'Books|Kids|Basic Concepts|Words', |
4969
|
|
|
|
|
|
|
11102 => 'Books|Kids|Biography', |
4970
|
|
|
|
|
|
|
11103 => 'Books|Kids|Careers & Occupations', |
4971
|
|
|
|
|
|
|
11104 => 'Books|Kids|Computers & Technology', |
4972
|
|
|
|
|
|
|
11105 => 'Books|Kids|Cooking & Food', |
4973
|
|
|
|
|
|
|
11106 => 'Books|Kids|Arts & Entertainment', |
4974
|
|
|
|
|
|
|
11107 => 'Books|Kids|Arts & Entertainment|Art', |
4975
|
|
|
|
|
|
|
11108 => 'Books|Kids|Arts & Entertainment|Crafts', |
4976
|
|
|
|
|
|
|
11109 => 'Books|Kids|Arts & Entertainment|Music', |
4977
|
|
|
|
|
|
|
11110 => 'Books|Kids|Arts & Entertainment|Performing Arts', |
4978
|
|
|
|
|
|
|
11111 => 'Books|Kids|Family', |
4979
|
|
|
|
|
|
|
11112 => 'Books|Kids|Fiction', |
4980
|
|
|
|
|
|
|
11113 => 'Books|Kids|Fiction|Action & Adventure', |
4981
|
|
|
|
|
|
|
11114 => 'Books|Kids|Fiction|Animals', |
4982
|
|
|
|
|
|
|
11115 => 'Books|Kids|Fiction|Classics', |
4983
|
|
|
|
|
|
|
11116 => 'Books|Kids|Fiction|Comics & Graphic Novels', |
4984
|
|
|
|
|
|
|
11117 => 'Books|Kids|Fiction|Culture, Places & People', |
4985
|
|
|
|
|
|
|
11118 => 'Books|Kids|Fiction|Family & Relationships', |
4986
|
|
|
|
|
|
|
11119 => 'Books|Kids|Fiction|Fantasy', |
4987
|
|
|
|
|
|
|
11120 => 'Books|Kids|Fiction|Fairy Tales, Myths & Fables', |
4988
|
|
|
|
|
|
|
11121 => 'Books|Kids|Fiction|Favorite Characters', |
4989
|
|
|
|
|
|
|
11122 => 'Books|Kids|Fiction|Historical', |
4990
|
|
|
|
|
|
|
11123 => 'Books|Kids|Fiction|Holidays & Celebrations', |
4991
|
|
|
|
|
|
|
11124 => 'Books|Kids|Fiction|Monsters & Ghosts', |
4992
|
|
|
|
|
|
|
11125 => 'Books|Kids|Fiction|Mysteries', |
4993
|
|
|
|
|
|
|
11126 => 'Books|Kids|Fiction|Nature', |
4994
|
|
|
|
|
|
|
11127 => 'Books|Kids|Fiction|Religion', |
4995
|
|
|
|
|
|
|
11128 => 'Books|Kids|Fiction|Sci-Fi', |
4996
|
|
|
|
|
|
|
11129 => 'Books|Kids|Fiction|Social Issues', |
4997
|
|
|
|
|
|
|
11130 => 'Books|Kids|Fiction|Sports & Recreation', |
4998
|
|
|
|
|
|
|
11131 => 'Books|Kids|Fiction|Transportation', |
4999
|
|
|
|
|
|
|
11132 => 'Books|Kids|Games & Activities', |
5000
|
|
|
|
|
|
|
11133 => 'Books|Kids|General Nonfiction', |
5001
|
|
|
|
|
|
|
11134 => 'Books|Kids|Health', |
5002
|
|
|
|
|
|
|
11135 => 'Books|Kids|History', |
5003
|
|
|
|
|
|
|
11136 => 'Books|Kids|Holidays & Celebrations', |
5004
|
|
|
|
|
|
|
11137 => 'Books|Kids|Holidays & Celebrations|Birthdays', |
5005
|
|
|
|
|
|
|
11138 => 'Books|Kids|Holidays & Celebrations|Christmas & Advent', |
5006
|
|
|
|
|
|
|
11139 => 'Books|Kids|Holidays & Celebrations|Easter & Lent', |
5007
|
|
|
|
|
|
|
11140 => 'Books|Kids|Holidays & Celebrations|General', |
5008
|
|
|
|
|
|
|
11141 => 'Books|Kids|Holidays & Celebrations|Halloween', |
5009
|
|
|
|
|
|
|
11142 => 'Books|Kids|Holidays & Celebrations|Hanukkah', |
5010
|
|
|
|
|
|
|
11143 => 'Books|Kids|Holidays & Celebrations|Other', |
5011
|
|
|
|
|
|
|
11144 => 'Books|Kids|Holidays & Celebrations|Passover', |
5012
|
|
|
|
|
|
|
11145 => 'Books|Kids|Holidays & Celebrations|Patriotic Holidays', |
5013
|
|
|
|
|
|
|
11146 => 'Books|Kids|Holidays & Celebrations|Ramadan', |
5014
|
|
|
|
|
|
|
11147 => 'Books|Kids|Holidays & Celebrations|Thanksgiving', |
5015
|
|
|
|
|
|
|
11148 => "Books|Kids|Holidays & Celebrations|Valentine's Day", |
5016
|
|
|
|
|
|
|
11149 => 'Books|Kids|Humor', |
5017
|
|
|
|
|
|
|
11150 => 'Books|Kids|Humor|Jokes & Riddles', |
5018
|
|
|
|
|
|
|
11151 => 'Books|Kids|Poetry', |
5019
|
|
|
|
|
|
|
11152 => 'Books|Kids|Learning to Read', |
5020
|
|
|
|
|
|
|
11153 => 'Books|Kids|Learning to Read|Chapter Books', |
5021
|
|
|
|
|
|
|
11154 => 'Books|Kids|Learning to Read|Early Readers', |
5022
|
|
|
|
|
|
|
11155 => 'Books|Kids|Learning to Read|Intermediate Readers', |
5023
|
|
|
|
|
|
|
11156 => 'Books|Kids|Nursery Rhymes', |
5024
|
|
|
|
|
|
|
11157 => 'Books|Kids|Government', |
5025
|
|
|
|
|
|
|
11158 => 'Books|Kids|Reference', |
5026
|
|
|
|
|
|
|
11159 => 'Books|Kids|Religion', |
5027
|
|
|
|
|
|
|
11160 => 'Books|Kids|Science & Nature', |
5028
|
|
|
|
|
|
|
11161 => 'Books|Kids|Social Issues', |
5029
|
|
|
|
|
|
|
11162 => 'Books|Kids|Social Studies', |
5030
|
|
|
|
|
|
|
11163 => 'Books|Kids|Sports & Recreation', |
5031
|
|
|
|
|
|
|
11164 => 'Books|Kids|Transportation', |
5032
|
|
|
|
|
|
|
11165 => 'Books|Young Adult', |
5033
|
|
|
|
|
|
|
11166 => 'Books|Young Adult|Animals', |
5034
|
|
|
|
|
|
|
11167 => 'Books|Young Adult|Biography', |
5035
|
|
|
|
|
|
|
11168 => 'Books|Young Adult|Careers & Occupations', |
5036
|
|
|
|
|
|
|
11169 => 'Books|Young Adult|Computers & Technology', |
5037
|
|
|
|
|
|
|
11170 => 'Books|Young Adult|Cooking & Food', |
5038
|
|
|
|
|
|
|
11171 => 'Books|Young Adult|Arts & Entertainment', |
5039
|
|
|
|
|
|
|
11172 => 'Books|Young Adult|Arts & Entertainment|Art', |
5040
|
|
|
|
|
|
|
11173 => 'Books|Young Adult|Arts & Entertainment|Crafts', |
5041
|
|
|
|
|
|
|
11174 => 'Books|Young Adult|Arts & Entertainment|Music', |
5042
|
|
|
|
|
|
|
11175 => 'Books|Young Adult|Arts & Entertainment|Performing Arts', |
5043
|
|
|
|
|
|
|
11176 => 'Books|Young Adult|Family', |
5044
|
|
|
|
|
|
|
11177 => 'Books|Young Adult|Fiction', |
5045
|
|
|
|
|
|
|
11178 => 'Books|Young Adult|Fiction|Action & Adventure', |
5046
|
|
|
|
|
|
|
11179 => 'Books|Young Adult|Fiction|Animals', |
5047
|
|
|
|
|
|
|
11180 => 'Books|Young Adult|Fiction|Classics', |
5048
|
|
|
|
|
|
|
11181 => 'Books|Young Adult|Fiction|Comics & Graphic Novels', |
5049
|
|
|
|
|
|
|
11182 => 'Books|Young Adult|Fiction|Culture, Places & People', |
5050
|
|
|
|
|
|
|
11183 => 'Books|Young Adult|Fiction|Dystopian', |
5051
|
|
|
|
|
|
|
11184 => 'Books|Young Adult|Fiction|Family & Relationships', |
5052
|
|
|
|
|
|
|
11185 => 'Books|Young Adult|Fiction|Fantasy', |
5053
|
|
|
|
|
|
|
11186 => 'Books|Young Adult|Fiction|Fairy Tales, Myths & Fables', |
5054
|
|
|
|
|
|
|
11187 => 'Books|Young Adult|Fiction|Favorite Characters', |
5055
|
|
|
|
|
|
|
11188 => 'Books|Young Adult|Fiction|Historical', |
5056
|
|
|
|
|
|
|
11189 => 'Books|Young Adult|Fiction|Holidays & Celebrations', |
5057
|
|
|
|
|
|
|
11190 => 'Books|Young Adult|Fiction|Horror, Monsters & Ghosts', |
5058
|
|
|
|
|
|
|
11191 => 'Books|Young Adult|Fiction|Crime & Mystery', |
5059
|
|
|
|
|
|
|
11192 => 'Books|Young Adult|Fiction|Nature', |
5060
|
|
|
|
|
|
|
11193 => 'Books|Young Adult|Fiction|Religion', |
5061
|
|
|
|
|
|
|
11194 => 'Books|Young Adult|Fiction|Romance', |
5062
|
|
|
|
|
|
|
11195 => 'Books|Young Adult|Fiction|Sci-Fi', |
5063
|
|
|
|
|
|
|
11196 => 'Books|Young Adult|Fiction|Coming of Age', |
5064
|
|
|
|
|
|
|
11197 => 'Books|Young Adult|Fiction|Sports & Recreation', |
5065
|
|
|
|
|
|
|
11198 => 'Books|Young Adult|Fiction|Transportation', |
5066
|
|
|
|
|
|
|
11199 => 'Books|Young Adult|Games & Activities', |
5067
|
|
|
|
|
|
|
11200 => 'Books|Young Adult|General Nonfiction', |
5068
|
|
|
|
|
|
|
11201 => 'Books|Young Adult|Health', |
5069
|
|
|
|
|
|
|
11202 => 'Books|Young Adult|History', |
5070
|
|
|
|
|
|
|
11203 => 'Books|Young Adult|Holidays & Celebrations', |
5071
|
|
|
|
|
|
|
11204 => 'Books|Young Adult|Holidays & Celebrations|Birthdays', |
5072
|
|
|
|
|
|
|
11205 => 'Books|Young Adult|Holidays & Celebrations|Christmas & Advent', |
5073
|
|
|
|
|
|
|
11206 => 'Books|Young Adult|Holidays & Celebrations|Easter & Lent', |
5074
|
|
|
|
|
|
|
11207 => 'Books|Young Adult|Holidays & Celebrations|General', |
5075
|
|
|
|
|
|
|
11208 => 'Books|Young Adult|Holidays & Celebrations|Halloween', |
5076
|
|
|
|
|
|
|
11209 => 'Books|Young Adult|Holidays & Celebrations|Hanukkah', |
5077
|
|
|
|
|
|
|
11210 => 'Books|Young Adult|Holidays & Celebrations|Other', |
5078
|
|
|
|
|
|
|
11211 => 'Books|Young Adult|Holidays & Celebrations|Passover', |
5079
|
|
|
|
|
|
|
11212 => 'Books|Young Adult|Holidays & Celebrations|Patriotic Holidays', |
5080
|
|
|
|
|
|
|
11213 => 'Books|Young Adult|Holidays & Celebrations|Ramadan', |
5081
|
|
|
|
|
|
|
11214 => 'Books|Young Adult|Holidays & Celebrations|Thanksgiving', |
5082
|
|
|
|
|
|
|
11215 => "Books|Young Adult|Holidays & Celebrations|Valentine's Day", |
5083
|
|
|
|
|
|
|
11216 => 'Books|Young Adult|Humor', |
5084
|
|
|
|
|
|
|
11217 => 'Books|Young Adult|Humor|Jokes & Riddles', |
5085
|
|
|
|
|
|
|
11218 => 'Books|Young Adult|Poetry', |
5086
|
|
|
|
|
|
|
11219 => 'Books|Young Adult|Politics & Government', |
5087
|
|
|
|
|
|
|
11220 => 'Books|Young Adult|Reference', |
5088
|
|
|
|
|
|
|
11221 => 'Books|Young Adult|Religion', |
5089
|
|
|
|
|
|
|
11222 => 'Books|Young Adult|Science & Nature', |
5090
|
|
|
|
|
|
|
11223 => 'Books|Young Adult|Coming of Age', |
5091
|
|
|
|
|
|
|
11224 => 'Books|Young Adult|Social Studies', |
5092
|
|
|
|
|
|
|
11225 => 'Books|Young Adult|Sports & Recreation', |
5093
|
|
|
|
|
|
|
11226 => 'Books|Young Adult|Transportation', |
5094
|
|
|
|
|
|
|
11227 => 'Books|Communications & Media', |
5095
|
|
|
|
|
|
|
11228 => 'Books|Military & Warfare', |
5096
|
|
|
|
|
|
|
11229 => 'Books|Romance|Inspirational', |
5097
|
|
|
|
|
|
|
11231 => 'Books|Romance|Holiday', |
5098
|
|
|
|
|
|
|
11232 => 'Books|Romance|Wholesome', |
5099
|
|
|
|
|
|
|
11233 => 'Books|Romance|Military', |
5100
|
|
|
|
|
|
|
11234 => 'Books|Arts & Entertainment|Art History', |
5101
|
|
|
|
|
|
|
11236 => 'Books|Arts & Entertainment|Design', |
5102
|
|
|
|
|
|
|
11243 => 'Books|Business & Personal Finance|Accounting', |
5103
|
|
|
|
|
|
|
11244 => 'Books|Business & Personal Finance|Hospitality', |
5104
|
|
|
|
|
|
|
11245 => 'Books|Business & Personal Finance|Real Estate', |
5105
|
|
|
|
|
|
|
11246 => 'Books|Humor|Jokes & Riddles', |
5106
|
|
|
|
|
|
|
11247 => 'Books|Religion & Spirituality|Comparative Religion', |
5107
|
|
|
|
|
|
|
11255 => 'Books|Cookbooks, Food & Wine|Culinary Arts', |
5108
|
|
|
|
|
|
|
11259 => 'Books|Mysteries & Thrillers|Cozy', |
5109
|
|
|
|
|
|
|
11260 => 'Books|Politics & Current Events|Current Events', |
5110
|
|
|
|
|
|
|
11261 => 'Books|Politics & Current Events|Foreign Policy & International Relations', |
5111
|
|
|
|
|
|
|
11262 => 'Books|Politics & Current Events|Local Government', |
5112
|
|
|
|
|
|
|
11263 => 'Books|Politics & Current Events|National Government', |
5113
|
|
|
|
|
|
|
11264 => 'Books|Politics & Current Events|Political Science', |
5114
|
|
|
|
|
|
|
11265 => 'Books|Politics & Current Events|Public Administration', |
5115
|
|
|
|
|
|
|
11266 => 'Books|Politics & Current Events|World Affairs', |
5116
|
|
|
|
|
|
|
11273 => 'Books|Nonfiction|Family & Relationships|Family & Childcare', |
5117
|
|
|
|
|
|
|
11274 => 'Books|Nonfiction|Family & Relationships|Love & Romance', |
5118
|
|
|
|
|
|
|
11275 => 'Books|Sci-Fi & Fantasy|Fantasy|Urban', |
5119
|
|
|
|
|
|
|
11276 => 'Books|Reference|Foreign Languages|Arabic', |
5120
|
|
|
|
|
|
|
11277 => 'Books|Reference|Foreign Languages|Bilingual Editions', |
5121
|
|
|
|
|
|
|
11278 => 'Books|Reference|Foreign Languages|African Languages', |
5122
|
|
|
|
|
|
|
11279 => 'Books|Reference|Foreign Languages|Ancient Languages', |
5123
|
|
|
|
|
|
|
11280 => 'Books|Reference|Foreign Languages|Chinese', |
5124
|
|
|
|
|
|
|
11281 => 'Books|Reference|Foreign Languages|English', |
5125
|
|
|
|
|
|
|
11282 => 'Books|Reference|Foreign Languages|French', |
5126
|
|
|
|
|
|
|
11283 => 'Books|Reference|Foreign Languages|German', |
5127
|
|
|
|
|
|
|
11284 => 'Books|Reference|Foreign Languages|Hebrew', |
5128
|
|
|
|
|
|
|
11285 => 'Books|Reference|Foreign Languages|Hindi', |
5129
|
|
|
|
|
|
|
11286 => 'Books|Reference|Foreign Languages|Italian', |
5130
|
|
|
|
|
|
|
11287 => 'Books|Reference|Foreign Languages|Japanese', |
5131
|
|
|
|
|
|
|
11288 => 'Books|Reference|Foreign Languages|Korean', |
5132
|
|
|
|
|
|
|
11289 => 'Books|Reference|Foreign Languages|Linguistics', |
5133
|
|
|
|
|
|
|
11290 => 'Books|Reference|Foreign Languages|Other Languages', |
5134
|
|
|
|
|
|
|
11291 => 'Books|Reference|Foreign Languages|Portuguese', |
5135
|
|
|
|
|
|
|
11292 => 'Books|Reference|Foreign Languages|Russian', |
5136
|
|
|
|
|
|
|
11293 => 'Books|Reference|Foreign Languages|Spanish', |
5137
|
|
|
|
|
|
|
11294 => 'Books|Reference|Foreign Languages|Speech Pathology', |
5138
|
|
|
|
|
|
|
11295 => 'Books|Science & Nature|Mathematics|Advanced Mathematics', |
5139
|
|
|
|
|
|
|
11296 => 'Books|Science & Nature|Mathematics|Algebra', |
5140
|
|
|
|
|
|
|
11297 => 'Books|Science & Nature|Mathematics|Arithmetic', |
5141
|
|
|
|
|
|
|
11298 => 'Books|Science & Nature|Mathematics|Calculus', |
5142
|
|
|
|
|
|
|
11299 => 'Books|Science & Nature|Mathematics|Geometry', |
5143
|
|
|
|
|
|
|
11300 => 'Books|Science & Nature|Mathematics|Statistics', |
5144
|
|
|
|
|
|
|
11301 => 'Books|Professional & Technical|Medical|Veterinary', |
5145
|
|
|
|
|
|
|
11302 => 'Books|Professional & Technical|Medical|Neuroscience', |
5146
|
|
|
|
|
|
|
11303 => 'Books|Professional & Technical|Medical|Immunology', |
5147
|
|
|
|
|
|
|
11304 => 'Books|Professional & Technical|Medical|Nursing', |
5148
|
|
|
|
|
|
|
11305 => 'Books|Professional & Technical|Medical|Pharmacology & Toxicology', |
5149
|
|
|
|
|
|
|
11306 => 'Books|Professional & Technical|Medical|Anatomy & Physiology', |
5150
|
|
|
|
|
|
|
11307 => 'Books|Professional & Technical|Medical|Dentistry', |
5151
|
|
|
|
|
|
|
11308 => 'Books|Professional & Technical|Medical|Emergency Medicine', |
5152
|
|
|
|
|
|
|
11309 => 'Books|Professional & Technical|Medical|Genetics', |
5153
|
|
|
|
|
|
|
11310 => 'Books|Professional & Technical|Medical|Psychiatry', |
5154
|
|
|
|
|
|
|
11311 => 'Books|Professional & Technical|Medical|Radiology', |
5155
|
|
|
|
|
|
|
11312 => 'Books|Professional & Technical|Medical|Alternative Medicine', |
5156
|
|
|
|
|
|
|
11317 => 'Books|Nonfiction|Philosophy|Political Philosophy', |
5157
|
|
|
|
|
|
|
11319 => 'Books|Nonfiction|Philosophy|Philosophy of Language', |
5158
|
|
|
|
|
|
|
11320 => 'Books|Nonfiction|Philosophy|Philosophy of Religion', |
5159
|
|
|
|
|
|
|
11327 => 'Books|Nonfiction|Social Science|Sociology', |
5160
|
|
|
|
|
|
|
11329 => 'Books|Professional & Technical|Engineering|Aeronautics', |
5161
|
|
|
|
|
|
|
11330 => 'Books|Professional & Technical|Engineering|Chemical & Petroleum Engineering', |
5162
|
|
|
|
|
|
|
11331 => 'Books|Professional & Technical|Engineering|Civil Engineering', |
5163
|
|
|
|
|
|
|
11332 => 'Books|Professional & Technical|Engineering|Computer Science', |
5164
|
|
|
|
|
|
|
11333 => 'Books|Professional & Technical|Engineering|Electrical Engineering', |
5165
|
|
|
|
|
|
|
11334 => 'Books|Professional & Technical|Engineering|Environmental Engineering', |
5166
|
|
|
|
|
|
|
11335 => 'Books|Professional & Technical|Engineering|Mechanical Engineering', |
5167
|
|
|
|
|
|
|
11336 => 'Books|Professional & Technical|Engineering|Power Resources', |
5168
|
|
|
|
|
|
|
11337 => 'Books|Comics & Graphic Novels|Manga|Boys', |
5169
|
|
|
|
|
|
|
11338 => 'Books|Comics & Graphic Novels|Manga|Men', |
5170
|
|
|
|
|
|
|
11339 => 'Books|Comics & Graphic Novels|Manga|Girls', |
5171
|
|
|
|
|
|
|
11340 => 'Books|Comics & Graphic Novels|Manga|Women', |
5172
|
|
|
|
|
|
|
11341 => 'Books|Comics & Graphic Novels|Manga|Other', |
5173
|
|
|
|
|
|
|
11342 => 'Books|Comics & Graphic Novels|Manga|Yaoi', |
5174
|
|
|
|
|
|
|
11343 => 'Books|Comics & Graphic Novels|Manga|Comic Essays', |
5175
|
|
|
|
|
|
|
12001 => 'Mac App Store|Business', |
5176
|
|
|
|
|
|
|
12002 => 'Mac App Store|Developer Tools', |
5177
|
|
|
|
|
|
|
12003 => 'Mac App Store|Education', |
5178
|
|
|
|
|
|
|
12004 => 'Mac App Store|Entertainment', |
5179
|
|
|
|
|
|
|
12005 => 'Mac App Store|Finance', |
5180
|
|
|
|
|
|
|
12006 => 'Mac App Store|Games', |
5181
|
|
|
|
|
|
|
12007 => 'Mac App Store|Health & Fitness', |
5182
|
|
|
|
|
|
|
12008 => 'Mac App Store|Lifestyle', |
5183
|
|
|
|
|
|
|
12010 => 'Mac App Store|Medical', |
5184
|
|
|
|
|
|
|
12011 => 'Mac App Store|Music', |
5185
|
|
|
|
|
|
|
12012 => 'Mac App Store|News', |
5186
|
|
|
|
|
|
|
12013 => 'Mac App Store|Photography', |
5187
|
|
|
|
|
|
|
12014 => 'Mac App Store|Productivity', |
5188
|
|
|
|
|
|
|
12015 => 'Mac App Store|Reference', |
5189
|
|
|
|
|
|
|
12016 => 'Mac App Store|Social Networking', |
5190
|
|
|
|
|
|
|
12017 => 'Mac App Store|Sports', |
5191
|
|
|
|
|
|
|
12018 => 'Mac App Store|Travel', |
5192
|
|
|
|
|
|
|
12019 => 'Mac App Store|Utilities', |
5193
|
|
|
|
|
|
|
12020 => 'Mac App Store|Video', |
5194
|
|
|
|
|
|
|
12021 => 'Mac App Store|Weather', |
5195
|
|
|
|
|
|
|
12022 => 'Mac App Store|Graphics & Design', |
5196
|
|
|
|
|
|
|
12201 => 'Mac App Store|Games|Action', |
5197
|
|
|
|
|
|
|
12202 => 'Mac App Store|Games|Adventure', |
5198
|
|
|
|
|
|
|
12203 => 'Mac App Store|Games|Casual', |
5199
|
|
|
|
|
|
|
12204 => 'Mac App Store|Games|Board', |
5200
|
|
|
|
|
|
|
12205 => 'Mac App Store|Games|Card', |
5201
|
|
|
|
|
|
|
12206 => 'Mac App Store|Games|Casino', |
5202
|
|
|
|
|
|
|
12207 => 'Mac App Store|Games|Dice', |
5203
|
|
|
|
|
|
|
12208 => 'Mac App Store|Games|Educational', |
5204
|
|
|
|
|
|
|
12209 => 'Mac App Store|Games|Family', |
5205
|
|
|
|
|
|
|
12210 => 'Mac App Store|Games|Kids', |
5206
|
|
|
|
|
|
|
12211 => 'Mac App Store|Games|Music', |
5207
|
|
|
|
|
|
|
12212 => 'Mac App Store|Games|Puzzle', |
5208
|
|
|
|
|
|
|
12213 => 'Mac App Store|Games|Racing', |
5209
|
|
|
|
|
|
|
12214 => 'Mac App Store|Games|Role Playing', |
5210
|
|
|
|
|
|
|
12215 => 'Mac App Store|Games|Simulation', |
5211
|
|
|
|
|
|
|
12216 => 'Mac App Store|Games|Sports', |
5212
|
|
|
|
|
|
|
12217 => 'Mac App Store|Games|Strategy', |
5213
|
|
|
|
|
|
|
12218 => 'Mac App Store|Games|Trivia', |
5214
|
|
|
|
|
|
|
12219 => 'Mac App Store|Games|Word', |
5215
|
|
|
|
|
|
|
13001 => 'App Store|Magazines & Newspapers|News & Politics', |
5216
|
|
|
|
|
|
|
13002 => 'App Store|Magazines & Newspapers|Fashion & Style', |
5217
|
|
|
|
|
|
|
13003 => 'App Store|Magazines & Newspapers|Home & Garden', |
5218
|
|
|
|
|
|
|
13004 => 'App Store|Magazines & Newspapers|Outdoors & Nature', |
5219
|
|
|
|
|
|
|
13005 => 'App Store|Magazines & Newspapers|Sports & Leisure', |
5220
|
|
|
|
|
|
|
13006 => 'App Store|Magazines & Newspapers|Automotive', |
5221
|
|
|
|
|
|
|
13007 => 'App Store|Magazines & Newspapers|Arts & Photography', |
5222
|
|
|
|
|
|
|
13008 => 'App Store|Magazines & Newspapers|Brides & Weddings', |
5223
|
|
|
|
|
|
|
13009 => 'App Store|Magazines & Newspapers|Business & Investing', |
5224
|
|
|
|
|
|
|
13010 => "App Store|Magazines & Newspapers|Children's Magazines", |
5225
|
|
|
|
|
|
|
13011 => 'App Store|Magazines & Newspapers|Computers & Internet', |
5226
|
|
|
|
|
|
|
13012 => 'App Store|Magazines & Newspapers|Cooking, Food & Drink', |
5227
|
|
|
|
|
|
|
13013 => 'App Store|Magazines & Newspapers|Crafts & Hobbies', |
5228
|
|
|
|
|
|
|
13014 => 'App Store|Magazines & Newspapers|Electronics & Audio', |
5229
|
|
|
|
|
|
|
13015 => 'App Store|Magazines & Newspapers|Entertainment', |
5230
|
|
|
|
|
|
|
13017 => 'App Store|Magazines & Newspapers|Health, Mind & Body', |
5231
|
|
|
|
|
|
|
13018 => 'App Store|Magazines & Newspapers|History', |
5232
|
|
|
|
|
|
|
13019 => 'App Store|Magazines & Newspapers|Literary Magazines & Journals', |
5233
|
|
|
|
|
|
|
13020 => "App Store|Magazines & Newspapers|Men's Interest", |
5234
|
|
|
|
|
|
|
13021 => 'App Store|Magazines & Newspapers|Movies & Music', |
5235
|
|
|
|
|
|
|
13023 => 'App Store|Magazines & Newspapers|Parenting & Family', |
5236
|
|
|
|
|
|
|
13024 => 'App Store|Magazines & Newspapers|Pets', |
5237
|
|
|
|
|
|
|
13025 => 'App Store|Magazines & Newspapers|Professional & Trade', |
5238
|
|
|
|
|
|
|
13026 => 'App Store|Magazines & Newspapers|Regional News', |
5239
|
|
|
|
|
|
|
13027 => 'App Store|Magazines & Newspapers|Science', |
5240
|
|
|
|
|
|
|
13028 => 'App Store|Magazines & Newspapers|Teens', |
5241
|
|
|
|
|
|
|
13029 => 'App Store|Magazines & Newspapers|Travel & Regional', |
5242
|
|
|
|
|
|
|
13030 => "App Store|Magazines & Newspapers|Women's Interest", |
5243
|
|
|
|
|
|
|
15000 => 'Textbooks|Arts & Entertainment', |
5244
|
|
|
|
|
|
|
15001 => 'Textbooks|Arts & Entertainment|Art & Architecture', |
5245
|
|
|
|
|
|
|
15002 => 'Textbooks|Arts & Entertainment|Art & Architecture|Urban Planning', |
5246
|
|
|
|
|
|
|
15003 => 'Textbooks|Arts & Entertainment|Art History', |
5247
|
|
|
|
|
|
|
15004 => 'Textbooks|Arts & Entertainment|Dance', |
5248
|
|
|
|
|
|
|
15005 => 'Textbooks|Arts & Entertainment|Design', |
5249
|
|
|
|
|
|
|
15006 => 'Textbooks|Arts & Entertainment|Fashion', |
5250
|
|
|
|
|
|
|
15007 => 'Textbooks|Arts & Entertainment|Film', |
5251
|
|
|
|
|
|
|
15008 => 'Textbooks|Arts & Entertainment|Games', |
5252
|
|
|
|
|
|
|
15009 => 'Textbooks|Arts & Entertainment|Interior Design', |
5253
|
|
|
|
|
|
|
15010 => 'Textbooks|Arts & Entertainment|Media Arts', |
5254
|
|
|
|
|
|
|
15011 => 'Textbooks|Arts & Entertainment|Music', |
5255
|
|
|
|
|
|
|
15012 => 'Textbooks|Arts & Entertainment|Performing Arts', |
5256
|
|
|
|
|
|
|
15013 => 'Textbooks|Arts & Entertainment|Photography', |
5257
|
|
|
|
|
|
|
15014 => 'Textbooks|Arts & Entertainment|Theater', |
5258
|
|
|
|
|
|
|
15015 => 'Textbooks|Arts & Entertainment|TV', |
5259
|
|
|
|
|
|
|
15016 => 'Textbooks|Arts & Entertainment|Visual Arts', |
5260
|
|
|
|
|
|
|
15017 => 'Textbooks|Biographies & Memoirs', |
5261
|
|
|
|
|
|
|
15018 => 'Textbooks|Business & Personal Finance', |
5262
|
|
|
|
|
|
|
15019 => 'Textbooks|Business & Personal Finance|Accounting', |
5263
|
|
|
|
|
|
|
15020 => 'Textbooks|Business & Personal Finance|Careers', |
5264
|
|
|
|
|
|
|
15021 => 'Textbooks|Business & Personal Finance|Economics', |
5265
|
|
|
|
|
|
|
15022 => 'Textbooks|Business & Personal Finance|Finance', |
5266
|
|
|
|
|
|
|
15023 => 'Textbooks|Business & Personal Finance|Hospitality', |
5267
|
|
|
|
|
|
|
15024 => 'Textbooks|Business & Personal Finance|Industries & Professions', |
5268
|
|
|
|
|
|
|
15025 => 'Textbooks|Business & Personal Finance|Investing', |
5269
|
|
|
|
|
|
|
15026 => 'Textbooks|Business & Personal Finance|Management & Leadership', |
5270
|
|
|
|
|
|
|
15027 => 'Textbooks|Business & Personal Finance|Marketing & Sales', |
5271
|
|
|
|
|
|
|
15028 => 'Textbooks|Business & Personal Finance|Personal Finance', |
5272
|
|
|
|
|
|
|
15029 => 'Textbooks|Business & Personal Finance|Real Estate', |
5273
|
|
|
|
|
|
|
15030 => 'Textbooks|Business & Personal Finance|Reference', |
5274
|
|
|
|
|
|
|
15031 => 'Textbooks|Business & Personal Finance|Small Business & Entrepreneurship', |
5275
|
|
|
|
|
|
|
15032 => 'Textbooks|Children & Teens', |
5276
|
|
|
|
|
|
|
15033 => 'Textbooks|Children & Teens|Fiction', |
5277
|
|
|
|
|
|
|
15034 => 'Textbooks|Children & Teens|Nonfiction', |
5278
|
|
|
|
|
|
|
15035 => 'Textbooks|Comics & Graphic Novels', |
5279
|
|
|
|
|
|
|
15036 => 'Textbooks|Comics & Graphic Novels|Graphic Novels', |
5280
|
|
|
|
|
|
|
15037 => 'Textbooks|Comics & Graphic Novels|Manga', |
5281
|
|
|
|
|
|
|
15038 => 'Textbooks|Communications & Media', |
5282
|
|
|
|
|
|
|
15039 => 'Textbooks|Communications & Media|Broadcasting', |
5283
|
|
|
|
|
|
|
15040 => 'Textbooks|Communications & Media|Digital Media', |
5284
|
|
|
|
|
|
|
15041 => 'Textbooks|Communications & Media|Journalism', |
5285
|
|
|
|
|
|
|
15042 => 'Textbooks|Communications & Media|Photojournalism', |
5286
|
|
|
|
|
|
|
15043 => 'Textbooks|Communications & Media|Print', |
5287
|
|
|
|
|
|
|
15044 => 'Textbooks|Communications & Media|Speech', |
5288
|
|
|
|
|
|
|
15045 => 'Textbooks|Communications & Media|Writing', |
5289
|
|
|
|
|
|
|
15046 => 'Textbooks|Computers & Internet', |
5290
|
|
|
|
|
|
|
15047 => 'Textbooks|Computers & Internet|Computers', |
5291
|
|
|
|
|
|
|
15048 => 'Textbooks|Computers & Internet|Databases', |
5292
|
|
|
|
|
|
|
15049 => 'Textbooks|Computers & Internet|Digital Media', |
5293
|
|
|
|
|
|
|
15050 => 'Textbooks|Computers & Internet|Internet', |
5294
|
|
|
|
|
|
|
15051 => 'Textbooks|Computers & Internet|Network', |
5295
|
|
|
|
|
|
|
15052 => 'Textbooks|Computers & Internet|Operating Systems', |
5296
|
|
|
|
|
|
|
15053 => 'Textbooks|Computers & Internet|Programming', |
5297
|
|
|
|
|
|
|
15054 => 'Textbooks|Computers & Internet|Software', |
5298
|
|
|
|
|
|
|
15055 => 'Textbooks|Computers & Internet|System Administration', |
5299
|
|
|
|
|
|
|
15056 => 'Textbooks|Cookbooks, Food & Wine', |
5300
|
|
|
|
|
|
|
15057 => 'Textbooks|Cookbooks, Food & Wine|Beverages', |
5301
|
|
|
|
|
|
|
15058 => 'Textbooks|Cookbooks, Food & Wine|Courses & Dishes', |
5302
|
|
|
|
|
|
|
15059 => 'Textbooks|Cookbooks, Food & Wine|Culinary Arts', |
5303
|
|
|
|
|
|
|
15060 => 'Textbooks|Cookbooks, Food & Wine|Methods', |
5304
|
|
|
|
|
|
|
15061 => 'Textbooks|Cookbooks, Food & Wine|Reference', |
5305
|
|
|
|
|
|
|
15062 => 'Textbooks|Cookbooks, Food & Wine|Regional & Ethnic', |
5306
|
|
|
|
|
|
|
15063 => 'Textbooks|Cookbooks, Food & Wine|Special Diet', |
5307
|
|
|
|
|
|
|
15064 => 'Textbooks|Cookbooks, Food & Wine|Special Occasions', |
5308
|
|
|
|
|
|
|
15065 => 'Textbooks|Cookbooks, Food & Wine|Specific Ingredients', |
5309
|
|
|
|
|
|
|
15066 => 'Textbooks|Engineering', |
5310
|
|
|
|
|
|
|
15067 => 'Textbooks|Engineering|Aeronautics', |
5311
|
|
|
|
|
|
|
15068 => 'Textbooks|Engineering|Chemical & Petroleum Engineering', |
5312
|
|
|
|
|
|
|
15069 => 'Textbooks|Engineering|Civil Engineering', |
5313
|
|
|
|
|
|
|
15070 => 'Textbooks|Engineering|Computer Science', |
5314
|
|
|
|
|
|
|
15071 => 'Textbooks|Engineering|Electrical Engineering', |
5315
|
|
|
|
|
|
|
15072 => 'Textbooks|Engineering|Environmental Engineering', |
5316
|
|
|
|
|
|
|
15073 => 'Textbooks|Engineering|Mechanical Engineering', |
5317
|
|
|
|
|
|
|
15074 => 'Textbooks|Engineering|Power Resources', |
5318
|
|
|
|
|
|
|
15075 => 'Textbooks|Fiction & Literature', |
5319
|
|
|
|
|
|
|
15076 => 'Textbooks|Fiction & Literature|Latino', |
5320
|
|
|
|
|
|
|
15077 => 'Textbooks|Fiction & Literature|Action & Adventure', |
5321
|
|
|
|
|
|
|
15078 => 'Textbooks|Fiction & Literature|African American', |
5322
|
|
|
|
|
|
|
15079 => 'Textbooks|Fiction & Literature|Anthologies', |
5323
|
|
|
|
|
|
|
15080 => 'Textbooks|Fiction & Literature|Classics', |
5324
|
|
|
|
|
|
|
15081 => 'Textbooks|Fiction & Literature|Comparative Literature', |
5325
|
|
|
|
|
|
|
15082 => 'Textbooks|Fiction & Literature|Erotica', |
5326
|
|
|
|
|
|
|
15083 => 'Textbooks|Fiction & Literature|Gay', |
5327
|
|
|
|
|
|
|
15084 => 'Textbooks|Fiction & Literature|Ghost', |
5328
|
|
|
|
|
|
|
15085 => 'Textbooks|Fiction & Literature|Historical', |
5329
|
|
|
|
|
|
|
15086 => 'Textbooks|Fiction & Literature|Horror', |
5330
|
|
|
|
|
|
|
15087 => 'Textbooks|Fiction & Literature|Literary', |
5331
|
|
|
|
|
|
|
15088 => 'Textbooks|Fiction & Literature|Literary Criticism', |
5332
|
|
|
|
|
|
|
15089 => 'Textbooks|Fiction & Literature|Poetry', |
5333
|
|
|
|
|
|
|
15090 => 'Textbooks|Fiction & Literature|Religious', |
5334
|
|
|
|
|
|
|
15091 => 'Textbooks|Fiction & Literature|Short Stories', |
5335
|
|
|
|
|
|
|
15092 => 'Textbooks|Health, Mind & Body', |
5336
|
|
|
|
|
|
|
15093 => 'Textbooks|Health, Mind & Body|Fitness', |
5337
|
|
|
|
|
|
|
15094 => 'Textbooks|Health, Mind & Body|Self-Improvement', |
5338
|
|
|
|
|
|
|
15095 => 'Textbooks|History', |
5339
|
|
|
|
|
|
|
15096 => 'Textbooks|History|Africa', |
5340
|
|
|
|
|
|
|
15097 => 'Textbooks|History|Americas', |
5341
|
|
|
|
|
|
|
15098 => 'Textbooks|History|Americas|Canada', |
5342
|
|
|
|
|
|
|
15099 => 'Textbooks|History|Americas|Latin America', |
5343
|
|
|
|
|
|
|
15100 => 'Textbooks|History|Americas|United States', |
5344
|
|
|
|
|
|
|
15101 => 'Textbooks|History|Ancient', |
5345
|
|
|
|
|
|
|
15102 => 'Textbooks|History|Asia', |
5346
|
|
|
|
|
|
|
15103 => 'Textbooks|History|Australia & Oceania', |
5347
|
|
|
|
|
|
|
15104 => 'Textbooks|History|Europe', |
5348
|
|
|
|
|
|
|
15105 => 'Textbooks|History|Middle East', |
5349
|
|
|
|
|
|
|
15106 => 'Textbooks|History|Military', |
5350
|
|
|
|
|
|
|
15107 => 'Textbooks|History|World', |
5351
|
|
|
|
|
|
|
15108 => 'Textbooks|Humor', |
5352
|
|
|
|
|
|
|
15109 => 'Textbooks|Language Studies', |
5353
|
|
|
|
|
|
|
15110 => 'Textbooks|Language Studies|African Languages', |
5354
|
|
|
|
|
|
|
15111 => 'Textbooks|Language Studies|Ancient Languages', |
5355
|
|
|
|
|
|
|
15112 => 'Textbooks|Language Studies|Arabic', |
5356
|
|
|
|
|
|
|
15113 => 'Textbooks|Language Studies|Bilingual Editions', |
5357
|
|
|
|
|
|
|
15114 => 'Textbooks|Language Studies|Chinese', |
5358
|
|
|
|
|
|
|
15115 => 'Textbooks|Language Studies|English', |
5359
|
|
|
|
|
|
|
15116 => 'Textbooks|Language Studies|French', |
5360
|
|
|
|
|
|
|
15117 => 'Textbooks|Language Studies|German', |
5361
|
|
|
|
|
|
|
15118 => 'Textbooks|Language Studies|Hebrew', |
5362
|
|
|
|
|
|
|
15119 => 'Textbooks|Language Studies|Hindi', |
5363
|
|
|
|
|
|
|
15120 => 'Textbooks|Language Studies|Indigenous Languages', |
5364
|
|
|
|
|
|
|
15121 => 'Textbooks|Language Studies|Italian', |
5365
|
|
|
|
|
|
|
15122 => 'Textbooks|Language Studies|Japanese', |
5366
|
|
|
|
|
|
|
15123 => 'Textbooks|Language Studies|Korean', |
5367
|
|
|
|
|
|
|
15124 => 'Textbooks|Language Studies|Linguistics', |
5368
|
|
|
|
|
|
|
15125 => 'Textbooks|Language Studies|Other Language', |
5369
|
|
|
|
|
|
|
15126 => 'Textbooks|Language Studies|Portuguese', |
5370
|
|
|
|
|
|
|
15127 => 'Textbooks|Language Studies|Russian', |
5371
|
|
|
|
|
|
|
15128 => 'Textbooks|Language Studies|Spanish', |
5372
|
|
|
|
|
|
|
15129 => 'Textbooks|Language Studies|Speech Pathology', |
5373
|
|
|
|
|
|
|
15130 => 'Textbooks|Lifestyle & Home', |
5374
|
|
|
|
|
|
|
15131 => 'Textbooks|Lifestyle & Home|Antiques & Collectibles', |
5375
|
|
|
|
|
|
|
15132 => 'Textbooks|Lifestyle & Home|Crafts & Hobbies', |
5376
|
|
|
|
|
|
|
15133 => 'Textbooks|Lifestyle & Home|Gardening', |
5377
|
|
|
|
|
|
|
15134 => 'Textbooks|Lifestyle & Home|Pets', |
5378
|
|
|
|
|
|
|
15135 => 'Textbooks|Mathematics', |
5379
|
|
|
|
|
|
|
15136 => 'Textbooks|Mathematics|Advanced Mathematics', |
5380
|
|
|
|
|
|
|
15137 => 'Textbooks|Mathematics|Algebra', |
5381
|
|
|
|
|
|
|
15138 => 'Textbooks|Mathematics|Arithmetic', |
5382
|
|
|
|
|
|
|
15139 => 'Textbooks|Mathematics|Calculus', |
5383
|
|
|
|
|
|
|
15140 => 'Textbooks|Mathematics|Geometry', |
5384
|
|
|
|
|
|
|
15141 => 'Textbooks|Mathematics|Statistics', |
5385
|
|
|
|
|
|
|
15142 => 'Textbooks|Medicine', |
5386
|
|
|
|
|
|
|
15143 => 'Textbooks|Medicine|Anatomy & Physiology', |
5387
|
|
|
|
|
|
|
15144 => 'Textbooks|Medicine|Dentistry', |
5388
|
|
|
|
|
|
|
15145 => 'Textbooks|Medicine|Emergency Medicine', |
5389
|
|
|
|
|
|
|
15146 => 'Textbooks|Medicine|Genetics', |
5390
|
|
|
|
|
|
|
15147 => 'Textbooks|Medicine|Immunology', |
5391
|
|
|
|
|
|
|
15148 => 'Textbooks|Medicine|Neuroscience', |
5392
|
|
|
|
|
|
|
15149 => 'Textbooks|Medicine|Nursing', |
5393
|
|
|
|
|
|
|
15150 => 'Textbooks|Medicine|Pharmacology & Toxicology', |
5394
|
|
|
|
|
|
|
15151 => 'Textbooks|Medicine|Psychiatry', |
5395
|
|
|
|
|
|
|
15152 => 'Textbooks|Medicine|Psychology', |
5396
|
|
|
|
|
|
|
15153 => 'Textbooks|Medicine|Radiology', |
5397
|
|
|
|
|
|
|
15154 => 'Textbooks|Medicine|Veterinary', |
5398
|
|
|
|
|
|
|
15155 => 'Textbooks|Mysteries & Thrillers', |
5399
|
|
|
|
|
|
|
15156 => 'Textbooks|Mysteries & Thrillers|British Detectives', |
5400
|
|
|
|
|
|
|
15157 => 'Textbooks|Mysteries & Thrillers|Hard-Boiled', |
5401
|
|
|
|
|
|
|
15158 => 'Textbooks|Mysteries & Thrillers|Historical', |
5402
|
|
|
|
|
|
|
15159 => 'Textbooks|Mysteries & Thrillers|Police Procedural', |
5403
|
|
|
|
|
|
|
15160 => 'Textbooks|Mysteries & Thrillers|Short Stories', |
5404
|
|
|
|
|
|
|
15161 => 'Textbooks|Mysteries & Thrillers|Women Sleuths', |
5405
|
|
|
|
|
|
|
15162 => 'Textbooks|Nonfiction', |
5406
|
|
|
|
|
|
|
15163 => 'Textbooks|Nonfiction|Family & Relationships', |
5407
|
|
|
|
|
|
|
15164 => 'Textbooks|Nonfiction|Transportation', |
5408
|
|
|
|
|
|
|
15165 => 'Textbooks|Nonfiction|True Crime', |
5409
|
|
|
|
|
|
|
15166 => 'Textbooks|Parenting', |
5410
|
|
|
|
|
|
|
15167 => 'Textbooks|Philosophy', |
5411
|
|
|
|
|
|
|
15168 => 'Textbooks|Philosophy|Aesthetics', |
5412
|
|
|
|
|
|
|
15169 => 'Textbooks|Philosophy|Epistemology', |
5413
|
|
|
|
|
|
|
15170 => 'Textbooks|Philosophy|Ethics', |
5414
|
|
|
|
|
|
|
15171 => 'Textbooks|Philosophy|Philosophy of Language', |
5415
|
|
|
|
|
|
|
15172 => 'Textbooks|Philosophy|Logic', |
5416
|
|
|
|
|
|
|
15173 => 'Textbooks|Philosophy|Metaphysics', |
5417
|
|
|
|
|
|
|
15174 => 'Textbooks|Philosophy|Political Philosophy', |
5418
|
|
|
|
|
|
|
15175 => 'Textbooks|Philosophy|Philosophy of Religion', |
5419
|
|
|
|
|
|
|
15176 => 'Textbooks|Politics & Current Events', |
5420
|
|
|
|
|
|
|
15177 => 'Textbooks|Politics & Current Events|Current Events', |
5421
|
|
|
|
|
|
|
15178 => 'Textbooks|Politics & Current Events|Foreign Policy & International Relations', |
5422
|
|
|
|
|
|
|
15179 => 'Textbooks|Politics & Current Events|Local Governments', |
5423
|
|
|
|
|
|
|
15180 => 'Textbooks|Politics & Current Events|National Governments', |
5424
|
|
|
|
|
|
|
15181 => 'Textbooks|Politics & Current Events|Political Science', |
5425
|
|
|
|
|
|
|
15182 => 'Textbooks|Politics & Current Events|Public Administration', |
5426
|
|
|
|
|
|
|
15183 => 'Textbooks|Politics & Current Events|World Affairs', |
5427
|
|
|
|
|
|
|
15184 => 'Textbooks|Professional & Technical', |
5428
|
|
|
|
|
|
|
15185 => 'Textbooks|Professional & Technical|Design', |
5429
|
|
|
|
|
|
|
15186 => 'Textbooks|Professional & Technical|Language Arts & Disciplines', |
5430
|
|
|
|
|
|
|
15187 => 'Textbooks|Professional & Technical|Engineering', |
5431
|
|
|
|
|
|
|
15188 => 'Textbooks|Professional & Technical|Law', |
5432
|
|
|
|
|
|
|
15189 => 'Textbooks|Professional & Technical|Medical', |
5433
|
|
|
|
|
|
|
15190 => 'Textbooks|Reference', |
5434
|
|
|
|
|
|
|
15191 => 'Textbooks|Reference|Almanacs & Yearbooks', |
5435
|
|
|
|
|
|
|
15192 => 'Textbooks|Reference|Atlases & Maps', |
5436
|
|
|
|
|
|
|
15193 => 'Textbooks|Reference|Catalogs & Directories', |
5437
|
|
|
|
|
|
|
15194 => 'Textbooks|Reference|Consumer Guides', |
5438
|
|
|
|
|
|
|
15195 => 'Textbooks|Reference|Dictionaries & Thesauruses', |
5439
|
|
|
|
|
|
|
15196 => 'Textbooks|Reference|Encyclopedias', |
5440
|
|
|
|
|
|
|
15197 => 'Textbooks|Reference|Etiquette', |
5441
|
|
|
|
|
|
|
15198 => 'Textbooks|Reference|Quotations', |
5442
|
|
|
|
|
|
|
15199 => 'Textbooks|Reference|Study Aids', |
5443
|
|
|
|
|
|
|
15200 => 'Textbooks|Reference|Words & Language', |
5444
|
|
|
|
|
|
|
15201 => 'Textbooks|Reference|Writing', |
5445
|
|
|
|
|
|
|
15202 => 'Textbooks|Religion & Spirituality', |
5446
|
|
|
|
|
|
|
15203 => 'Textbooks|Religion & Spirituality|Bible Studies', |
5447
|
|
|
|
|
|
|
15204 => 'Textbooks|Religion & Spirituality|Bibles', |
5448
|
|
|
|
|
|
|
15205 => 'Textbooks|Religion & Spirituality|Buddhism', |
5449
|
|
|
|
|
|
|
15206 => 'Textbooks|Religion & Spirituality|Christianity', |
5450
|
|
|
|
|
|
|
15207 => 'Textbooks|Religion & Spirituality|Comparative Religion', |
5451
|
|
|
|
|
|
|
15208 => 'Textbooks|Religion & Spirituality|Hinduism', |
5452
|
|
|
|
|
|
|
15209 => 'Textbooks|Religion & Spirituality|Islam', |
5453
|
|
|
|
|
|
|
15210 => 'Textbooks|Religion & Spirituality|Judaism', |
5454
|
|
|
|
|
|
|
15211 => 'Textbooks|Religion & Spirituality|Spirituality', |
5455
|
|
|
|
|
|
|
15212 => 'Textbooks|Romance', |
5456
|
|
|
|
|
|
|
15213 => 'Textbooks|Romance|Contemporary', |
5457
|
|
|
|
|
|
|
15214 => 'Textbooks|Romance|Erotic Romance', |
5458
|
|
|
|
|
|
|
15215 => 'Textbooks|Romance|Paranormal', |
5459
|
|
|
|
|
|
|
15216 => 'Textbooks|Romance|Historical', |
5460
|
|
|
|
|
|
|
15217 => 'Textbooks|Romance|Short Stories', |
5461
|
|
|
|
|
|
|
15218 => 'Textbooks|Romance|Suspense', |
5462
|
|
|
|
|
|
|
15219 => 'Textbooks|Romance|Western', |
5463
|
|
|
|
|
|
|
15220 => 'Textbooks|Sci-Fi & Fantasy', |
5464
|
|
|
|
|
|
|
15221 => 'Textbooks|Sci-Fi & Fantasy|Fantasy', |
5465
|
|
|
|
|
|
|
15222 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Contemporary', |
5466
|
|
|
|
|
|
|
15223 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Epic', |
5467
|
|
|
|
|
|
|
15224 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Historical', |
5468
|
|
|
|
|
|
|
15225 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Paranormal', |
5469
|
|
|
|
|
|
|
15226 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Short Stories', |
5470
|
|
|
|
|
|
|
15227 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction', |
5471
|
|
|
|
|
|
|
15228 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature', |
5472
|
|
|
|
|
|
|
15229 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|Adventure', |
5473
|
|
|
|
|
|
|
15230 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|High Tech', |
5474
|
|
|
|
|
|
|
15231 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|Short Stories', |
5475
|
|
|
|
|
|
|
15232 => 'Textbooks|Science & Nature', |
5476
|
|
|
|
|
|
|
15233 => 'Textbooks|Science & Nature|Agriculture', |
5477
|
|
|
|
|
|
|
15234 => 'Textbooks|Science & Nature|Astronomy', |
5478
|
|
|
|
|
|
|
15235 => 'Textbooks|Science & Nature|Atmosphere', |
5479
|
|
|
|
|
|
|
15236 => 'Textbooks|Science & Nature|Biology', |
5480
|
|
|
|
|
|
|
15237 => 'Textbooks|Science & Nature|Chemistry', |
5481
|
|
|
|
|
|
|
15238 => 'Textbooks|Science & Nature|Earth Sciences', |
5482
|
|
|
|
|
|
|
15239 => 'Textbooks|Science & Nature|Ecology', |
5483
|
|
|
|
|
|
|
15240 => 'Textbooks|Science & Nature|Environment', |
5484
|
|
|
|
|
|
|
15241 => 'Textbooks|Science & Nature|Essays', |
5485
|
|
|
|
|
|
|
15242 => 'Textbooks|Science & Nature|Geography', |
5486
|
|
|
|
|
|
|
15243 => 'Textbooks|Science & Nature|Geology', |
5487
|
|
|
|
|
|
|
15244 => 'Textbooks|Science & Nature|History', |
5488
|
|
|
|
|
|
|
15245 => 'Textbooks|Science & Nature|Life Sciences', |
5489
|
|
|
|
|
|
|
15246 => 'Textbooks|Science & Nature|Nature', |
5490
|
|
|
|
|
|
|
15247 => 'Textbooks|Science & Nature|Physics', |
5491
|
|
|
|
|
|
|
15248 => 'Textbooks|Science & Nature|Reference', |
5492
|
|
|
|
|
|
|
15249 => 'Textbooks|Social Science', |
5493
|
|
|
|
|
|
|
15250 => 'Textbooks|Social Science|Anthropology', |
5494
|
|
|
|
|
|
|
15251 => 'Textbooks|Social Science|Archaeology', |
5495
|
|
|
|
|
|
|
15252 => 'Textbooks|Social Science|Civics', |
5496
|
|
|
|
|
|
|
15253 => 'Textbooks|Social Science|Government', |
5497
|
|
|
|
|
|
|
15254 => 'Textbooks|Social Science|Social Studies', |
5498
|
|
|
|
|
|
|
15255 => 'Textbooks|Social Science|Social Welfare', |
5499
|
|
|
|
|
|
|
15256 => 'Textbooks|Social Science|Society', |
5500
|
|
|
|
|
|
|
15257 => 'Textbooks|Social Science|Society|African Studies', |
5501
|
|
|
|
|
|
|
15258 => 'Textbooks|Social Science|Society|American Studies', |
5502
|
|
|
|
|
|
|
15259 => 'Textbooks|Social Science|Society|Asia Pacific Studies', |
5503
|
|
|
|
|
|
|
15260 => 'Textbooks|Social Science|Society|Cross-Cultural Studies', |
5504
|
|
|
|
|
|
|
15261 => 'Textbooks|Social Science|Society|European Studies', |
5505
|
|
|
|
|
|
|
15262 => 'Textbooks|Social Science|Society|Immigration & Emigration', |
5506
|
|
|
|
|
|
|
15263 => 'Textbooks|Social Science|Society|Indigenous Studies', |
5507
|
|
|
|
|
|
|
15264 => 'Textbooks|Social Science|Society|Latin & Caribbean Studies', |
5508
|
|
|
|
|
|
|
15265 => 'Textbooks|Social Science|Society|Middle Eastern Studies', |
5509
|
|
|
|
|
|
|
15266 => 'Textbooks|Social Science|Society|Race & Ethnicity Studies', |
5510
|
|
|
|
|
|
|
15267 => 'Textbooks|Social Science|Society|Sexuality Studies', |
5511
|
|
|
|
|
|
|
15268 => "Textbooks|Social Science|Society|Women's Studies", |
5512
|
|
|
|
|
|
|
15269 => 'Textbooks|Social Science|Sociology', |
5513
|
|
|
|
|
|
|
15270 => 'Textbooks|Sports & Outdoors', |
5514
|
|
|
|
|
|
|
15271 => 'Textbooks|Sports & Outdoors|Baseball', |
5515
|
|
|
|
|
|
|
15272 => 'Textbooks|Sports & Outdoors|Basketball', |
5516
|
|
|
|
|
|
|
15273 => 'Textbooks|Sports & Outdoors|Coaching', |
5517
|
|
|
|
|
|
|
15274 => 'Textbooks|Sports & Outdoors|Equestrian', |
5518
|
|
|
|
|
|
|
15275 => 'Textbooks|Sports & Outdoors|Extreme Sports', |
5519
|
|
|
|
|
|
|
15276 => 'Textbooks|Sports & Outdoors|Football', |
5520
|
|
|
|
|
|
|
15277 => 'Textbooks|Sports & Outdoors|Golf', |
5521
|
|
|
|
|
|
|
15278 => 'Textbooks|Sports & Outdoors|Hockey', |
5522
|
|
|
|
|
|
|
15279 => 'Textbooks|Sports & Outdoors|Motor Sports', |
5523
|
|
|
|
|
|
|
15280 => 'Textbooks|Sports & Outdoors|Mountaineering', |
5524
|
|
|
|
|
|
|
15281 => 'Textbooks|Sports & Outdoors|Outdoors', |
5525
|
|
|
|
|
|
|
15282 => 'Textbooks|Sports & Outdoors|Racket Sports', |
5526
|
|
|
|
|
|
|
15283 => 'Textbooks|Sports & Outdoors|Reference', |
5527
|
|
|
|
|
|
|
15284 => 'Textbooks|Sports & Outdoors|Soccer', |
5528
|
|
|
|
|
|
|
15285 => 'Textbooks|Sports & Outdoors|Training', |
5529
|
|
|
|
|
|
|
15286 => 'Textbooks|Sports & Outdoors|Water Sports', |
5530
|
|
|
|
|
|
|
15287 => 'Textbooks|Sports & Outdoors|Winter Sports', |
5531
|
|
|
|
|
|
|
15288 => 'Textbooks|Teaching & Learning', |
5532
|
|
|
|
|
|
|
15289 => 'Textbooks|Teaching & Learning|Adult Education', |
5533
|
|
|
|
|
|
|
15290 => 'Textbooks|Teaching & Learning|Curriculum & Teaching', |
5534
|
|
|
|
|
|
|
15291 => 'Textbooks|Teaching & Learning|Educational Leadership', |
5535
|
|
|
|
|
|
|
15292 => 'Textbooks|Teaching & Learning|Educational Technology', |
5536
|
|
|
|
|
|
|
15293 => 'Textbooks|Teaching & Learning|Family & Childcare', |
5537
|
|
|
|
|
|
|
15294 => 'Textbooks|Teaching & Learning|Information & Library Science', |
5538
|
|
|
|
|
|
|
15295 => 'Textbooks|Teaching & Learning|Learning Resources', |
5539
|
|
|
|
|
|
|
15296 => 'Textbooks|Teaching & Learning|Psychology & Research', |
5540
|
|
|
|
|
|
|
15297 => 'Textbooks|Teaching & Learning|Special Education', |
5541
|
|
|
|
|
|
|
15298 => 'Textbooks|Travel & Adventure', |
5542
|
|
|
|
|
|
|
15299 => 'Textbooks|Travel & Adventure|Africa', |
5543
|
|
|
|
|
|
|
15300 => 'Textbooks|Travel & Adventure|Americas', |
5544
|
|
|
|
|
|
|
15301 => 'Textbooks|Travel & Adventure|Americas|Canada', |
5545
|
|
|
|
|
|
|
15302 => 'Textbooks|Travel & Adventure|Americas|Latin America', |
5546
|
|
|
|
|
|
|
15303 => 'Textbooks|Travel & Adventure|Americas|United States', |
5547
|
|
|
|
|
|
|
15304 => 'Textbooks|Travel & Adventure|Asia', |
5548
|
|
|
|
|
|
|
15305 => 'Textbooks|Travel & Adventure|Caribbean', |
5549
|
|
|
|
|
|
|
15306 => 'Textbooks|Travel & Adventure|Essays & Memoirs', |
5550
|
|
|
|
|
|
|
15307 => 'Textbooks|Travel & Adventure|Europe', |
5551
|
|
|
|
|
|
|
15308 => 'Textbooks|Travel & Adventure|Middle East', |
5552
|
|
|
|
|
|
|
15309 => 'Textbooks|Travel & Adventure|Oceania', |
5553
|
|
|
|
|
|
|
15310 => 'Textbooks|Travel & Adventure|Specialty Travel', |
5554
|
|
|
|
|
|
|
15311 => 'Textbooks|Comics & Graphic Novels|Comics', |
5555
|
|
|
|
|
|
|
15312 => 'Textbooks|Reference|Manuals', |
5556
|
|
|
|
|
|
|
16001 => 'App Store|Stickers|Emoji & Expressions', |
5557
|
|
|
|
|
|
|
16003 => 'App Store|Stickers|Animals & Nature', |
5558
|
|
|
|
|
|
|
16005 => 'App Store|Stickers|Art', |
5559
|
|
|
|
|
|
|
16006 => 'App Store|Stickers|Celebrations', |
5560
|
|
|
|
|
|
|
16007 => 'App Store|Stickers|Celebrities', |
5561
|
|
|
|
|
|
|
16008 => 'App Store|Stickers|Comics & Cartoons', |
5562
|
|
|
|
|
|
|
16009 => 'App Store|Stickers|Eating & Drinking', |
5563
|
|
|
|
|
|
|
16010 => 'App Store|Stickers|Gaming', |
5564
|
|
|
|
|
|
|
16014 => 'App Store|Stickers|Movies & TV', |
5565
|
|
|
|
|
|
|
16015 => 'App Store|Stickers|Music', |
5566
|
|
|
|
|
|
|
16017 => 'App Store|Stickers|People', |
5567
|
|
|
|
|
|
|
16019 => 'App Store|Stickers|Places & Objects', |
5568
|
|
|
|
|
|
|
16021 => 'App Store|Stickers|Sports & Activities', |
5569
|
|
|
|
|
|
|
16025 => 'App Store|Stickers|Kids & Family', |
5570
|
|
|
|
|
|
|
16026 => 'App Store|Stickers|Fashion', |
5571
|
|
|
|
|
|
|
100000 => 'Music|Christian & Gospel', |
5572
|
|
|
|
|
|
|
100001 => 'Music|Classical|Art Song', |
5573
|
|
|
|
|
|
|
100002 => 'Music|Classical|Brass & Woodwinds', |
5574
|
|
|
|
|
|
|
100003 => 'Music|Classical|Solo Instrumental', |
5575
|
|
|
|
|
|
|
100004 => 'Music|Classical|Contemporary Era', |
5576
|
|
|
|
|
|
|
100005 => 'Music|Classical|Oratorio', |
5577
|
|
|
|
|
|
|
100006 => 'Music|Classical|Cantata', |
5578
|
|
|
|
|
|
|
100007 => 'Music|Classical|Electronic', |
5579
|
|
|
|
|
|
|
100008 => 'Music|Classical|Sacred', |
5580
|
|
|
|
|
|
|
100009 => 'Music|Classical|Guitar', |
5581
|
|
|
|
|
|
|
100010 => 'Music|Classical|Piano', |
5582
|
|
|
|
|
|
|
100011 => 'Music|Classical|Violin', |
5583
|
|
|
|
|
|
|
100012 => 'Music|Classical|Cello', |
5584
|
|
|
|
|
|
|
100013 => 'Music|Classical|Percussion', |
5585
|
|
|
|
|
|
|
100014 => 'Music|Electronic|Dubstep', |
5586
|
|
|
|
|
|
|
100015 => 'Music|Electronic|Bass', |
5587
|
|
|
|
|
|
|
100016 => 'Music|Hip-Hop/Rap|UK Hip-Hop', |
5588
|
|
|
|
|
|
|
100017 => 'Music|Reggae|Lovers Rock', |
5589
|
|
|
|
|
|
|
100018 => 'Music|Alternative|EMO', |
5590
|
|
|
|
|
|
|
100019 => 'Music|Alternative|Pop Punk', |
5591
|
|
|
|
|
|
|
100020 => 'Music|Alternative|Indie Pop', |
5592
|
|
|
|
|
|
|
100021 => 'Music|New Age|Yoga', |
5593
|
|
|
|
|
|
|
100022 => 'Music|Pop|Tribute', |
5594
|
|
|
|
|
|
|
100023 => 'Music|Pop|Shows', |
5595
|
|
|
|
|
|
|
100024 => 'Music|Cuban', |
5596
|
|
|
|
|
|
|
100025 => 'Music|Cuban|Mambo', |
5597
|
|
|
|
|
|
|
100026 => 'Music|Cuban|Chachacha', |
5598
|
|
|
|
|
|
|
100027 => 'Music|Cuban|Guajira', |
5599
|
|
|
|
|
|
|
100028 => 'Music|Cuban|Son', |
5600
|
|
|
|
|
|
|
100029 => 'Music|Cuban|Bolero', |
5601
|
|
|
|
|
|
|
100030 => 'Music|Cuban|Guaracha', |
5602
|
|
|
|
|
|
|
100031 => 'Music|Cuban|Timba', |
5603
|
|
|
|
|
|
|
100032 => 'Music|Soundtrack|Video Game', |
5604
|
|
|
|
|
|
|
100033 => 'Music|Indian|Regional Indian|Punjabi|Punjabi Pop', |
5605
|
|
|
|
|
|
|
100034 => 'Music|Indian|Regional Indian|Bengali|Rabindra Sangeet', |
5606
|
|
|
|
|
|
|
100035 => 'Music|Indian|Regional Indian|Malayalam', |
5607
|
|
|
|
|
|
|
100036 => 'Music|Indian|Regional Indian|Kannada', |
5608
|
|
|
|
|
|
|
100037 => 'Music|Indian|Regional Indian|Marathi', |
5609
|
|
|
|
|
|
|
100038 => 'Music|Indian|Regional Indian|Gujarati', |
5610
|
|
|
|
|
|
|
100039 => 'Music|Indian|Regional Indian|Assamese', |
5611
|
|
|
|
|
|
|
100040 => 'Music|Indian|Regional Indian|Bhojpuri', |
5612
|
|
|
|
|
|
|
100041 => 'Music|Indian|Regional Indian|Haryanvi', |
5613
|
|
|
|
|
|
|
100042 => 'Music|Indian|Regional Indian|Odia', |
5614
|
|
|
|
|
|
|
100043 => 'Music|Indian|Regional Indian|Rajasthani', |
5615
|
|
|
|
|
|
|
100044 => 'Music|Indian|Regional Indian|Urdu', |
5616
|
|
|
|
|
|
|
100045 => 'Music|Indian|Regional Indian|Punjabi', |
5617
|
|
|
|
|
|
|
100046 => 'Music|Indian|Regional Indian|Bengali', |
5618
|
|
|
|
|
|
|
100047 => 'Music|Indian|Indian Classical|Carnatic Classical', |
5619
|
|
|
|
|
|
|
100048 => 'Music|Indian|Indian Classical|Hindustani Classical', |
5620
|
|
|
|
|
|
|
100049 => 'Music|African|Afro House', |
5621
|
|
|
|
|
|
|
100050 => 'Music|African|Afro Soul', |
5622
|
|
|
|
|
|
|
100051 => 'Music|African|Afrobeats', |
5623
|
|
|
|
|
|
|
100052 => 'Music|African|Benga', |
5624
|
|
|
|
|
|
|
100053 => 'Music|African|Bongo-Flava', |
5625
|
|
|
|
|
|
|
100054 => 'Music|African|Coupe-Decale', |
5626
|
|
|
|
|
|
|
100055 => 'Music|African|Gqom', |
5627
|
|
|
|
|
|
|
100056 => 'Music|African|Highlife', |
5628
|
|
|
|
|
|
|
100057 => 'Music|African|Kuduro', |
5629
|
|
|
|
|
|
|
100058 => 'Music|African|Kizomba', |
5630
|
|
|
|
|
|
|
100059 => 'Music|African|Kwaito', |
5631
|
|
|
|
|
|
|
100060 => 'Music|African|Mbalax', |
5632
|
|
|
|
|
|
|
100061 => 'Music|African|Ndombolo', |
5633
|
|
|
|
|
|
|
100062 => 'Music|African|Shangaan Electro', |
5634
|
|
|
|
|
|
|
100063 => 'Music|African|Soukous', |
5635
|
|
|
|
|
|
|
100064 => 'Music|African|Taarab', |
5636
|
|
|
|
|
|
|
100065 => 'Music|African|Zouglou', |
5637
|
|
|
|
|
|
|
100066 => 'Music|Turkish|Ozgun', |
5638
|
|
|
|
|
|
|
100067 => 'Music|Turkish|Fantezi', |
5639
|
|
|
|
|
|
|
100068 => 'Music|Turkish|Religious', |
5640
|
|
|
|
|
|
|
100069 => 'Music|Pop|Turkish Pop', |
5641
|
|
|
|
|
|
|
100070 => 'Music|Rock|Turkish Rock', |
5642
|
|
|
|
|
|
|
100071 => 'Music|Alternative|Turkish Alternative', |
5643
|
|
|
|
|
|
|
100072 => 'Music|Hip-Hop/Rap|Turkish Hip-Hop/Rap', |
5644
|
|
|
|
|
|
|
100073 => 'Music|African|Maskandi', |
5645
|
|
|
|
|
|
|
100074 => 'Music|Russian|Russian Romance', |
5646
|
|
|
|
|
|
|
100075 => 'Music|Russian|Russian Bard', |
5647
|
|
|
|
|
|
|
100076 => 'Music|Russian|Russian Pop', |
5648
|
|
|
|
|
|
|
100077 => 'Music|Russian|Russian Rock', |
5649
|
|
|
|
|
|
|
100078 => 'Music|Russian|Russian Hip-Hop', |
5650
|
|
|
|
|
|
|
100079 => 'Music|Arabic|Levant', |
5651
|
|
|
|
|
|
|
100080 => 'Music|Arabic|Levant|Dabke', |
5652
|
|
|
|
|
|
|
100081 => 'Music|Arabic|Maghreb Rai', |
5653
|
|
|
|
|
|
|
100082 => 'Music|Arabic|Khaleeji|Khaleeji Jalsat', |
5654
|
|
|
|
|
|
|
100083 => 'Music|Arabic|Khaleeji|Khaleeji Shailat', |
5655
|
|
|
|
|
|
|
100084 => 'Music|Tarab', |
5656
|
|
|
|
|
|
|
100085 => 'Music|Tarab|Iraqi Tarab', |
5657
|
|
|
|
|
|
|
100086 => 'Music|Tarab|Egyptian Tarab', |
5658
|
|
|
|
|
|
|
100087 => 'Music|Tarab|Khaleeji Tarab', |
5659
|
|
|
|
|
|
|
100088 => 'Music|Pop|Levant Pop', |
5660
|
|
|
|
|
|
|
100089 => 'Music|Pop|Iraqi Pop', |
5661
|
|
|
|
|
|
|
100090 => 'Music|Pop|Egyptian Pop', |
5662
|
|
|
|
|
|
|
100091 => 'Music|Pop|Maghreb Pop', |
5663
|
|
|
|
|
|
|
100092 => 'Music|Pop|Khaleeji Pop', |
5664
|
|
|
|
|
|
|
100093 => 'Music|Hip-Hop/Rap|Levant Hip-Hop', |
5665
|
|
|
|
|
|
|
100094 => 'Music|Hip-Hop/Rap|Egyptian Hip-Hop', |
5666
|
|
|
|
|
|
|
100095 => 'Music|Hip-Hop/Rap|Maghreb Hip-Hop', |
5667
|
|
|
|
|
|
|
100096 => 'Music|Hip-Hop/Rap|Khaleeji Hip-Hop', |
5668
|
|
|
|
|
|
|
100097 => 'Music|Alternative|Indie Levant', |
5669
|
|
|
|
|
|
|
100098 => 'Music|Alternative|Indie Egyptian', |
5670
|
|
|
|
|
|
|
100099 => 'Music|Alternative|Indie Maghreb', |
5671
|
|
|
|
|
|
|
100100 => 'Music|Electronic|Levant Electronic', |
5672
|
|
|
|
|
|
|
100101 => "Music|Electronic|Electro-Cha'abi", |
5673
|
|
|
|
|
|
|
100102 => 'Music|Electronic|Maghreb Electronic', |
5674
|
|
|
|
|
|
|
100103 => 'Music|Folk|Iraqi Folk', |
5675
|
|
|
|
|
|
|
100104 => 'Music|Folk|Khaleeji Folk', |
5676
|
|
|
|
|
|
|
100105 => 'Music|Dance|Maghreb Dance', |
5677
|
|
|
|
|
|
|
40000000 => 'iTunes U', |
5678
|
|
|
|
|
|
|
40000001 => 'iTunes U|Business & Economics', |
5679
|
|
|
|
|
|
|
40000002 => 'iTunes U|Business & Economics|Economics', |
5680
|
|
|
|
|
|
|
40000003 => 'iTunes U|Business & Economics|Finance', |
5681
|
|
|
|
|
|
|
40000004 => 'iTunes U|Business & Economics|Hospitality', |
5682
|
|
|
|
|
|
|
40000005 => 'iTunes U|Business & Economics|Management', |
5683
|
|
|
|
|
|
|
40000006 => 'iTunes U|Business & Economics|Marketing', |
5684
|
|
|
|
|
|
|
40000007 => 'iTunes U|Business & Economics|Personal Finance', |
5685
|
|
|
|
|
|
|
40000008 => 'iTunes U|Business & Economics|Real Estate', |
5686
|
|
|
|
|
|
|
40000009 => 'iTunes U|Engineering', |
5687
|
|
|
|
|
|
|
40000010 => 'iTunes U|Engineering|Chemical & Petroleum Engineering', |
5688
|
|
|
|
|
|
|
40000011 => 'iTunes U|Engineering|Civil Engineering', |
5689
|
|
|
|
|
|
|
40000012 => 'iTunes U|Engineering|Computer Science', |
5690
|
|
|
|
|
|
|
40000013 => 'iTunes U|Engineering|Electrical Engineering', |
5691
|
|
|
|
|
|
|
40000014 => 'iTunes U|Engineering|Environmental Engineering', |
5692
|
|
|
|
|
|
|
40000015 => 'iTunes U|Engineering|Mechanical Engineering', |
5693
|
|
|
|
|
|
|
40000016 => 'iTunes U|Music, Art, & Design', |
5694
|
|
|
|
|
|
|
40000017 => 'iTunes U|Music, Art, & Design|Architecture', |
5695
|
|
|
|
|
|
|
40000019 => 'iTunes U|Music, Art, & Design|Art History', |
5696
|
|
|
|
|
|
|
40000020 => 'iTunes U|Music, Art, & Design|Dance', |
5697
|
|
|
|
|
|
|
40000021 => 'iTunes U|Music, Art, & Design|Film', |
5698
|
|
|
|
|
|
|
40000022 => 'iTunes U|Music, Art, & Design|Design', |
5699
|
|
|
|
|
|
|
40000023 => 'iTunes U|Music, Art, & Design|Interior Design', |
5700
|
|
|
|
|
|
|
40000024 => 'iTunes U|Music, Art, & Design|Music', |
5701
|
|
|
|
|
|
|
40000025 => 'iTunes U|Music, Art, & Design|Theater', |
5702
|
|
|
|
|
|
|
40000026 => 'iTunes U|Health & Medicine', |
5703
|
|
|
|
|
|
|
40000027 => 'iTunes U|Health & Medicine|Anatomy & Physiology', |
5704
|
|
|
|
|
|
|
40000028 => 'iTunes U|Health & Medicine|Behavioral Science', |
5705
|
|
|
|
|
|
|
40000029 => 'iTunes U|Health & Medicine|Dentistry', |
5706
|
|
|
|
|
|
|
40000030 => 'iTunes U|Health & Medicine|Diet & Nutrition', |
5707
|
|
|
|
|
|
|
40000031 => 'iTunes U|Health & Medicine|Emergency Medicine', |
5708
|
|
|
|
|
|
|
40000032 => 'iTunes U|Health & Medicine|Genetics', |
5709
|
|
|
|
|
|
|
40000033 => 'iTunes U|Health & Medicine|Gerontology', |
5710
|
|
|
|
|
|
|
40000034 => 'iTunes U|Health & Medicine|Health & Exercise Science', |
5711
|
|
|
|
|
|
|
40000035 => 'iTunes U|Health & Medicine|Immunology', |
5712
|
|
|
|
|
|
|
40000036 => 'iTunes U|Health & Medicine|Neuroscience', |
5713
|
|
|
|
|
|
|
40000037 => 'iTunes U|Health & Medicine|Pharmacology & Toxicology', |
5714
|
|
|
|
|
|
|
40000038 => 'iTunes U|Health & Medicine|Psychiatry', |
5715
|
|
|
|
|
|
|
40000039 => 'iTunes U|Health & Medicine|Global Health', |
5716
|
|
|
|
|
|
|
40000040 => 'iTunes U|Health & Medicine|Radiology', |
5717
|
|
|
|
|
|
|
40000041 => 'iTunes U|History', |
5718
|
|
|
|
|
|
|
40000042 => 'iTunes U|History|Ancient History', |
5719
|
|
|
|
|
|
|
40000043 => 'iTunes U|History|Medieval History', |
5720
|
|
|
|
|
|
|
40000044 => 'iTunes U|History|Military History', |
5721
|
|
|
|
|
|
|
40000045 => 'iTunes U|History|Modern History', |
5722
|
|
|
|
|
|
|
40000046 => 'iTunes U|History|African History', |
5723
|
|
|
|
|
|
|
40000047 => 'iTunes U|History|Asia-Pacific History', |
5724
|
|
|
|
|
|
|
40000048 => 'iTunes U|History|European History', |
5725
|
|
|
|
|
|
|
40000049 => 'iTunes U|History|Middle Eastern History', |
5726
|
|
|
|
|
|
|
40000050 => 'iTunes U|History|North American History', |
5727
|
|
|
|
|
|
|
40000051 => 'iTunes U|History|South American History', |
5728
|
|
|
|
|
|
|
40000053 => 'iTunes U|Communications & Journalism', |
5729
|
|
|
|
|
|
|
40000054 => 'iTunes U|Philosophy', |
5730
|
|
|
|
|
|
|
40000055 => 'iTunes U|Religion & Spirituality', |
5731
|
|
|
|
|
|
|
40000056 => 'iTunes U|Languages', |
5732
|
|
|
|
|
|
|
40000057 => 'iTunes U|Languages|African Languages', |
5733
|
|
|
|
|
|
|
40000058 => 'iTunes U|Languages|Ancient Languages', |
5734
|
|
|
|
|
|
|
40000061 => 'iTunes U|Languages|English', |
5735
|
|
|
|
|
|
|
40000063 => 'iTunes U|Languages|French', |
5736
|
|
|
|
|
|
|
40000064 => 'iTunes U|Languages|German', |
5737
|
|
|
|
|
|
|
40000065 => 'iTunes U|Languages|Italian', |
5738
|
|
|
|
|
|
|
40000066 => 'iTunes U|Languages|Linguistics', |
5739
|
|
|
|
|
|
|
40000068 => 'iTunes U|Languages|Spanish', |
5740
|
|
|
|
|
|
|
40000069 => 'iTunes U|Languages|Speech Pathology', |
5741
|
|
|
|
|
|
|
40000070 => 'iTunes U|Writing & Literature', |
5742
|
|
|
|
|
|
|
40000071 => 'iTunes U|Writing & Literature|Anthologies', |
5743
|
|
|
|
|
|
|
40000072 => 'iTunes U|Writing & Literature|Biography', |
5744
|
|
|
|
|
|
|
40000073 => 'iTunes U|Writing & Literature|Classics', |
5745
|
|
|
|
|
|
|
40000074 => 'iTunes U|Writing & Literature|Literary Criticism', |
5746
|
|
|
|
|
|
|
40000075 => 'iTunes U|Writing & Literature|Fiction', |
5747
|
|
|
|
|
|
|
40000076 => 'iTunes U|Writing & Literature|Poetry', |
5748
|
|
|
|
|
|
|
40000077 => 'iTunes U|Mathematics', |
5749
|
|
|
|
|
|
|
40000078 => 'iTunes U|Mathematics|Advanced Mathematics', |
5750
|
|
|
|
|
|
|
40000079 => 'iTunes U|Mathematics|Algebra', |
5751
|
|
|
|
|
|
|
40000080 => 'iTunes U|Mathematics|Arithmetic', |
5752
|
|
|
|
|
|
|
40000081 => 'iTunes U|Mathematics|Calculus', |
5753
|
|
|
|
|
|
|
40000082 => 'iTunes U|Mathematics|Geometry', |
5754
|
|
|
|
|
|
|
40000083 => 'iTunes U|Mathematics|Statistics', |
5755
|
|
|
|
|
|
|
40000084 => 'iTunes U|Science', |
5756
|
|
|
|
|
|
|
40000085 => 'iTunes U|Science|Agricultural', |
5757
|
|
|
|
|
|
|
40000086 => 'iTunes U|Science|Astronomy', |
5758
|
|
|
|
|
|
|
40000087 => 'iTunes U|Science|Atmosphere', |
5759
|
|
|
|
|
|
|
40000088 => 'iTunes U|Science|Biology', |
5760
|
|
|
|
|
|
|
40000089 => 'iTunes U|Science|Chemistry', |
5761
|
|
|
|
|
|
|
40000090 => 'iTunes U|Science|Ecology', |
5762
|
|
|
|
|
|
|
40000091 => 'iTunes U|Science|Geography', |
5763
|
|
|
|
|
|
|
40000092 => 'iTunes U|Science|Geology', |
5764
|
|
|
|
|
|
|
40000093 => 'iTunes U|Science|Physics', |
5765
|
|
|
|
|
|
|
40000094 => 'iTunes U|Social Science', |
5766
|
|
|
|
|
|
|
40000095 => 'iTunes U|Law & Politics|Law', |
5767
|
|
|
|
|
|
|
40000096 => 'iTunes U|Law & Politics|Political Science', |
5768
|
|
|
|
|
|
|
40000097 => 'iTunes U|Law & Politics|Public Administration', |
5769
|
|
|
|
|
|
|
40000098 => 'iTunes U|Social Science|Psychology', |
5770
|
|
|
|
|
|
|
40000099 => 'iTunes U|Social Science|Social Welfare', |
5771
|
|
|
|
|
|
|
40000100 => 'iTunes U|Social Science|Sociology', |
5772
|
|
|
|
|
|
|
40000101 => 'iTunes U|Society', |
5773
|
|
|
|
|
|
|
40000103 => 'iTunes U|Society|Asia Pacific Studies', |
5774
|
|
|
|
|
|
|
40000104 => 'iTunes U|Society|European Studies', |
5775
|
|
|
|
|
|
|
40000105 => 'iTunes U|Society|Indigenous Studies', |
5776
|
|
|
|
|
|
|
40000106 => 'iTunes U|Society|Latin & Caribbean Studies', |
5777
|
|
|
|
|
|
|
40000107 => 'iTunes U|Society|Middle Eastern Studies', |
5778
|
|
|
|
|
|
|
40000108 => "iTunes U|Society|Women's Studies", |
5779
|
|
|
|
|
|
|
40000109 => 'iTunes U|Teaching & Learning', |
5780
|
|
|
|
|
|
|
40000110 => 'iTunes U|Teaching & Learning|Curriculum & Teaching', |
5781
|
|
|
|
|
|
|
40000111 => 'iTunes U|Teaching & Learning|Educational Leadership', |
5782
|
|
|
|
|
|
|
40000112 => 'iTunes U|Teaching & Learning|Family & Childcare', |
5783
|
|
|
|
|
|
|
40000113 => 'iTunes U|Teaching & Learning|Learning Resources', |
5784
|
|
|
|
|
|
|
40000114 => 'iTunes U|Teaching & Learning|Psychology & Research', |
5785
|
|
|
|
|
|
|
40000115 => 'iTunes U|Teaching & Learning|Special Education', |
5786
|
|
|
|
|
|
|
40000116 => 'iTunes U|Music, Art, & Design|Culinary Arts', |
5787
|
|
|
|
|
|
|
40000117 => 'iTunes U|Music, Art, & Design|Fashion', |
5788
|
|
|
|
|
|
|
40000118 => 'iTunes U|Music, Art, & Design|Media Arts', |
5789
|
|
|
|
|
|
|
40000119 => 'iTunes U|Music, Art, & Design|Photography', |
5790
|
|
|
|
|
|
|
40000120 => 'iTunes U|Music, Art, & Design|Visual Art', |
5791
|
|
|
|
|
|
|
40000121 => 'iTunes U|Business & Economics|Entrepreneurship', |
5792
|
|
|
|
|
|
|
40000122 => 'iTunes U|Communications & Journalism|Broadcasting', |
5793
|
|
|
|
|
|
|
40000123 => 'iTunes U|Communications & Journalism|Digital Media', |
5794
|
|
|
|
|
|
|
40000124 => 'iTunes U|Communications & Journalism|Journalism', |
5795
|
|
|
|
|
|
|
40000125 => 'iTunes U|Communications & Journalism|Photojournalism', |
5796
|
|
|
|
|
|
|
40000126 => 'iTunes U|Communications & Journalism|Print', |
5797
|
|
|
|
|
|
|
40000127 => 'iTunes U|Communications & Journalism|Speech', |
5798
|
|
|
|
|
|
|
40000128 => 'iTunes U|Communications & Journalism|Writing', |
5799
|
|
|
|
|
|
|
40000129 => 'iTunes U|Health & Medicine|Nursing', |
5800
|
|
|
|
|
|
|
40000130 => 'iTunes U|Languages|Arabic', |
5801
|
|
|
|
|
|
|
40000131 => 'iTunes U|Languages|Chinese', |
5802
|
|
|
|
|
|
|
40000132 => 'iTunes U|Languages|Hebrew', |
5803
|
|
|
|
|
|
|
40000133 => 'iTunes U|Languages|Hindi', |
5804
|
|
|
|
|
|
|
40000134 => 'iTunes U|Languages|Indigenous Languages', |
5805
|
|
|
|
|
|
|
40000135 => 'iTunes U|Languages|Japanese', |
5806
|
|
|
|
|
|
|
40000136 => 'iTunes U|Languages|Korean', |
5807
|
|
|
|
|
|
|
40000137 => 'iTunes U|Languages|Other Languages', |
5808
|
|
|
|
|
|
|
40000138 => 'iTunes U|Languages|Portuguese', |
5809
|
|
|
|
|
|
|
40000139 => 'iTunes U|Languages|Russian', |
5810
|
|
|
|
|
|
|
40000140 => 'iTunes U|Law & Politics', |
5811
|
|
|
|
|
|
|
40000141 => 'iTunes U|Law & Politics|Foreign Policy & International Relations', |
5812
|
|
|
|
|
|
|
40000142 => 'iTunes U|Law & Politics|Local Governments', |
5813
|
|
|
|
|
|
|
40000143 => 'iTunes U|Law & Politics|National Governments', |
5814
|
|
|
|
|
|
|
40000144 => 'iTunes U|Law & Politics|World Affairs', |
5815
|
|
|
|
|
|
|
40000145 => 'iTunes U|Writing & Literature|Comparative Literature', |
5816
|
|
|
|
|
|
|
40000146 => 'iTunes U|Philosophy|Aesthetics', |
5817
|
|
|
|
|
|
|
40000147 => 'iTunes U|Philosophy|Epistemology', |
5818
|
|
|
|
|
|
|
40000148 => 'iTunes U|Philosophy|Ethics', |
5819
|
|
|
|
|
|
|
40000149 => 'iTunes U|Philosophy|Metaphysics', |
5820
|
|
|
|
|
|
|
40000150 => 'iTunes U|Philosophy|Political Philosophy', |
5821
|
|
|
|
|
|
|
40000151 => 'iTunes U|Philosophy|Logic', |
5822
|
|
|
|
|
|
|
40000152 => 'iTunes U|Philosophy|Philosophy of Language', |
5823
|
|
|
|
|
|
|
40000153 => 'iTunes U|Philosophy|Philosophy of Religion', |
5824
|
|
|
|
|
|
|
40000154 => 'iTunes U|Social Science|Archaeology', |
5825
|
|
|
|
|
|
|
40000155 => 'iTunes U|Social Science|Anthropology', |
5826
|
|
|
|
|
|
|
40000156 => 'iTunes U|Religion & Spirituality|Buddhism', |
5827
|
|
|
|
|
|
|
40000157 => 'iTunes U|Religion & Spirituality|Christianity', |
5828
|
|
|
|
|
|
|
40000158 => 'iTunes U|Religion & Spirituality|Comparative Religion', |
5829
|
|
|
|
|
|
|
40000159 => 'iTunes U|Religion & Spirituality|Hinduism', |
5830
|
|
|
|
|
|
|
40000160 => 'iTunes U|Religion & Spirituality|Islam', |
5831
|
|
|
|
|
|
|
40000161 => 'iTunes U|Religion & Spirituality|Judaism', |
5832
|
|
|
|
|
|
|
40000162 => 'iTunes U|Religion & Spirituality|Other Religions', |
5833
|
|
|
|
|
|
|
40000163 => 'iTunes U|Religion & Spirituality|Spirituality', |
5834
|
|
|
|
|
|
|
40000164 => 'iTunes U|Science|Environment', |
5835
|
|
|
|
|
|
|
40000165 => 'iTunes U|Society|African Studies', |
5836
|
|
|
|
|
|
|
40000166 => 'iTunes U|Society|American Studies', |
5837
|
|
|
|
|
|
|
40000167 => 'iTunes U|Society|Cross-cultural Studies', |
5838
|
|
|
|
|
|
|
40000168 => 'iTunes U|Society|Immigration & Emigration', |
5839
|
|
|
|
|
|
|
40000169 => 'iTunes U|Society|Race & Ethnicity Studies', |
5840
|
|
|
|
|
|
|
40000170 => 'iTunes U|Society|Sexuality Studies', |
5841
|
|
|
|
|
|
|
40000171 => 'iTunes U|Teaching & Learning|Educational Technology', |
5842
|
|
|
|
|
|
|
40000172 => 'iTunes U|Teaching & Learning|Information/Library Science', |
5843
|
|
|
|
|
|
|
40000173 => 'iTunes U|Languages|Dutch', |
5844
|
|
|
|
|
|
|
40000174 => 'iTunes U|Languages|Luxembourgish', |
5845
|
|
|
|
|
|
|
40000175 => 'iTunes U|Languages|Swedish', |
5846
|
|
|
|
|
|
|
40000176 => 'iTunes U|Languages|Norwegian', |
5847
|
|
|
|
|
|
|
40000177 => 'iTunes U|Languages|Finnish', |
5848
|
|
|
|
|
|
|
40000178 => 'iTunes U|Languages|Danish', |
5849
|
|
|
|
|
|
|
40000179 => 'iTunes U|Languages|Polish', |
5850
|
|
|
|
|
|
|
40000180 => 'iTunes U|Languages|Turkish', |
5851
|
|
|
|
|
|
|
40000181 => 'iTunes U|Languages|Flemish', |
5852
|
|
|
|
|
|
|
50000024 => 'Audiobooks', |
5853
|
|
|
|
|
|
|
50000040 => 'Audiobooks|Fiction', |
5854
|
|
|
|
|
|
|
50000041 => 'Audiobooks|Arts & Entertainment', |
5855
|
|
|
|
|
|
|
50000042 => 'Audiobooks|Biographies & Memoirs', |
5856
|
|
|
|
|
|
|
50000043 => 'Audiobooks|Business & Personal Finance', |
5857
|
|
|
|
|
|
|
50000044 => 'Audiobooks|Kids & Young Adults', |
5858
|
|
|
|
|
|
|
50000045 => 'Audiobooks|Classics', |
5859
|
|
|
|
|
|
|
50000046 => 'Audiobooks|Comedy', |
5860
|
|
|
|
|
|
|
50000047 => 'Audiobooks|Drama & Poetry', |
5861
|
|
|
|
|
|
|
50000048 => 'Audiobooks|Speakers & Storytellers', |
5862
|
|
|
|
|
|
|
50000049 => 'Audiobooks|History', |
5863
|
|
|
|
|
|
|
50000050 => 'Audiobooks|Languages', |
5864
|
|
|
|
|
|
|
50000051 => 'Audiobooks|Mysteries & Thrillers', |
5865
|
|
|
|
|
|
|
50000052 => 'Audiobooks|Nonfiction', |
5866
|
|
|
|
|
|
|
50000053 => 'Audiobooks|Religion & Spirituality', |
5867
|
|
|
|
|
|
|
50000054 => 'Audiobooks|Science & Nature', |
5868
|
|
|
|
|
|
|
50000055 => 'Audiobooks|Sci Fi & Fantasy', |
5869
|
|
|
|
|
|
|
50000056 => 'Audiobooks|Self-Development', |
5870
|
|
|
|
|
|
|
50000057 => 'Audiobooks|Sports & Outdoors', |
5871
|
|
|
|
|
|
|
50000058 => 'Audiobooks|Technology', |
5872
|
|
|
|
|
|
|
50000059 => 'Audiobooks|Travel & Adventure', |
5873
|
|
|
|
|
|
|
50000061 => 'Music|Spoken Word', |
5874
|
|
|
|
|
|
|
50000063 => 'Music|Disney', |
5875
|
|
|
|
|
|
|
50000064 => 'Music|French Pop', |
5876
|
|
|
|
|
|
|
50000066 => 'Music|German Pop', |
5877
|
|
|
|
|
|
|
50000068 => 'Music|German Folk', |
5878
|
|
|
|
|
|
|
50000069 => 'Audiobooks|Romance', |
5879
|
|
|
|
|
|
|
50000070 => 'Audiobooks|Audiobooks Latino', |
5880
|
|
|
|
|
|
|
50000071 => 'Books|Comics & Graphic Novels|Manga|Action', |
5881
|
|
|
|
|
|
|
50000072 => 'Books|Comics & Graphic Novels|Manga|Comedy', |
5882
|
|
|
|
|
|
|
50000073 => 'Books|Comics & Graphic Novels|Manga|Erotica', |
5883
|
|
|
|
|
|
|
50000074 => 'Books|Comics & Graphic Novels|Manga|Fantasy', |
5884
|
|
|
|
|
|
|
50000075 => 'Books|Comics & Graphic Novels|Manga|Four Cell Manga', |
5885
|
|
|
|
|
|
|
50000076 => 'Books|Comics & Graphic Novels|Manga|Gay & Lesbian', |
5886
|
|
|
|
|
|
|
50000077 => 'Books|Comics & Graphic Novels|Manga|Hard-Boiled', |
5887
|
|
|
|
|
|
|
50000078 => 'Books|Comics & Graphic Novels|Manga|Heroes', |
5888
|
|
|
|
|
|
|
50000079 => 'Books|Comics & Graphic Novels|Manga|Historical Fiction', |
5889
|
|
|
|
|
|
|
50000080 => 'Books|Comics & Graphic Novels|Manga|Mecha', |
5890
|
|
|
|
|
|
|
50000081 => 'Books|Comics & Graphic Novels|Manga|Mystery', |
5891
|
|
|
|
|
|
|
50000082 => 'Books|Comics & Graphic Novels|Manga|Nonfiction', |
5892
|
|
|
|
|
|
|
50000083 => 'Books|Comics & Graphic Novels|Manga|Religious', |
5893
|
|
|
|
|
|
|
50000084 => 'Books|Comics & Graphic Novels|Manga|Romance', |
5894
|
|
|
|
|
|
|
50000085 => 'Books|Comics & Graphic Novels|Manga|Romantic Comedy', |
5895
|
|
|
|
|
|
|
50000086 => 'Books|Comics & Graphic Novels|Manga|Science Fiction', |
5896
|
|
|
|
|
|
|
50000087 => 'Books|Comics & Graphic Novels|Manga|Sports', |
5897
|
|
|
|
|
|
|
50000088 => 'Books|Fiction & Literature|Light Novels', |
5898
|
|
|
|
|
|
|
50000089 => 'Books|Comics & Graphic Novels|Manga|Horror', |
5899
|
|
|
|
|
|
|
50000090 => 'Books|Comics & Graphic Novels|Comics', |
5900
|
|
|
|
|
|
|
50000091 => 'Books|Romance|Multicultural', |
5901
|
|
|
|
|
|
|
50000092 => 'Audiobooks|Erotica', |
5902
|
|
|
|
|
|
|
50000093 => 'Audiobooks|Light Novels', |
5903
|
|
|
|
|
|
|
}, |
5904
|
|
|
|
|
|
|
}, |
5905
|
|
|
|
|
|
|
grup => { Name => 'Grouping', Avoid => 1 }, #10 |
5906
|
|
|
|
|
|
|
hdvd => { #10 |
5907
|
|
|
|
|
|
|
Name => 'HDVideo', |
5908
|
|
|
|
|
|
|
Format => 'int8u', #24 |
5909
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
5910
|
|
|
|
|
|
|
PrintConv => { 0 => 'No', 1 => 'Yes' }, |
5911
|
|
|
|
|
|
|
}, |
5912
|
|
|
|
|
|
|
keyw => 'Keyword', #7 |
5913
|
|
|
|
|
|
|
ldes => 'LongDescription', #10 |
5914
|
|
|
|
|
|
|
pcst => { #7 |
5915
|
|
|
|
|
|
|
Name => 'Podcast', |
5916
|
|
|
|
|
|
|
Format => 'int8u', #23 |
5917
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
5918
|
|
|
|
|
|
|
PrintConv => { 0 => 'No', 1 => 'Yes' }, |
5919
|
|
|
|
|
|
|
}, |
5920
|
|
|
|
|
|
|
perf => 'Performer', |
5921
|
|
|
|
|
|
|
plID => { #10 (or TV season) |
5922
|
|
|
|
|
|
|
Name => 'PlayListID', |
5923
|
|
|
|
|
|
|
Format => 'int8u', # actually int64u, but split it up |
5924
|
|
|
|
|
|
|
Writable => 'int32s', #27 |
5925
|
|
|
|
|
|
|
}, |
5926
|
|
|
|
|
|
|
purd => 'PurchaseDate', #7 |
5927
|
|
|
|
|
|
|
purl => 'PodcastURL', #7 |
5928
|
|
|
|
|
|
|
rtng => { #10 |
5929
|
|
|
|
|
|
|
Name => 'Rating', |
5930
|
|
|
|
|
|
|
Format => 'int8u', #23 |
5931
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
5932
|
|
|
|
|
|
|
PrintConv => { |
5933
|
|
|
|
|
|
|
0 => 'none', |
5934
|
|
|
|
|
|
|
1 => 'Explicit', |
5935
|
|
|
|
|
|
|
2 => 'Clean', |
5936
|
|
|
|
|
|
|
4 => 'Explicit (old)', |
5937
|
|
|
|
|
|
|
}, |
5938
|
|
|
|
|
|
|
}, |
5939
|
|
|
|
|
|
|
sfID => { #10 |
5940
|
|
|
|
|
|
|
Name => 'AppleStoreCountry', |
5941
|
|
|
|
|
|
|
Format => 'int32u', |
5942
|
|
|
|
|
|
|
Writable => 'int32s', #27 |
5943
|
|
|
|
|
|
|
SeparateTable => 1, |
5944
|
|
|
|
|
|
|
PrintConv => { #21 |
5945
|
|
|
|
|
|
|
143441 => 'United States', # US |
5946
|
|
|
|
|
|
|
143442 => 'France', # FR |
5947
|
|
|
|
|
|
|
143443 => 'Germany', # DE |
5948
|
|
|
|
|
|
|
143444 => 'United Kingdom', # GB |
5949
|
|
|
|
|
|
|
143445 => 'Austria', # AT |
5950
|
|
|
|
|
|
|
143446 => 'Belgium', # BE |
5951
|
|
|
|
|
|
|
143447 => 'Finland', # FI |
5952
|
|
|
|
|
|
|
143448 => 'Greece', # GR |
5953
|
|
|
|
|
|
|
143449 => 'Ireland', # IE |
5954
|
|
|
|
|
|
|
143450 => 'Italy', # IT |
5955
|
|
|
|
|
|
|
143451 => 'Luxembourg', # LU |
5956
|
|
|
|
|
|
|
143452 => 'Netherlands', # NL |
5957
|
|
|
|
|
|
|
143453 => 'Portugal', # PT |
5958
|
|
|
|
|
|
|
143454 => 'Spain', # ES |
5959
|
|
|
|
|
|
|
143455 => 'Canada', # CA |
5960
|
|
|
|
|
|
|
143456 => 'Sweden', # SE |
5961
|
|
|
|
|
|
|
143457 => 'Norway', # NO |
5962
|
|
|
|
|
|
|
143458 => 'Denmark', # DK |
5963
|
|
|
|
|
|
|
143459 => 'Switzerland', # CH |
5964
|
|
|
|
|
|
|
143460 => 'Australia', # AU |
5965
|
|
|
|
|
|
|
143461 => 'New Zealand', # NZ |
5966
|
|
|
|
|
|
|
143462 => 'Japan', # JP |
5967
|
|
|
|
|
|
|
143463 => 'Hong Kong', # HK |
5968
|
|
|
|
|
|
|
143464 => 'Singapore', # SG |
5969
|
|
|
|
|
|
|
143465 => 'China', # CN |
5970
|
|
|
|
|
|
|
143466 => 'Republic of Korea', # KR |
5971
|
|
|
|
|
|
|
143467 => 'India', # IN |
5972
|
|
|
|
|
|
|
143468 => 'Mexico', # MX |
5973
|
|
|
|
|
|
|
143469 => 'Russia', # RU |
5974
|
|
|
|
|
|
|
143470 => 'Taiwan', # TW |
5975
|
|
|
|
|
|
|
143471 => 'Vietnam', # VN |
5976
|
|
|
|
|
|
|
143472 => 'South Africa', # ZA |
5977
|
|
|
|
|
|
|
143473 => 'Malaysia', # MY |
5978
|
|
|
|
|
|
|
143474 => 'Philippines', # PH |
5979
|
|
|
|
|
|
|
143475 => 'Thailand', # TH |
5980
|
|
|
|
|
|
|
143476 => 'Indonesia', # ID |
5981
|
|
|
|
|
|
|
143477 => 'Pakistan', # PK |
5982
|
|
|
|
|
|
|
143478 => 'Poland', # PL |
5983
|
|
|
|
|
|
|
143479 => 'Saudi Arabia', # SA |
5984
|
|
|
|
|
|
|
143480 => 'Turkey', # TR |
5985
|
|
|
|
|
|
|
143481 => 'United Arab Emirates', # AE |
5986
|
|
|
|
|
|
|
143482 => 'Hungary', # HU |
5987
|
|
|
|
|
|
|
143483 => 'Chile', # CL |
5988
|
|
|
|
|
|
|
143484 => 'Nepal', # NP |
5989
|
|
|
|
|
|
|
143485 => 'Panama', # PA |
5990
|
|
|
|
|
|
|
143486 => 'Sri Lanka', # LK |
5991
|
|
|
|
|
|
|
143487 => 'Romania', # RO |
5992
|
|
|
|
|
|
|
143489 => 'Czech Republic', # CZ |
5993
|
|
|
|
|
|
|
143491 => 'Israel', # IL |
5994
|
|
|
|
|
|
|
143492 => 'Ukraine', # UA |
5995
|
|
|
|
|
|
|
143493 => 'Kuwait', # KW |
5996
|
|
|
|
|
|
|
143494 => 'Croatia', # HR |
5997
|
|
|
|
|
|
|
143495 => 'Costa Rica', # CR |
5998
|
|
|
|
|
|
|
143496 => 'Slovakia', # SK |
5999
|
|
|
|
|
|
|
143497 => 'Lebanon', # LB |
6000
|
|
|
|
|
|
|
143498 => 'Qatar', # QA |
6001
|
|
|
|
|
|
|
143499 => 'Slovenia', # SI |
6002
|
|
|
|
|
|
|
143501 => 'Colombia', # CO |
6003
|
|
|
|
|
|
|
143502 => 'Venezuela', # VE |
6004
|
|
|
|
|
|
|
143503 => 'Brazil', # BR |
6005
|
|
|
|
|
|
|
143504 => 'Guatemala', # GT |
6006
|
|
|
|
|
|
|
143505 => 'Argentina', # AR |
6007
|
|
|
|
|
|
|
143506 => 'El Salvador', # SV |
6008
|
|
|
|
|
|
|
143507 => 'Peru', # PE |
6009
|
|
|
|
|
|
|
143508 => 'Dominican Republic', # DO |
6010
|
|
|
|
|
|
|
143509 => 'Ecuador', # EC |
6011
|
|
|
|
|
|
|
143510 => 'Honduras', # HN |
6012
|
|
|
|
|
|
|
143511 => 'Jamaica', # JM |
6013
|
|
|
|
|
|
|
143512 => 'Nicaragua', # NI |
6014
|
|
|
|
|
|
|
143513 => 'Paraguay', # PY |
6015
|
|
|
|
|
|
|
143514 => 'Uruguay', # UY |
6016
|
|
|
|
|
|
|
143515 => 'Macau', # MO |
6017
|
|
|
|
|
|
|
143516 => 'Egypt', # EG |
6018
|
|
|
|
|
|
|
143517 => 'Kazakhstan', # KZ |
6019
|
|
|
|
|
|
|
143518 => 'Estonia', # EE |
6020
|
|
|
|
|
|
|
143519 => 'Latvia', # LV |
6021
|
|
|
|
|
|
|
143520 => 'Lithuania', # LT |
6022
|
|
|
|
|
|
|
143521 => 'Malta', # MT |
6023
|
|
|
|
|
|
|
143523 => 'Moldova', # MD |
6024
|
|
|
|
|
|
|
143524 => 'Armenia', # AM |
6025
|
|
|
|
|
|
|
143525 => 'Botswana', # BW |
6026
|
|
|
|
|
|
|
143526 => 'Bulgaria', # BG |
6027
|
|
|
|
|
|
|
143528 => 'Jordan', # JO |
6028
|
|
|
|
|
|
|
143529 => 'Kenya', # KE |
6029
|
|
|
|
|
|
|
143530 => 'Macedonia', # MK |
6030
|
|
|
|
|
|
|
143531 => 'Madagascar', # MG |
6031
|
|
|
|
|
|
|
143532 => 'Mali', # ML |
6032
|
|
|
|
|
|
|
143533 => 'Mauritius', # MU |
6033
|
|
|
|
|
|
|
143534 => 'Niger', # NE |
6034
|
|
|
|
|
|
|
143535 => 'Senegal', # SN |
6035
|
|
|
|
|
|
|
143536 => 'Tunisia', # TN |
6036
|
|
|
|
|
|
|
143537 => 'Uganda', # UG |
6037
|
|
|
|
|
|
|
143538 => 'Anguilla', # AI |
6038
|
|
|
|
|
|
|
143539 => 'Bahamas', # BS |
6039
|
|
|
|
|
|
|
143540 => 'Antigua and Barbuda', # AG |
6040
|
|
|
|
|
|
|
143541 => 'Barbados', # BB |
6041
|
|
|
|
|
|
|
143542 => 'Bermuda', # BM |
6042
|
|
|
|
|
|
|
143543 => 'British Virgin Islands', # VG |
6043
|
|
|
|
|
|
|
143544 => 'Cayman Islands', # KY |
6044
|
|
|
|
|
|
|
143545 => 'Dominica', # DM |
6045
|
|
|
|
|
|
|
143546 => 'Grenada', # GD |
6046
|
|
|
|
|
|
|
143547 => 'Montserrat', # MS |
6047
|
|
|
|
|
|
|
143548 => 'St. Kitts and Nevis', # KN |
6048
|
|
|
|
|
|
|
143549 => 'St. Lucia', # LC |
6049
|
|
|
|
|
|
|
143550 => 'St. Vincent and The Grenadines', # VC |
6050
|
|
|
|
|
|
|
143551 => 'Trinidad and Tobago', # TT |
6051
|
|
|
|
|
|
|
143552 => 'Turks and Caicos', # TC |
6052
|
|
|
|
|
|
|
143553 => 'Guyana', # GY |
6053
|
|
|
|
|
|
|
143554 => 'Suriname', # SR |
6054
|
|
|
|
|
|
|
143555 => 'Belize', # BZ |
6055
|
|
|
|
|
|
|
143556 => 'Bolivia', # BO |
6056
|
|
|
|
|
|
|
143557 => 'Cyprus', # CY |
6057
|
|
|
|
|
|
|
143558 => 'Iceland', # IS |
6058
|
|
|
|
|
|
|
143559 => 'Bahrain', # BH |
6059
|
|
|
|
|
|
|
143560 => 'Brunei Darussalam', # BN |
6060
|
|
|
|
|
|
|
143561 => 'Nigeria', # NG |
6061
|
|
|
|
|
|
|
143562 => 'Oman', # OM |
6062
|
|
|
|
|
|
|
143563 => 'Algeria', # DZ |
6063
|
|
|
|
|
|
|
143564 => 'Angola', # AO |
6064
|
|
|
|
|
|
|
143565 => 'Belarus', # BY |
6065
|
|
|
|
|
|
|
143566 => 'Uzbekistan', # UZ |
6066
|
|
|
|
|
|
|
143568 => 'Azerbaijan', # AZ |
6067
|
|
|
|
|
|
|
143571 => 'Yemen', # YE |
6068
|
|
|
|
|
|
|
143572 => 'Tanzania', # TZ |
6069
|
|
|
|
|
|
|
143573 => 'Ghana', # GH |
6070
|
|
|
|
|
|
|
143575 => 'Albania', # AL |
6071
|
|
|
|
|
|
|
143576 => 'Benin', # BJ |
6072
|
|
|
|
|
|
|
143577 => 'Bhutan', # BT |
6073
|
|
|
|
|
|
|
143578 => 'Burkina Faso', # BF |
6074
|
|
|
|
|
|
|
143579 => 'Cambodia', # KH |
6075
|
|
|
|
|
|
|
143580 => 'Cape Verde', # CV |
6076
|
|
|
|
|
|
|
143581 => 'Chad', # TD |
6077
|
|
|
|
|
|
|
143582 => 'Republic of the Congo', # CG |
6078
|
|
|
|
|
|
|
143583 => 'Fiji', # FJ |
6079
|
|
|
|
|
|
|
143584 => 'Gambia', # GM |
6080
|
|
|
|
|
|
|
143585 => 'Guinea-Bissau', # GW |
6081
|
|
|
|
|
|
|
143586 => 'Kyrgyzstan', # KG |
6082
|
|
|
|
|
|
|
143587 => "Lao People's Democratic Republic", # LA |
6083
|
|
|
|
|
|
|
143588 => 'Liberia', # LR |
6084
|
|
|
|
|
|
|
143589 => 'Malawi', # MW |
6085
|
|
|
|
|
|
|
143590 => 'Mauritania', # MR |
6086
|
|
|
|
|
|
|
143591 => 'Federated States of Micronesia', # FM |
6087
|
|
|
|
|
|
|
143592 => 'Mongolia', # MN |
6088
|
|
|
|
|
|
|
143593 => 'Mozambique', # MZ |
6089
|
|
|
|
|
|
|
143594 => 'Namibia', # NA |
6090
|
|
|
|
|
|
|
143595 => 'Palau', # PW |
6091
|
|
|
|
|
|
|
143597 => 'Papua New Guinea', # PG |
6092
|
|
|
|
|
|
|
143598 => 'Sao Tome and Principe', # ST (São Tomé and Príncipe) |
6093
|
|
|
|
|
|
|
143599 => 'Seychelles', # SC |
6094
|
|
|
|
|
|
|
143600 => 'Sierra Leone', # SL |
6095
|
|
|
|
|
|
|
143601 => 'Solomon Islands', # SB |
6096
|
|
|
|
|
|
|
143602 => 'Swaziland', # SZ |
6097
|
|
|
|
|
|
|
143603 => 'Tajikistan', # TJ |
6098
|
|
|
|
|
|
|
143604 => 'Turkmenistan', # TM |
6099
|
|
|
|
|
|
|
143605 => 'Zimbabwe', # ZW |
6100
|
|
|
|
|
|
|
}, |
6101
|
|
|
|
|
|
|
}, |
6102
|
|
|
|
|
|
|
soaa => 'SortAlbumArtist', #10 |
6103
|
|
|
|
|
|
|
soal => 'SortAlbum', #10 |
6104
|
|
|
|
|
|
|
soar => 'SortArtist', #10 |
6105
|
|
|
|
|
|
|
soco => 'SortComposer', #10 |
6106
|
|
|
|
|
|
|
sonm => 'SortName', #10 |
6107
|
|
|
|
|
|
|
sosn => 'SortShow', #10 |
6108
|
|
|
|
|
|
|
stik => { #10 |
6109
|
|
|
|
|
|
|
Name => 'MediaType', |
6110
|
|
|
|
|
|
|
Format => 'int8u', #23 |
6111
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
6112
|
|
|
|
|
|
|
PrintConvColumns => 2, |
6113
|
|
|
|
|
|
|
PrintConv => { #(http://weblog.xanga.com/gryphondwb/615474010/iphone-ringtones---what-did-itunes-741-really-do.html) |
6114
|
|
|
|
|
|
|
0 => 'Movie (old)', #forum9059 (was Movie) |
6115
|
|
|
|
|
|
|
1 => 'Normal (Music)', |
6116
|
|
|
|
|
|
|
2 => 'Audiobook', |
6117
|
|
|
|
|
|
|
5 => 'Whacked Bookmark', |
6118
|
|
|
|
|
|
|
6 => 'Music Video', |
6119
|
|
|
|
|
|
|
9 => 'Movie', #forum9059 (was Short Film) |
6120
|
|
|
|
|
|
|
10 => 'TV Show', |
6121
|
|
|
|
|
|
|
11 => 'Booklet', |
6122
|
|
|
|
|
|
|
14 => 'Ringtone', |
6123
|
|
|
|
|
|
|
21 => 'Podcast', #15 |
6124
|
|
|
|
|
|
|
23 => 'iTunes U', #forum9059 |
6125
|
|
|
|
|
|
|
}, |
6126
|
|
|
|
|
|
|
}, |
6127
|
|
|
|
|
|
|
rate => 'RatingPercent', #PH |
6128
|
|
|
|
|
|
|
titl => { Name => 'Title', Avoid => 1 }, |
6129
|
|
|
|
|
|
|
tven => 'TVEpisodeID', #7 |
6130
|
|
|
|
|
|
|
tves => { #7/10 |
6131
|
|
|
|
|
|
|
Name => 'TVEpisode', |
6132
|
|
|
|
|
|
|
Format => 'int32u', |
6133
|
|
|
|
|
|
|
Writable => 'int32s', #27 |
6134
|
|
|
|
|
|
|
}, |
6135
|
|
|
|
|
|
|
tvnn => 'TVNetworkName', #7 |
6136
|
|
|
|
|
|
|
tvsh => 'TVShow', #10 |
6137
|
|
|
|
|
|
|
tvsn => { #7/10 |
6138
|
|
|
|
|
|
|
Name => 'TVSeason', |
6139
|
|
|
|
|
|
|
Format => 'int32u', |
6140
|
|
|
|
|
|
|
}, |
6141
|
|
|
|
|
|
|
yrrc => 'Year', #(ffmpeg source) |
6142
|
|
|
|
|
|
|
itnu => { #PH (iTunes 10.5) |
6143
|
|
|
|
|
|
|
Name => 'iTunesU', |
6144
|
|
|
|
|
|
|
Format => 'int8u', #27 |
6145
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
6146
|
|
|
|
|
|
|
Description => 'iTunes U', |
6147
|
|
|
|
|
|
|
PrintConv => { 0 => 'No', 1 => 'Yes' }, |
6148
|
|
|
|
|
|
|
}, |
6149
|
|
|
|
|
|
|
#https://github.com/communitymedia/mediautilities/blob/master/src/net/sourceforge/jaad/mp4/boxes/BoxTypes.java |
6150
|
|
|
|
|
|
|
gshh => { Name => 'GoogleHostHeader', Format => 'string' }, |
6151
|
|
|
|
|
|
|
gspm => { Name => 'GooglePingMessage', Format => 'string' }, |
6152
|
|
|
|
|
|
|
gspu => { Name => 'GooglePingURL', Format => 'string' }, |
6153
|
|
|
|
|
|
|
gssd => { Name => 'GoogleSourceData', Format => 'string' }, |
6154
|
|
|
|
|
|
|
gsst => { Name => 'GoogleStartTime', Format => 'string' }, |
6155
|
|
|
|
|
|
|
gstd => { |
6156
|
|
|
|
|
|
|
Name => 'GoogleTrackDuration', |
6157
|
|
|
|
|
|
|
Format => 'string', |
6158
|
|
|
|
|
|
|
ValueConv => '$val / 1000', |
6159
|
|
|
|
|
|
|
ValueConvInv => '$val * 1000', |
6160
|
|
|
|
|
|
|
PrintConv => 'ConvertDuration($val)', |
6161
|
|
|
|
|
|
|
PrintConvInv => q{ |
6162
|
|
|
|
|
|
|
$val =~ s/ s$//; |
6163
|
|
|
|
|
|
|
my @a = split /(:| days )/, $val; |
6164
|
|
|
|
|
|
|
my $sign = ($val =~ s/^-//) ? -1 : 1; |
6165
|
|
|
|
|
|
|
$a[0] += shift(@a) * 24 if @a == 4; |
6166
|
|
|
|
|
|
|
$a[0] += shift(@a) * 60 while @a > 1; |
6167
|
|
|
|
|
|
|
return $a[0] * $sign; |
6168
|
|
|
|
|
|
|
}, |
6169
|
|
|
|
|
|
|
}, |
6170
|
|
|
|
|
|
|
|
6171
|
|
|
|
|
|
|
# atoms observed in AAX audiobooks (ref PH) |
6172
|
|
|
|
|
|
|
"\xa9cpy" => { Name => 'Copyright', Avoid => 1, Groups => { 2 => 'Author' } }, |
6173
|
|
|
|
|
|
|
"\xa9pub" => 'Publisher', |
6174
|
|
|
|
|
|
|
"\xa9nrt" => 'Narrator', |
6175
|
|
|
|
|
|
|
'@pti' => 'ParentTitle', # (guess -- same as "\xa9nam") |
6176
|
|
|
|
|
|
|
'@PST' => 'ParentShortTitle', # (guess -- same as "\xa9nam") |
6177
|
|
|
|
|
|
|
'@ppi' => 'ParentProductID', # (guess -- same as 'prID') |
6178
|
|
|
|
|
|
|
'@sti' => 'ShortTitle', # (guess -- same as "\xa9nam") |
6179
|
|
|
|
|
|
|
prID => 'ProductID', |
6180
|
|
|
|
|
|
|
rldt => { Name => 'ReleaseDate', Groups => { 2 => 'Time' }}, |
6181
|
|
|
|
|
|
|
CDEK => { Name => 'Unknown_CDEK', Unknown => 1 }, # eg: "B004ZMTFEG" - used in URL's ("asin=") |
6182
|
|
|
|
|
|
|
CDET => { Name => 'Unknown_CDET', Unknown => 1 }, # eg: "ADBL" |
6183
|
|
|
|
|
|
|
VERS => 'ProductVersion', |
6184
|
|
|
|
|
|
|
GUID => 'GUID', |
6185
|
|
|
|
|
|
|
AACR => { Name => 'Unknown_AACR', Unknown => 1 }, # eg: "CR!1T1H1QH6WX7T714G2BMFX3E9MC4S" |
6186
|
|
|
|
|
|
|
# ausr - 30 bytes (User Alias?) |
6187
|
|
|
|
|
|
|
"\xa9xyz" => { #PH (written by Google Photos) |
6188
|
|
|
|
|
|
|
Name => 'GPSCoordinates', |
6189
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
6190
|
|
|
|
|
|
|
ValueConv => \&ConvertISO6709, |
6191
|
|
|
|
|
|
|
ValueConvInv => \&ConvInvISO6709, |
6192
|
|
|
|
|
|
|
PrintConv => \&PrintGPSCoordinates, |
6193
|
|
|
|
|
|
|
PrintConvInv => \&PrintInvGPSCoordinates, |
6194
|
|
|
|
|
|
|
}, |
6195
|
|
|
|
|
|
|
# the following tags written by iTunes 12.5.1.21 |
6196
|
|
|
|
|
|
|
# (ref https://www.ventismedia.com/mantis/view.php?id=14963 |
6197
|
|
|
|
|
|
|
# https://community.mp3tag.de/t/x-mp4-new-tag-problems/19488) |
6198
|
|
|
|
|
|
|
"\xa9wrk" => 'Work', #PH |
6199
|
|
|
|
|
|
|
"\xa9mvn" => 'MovementName', #PH |
6200
|
|
|
|
|
|
|
"\xa9mvi" => { #PH |
6201
|
|
|
|
|
|
|
Name => 'MovementNumber', |
6202
|
|
|
|
|
|
|
Format => 'int16u', #27 |
6203
|
|
|
|
|
|
|
Writable => 'int16s', #27 |
6204
|
|
|
|
|
|
|
}, |
6205
|
|
|
|
|
|
|
"\xa9mvc" => { #PH |
6206
|
|
|
|
|
|
|
Name => 'MovementCount', |
6207
|
|
|
|
|
|
|
Format => 'int16u', #27 |
6208
|
|
|
|
|
|
|
Writable => 'int16s', #27 |
6209
|
|
|
|
|
|
|
}, |
6210
|
|
|
|
|
|
|
shwm => { #PH |
6211
|
|
|
|
|
|
|
Name => 'ShowMovement', |
6212
|
|
|
|
|
|
|
Format => 'int8u', #27 |
6213
|
|
|
|
|
|
|
Writable => 'int8s', #27 |
6214
|
|
|
|
|
|
|
PrintConv => { 0 => 'No', 1 => 'Yes' }, |
6215
|
|
|
|
|
|
|
}, |
6216
|
|
|
|
|
|
|
); |
6217
|
|
|
|
|
|
|
|
6218
|
|
|
|
|
|
|
# tag decoded from timed face records |
6219
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::FaceInfo = ( |
6220
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6221
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
6222
|
|
|
|
|
|
|
crec => { |
6223
|
|
|
|
|
|
|
Name => 'FaceRec', |
6224
|
|
|
|
|
|
|
SubDirectory => { |
6225
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::FaceRec', |
6226
|
|
|
|
|
|
|
}, |
6227
|
|
|
|
|
|
|
}, |
6228
|
|
|
|
|
|
|
); |
6229
|
|
|
|
|
|
|
|
6230
|
|
|
|
|
|
|
# tag decoded from timed face records |
6231
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::FaceRec = ( |
6232
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6233
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
6234
|
|
|
|
|
|
|
cits => { |
6235
|
|
|
|
|
|
|
Name => 'FaceItem', |
6236
|
|
|
|
|
|
|
SubDirectory => { |
6237
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Keys', |
6238
|
|
|
|
|
|
|
ProcessProc => \&Process_mebx, |
6239
|
|
|
|
|
|
|
}, |
6240
|
|
|
|
|
|
|
}, |
6241
|
|
|
|
|
|
|
); |
6242
|
|
|
|
|
|
|
|
6243
|
|
|
|
|
|
|
# item list keys (ref PH) |
6244
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Keys = ( |
6245
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessKeys, |
6246
|
|
|
|
|
|
|
WRITE_PROC => \&WriteKeys, |
6247
|
|
|
|
|
|
|
CHECK_PROC => \&CheckQTValue, |
6248
|
|
|
|
|
|
|
VARS => { LONG_TAGS => 7 }, |
6249
|
|
|
|
|
|
|
WRITABLE => 1, |
6250
|
|
|
|
|
|
|
# (not PREFERRED when writing) |
6251
|
|
|
|
|
|
|
GROUPS => { 1 => 'Keys' }, |
6252
|
|
|
|
|
|
|
WRITE_GROUP => 'Keys', |
6253
|
|
|
|
|
|
|
LANG_INFO => \&GetLangInfo, |
6254
|
|
|
|
|
|
|
NOTES => q{ |
6255
|
|
|
|
|
|
|
This directory contains a list of key names which are used to decode tags |
6256
|
|
|
|
|
|
|
written by the "mdta" handler. Also in this table are a few tags found in |
6257
|
|
|
|
|
|
|
timed metadata that are not yet writable by ExifTool. The prefix of |
6258
|
|
|
|
|
|
|
"com.apple.quicktime." has been removed from the TagID's below. These tags |
6259
|
|
|
|
|
|
|
support alternate languages in the same way as the |
6260
|
|
|
|
|
|
|
L tags. Note |
6261
|
|
|
|
|
|
|
that by default, |
6262
|
|
|
|
|
|
|
L and |
6263
|
|
|
|
|
|
|
L tags are |
6264
|
|
|
|
|
|
|
preferred when writing, so to create a tag when a same-named tag exists in |
6265
|
|
|
|
|
|
|
either of these tables, either the "Keys" location must be specified (eg. |
6266
|
|
|
|
|
|
|
C<-Keys:Author=Phil> on the command line), or the PREFERRED level must be |
6267
|
|
|
|
|
|
|
changed via L. |
6268
|
|
|
|
|
|
|
}, |
6269
|
|
|
|
|
|
|
version => 'Version', |
6270
|
|
|
|
|
|
|
album => 'Album', |
6271
|
|
|
|
|
|
|
artist => { }, |
6272
|
|
|
|
|
|
|
artwork => { }, |
6273
|
|
|
|
|
|
|
author => { Name => 'Author', Groups => { 2 => 'Author' } }, |
6274
|
|
|
|
|
|
|
comment => { }, |
6275
|
|
|
|
|
|
|
copyright => { Name => 'Copyright', Groups => { 2 => 'Author' } }, |
6276
|
|
|
|
|
|
|
creationdate=> { |
6277
|
|
|
|
|
|
|
Name => 'CreationDate', |
6278
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
6279
|
|
|
|
|
|
|
Shift => 'Time', |
6280
|
|
|
|
|
|
|
ValueConv => q{ |
6281
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
6282
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::ConvertXMPDate($val,1); |
6283
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary |
6284
|
|
|
|
|
|
|
return $val; |
6285
|
|
|
|
|
|
|
}, |
6286
|
|
|
|
|
|
|
ValueConvInv => q{ |
6287
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
6288
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::FormatXMPDate($val); |
6289
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon |
6290
|
|
|
|
|
|
|
return $val; |
6291
|
|
|
|
|
|
|
}, |
6292
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
6293
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) |
6294
|
|
|
|
|
|
|
}, |
6295
|
|
|
|
|
|
|
description => { }, |
6296
|
|
|
|
|
|
|
director => { }, |
6297
|
|
|
|
|
|
|
displayname => { Name => 'DisplayName' }, |
6298
|
|
|
|
|
|
|
title => { }, #22 |
6299
|
|
|
|
|
|
|
genre => { }, |
6300
|
|
|
|
|
|
|
information => { }, |
6301
|
|
|
|
|
|
|
keywords => { }, |
6302
|
|
|
|
|
|
|
producer => { }, #22 |
6303
|
|
|
|
|
|
|
make => { Name => 'Make', Groups => { 2 => 'Camera' } }, |
6304
|
|
|
|
|
|
|
model => { Name => 'Model', Groups => { 2 => 'Camera' } }, |
6305
|
|
|
|
|
|
|
publisher => { }, |
6306
|
|
|
|
|
|
|
software => { }, |
6307
|
|
|
|
|
|
|
year => { Groups => { 2 => 'Time' } }, |
6308
|
|
|
|
|
|
|
'camera.identifier' => 'CameraIdentifier', # (iPhone 4) |
6309
|
|
|
|
|
|
|
'camera.framereadouttimeinmicroseconds' => { # (iPhone 4) |
6310
|
|
|
|
|
|
|
Name => 'FrameReadoutTime', |
6311
|
|
|
|
|
|
|
ValueConv => '$val * 1e-6', |
6312
|
|
|
|
|
|
|
ValueConvInv => 'int($val * 1e6 + 0.5)', |
6313
|
|
|
|
|
|
|
PrintConv => '$val * 1e6 . " microseconds"', |
6314
|
|
|
|
|
|
|
PrintConvInv => '$val =~ s/ .*//; $val * 1e-6', |
6315
|
|
|
|
|
|
|
}, |
6316
|
|
|
|
|
|
|
'location.ISO6709' => { |
6317
|
|
|
|
|
|
|
Name => 'GPSCoordinates', |
6318
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
6319
|
|
|
|
|
|
|
Notes => q{ |
6320
|
|
|
|
|
|
|
Google Photos may ignore this if the coorinates have more than 5 digits |
6321
|
|
|
|
|
|
|
after the decimal |
6322
|
|
|
|
|
|
|
}, |
6323
|
|
|
|
|
|
|
ValueConv => \&ConvertISO6709, |
6324
|
|
|
|
|
|
|
ValueConvInv => \&ConvInvISO6709, |
6325
|
|
|
|
|
|
|
PrintConv => \&PrintGPSCoordinates, |
6326
|
|
|
|
|
|
|
PrintConvInv => \&PrintInvGPSCoordinates, |
6327
|
|
|
|
|
|
|
}, |
6328
|
|
|
|
|
|
|
'location.name' => { Name => 'LocationName', Groups => { 2 => 'Location' } }, |
6329
|
|
|
|
|
|
|
'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } }, |
6330
|
|
|
|
|
|
|
'location.note' => { Name => 'LocationNote', Groups => { 2 => 'Location' } }, |
6331
|
|
|
|
|
|
|
'location.role' => { |
6332
|
|
|
|
|
|
|
Name => 'LocationRole', |
6333
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
6334
|
|
|
|
|
|
|
PrintConv => { |
6335
|
|
|
|
|
|
|
0 => 'Shooting Location', |
6336
|
|
|
|
|
|
|
1 => 'Real Location', |
6337
|
|
|
|
|
|
|
2 => 'Fictional Location', |
6338
|
|
|
|
|
|
|
}, |
6339
|
|
|
|
|
|
|
}, |
6340
|
|
|
|
|
|
|
'location.date' => { |
6341
|
|
|
|
|
|
|
Name => 'LocationDate', |
6342
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
6343
|
|
|
|
|
|
|
Shift => 'Time', |
6344
|
|
|
|
|
|
|
ValueConv => q{ |
6345
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
6346
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::ConvertXMPDate($val); |
6347
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary |
6348
|
|
|
|
|
|
|
return $val; |
6349
|
|
|
|
|
|
|
}, |
6350
|
|
|
|
|
|
|
ValueConvInv => q{ |
6351
|
|
|
|
|
|
|
require Image::ExifTool::XMP; |
6352
|
|
|
|
|
|
|
$val = Image::ExifTool::XMP::FormatXMPDate($val); |
6353
|
|
|
|
|
|
|
$val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon |
6354
|
|
|
|
|
|
|
return $val; |
6355
|
|
|
|
|
|
|
}, |
6356
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
6357
|
|
|
|
|
|
|
PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) |
6358
|
|
|
|
|
|
|
}, |
6359
|
|
|
|
|
|
|
'location.accuracy.horizontal' => { Name => 'LocationAccuracyHorizontal' }, |
6360
|
|
|
|
|
|
|
'live-photo.auto' => { Name => 'LivePhotoAuto', Writable => 'int8u' }, |
6361
|
|
|
|
|
|
|
'live-photo.vitality-score' => { Name => 'LivePhotoVitalityScore', Writable => 'float' }, |
6362
|
|
|
|
|
|
|
'live-photo.vitality-scoring-version' => { Name => 'LivePhotoVitalityScoringVersion', Writable => 'int64s' }, |
6363
|
|
|
|
|
|
|
'apple.photos.variation-identifier' => { Name => 'ApplePhotosVariationIdentifier', Writable => 'int64s' }, |
6364
|
|
|
|
|
|
|
'direction.facing' => { Name => 'CameraDirection', Groups => { 2 => 'Location' } }, |
6365
|
|
|
|
|
|
|
'direction.motion' => { Name => 'CameraMotion', Groups => { 2 => 'Location' } }, |
6366
|
|
|
|
|
|
|
'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } }, |
6367
|
|
|
|
|
|
|
'player.version' => 'PlayerVersion', |
6368
|
|
|
|
|
|
|
'player.movie.visual.brightness'=> 'Brightness', |
6369
|
|
|
|
|
|
|
'player.movie.visual.color' => 'Color', |
6370
|
|
|
|
|
|
|
'player.movie.visual.tint' => 'Tint', |
6371
|
|
|
|
|
|
|
'player.movie.visual.contrast' => 'Contrast', |
6372
|
|
|
|
|
|
|
'player.movie.audio.gain' => 'AudioGain', |
6373
|
|
|
|
|
|
|
'player.movie.audio.treble' => 'Treble', |
6374
|
|
|
|
|
|
|
'player.movie.audio.bass' => 'Bass', |
6375
|
|
|
|
|
|
|
'player.movie.audio.balance' => 'Balance', |
6376
|
|
|
|
|
|
|
'player.movie.audio.pitchshift' => 'PitchShift', |
6377
|
|
|
|
|
|
|
'player.movie.audio.mute' => { |
6378
|
|
|
|
|
|
|
Name => 'Mute', |
6379
|
|
|
|
|
|
|
Format => 'int8u', |
6380
|
|
|
|
|
|
|
PrintConv => { 0 => 'Off', 1 => 'On' }, |
6381
|
|
|
|
|
|
|
}, |
6382
|
|
|
|
|
|
|
'rating.user' => 'UserRating', # (Canon ELPH 510 HS) |
6383
|
|
|
|
|
|
|
'collection.user' => 'UserCollection', #22 |
6384
|
|
|
|
|
|
|
'Encoded_With' => 'EncodedWith', |
6385
|
|
|
|
|
|
|
# |
6386
|
|
|
|
|
|
|
# the following tags aren't in the com.apple.quicktime namespace: |
6387
|
|
|
|
|
|
|
# |
6388
|
|
|
|
|
|
|
'com.apple.photos.captureMode' => 'CaptureMode', |
6389
|
|
|
|
|
|
|
'com.android.version' => 'AndroidVersion', |
6390
|
|
|
|
|
|
|
# |
6391
|
|
|
|
|
|
|
# also seen |
6392
|
|
|
|
|
|
|
# |
6393
|
|
|
|
|
|
|
# com.divergentmedia.clipwrap.model ('NEX-FS700EK') |
6394
|
|
|
|
|
|
|
# com.divergentmedia.clipwrap.model1 ('49') |
6395
|
|
|
|
|
|
|
# com.divergentmedia.clipwrap.model2 ('0') |
6396
|
|
|
|
|
|
|
# com.divergentmedia.clipwrap.manufacturer ('Sony') |
6397
|
|
|
|
|
|
|
# com.divergentmedia.clipwrap.originalDateTime ('2013/2/6 10:30:40+0200') |
6398
|
|
|
|
|
|
|
# |
6399
|
|
|
|
|
|
|
# seen in timed metadata (mebx), and added dynamically to the table via SaveMetaKeys() |
6400
|
|
|
|
|
|
|
# NOTE: these tags are not writable! (timed metadata cannot yet be written) |
6401
|
|
|
|
|
|
|
# |
6402
|
|
|
|
|
|
|
# (mdta)com.apple.quicktime.video-orientation (dtyp=66, int16s) |
6403
|
|
|
|
|
|
|
'video-orientation' => { |
6404
|
|
|
|
|
|
|
Name => 'VideoOrientation', |
6405
|
|
|
|
|
|
|
Writable => 0, |
6406
|
|
|
|
|
|
|
PrintConv => \%Image::ExifTool::Exif::orientation, #PH (NC) |
6407
|
|
|
|
|
|
|
}, |
6408
|
|
|
|
|
|
|
# (mdta)com.apple.quicktime.live-photo-info (dtyp=com.apple.quicktime.com.apple.quicktime.live-photo-info) |
6409
|
|
|
|
|
|
|
'live-photo-info' => { |
6410
|
|
|
|
|
|
|
Name => 'LivePhotoInfo', |
6411
|
|
|
|
|
|
|
Writable => 0, |
6412
|
|
|
|
|
|
|
# not sure what these values mean, but unpack them anyway - PH |
6413
|
|
|
|
|
|
|
# (ignore the fact that the "f" and "l" unpacks won't work on a big-endian machine) |
6414
|
|
|
|
|
|
|
ValueConv => 'join " ",unpack "VfVVf6c4lCCcclf4Vvv", $val', |
6415
|
|
|
|
|
|
|
}, |
6416
|
|
|
|
|
|
|
# (mdta)com.apple.quicktime.still-image-time (dtyp=65, int8s) |
6417
|
|
|
|
|
|
|
'still-image-time' => { # (found in live photo) |
6418
|
|
|
|
|
|
|
Name => 'StillImageTime', |
6419
|
|
|
|
|
|
|
Writable => 0, |
6420
|
|
|
|
|
|
|
Notes => q{ |
6421
|
|
|
|
|
|
|
this tag always has a value of -1; the time of the still image is obtained |
6422
|
|
|
|
|
|
|
from the associated SampleTime |
6423
|
|
|
|
|
|
|
}, |
6424
|
|
|
|
|
|
|
}, |
6425
|
|
|
|
|
|
|
# (mdta)com.apple.quicktime.detected-face (dtyp='com.apple.quicktime.detected-face') |
6426
|
|
|
|
|
|
|
'detected-face' => { |
6427
|
|
|
|
|
|
|
Name => 'FaceInfo', |
6428
|
|
|
|
|
|
|
Writable => 0, |
6429
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::FaceInfo' }, |
6430
|
|
|
|
|
|
|
}, |
6431
|
|
|
|
|
|
|
# ---- detected-face fields ( ---- |
6432
|
|
|
|
|
|
|
# --> back here after a round trip through FaceInfo -> FaceRec -> FaceItem |
6433
|
|
|
|
|
|
|
# (fiel)com.apple.quicktime.detected-face.bounds (dtyp=80, float[8]) |
6434
|
|
|
|
|
|
|
'detected-face.bounds' => { |
6435
|
|
|
|
|
|
|
Name => 'DetectedFaceBounds', |
6436
|
|
|
|
|
|
|
Writable => 0, |
6437
|
|
|
|
|
|
|
# round to a reasonable number of decimal places |
6438
|
|
|
|
|
|
|
PrintConv => 'my @a=split " ",$val;$_=int($_*1e6+.5)/1e6 foreach @a;join " ",@a', |
6439
|
|
|
|
|
|
|
PrintConvInv => '$val', |
6440
|
|
|
|
|
|
|
}, |
6441
|
|
|
|
|
|
|
# (fiel)com.apple.quicktime.detected-face.face-id (dtyp=77, int32u) |
6442
|
|
|
|
|
|
|
'detected-face.face-id' => { Name => 'DetectedFaceID', Writable => 0 }, |
6443
|
|
|
|
|
|
|
# (fiel)com.apple.quicktime.detected-face.roll-angle (dtyp=23, float) |
6444
|
|
|
|
|
|
|
'detected-face.roll-angle' => { Name => 'DetectedFaceRollAngle', Writable => 0 }, |
6445
|
|
|
|
|
|
|
# (fiel)com.apple.quicktime.detected-face.yaw-angle (dtyp=23, float) |
6446
|
|
|
|
|
|
|
'detected-face.yaw-angle' => { Name => 'DetectedFaceYawAngle', Writable => 0 }, |
6447
|
|
|
|
|
|
|
# |
6448
|
|
|
|
|
|
|
# seen in Apple ProRes RAW file |
6449
|
|
|
|
|
|
|
# |
6450
|
|
|
|
|
|
|
# (mdta)com.apple.proapps.manufacturer (eg. "Sony") |
6451
|
|
|
|
|
|
|
# (mdta)com.apple.proapps.exif.{Exif}.FNumber (float, eg. 1.0) |
6452
|
|
|
|
|
|
|
# (mdta)org.smpte.rdd18.lens.irisfnumber (eg. "F1.0") |
6453
|
|
|
|
|
|
|
# (mdta)com.apple.proapps.exif.{Exif}.ShutterSpeedValue (float, eg. 1.006) |
6454
|
|
|
|
|
|
|
# (mdta)org.smpte.rdd18.camera.shutterspeed_angle (eg. "179.2deg") |
6455
|
|
|
|
|
|
|
# (mdta)org.smpte.rdd18.camera.neutraldensityfilterwheelsetting (eg. "ND1") |
6456
|
|
|
|
|
|
|
# (mdta)org.smpte.rdd18.camera.whitebalance (eg. "4300K") |
6457
|
|
|
|
|
|
|
# (mdta)com.apple.proapps.exif.{Exif}.ExposureIndex (float, eg. 4000) |
6458
|
|
|
|
|
|
|
# (mdta)org.smpte.rdd18.camera.isosensitivity (eg. "4000") |
6459
|
|
|
|
|
|
|
# (mdta)com.apple.proapps.image.{TIFF}.Make (eg. "Atmos") |
6460
|
|
|
|
|
|
|
# (mdta)com.apple.proapps.image.{TIFF}.Model (eg. "ShogunInferno") |
6461
|
|
|
|
|
|
|
# (mdta)com.apple.proapps.image.{TIFF}.Software (eg. "9.0") |
6462
|
|
|
|
|
|
|
); |
6463
|
|
|
|
|
|
|
|
6464
|
|
|
|
|
|
|
# iTunes info ('----') atoms |
6465
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::iTunesInfo = ( |
6466
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6467
|
|
|
|
|
|
|
GROUPS => { 1 => 'iTunes', 2 => 'Audio' }, |
6468
|
|
|
|
|
|
|
VARS => { LONG_TAGS => 0 }, # (hack for discrepancy in the way long tags are counted in BuildTagLookup) |
6469
|
|
|
|
|
|
|
NOTES => q{ |
6470
|
|
|
|
|
|
|
ExifTool will extract any iTunesInfo tags that exist, even if they are not |
6471
|
|
|
|
|
|
|
defined in this table. These tags belong to the family 1 "iTunes" group, |
6472
|
|
|
|
|
|
|
and are not currently writable. |
6473
|
|
|
|
|
|
|
}, |
6474
|
|
|
|
|
|
|
# 'mean'/'name'/'data' atoms form a triplet, but unfortunately |
6475
|
|
|
|
|
|
|
# I haven't been able to find any documentation on this. |
6476
|
|
|
|
|
|
|
# 'mean' is normally 'com.apple.iTunes' |
6477
|
|
|
|
|
|
|
mean => { |
6478
|
|
|
|
|
|
|
Name => 'Mean', |
6479
|
|
|
|
|
|
|
# the 'Triplet' flag tells ProcessMOV() to generate |
6480
|
|
|
|
|
|
|
# a single tag from the mean/name/data triplet |
6481
|
|
|
|
|
|
|
Triplet => 1, |
6482
|
|
|
|
|
|
|
Hidden => 1, |
6483
|
|
|
|
|
|
|
}, |
6484
|
|
|
|
|
|
|
name => { |
6485
|
|
|
|
|
|
|
Name => 'Name', |
6486
|
|
|
|
|
|
|
Triplet => 1, |
6487
|
|
|
|
|
|
|
Hidden => 1, |
6488
|
|
|
|
|
|
|
}, |
6489
|
|
|
|
|
|
|
data => { |
6490
|
|
|
|
|
|
|
Name => 'Data', |
6491
|
|
|
|
|
|
|
Triplet => 1, |
6492
|
|
|
|
|
|
|
Hidden => 1, |
6493
|
|
|
|
|
|
|
}, |
6494
|
|
|
|
|
|
|
# the tag ID's below are composed from "mean/name", |
6495
|
|
|
|
|
|
|
# but "mean/" is omitted if it is "com.apple.iTunes/": |
6496
|
|
|
|
|
|
|
'iTunMOVI' => { |
6497
|
|
|
|
|
|
|
Name => 'iTunMOVI', |
6498
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::PLIST::Main' }, |
6499
|
|
|
|
|
|
|
}, |
6500
|
|
|
|
|
|
|
'tool' => { |
6501
|
|
|
|
|
|
|
Name => 'iTunTool', |
6502
|
|
|
|
|
|
|
Description => 'iTunTool', |
6503
|
|
|
|
|
|
|
Format => 'int32u', |
6504
|
|
|
|
|
|
|
PrintConv => 'sprintf("0x%.8x",$val)', |
6505
|
|
|
|
|
|
|
}, |
6506
|
|
|
|
|
|
|
'iTunEXTC' => { |
6507
|
|
|
|
|
|
|
Name => 'ContentRating', |
6508
|
|
|
|
|
|
|
Notes => 'standard | rating | score | reasons', |
6509
|
|
|
|
|
|
|
# eg. 'us-tv|TV-14|500|V', 'mpaa|PG-13|300|For violence and sexuality' |
6510
|
|
|
|
|
|
|
# (see http://shadowofged.blogspot.ca/2008/06/itunes-content-ratings.html) |
6511
|
|
|
|
|
|
|
}, |
6512
|
|
|
|
|
|
|
'iTunNORM' => { |
6513
|
|
|
|
|
|
|
Name => 'VolumeNormalization', |
6514
|
|
|
|
|
|
|
PrintConv => '$val=~s/ 0+(\w)/ $1/g; $val=~s/^\s+//; $val', |
6515
|
|
|
|
|
|
|
}, |
6516
|
|
|
|
|
|
|
'iTunSMPB' => { |
6517
|
|
|
|
|
|
|
Name => 'iTunSMPB', |
6518
|
|
|
|
|
|
|
Description => 'iTunSMPB', |
6519
|
|
|
|
|
|
|
# hex format, similar to iTunNORM, but 12 words instead of 10, |
6520
|
|
|
|
|
|
|
# and 4th word is 16 hex digits (all others are 8) |
6521
|
|
|
|
|
|
|
# (gives AAC encoder delay, ref http://code.google.com/p/l-smash/issues/detail?id=1) |
6522
|
|
|
|
|
|
|
PrintConv => '$val=~s/ 0+(\w)/ $1/g; $val=~s/^\s+//; $val', |
6523
|
|
|
|
|
|
|
}, |
6524
|
|
|
|
|
|
|
# (CDDB = Compact Disc DataBase) |
6525
|
|
|
|
|
|
|
# iTunes_CDDB_1 = +<# tracks>+... |
6526
|
|
|
|
|
|
|
'iTunes_CDDB_1' => 'CDDB1Info', |
6527
|
|
|
|
|
|
|
'iTunes_CDDB_TrackNumber' => 'CDDBTrackNumber', |
6528
|
|
|
|
|
|
|
'Encoding Params' => { |
6529
|
|
|
|
|
|
|
Name => 'EncodingParams', |
6530
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::EncodingParams' }, |
6531
|
|
|
|
|
|
|
}, |
6532
|
|
|
|
|
|
|
# also heard about 'iTunPGAP', but I haven't seen a sample |
6533
|
|
|
|
|
|
|
# all tags below were added based on samples I have seen - PH |
6534
|
|
|
|
|
|
|
DISCNUMBER => 'DiscNumber', |
6535
|
|
|
|
|
|
|
TRACKNUMBER => 'TrackNumber', |
6536
|
|
|
|
|
|
|
ARTISTS => 'Artists', |
6537
|
|
|
|
|
|
|
CATALOGNUMBER => 'CatalogNumber', |
6538
|
|
|
|
|
|
|
RATING => 'Rating', |
6539
|
|
|
|
|
|
|
MEDIA => 'Media', |
6540
|
|
|
|
|
|
|
SCRIPT => 'Script', # character set? (seen 'Latn') |
6541
|
|
|
|
|
|
|
BARCODE => 'Barcode', |
6542
|
|
|
|
|
|
|
LABEL => 'Label', |
6543
|
|
|
|
|
|
|
MOOD => 'Mood', |
6544
|
|
|
|
|
|
|
popularimeter => 'Popularimeter', |
6545
|
|
|
|
|
|
|
'Dynamic Range (DR)'=> 'DynamicRange', |
6546
|
|
|
|
|
|
|
initialkey => 'InitialKey', |
6547
|
|
|
|
|
|
|
originalyear => 'OriginalYear', |
6548
|
|
|
|
|
|
|
originaldate => 'OriginalDate', |
6549
|
|
|
|
|
|
|
'~length' => 'Length', # play length? (ie. duration?) |
6550
|
|
|
|
|
|
|
replaygain_track_gain=>'ReplayTrackGain', |
6551
|
|
|
|
|
|
|
replaygain_track_peak=>'ReplayTrackPeak', |
6552
|
|
|
|
|
|
|
'Volume Level (ReplayGain)'=> 'ReplayVolumeLevel', |
6553
|
|
|
|
|
|
|
'Dynamic Range (R128)'=> 'DynamicRangeR128', |
6554
|
|
|
|
|
|
|
'Volume Level (R128)' => 'VolumeLevelR128', |
6555
|
|
|
|
|
|
|
'Peak Level (Sample)' => 'PeakLevelSample', |
6556
|
|
|
|
|
|
|
'Peak Level (R128)' => 'PeakLevelR128', |
6557
|
|
|
|
|
|
|
# also seen (many from forum12777): |
6558
|
|
|
|
|
|
|
# 'MusicBrainz Album Release Country' |
6559
|
|
|
|
|
|
|
# 'MusicBrainz Album Type' |
6560
|
|
|
|
|
|
|
# 'MusicBrainz Album Status' |
6561
|
|
|
|
|
|
|
# 'MusicBrainz Track Id' |
6562
|
|
|
|
|
|
|
# 'MusicBrainz Release Track Id' |
6563
|
|
|
|
|
|
|
# 'MusicBrainz Album Id' |
6564
|
|
|
|
|
|
|
# 'MusicBrainz Album Artist Id' |
6565
|
|
|
|
|
|
|
# 'MusicBrainz Artist Id' |
6566
|
|
|
|
|
|
|
# 'Acoustid Id' (sic) |
6567
|
|
|
|
|
|
|
# 'Tool Version' |
6568
|
|
|
|
|
|
|
# 'Tool Name' |
6569
|
|
|
|
|
|
|
# 'ISRC' |
6570
|
|
|
|
|
|
|
# 'HDCD' |
6571
|
|
|
|
|
|
|
# 'Waveform' |
6572
|
|
|
|
|
|
|
); |
6573
|
|
|
|
|
|
|
|
6574
|
|
|
|
|
|
|
# iTunes audio encoding parameters |
6575
|
|
|
|
|
|
|
# ref https://developer.apple.com/library/mac/#documentation/MusicAudio/Reference/AudioCodecServicesRef/Reference/reference.html |
6576
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::EncodingParams = ( |
6577
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessEncodingParams, |
6578
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
6579
|
|
|
|
|
|
|
# (I have commented out the ones that don't have integer values because they |
6580
|
|
|
|
|
|
|
# probably don't appear, and definitely wouldn't work with current decoding - PH) |
6581
|
|
|
|
|
|
|
|
6582
|
|
|
|
|
|
|
# global codec properties |
6583
|
|
|
|
|
|
|
#'lnam' => 'AudioCodecName', |
6584
|
|
|
|
|
|
|
#'lmak' => 'AudioCodecManufacturer', |
6585
|
|
|
|
|
|
|
#'lfor' => 'AudioCodecFormat', |
6586
|
|
|
|
|
|
|
'vpk?' => 'AudioHasVariablePacketByteSizes', |
6587
|
|
|
|
|
|
|
#'ifm#' => 'AudioSupportedInputFormats', |
6588
|
|
|
|
|
|
|
#'ofm#' => 'AudioSupportedOutputFormats', |
6589
|
|
|
|
|
|
|
#'aisr' => 'AudioAvailableInputSampleRates', |
6590
|
|
|
|
|
|
|
#'aosr' => 'AudioAvailableOutputSampleRates', |
6591
|
|
|
|
|
|
|
'abrt' => 'AudioAvailableBitRateRange', |
6592
|
|
|
|
|
|
|
'mnip' => 'AudioMinimumNumberInputPackets', |
6593
|
|
|
|
|
|
|
'mnop' => 'AudioMinimumNumberOutputPackets', |
6594
|
|
|
|
|
|
|
'cmnc' => 'AudioAvailableNumberChannels', |
6595
|
|
|
|
|
|
|
'lmrc' => 'AudioDoesSampleRateConversion', |
6596
|
|
|
|
|
|
|
#'aicl' => 'AudioAvailableInputChannelLayoutTags', |
6597
|
|
|
|
|
|
|
#'aocl' => 'AudioAvailableOutputChannelLayoutTags', |
6598
|
|
|
|
|
|
|
#'if4o' => 'AudioInputFormatsForOutputFormat', |
6599
|
|
|
|
|
|
|
#'of4i' => 'AudioOutputFormatsForInputFormat', |
6600
|
|
|
|
|
|
|
#'acfi' => 'AudioFormatInfo', |
6601
|
|
|
|
|
|
|
|
6602
|
|
|
|
|
|
|
# instance codec properties |
6603
|
|
|
|
|
|
|
'tbuf' => 'AudioInputBufferSize', |
6604
|
|
|
|
|
|
|
'pakf' => 'AudioPacketFrameSize', |
6605
|
|
|
|
|
|
|
'pakb' => 'AudioMaximumPacketByteSize', |
6606
|
|
|
|
|
|
|
#'ifmt' => 'AudioCurrentInputFormat', |
6607
|
|
|
|
|
|
|
#'ofmt' => 'AudioCurrentOutputFormat', |
6608
|
|
|
|
|
|
|
#'kuki' => 'AudioMagicCookie', |
6609
|
|
|
|
|
|
|
'ubuf' => 'AudioUsedInputBufferSize', |
6610
|
|
|
|
|
|
|
'init' => 'AudioIsInitialized', |
6611
|
|
|
|
|
|
|
'brat' => 'AudioCurrentTargetBitRate', |
6612
|
|
|
|
|
|
|
#'cisr' => 'AudioCurrentInputSampleRate', |
6613
|
|
|
|
|
|
|
#'cosr' => 'AudioCurrentOutputSampleRate', |
6614
|
|
|
|
|
|
|
'srcq' => 'AudioQualitySetting', |
6615
|
|
|
|
|
|
|
#'brta' => 'AudioApplicableBitRateRange', |
6616
|
|
|
|
|
|
|
#'isra' => 'AudioApplicableInputSampleRates', |
6617
|
|
|
|
|
|
|
#'osra' => 'AudioApplicableOutputSampleRates', |
6618
|
|
|
|
|
|
|
'pad0' => 'AudioZeroFramesPadded', |
6619
|
|
|
|
|
|
|
'prmm' => 'AudioCodecPrimeMethod', |
6620
|
|
|
|
|
|
|
#'prim' => 'AudioCodecPrimeInfo', |
6621
|
|
|
|
|
|
|
#'icl ' => 'AudioInputChannelLayout', |
6622
|
|
|
|
|
|
|
#'ocl ' => 'AudioOutputChannelLayout', |
6623
|
|
|
|
|
|
|
#'acs ' => 'AudioCodecSettings', |
6624
|
|
|
|
|
|
|
#'acfl' => 'AudioCodecFormatList', |
6625
|
|
|
|
|
|
|
'acbf' => 'AudioBitRateControlMode', |
6626
|
|
|
|
|
|
|
'vbrq' => 'AudioVBRQuality', |
6627
|
|
|
|
|
|
|
'mdel' => 'AudioMinimumDelayMode', |
6628
|
|
|
|
|
|
|
|
6629
|
|
|
|
|
|
|
# deprecated |
6630
|
|
|
|
|
|
|
'pakd' => 'AudioRequiresPacketDescription', |
6631
|
|
|
|
|
|
|
#'brt#' => 'AudioAvailableBitRates', |
6632
|
|
|
|
|
|
|
'acef' => 'AudioExtendFrequencies', |
6633
|
|
|
|
|
|
|
'ursr' => 'AudioUseRecommendedSampleRate', |
6634
|
|
|
|
|
|
|
'oppr' => 'AudioOutputPrecedence', |
6635
|
|
|
|
|
|
|
#'loud' => 'AudioCurrentLoudnessStatistics', |
6636
|
|
|
|
|
|
|
|
6637
|
|
|
|
|
|
|
# others |
6638
|
|
|
|
|
|
|
'vers' => 'AudioEncodingParamsVersion', #PH |
6639
|
|
|
|
|
|
|
'cdcv' => { #PH |
6640
|
|
|
|
|
|
|
Name => 'AudioComponentVersion', |
6641
|
|
|
|
|
|
|
ValueConv => 'join ".", unpack("ncc", pack("N",$val))', |
6642
|
|
|
|
|
|
|
}, |
6643
|
|
|
|
|
|
|
); |
6644
|
|
|
|
|
|
|
|
6645
|
|
|
|
|
|
|
# print to video data block |
6646
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Video = ( |
6647
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
6648
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
6649
|
|
|
|
|
|
|
0 => { |
6650
|
|
|
|
|
|
|
Name => 'DisplaySize', |
6651
|
|
|
|
|
|
|
PrintConv => { |
6652
|
|
|
|
|
|
|
0 => 'Normal', |
6653
|
|
|
|
|
|
|
1 => 'Double Size', |
6654
|
|
|
|
|
|
|
2 => 'Half Size', |
6655
|
|
|
|
|
|
|
3 => 'Full Screen', |
6656
|
|
|
|
|
|
|
4 => 'Current Size', |
6657
|
|
|
|
|
|
|
}, |
6658
|
|
|
|
|
|
|
}, |
6659
|
|
|
|
|
|
|
6 => { |
6660
|
|
|
|
|
|
|
Name => 'SlideShow', |
6661
|
|
|
|
|
|
|
PrintConv => { |
6662
|
|
|
|
|
|
|
0 => 'No', |
6663
|
|
|
|
|
|
|
1 => 'Yes', |
6664
|
|
|
|
|
|
|
}, |
6665
|
|
|
|
|
|
|
}, |
6666
|
|
|
|
|
|
|
); |
6667
|
|
|
|
|
|
|
|
6668
|
|
|
|
|
|
|
# 'hnti' atoms |
6669
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::HintInfo = ( |
6670
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6671
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
6672
|
|
|
|
|
|
|
'rtp ' => { |
6673
|
|
|
|
|
|
|
Name => 'RealtimeStreamingProtocol', |
6674
|
|
|
|
|
|
|
PrintConv => '$val=~s/^sdp /(SDP) /; $val', |
6675
|
|
|
|
|
|
|
}, |
6676
|
|
|
|
|
|
|
'sdp ' => 'StreamingDataProtocol', |
6677
|
|
|
|
|
|
|
); |
6678
|
|
|
|
|
|
|
|
6679
|
|
|
|
|
|
|
# 'hinf' atoms |
6680
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::HintTrackInfo = ( |
6681
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6682
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
6683
|
|
|
|
|
|
|
trpY => { Name => 'TotalBytes', Format => 'int64u' }, #(documented) |
6684
|
|
|
|
|
|
|
trpy => { Name => 'TotalBytes', Format => 'int64u' }, #(observed) |
6685
|
|
|
|
|
|
|
totl => { Name => 'TotalBytes', Format => 'int32u' }, |
6686
|
|
|
|
|
|
|
nump => { Name => 'NumPackets', Format => 'int64u' }, |
6687
|
|
|
|
|
|
|
npck => { Name => 'NumPackets', Format => 'int32u' }, |
6688
|
|
|
|
|
|
|
tpyl => { Name => 'TotalBytesNoRTPHeaders', Format => 'int64u' }, |
6689
|
|
|
|
|
|
|
tpaY => { Name => 'TotalBytesNoRTPHeaders', Format => 'int32u' }, #(documented) |
6690
|
|
|
|
|
|
|
tpay => { Name => 'TotalBytesNoRTPHeaders', Format => 'int32u' }, #(observed) |
6691
|
|
|
|
|
|
|
maxr => { |
6692
|
|
|
|
|
|
|
Name => 'MaxDataRate', |
6693
|
|
|
|
|
|
|
Format => 'int32u', |
6694
|
|
|
|
|
|
|
Count => 2, |
6695
|
|
|
|
|
|
|
PrintConv => 'my @a=split(" ",$val);sprintf("%d bytes in %.3f s",$a[1],$a[0]/1000)', |
6696
|
|
|
|
|
|
|
}, |
6697
|
|
|
|
|
|
|
dmed => { Name => 'MediaTrackBytes', Format => 'int64u' }, |
6698
|
|
|
|
|
|
|
dimm => { Name => 'ImmediateDataBytes', Format => 'int64u' }, |
6699
|
|
|
|
|
|
|
drep => { Name => 'RepeatedDataBytes', Format => 'int64u' }, |
6700
|
|
|
|
|
|
|
tmin => { |
6701
|
|
|
|
|
|
|
Name => 'MinTransmissionTime', |
6702
|
|
|
|
|
|
|
Format => 'int32u', |
6703
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.3f s",$val/1000)', |
6704
|
|
|
|
|
|
|
}, |
6705
|
|
|
|
|
|
|
tmax => { |
6706
|
|
|
|
|
|
|
Name => 'MaxTransmissionTime', |
6707
|
|
|
|
|
|
|
Format => 'int32u', |
6708
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.3f s",$val/1000)', |
6709
|
|
|
|
|
|
|
}, |
6710
|
|
|
|
|
|
|
pmax => { Name => 'LargestPacketSize', Format => 'int32u' }, |
6711
|
|
|
|
|
|
|
dmax => { |
6712
|
|
|
|
|
|
|
Name => 'LargestPacketDuration', |
6713
|
|
|
|
|
|
|
Format => 'int32u', |
6714
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.3f s",$val/1000)', |
6715
|
|
|
|
|
|
|
}, |
6716
|
|
|
|
|
|
|
payt => { |
6717
|
|
|
|
|
|
|
Name => 'PayloadType', |
6718
|
|
|
|
|
|
|
Format => 'undef', # (necessary to prevent decoding as string!) |
6719
|
|
|
|
|
|
|
ValueConv => 'unpack("N",$val) . " " . substr($val, 5)', |
6720
|
|
|
|
|
|
|
PrintConv => '$val=~s/ /, /;$val', |
6721
|
|
|
|
|
|
|
}, |
6722
|
|
|
|
|
|
|
); |
6723
|
|
|
|
|
|
|
|
6724
|
|
|
|
|
|
|
# MP4 media box (ref 5) |
6725
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Media = ( |
6726
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6727
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
6728
|
|
|
|
|
|
|
GROUPS => { 1 => 'Track#', 2 => 'Video' }, |
6729
|
|
|
|
|
|
|
NOTES => 'MP4 media box.', |
6730
|
|
|
|
|
|
|
mdhd => { |
6731
|
|
|
|
|
|
|
Name => 'MediaHeader', |
6732
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MediaHeader' }, |
6733
|
|
|
|
|
|
|
}, |
6734
|
|
|
|
|
|
|
hdlr => { |
6735
|
|
|
|
|
|
|
Name => 'Handler', |
6736
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Handler' }, |
6737
|
|
|
|
|
|
|
}, |
6738
|
|
|
|
|
|
|
minf => { |
6739
|
|
|
|
|
|
|
Name => 'MediaInfo', |
6740
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MediaInfo' }, |
6741
|
|
|
|
|
|
|
}, |
6742
|
|
|
|
|
|
|
); |
6743
|
|
|
|
|
|
|
|
6744
|
|
|
|
|
|
|
# MP4 media header box (ref 5) |
6745
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MediaHeader = ( |
6746
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
6747
|
|
|
|
|
|
|
WRITE_PROC => \&Image::ExifTool::WriteBinaryData, |
6748
|
|
|
|
|
|
|
CHECK_PROC => \&Image::ExifTool::CheckBinaryData, |
6749
|
|
|
|
|
|
|
GROUPS => { 1 => 'Track#', 2 => 'Video' }, |
6750
|
|
|
|
|
|
|
FORMAT => 'int32u', |
6751
|
|
|
|
|
|
|
DATAMEMBER => [ 0, 1, 2, 3, 4 ], |
6752
|
|
|
|
|
|
|
0 => { |
6753
|
|
|
|
|
|
|
Name => 'MediaHeaderVersion', |
6754
|
|
|
|
|
|
|
RawConv => '$$self{MediaHeaderVersion} = $val', |
6755
|
|
|
|
|
|
|
}, |
6756
|
|
|
|
|
|
|
1 => { |
6757
|
|
|
|
|
|
|
Name => 'MediaCreateDate', |
6758
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
6759
|
|
|
|
|
|
|
%timeInfo, |
6760
|
|
|
|
|
|
|
# this is int64u if MediaHeaderVersion == 1 (ref 5/13) |
6761
|
|
|
|
|
|
|
Hook => '$$self{MediaHeaderVersion} and $format = "int64u", $varSize += 4', |
6762
|
|
|
|
|
|
|
}, |
6763
|
|
|
|
|
|
|
2 => { |
6764
|
|
|
|
|
|
|
Name => 'MediaModifyDate', |
6765
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
6766
|
|
|
|
|
|
|
%timeInfo, |
6767
|
|
|
|
|
|
|
# this is int64u if MediaHeaderVersion == 1 (ref 5/13) |
6768
|
|
|
|
|
|
|
Hook => '$$self{MediaHeaderVersion} and $format = "int64u", $varSize += 4', |
6769
|
|
|
|
|
|
|
}, |
6770
|
|
|
|
|
|
|
3 => { |
6771
|
|
|
|
|
|
|
Name => 'MediaTimeScale', |
6772
|
|
|
|
|
|
|
RawConv => '$$self{MediaTS} = $val', |
6773
|
|
|
|
|
|
|
}, |
6774
|
|
|
|
|
|
|
4 => { |
6775
|
|
|
|
|
|
|
Name => 'MediaDuration', |
6776
|
|
|
|
|
|
|
RawConv => '$$self{MediaTS} ? $val / $$self{MediaTS} : $val', |
6777
|
|
|
|
|
|
|
PrintConv => '$$self{MediaTS} ? ConvertDuration($val) : $val', |
6778
|
|
|
|
|
|
|
# this is int64u if MediaHeaderVersion == 1 (ref 5/13) |
6779
|
|
|
|
|
|
|
Hook => '$$self{MediaHeaderVersion} and $format = "int64u", $varSize += 4', |
6780
|
|
|
|
|
|
|
}, |
6781
|
|
|
|
|
|
|
5 => { |
6782
|
|
|
|
|
|
|
Name => 'MediaLanguageCode', |
6783
|
|
|
|
|
|
|
Format => 'int16u', |
6784
|
|
|
|
|
|
|
RawConv => '$val ? $val : undef', |
6785
|
|
|
|
|
|
|
# allow both Macintosh (for MOV files) and ISO (for MP4 files) language codes |
6786
|
|
|
|
|
|
|
ValueConv => '($val < 0x400 or $val == 0x7fff) ? $val : pack "C*", map { (($val>>$_)&0x1f)+0x60 } 10, 5, 0', |
6787
|
|
|
|
|
|
|
PrintConv => q{ |
6788
|
|
|
|
|
|
|
return $val unless $val =~ /^\d+$/; |
6789
|
|
|
|
|
|
|
require Image::ExifTool::Font; |
6790
|
|
|
|
|
|
|
return $Image::ExifTool::Font::ttLang{Macintosh}{$val} || "Unknown ($val)"; |
6791
|
|
|
|
|
|
|
}, |
6792
|
|
|
|
|
|
|
}, |
6793
|
|
|
|
|
|
|
); |
6794
|
|
|
|
|
|
|
|
6795
|
|
|
|
|
|
|
# MP4 media information box (ref 5) |
6796
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MediaInfo = ( |
6797
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6798
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
6799
|
|
|
|
|
|
|
GROUPS => { 1 => 'Track#', 2 => 'Video' }, |
6800
|
|
|
|
|
|
|
NOTES => 'MP4 media info box.', |
6801
|
|
|
|
|
|
|
vmhd => { |
6802
|
|
|
|
|
|
|
Name => 'VideoHeader', |
6803
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::VideoHeader' }, |
6804
|
|
|
|
|
|
|
}, |
6805
|
|
|
|
|
|
|
smhd => { |
6806
|
|
|
|
|
|
|
Name => 'AudioHeader', |
6807
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AudioHeader' }, |
6808
|
|
|
|
|
|
|
}, |
6809
|
|
|
|
|
|
|
hmhd => { |
6810
|
|
|
|
|
|
|
Name => 'HintHeader', |
6811
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintHeader' }, |
6812
|
|
|
|
|
|
|
}, |
6813
|
|
|
|
|
|
|
nmhd => { |
6814
|
|
|
|
|
|
|
Name => 'NullMediaHeader', |
6815
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6816
|
|
|
|
|
|
|
}, |
6817
|
|
|
|
|
|
|
dinf => { |
6818
|
|
|
|
|
|
|
Name => 'DataInfo', # (don't change this name -- used to recognize directory when writing) |
6819
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DataInfo' }, |
6820
|
|
|
|
|
|
|
}, |
6821
|
|
|
|
|
|
|
gmhd => { |
6822
|
|
|
|
|
|
|
Name => 'GenMediaHeader', |
6823
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::GenMediaHeader' }, |
6824
|
|
|
|
|
|
|
}, |
6825
|
|
|
|
|
|
|
hdlr => { #PH |
6826
|
|
|
|
|
|
|
Name => 'Handler', |
6827
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Handler' }, |
6828
|
|
|
|
|
|
|
}, |
6829
|
|
|
|
|
|
|
stbl => { |
6830
|
|
|
|
|
|
|
Name => 'SampleTable', |
6831
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SampleTable' }, |
6832
|
|
|
|
|
|
|
}, |
6833
|
|
|
|
|
|
|
); |
6834
|
|
|
|
|
|
|
|
6835
|
|
|
|
|
|
|
# MP4 video media header (ref 5) |
6836
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::VideoHeader = ( |
6837
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
6838
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
6839
|
|
|
|
|
|
|
NOTES => 'MP4 video media header.', |
6840
|
|
|
|
|
|
|
FORMAT => 'int16u', |
6841
|
|
|
|
|
|
|
2 => { |
6842
|
|
|
|
|
|
|
Name => 'GraphicsMode', |
6843
|
|
|
|
|
|
|
PrintHex => 1, |
6844
|
|
|
|
|
|
|
SeparateTable => 'GraphicsMode', |
6845
|
|
|
|
|
|
|
PrintConv => \%graphicsMode, |
6846
|
|
|
|
|
|
|
}, |
6847
|
|
|
|
|
|
|
3 => { Name => 'OpColor', Format => 'int16u[3]' }, |
6848
|
|
|
|
|
|
|
); |
6849
|
|
|
|
|
|
|
|
6850
|
|
|
|
|
|
|
# MP4 audio media header (ref 5) |
6851
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::AudioHeader = ( |
6852
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
6853
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
6854
|
|
|
|
|
|
|
NOTES => 'MP4 audio media header.', |
6855
|
|
|
|
|
|
|
FORMAT => 'int16u', |
6856
|
|
|
|
|
|
|
2 => { Name => 'Balance', Format => 'fixed16s' }, |
6857
|
|
|
|
|
|
|
); |
6858
|
|
|
|
|
|
|
|
6859
|
|
|
|
|
|
|
# MP4 hint media header (ref 5) |
6860
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::HintHeader = ( |
6861
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
6862
|
|
|
|
|
|
|
NOTES => 'MP4 hint media header.', |
6863
|
|
|
|
|
|
|
FORMAT => 'int16u', |
6864
|
|
|
|
|
|
|
2 => 'MaxPDUSize', |
6865
|
|
|
|
|
|
|
3 => 'AvgPDUSize', |
6866
|
|
|
|
|
|
|
4 => { Name => 'MaxBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, |
6867
|
|
|
|
|
|
|
6 => { Name => 'AvgBitrate', Format => 'int32u', PrintConv => 'ConvertBitrate($val)' }, |
6868
|
|
|
|
|
|
|
); |
6869
|
|
|
|
|
|
|
|
6870
|
|
|
|
|
|
|
# MP4 sample table box (ref 5) |
6871
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::SampleTable = ( |
6872
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
6873
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, |
6874
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
6875
|
|
|
|
|
|
|
NOTES => 'MP4 sample table box.', |
6876
|
|
|
|
|
|
|
stsd => [ |
6877
|
|
|
|
|
|
|
{ |
6878
|
|
|
|
|
|
|
Name => 'AudioSampleDesc', |
6879
|
|
|
|
|
|
|
Condition => '$$self{HandlerType} and $$self{HandlerType} eq "soun"', |
6880
|
|
|
|
|
|
|
SubDirectory => { |
6881
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::AudioSampleDesc', |
6882
|
|
|
|
|
|
|
ProcessProc => \&ProcessSampleDesc, |
6883
|
|
|
|
|
|
|
}, |
6884
|
|
|
|
|
|
|
},{ |
6885
|
|
|
|
|
|
|
Name => 'VideoSampleDesc', |
6886
|
|
|
|
|
|
|
Condition => '$$self{HandlerType} and $$self{HandlerType} eq "vide"', |
6887
|
|
|
|
|
|
|
SubDirectory => { |
6888
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::ImageDesc', |
6889
|
|
|
|
|
|
|
ProcessProc => \&ProcessSampleDesc, |
6890
|
|
|
|
|
|
|
}, |
6891
|
|
|
|
|
|
|
},{ |
6892
|
|
|
|
|
|
|
Name => 'HintSampleDesc', |
6893
|
|
|
|
|
|
|
Condition => '$$self{HandlerType} and $$self{HandlerType} eq "hint"', |
6894
|
|
|
|
|
|
|
SubDirectory => { |
6895
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::HintSampleDesc', |
6896
|
|
|
|
|
|
|
ProcessProc => \&ProcessSampleDesc, |
6897
|
|
|
|
|
|
|
}, |
6898
|
|
|
|
|
|
|
},{ |
6899
|
|
|
|
|
|
|
Name => 'MetaSampleDesc', |
6900
|
|
|
|
|
|
|
Condition => '$$self{HandlerType} and $$self{HandlerType} eq "meta"', |
6901
|
|
|
|
|
|
|
SubDirectory => { |
6902
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::MetaSampleDesc', |
6903
|
|
|
|
|
|
|
ProcessProc => \&ProcessSampleDesc, |
6904
|
|
|
|
|
|
|
}, |
6905
|
|
|
|
|
|
|
},{ |
6906
|
|
|
|
|
|
|
Name => 'OtherSampleDesc', |
6907
|
|
|
|
|
|
|
SubDirectory => { |
6908
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::OtherSampleDesc', |
6909
|
|
|
|
|
|
|
ProcessProc => \&ProcessSampleDesc, |
6910
|
|
|
|
|
|
|
}, |
6911
|
|
|
|
|
|
|
}, |
6912
|
|
|
|
|
|
|
# (Note: "alis" HandlerType handled by the parent audio or video handler) |
6913
|
|
|
|
|
|
|
], |
6914
|
|
|
|
|
|
|
stts => [ # decoding time-to-sample table |
6915
|
|
|
|
|
|
|
{ |
6916
|
|
|
|
|
|
|
Name => 'VideoFrameRate', |
6917
|
|
|
|
|
|
|
Notes => 'average rate calculated from time-to-sample table for video media', |
6918
|
|
|
|
|
|
|
Condition => '$$self{HandlerType} and $$self{HandlerType} eq "vide"', |
6919
|
|
|
|
|
|
|
Format => 'undef', # (necessary to prevent decoding as string!) |
6920
|
|
|
|
|
|
|
# (must be RawConv so appropriate MediaTS is used in calculation) |
6921
|
|
|
|
|
|
|
RawConv => 'Image::ExifTool::QuickTime::CalcSampleRate($self, \$val)', |
6922
|
|
|
|
|
|
|
PrintConv => 'int($val * 1000 + 0.5) / 1000', |
6923
|
|
|
|
|
|
|
}, |
6924
|
|
|
|
|
|
|
{ |
6925
|
|
|
|
|
|
|
Name => 'TimeToSampleTable', |
6926
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6927
|
|
|
|
|
|
|
}, |
6928
|
|
|
|
|
|
|
], |
6929
|
|
|
|
|
|
|
ctts => { |
6930
|
|
|
|
|
|
|
Name => 'CompositionTimeToSample', |
6931
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6932
|
|
|
|
|
|
|
}, |
6933
|
|
|
|
|
|
|
stsc => { |
6934
|
|
|
|
|
|
|
Name => 'SampleToChunk', |
6935
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6936
|
|
|
|
|
|
|
}, |
6937
|
|
|
|
|
|
|
stsz => { |
6938
|
|
|
|
|
|
|
Name => 'SampleSizes', |
6939
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6940
|
|
|
|
|
|
|
}, |
6941
|
|
|
|
|
|
|
stz2 => { |
6942
|
|
|
|
|
|
|
Name => 'CompactSampleSizes', |
6943
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6944
|
|
|
|
|
|
|
}, |
6945
|
|
|
|
|
|
|
stco => { |
6946
|
|
|
|
|
|
|
Name => 'ChunkOffset', |
6947
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6948
|
|
|
|
|
|
|
}, |
6949
|
|
|
|
|
|
|
co64 => { |
6950
|
|
|
|
|
|
|
Name => 'ChunkOffset64', |
6951
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6952
|
|
|
|
|
|
|
}, |
6953
|
|
|
|
|
|
|
stss => { |
6954
|
|
|
|
|
|
|
Name => 'SyncSampleTable', |
6955
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6956
|
|
|
|
|
|
|
}, |
6957
|
|
|
|
|
|
|
stsh => { |
6958
|
|
|
|
|
|
|
Name => 'ShadowSyncSampleTable', |
6959
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6960
|
|
|
|
|
|
|
}, |
6961
|
|
|
|
|
|
|
padb => { |
6962
|
|
|
|
|
|
|
Name => 'SamplePaddingBits', |
6963
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6964
|
|
|
|
|
|
|
}, |
6965
|
|
|
|
|
|
|
stdp => { |
6966
|
|
|
|
|
|
|
Name => 'SampleDegradationPriority', |
6967
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6968
|
|
|
|
|
|
|
}, |
6969
|
|
|
|
|
|
|
sdtp => { |
6970
|
|
|
|
|
|
|
Name => 'IdependentAndDisposableSamples', |
6971
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6972
|
|
|
|
|
|
|
}, |
6973
|
|
|
|
|
|
|
sbgp => { |
6974
|
|
|
|
|
|
|
Name => 'SampleToGroup', |
6975
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6976
|
|
|
|
|
|
|
}, |
6977
|
|
|
|
|
|
|
sgpd => { |
6978
|
|
|
|
|
|
|
Name => 'SampleGroupDescription', |
6979
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6980
|
|
|
|
|
|
|
# bytes 4-7 give grouping type (ref ISO/IEC 14496-15:2014) |
6981
|
|
|
|
|
|
|
# tsas - temporal sublayer sample |
6982
|
|
|
|
|
|
|
# stsa - step-wise temporal layer access |
6983
|
|
|
|
|
|
|
# avss - AVC sample |
6984
|
|
|
|
|
|
|
# tscl - temporal layer scalability |
6985
|
|
|
|
|
|
|
# sync - sync sample |
6986
|
|
|
|
|
|
|
}, |
6987
|
|
|
|
|
|
|
subs => { |
6988
|
|
|
|
|
|
|
Name => 'Sub-sampleInformation', |
6989
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6990
|
|
|
|
|
|
|
}, |
6991
|
|
|
|
|
|
|
cslg => { |
6992
|
|
|
|
|
|
|
Name => 'CompositionToDecodeTimelineMapping', |
6993
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
6994
|
|
|
|
|
|
|
}, |
6995
|
|
|
|
|
|
|
stps => { |
6996
|
|
|
|
|
|
|
Name => 'PartialSyncSamples', |
6997
|
|
|
|
|
|
|
ValueConv => 'join " ",unpack("x8N*",$val)', |
6998
|
|
|
|
|
|
|
}, |
6999
|
|
|
|
|
|
|
# mark - 8 bytes all zero (GoPro) |
7000
|
|
|
|
|
|
|
); |
7001
|
|
|
|
|
|
|
|
7002
|
|
|
|
|
|
|
# MP4 audio sample description box (ref 5/AtomicParsley 0.9.4 parsley.cpp) |
7003
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::AudioSampleDesc = ( |
7004
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessHybrid, |
7005
|
|
|
|
|
|
|
VARS => { ID_LABEL => 'ID/Index' }, |
7006
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
7007
|
|
|
|
|
|
|
NOTES => q{ |
7008
|
|
|
|
|
|
|
MP4 audio sample description. This hybrid atom contains both data and child |
7009
|
|
|
|
|
|
|
atoms. |
7010
|
|
|
|
|
|
|
}, |
7011
|
|
|
|
|
|
|
4 => { |
7012
|
|
|
|
|
|
|
Name => 'AudioFormat', |
7013
|
|
|
|
|
|
|
Format => 'undef[4]', |
7014
|
|
|
|
|
|
|
RawConv => q{ |
7015
|
|
|
|
|
|
|
$$self{AudioFormat} = $val; |
7016
|
|
|
|
|
|
|
return undef unless $val =~ /^[\w ]{4}$/i; |
7017
|
|
|
|
|
|
|
# check for protected audio format |
7018
|
|
|
|
|
|
|
$self->OverrideFileType('M4P') if $val eq 'drms' and $$self{VALUE}{FileType} eq 'M4A'; |
7019
|
|
|
|
|
|
|
return $val; |
7020
|
|
|
|
|
|
|
}, |
7021
|
|
|
|
|
|
|
# see this link for print conversions (not complete): |
7022
|
|
|
|
|
|
|
# https://github.com/yannickcr/brooser/blob/master/php/librairies/getid3/module.audio-video.quicktime.php |
7023
|
|
|
|
|
|
|
}, |
7024
|
|
|
|
|
|
|
20 => { #PH |
7025
|
|
|
|
|
|
|
Name => 'AudioVendorID', |
7026
|
|
|
|
|
|
|
Condition => '$$self{AudioFormat} ne "mp4s"', |
7027
|
|
|
|
|
|
|
Format => 'undef[4]', |
7028
|
|
|
|
|
|
|
RawConv => '$val eq "\0\0\0\0" ? undef : $val', |
7029
|
|
|
|
|
|
|
PrintConv => \%vendorID, |
7030
|
|
|
|
|
|
|
SeparateTable => 'VendorID', |
7031
|
|
|
|
|
|
|
}, |
7032
|
|
|
|
|
|
|
24 => { Name => 'AudioChannels', Format => 'int16u' }, |
7033
|
|
|
|
|
|
|
26 => { Name => 'AudioBitsPerSample', Format => 'int16u' }, |
7034
|
|
|
|
|
|
|
32 => { Name => 'AudioSampleRate', Format => 'fixed32u' }, |
7035
|
|
|
|
|
|
|
# |
7036
|
|
|
|
|
|
|
# Observed offsets for child atoms of various AudioFormat types: |
7037
|
|
|
|
|
|
|
# |
7038
|
|
|
|
|
|
|
# AudioFormat Offset Child atoms |
7039
|
|
|
|
|
|
|
# ----------- ------ ---------------- |
7040
|
|
|
|
|
|
|
# mp4a 52 * wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max) |
7041
|
|
|
|
|
|
|
# in24 52 wave, chan |
7042
|
|
|
|
|
|
|
# "ms\0\x11" 52 wave |
7043
|
|
|
|
|
|
|
# sowt 52 chan |
7044
|
|
|
|
|
|
|
# mp4a 36 * esds, pinf |
7045
|
|
|
|
|
|
|
# drms 36 esds, sinf |
7046
|
|
|
|
|
|
|
# samr 36 damr |
7047
|
|
|
|
|
|
|
# alac 36 alac |
7048
|
|
|
|
|
|
|
# ac-3 36 dac3 |
7049
|
|
|
|
|
|
|
# |
7050
|
|
|
|
|
|
|
# (* child atoms found at different offsets in mp4a) |
7051
|
|
|
|
|
|
|
# |
7052
|
|
|
|
|
|
|
pinf => { |
7053
|
|
|
|
|
|
|
Name => 'PurchaseInfo', |
7054
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ProtectionInfo' }, |
7055
|
|
|
|
|
|
|
}, |
7056
|
|
|
|
|
|
|
sinf => { # "protection scheme information" |
7057
|
|
|
|
|
|
|
Name => 'ProtectionInfo', #3 |
7058
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ProtectionInfo' }, |
7059
|
|
|
|
|
|
|
}, |
7060
|
|
|
|
|
|
|
# f - 16/36 bytes |
7061
|
|
|
|
|
|
|
# esds - 31/40/42/43 bytes - ES descriptor (ref 3) |
7062
|
|
|
|
|
|
|
damr => { #3 |
7063
|
|
|
|
|
|
|
Name => 'DecodeConfig', |
7064
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DecodeConfig' }, |
7065
|
|
|
|
|
|
|
}, |
7066
|
|
|
|
|
|
|
wave => { |
7067
|
|
|
|
|
|
|
Name => 'Wave', |
7068
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Wave' }, |
7069
|
|
|
|
|
|
|
}, |
7070
|
|
|
|
|
|
|
chan => { |
7071
|
|
|
|
|
|
|
Name => 'AudioChannelLayout', |
7072
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ChannelLayout' }, |
7073
|
|
|
|
|
|
|
} |
7074
|
|
|
|
|
|
|
# alac - 28 bytes |
7075
|
|
|
|
|
|
|
# adrm - AAX DRM atom? 148 bytes |
7076
|
|
|
|
|
|
|
# aabd - AAX unknown 17kB (contains 'aavd' strings) |
7077
|
|
|
|
|
|
|
# SA3D - written by Garmin VIRB360 |
7078
|
|
|
|
|
|
|
); |
7079
|
|
|
|
|
|
|
|
7080
|
|
|
|
|
|
|
# AMR decode config box (ref 3) |
7081
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::DecodeConfig = ( |
7082
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
7083
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
7084
|
|
|
|
|
|
|
0 => { |
7085
|
|
|
|
|
|
|
Name => 'EncoderVendor', |
7086
|
|
|
|
|
|
|
Format => 'undef[4]', |
7087
|
|
|
|
|
|
|
}, |
7088
|
|
|
|
|
|
|
4 => 'EncoderVersion', |
7089
|
|
|
|
|
|
|
# 5 - int16u - packet modes |
7090
|
|
|
|
|
|
|
# 7 - int8u - number of packet mode changes |
7091
|
|
|
|
|
|
|
# 8 - int8u - bytes per packet |
7092
|
|
|
|
|
|
|
); |
7093
|
|
|
|
|
|
|
|
7094
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ProtectionInfo = ( |
7095
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7096
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
7097
|
|
|
|
|
|
|
NOTES => 'Child atoms found in "sinf" and/or "pinf" atoms.', |
7098
|
|
|
|
|
|
|
frma => 'OriginalFormat', |
7099
|
|
|
|
|
|
|
# imif - IPMP information |
7100
|
|
|
|
|
|
|
schm => { |
7101
|
|
|
|
|
|
|
Name => 'SchemeType', |
7102
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeType' }, |
7103
|
|
|
|
|
|
|
}, |
7104
|
|
|
|
|
|
|
schi => { |
7105
|
|
|
|
|
|
|
Name => 'SchemeInfo', |
7106
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeInfo' }, |
7107
|
|
|
|
|
|
|
}, |
7108
|
|
|
|
|
|
|
enda => { |
7109
|
|
|
|
|
|
|
Name => 'Endianness', |
7110
|
|
|
|
|
|
|
Format => 'int16u', |
7111
|
|
|
|
|
|
|
PrintConv => { |
7112
|
|
|
|
|
|
|
0 => 'Big-endian (Motorola, MM)', |
7113
|
|
|
|
|
|
|
1 => 'Little-endian (Intel, II)', |
7114
|
|
|
|
|
|
|
}, |
7115
|
|
|
|
|
|
|
}, |
7116
|
|
|
|
|
|
|
# skcr |
7117
|
|
|
|
|
|
|
); |
7118
|
|
|
|
|
|
|
|
7119
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Wave = ( |
7120
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7121
|
|
|
|
|
|
|
frma => 'PurchaseFileFormat', |
7122
|
|
|
|
|
|
|
enda => { |
7123
|
|
|
|
|
|
|
Name => 'Endianness', |
7124
|
|
|
|
|
|
|
Format => 'int16u', |
7125
|
|
|
|
|
|
|
PrintConv => { |
7126
|
|
|
|
|
|
|
0 => 'Big-endian (Motorola, MM)', |
7127
|
|
|
|
|
|
|
1 => 'Little-endian (Intel, II)', |
7128
|
|
|
|
|
|
|
}, |
7129
|
|
|
|
|
|
|
}, |
7130
|
|
|
|
|
|
|
# "ms\0\x11" - 20 bytes |
7131
|
|
|
|
|
|
|
); |
7132
|
|
|
|
|
|
|
|
7133
|
|
|
|
|
|
|
# audio channel layout (ref CoreAudioTypes.h) |
7134
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::ChannelLayout = ( |
7135
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
7136
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
7137
|
|
|
|
|
|
|
DATAMEMBER => [ 0, 8 ], |
7138
|
|
|
|
|
|
|
NOTES => 'Audio channel layout.', |
7139
|
|
|
|
|
|
|
# 0 - version and flags |
7140
|
|
|
|
|
|
|
4 => { |
7141
|
|
|
|
|
|
|
Name => 'LayoutFlags', |
7142
|
|
|
|
|
|
|
Format => 'int16u', |
7143
|
|
|
|
|
|
|
RawConv => '$$self{LayoutFlags} = $val', |
7144
|
|
|
|
|
|
|
PrintConvColumns => 2, |
7145
|
|
|
|
|
|
|
PrintConv => { |
7146
|
|
|
|
|
|
|
0 => 'UseDescriptions', |
7147
|
|
|
|
|
|
|
1 => 'UseBitmap', |
7148
|
|
|
|
|
|
|
100 => 'Mono', |
7149
|
|
|
|
|
|
|
101 => 'Stereo', |
7150
|
|
|
|
|
|
|
102 => 'StereoHeadphones', |
7151
|
|
|
|
|
|
|
100 => 'Mono', |
7152
|
|
|
|
|
|
|
101 => 'Stereo', |
7153
|
|
|
|
|
|
|
102 => 'StereoHeadphones', |
7154
|
|
|
|
|
|
|
103 => 'MatrixStereo', |
7155
|
|
|
|
|
|
|
104 => 'MidSide', |
7156
|
|
|
|
|
|
|
105 => 'XY', |
7157
|
|
|
|
|
|
|
106 => 'Binaural', |
7158
|
|
|
|
|
|
|
107 => 'Ambisonic_B_Format', |
7159
|
|
|
|
|
|
|
108 => 'Quadraphonic', |
7160
|
|
|
|
|
|
|
109 => 'Pentagonal', |
7161
|
|
|
|
|
|
|
110 => 'Hexagonal', |
7162
|
|
|
|
|
|
|
111 => 'Octagonal', |
7163
|
|
|
|
|
|
|
112 => 'Cube', |
7164
|
|
|
|
|
|
|
113 => 'MPEG_3_0_A', |
7165
|
|
|
|
|
|
|
114 => 'MPEG_3_0_B', |
7166
|
|
|
|
|
|
|
115 => 'MPEG_4_0_A', |
7167
|
|
|
|
|
|
|
116 => 'MPEG_4_0_B', |
7168
|
|
|
|
|
|
|
117 => 'MPEG_5_0_A', |
7169
|
|
|
|
|
|
|
118 => 'MPEG_5_0_B', |
7170
|
|
|
|
|
|
|
119 => 'MPEG_5_0_C', |
7171
|
|
|
|
|
|
|
120 => 'MPEG_5_0_D', |
7172
|
|
|
|
|
|
|
121 => 'MPEG_5_1_A', |
7173
|
|
|
|
|
|
|
122 => 'MPEG_5_1_B', |
7174
|
|
|
|
|
|
|
123 => 'MPEG_5_1_C', |
7175
|
|
|
|
|
|
|
124 => 'MPEG_5_1_D', |
7176
|
|
|
|
|
|
|
125 => 'MPEG_6_1_A', |
7177
|
|
|
|
|
|
|
126 => 'MPEG_7_1_A', |
7178
|
|
|
|
|
|
|
127 => 'MPEG_7_1_B', |
7179
|
|
|
|
|
|
|
128 => 'MPEG_7_1_C', |
7180
|
|
|
|
|
|
|
129 => 'Emagic_Default_7_1', |
7181
|
|
|
|
|
|
|
130 => 'SMPTE_DTV', |
7182
|
|
|
|
|
|
|
131 => 'ITU_2_1', |
7183
|
|
|
|
|
|
|
132 => 'ITU_2_2', |
7184
|
|
|
|
|
|
|
133 => 'DVD_4', |
7185
|
|
|
|
|
|
|
134 => 'DVD_5', |
7186
|
|
|
|
|
|
|
135 => 'DVD_6', |
7187
|
|
|
|
|
|
|
136 => 'DVD_10', |
7188
|
|
|
|
|
|
|
137 => 'DVD_11', |
7189
|
|
|
|
|
|
|
138 => 'DVD_18', |
7190
|
|
|
|
|
|
|
139 => 'AudioUnit_6_0', |
7191
|
|
|
|
|
|
|
140 => 'AudioUnit_7_0', |
7192
|
|
|
|
|
|
|
141 => 'AAC_6_0', |
7193
|
|
|
|
|
|
|
142 => 'AAC_6_1', |
7194
|
|
|
|
|
|
|
143 => 'AAC_7_0', |
7195
|
|
|
|
|
|
|
144 => 'AAC_Octagonal', |
7196
|
|
|
|
|
|
|
145 => 'TMH_10_2_std', |
7197
|
|
|
|
|
|
|
146 => 'TMH_10_2_full', |
7198
|
|
|
|
|
|
|
147 => 'DiscreteInOrder', |
7199
|
|
|
|
|
|
|
148 => 'AudioUnit_7_0_Front', |
7200
|
|
|
|
|
|
|
149 => 'AC3_1_0_1', |
7201
|
|
|
|
|
|
|
150 => 'AC3_3_0', |
7202
|
|
|
|
|
|
|
151 => 'AC3_3_1', |
7203
|
|
|
|
|
|
|
152 => 'AC3_3_0_1', |
7204
|
|
|
|
|
|
|
153 => 'AC3_2_1_1', |
7205
|
|
|
|
|
|
|
154 => 'AC3_3_1_1', |
7206
|
|
|
|
|
|
|
155 => 'EAC_6_0_A', |
7207
|
|
|
|
|
|
|
156 => 'EAC_7_0_A', |
7208
|
|
|
|
|
|
|
157 => 'EAC3_6_1_A', |
7209
|
|
|
|
|
|
|
158 => 'EAC3_6_1_B', |
7210
|
|
|
|
|
|
|
159 => 'EAC3_6_1_C', |
7211
|
|
|
|
|
|
|
160 => 'EAC3_7_1_A', |
7212
|
|
|
|
|
|
|
161 => 'EAC3_7_1_B', |
7213
|
|
|
|
|
|
|
162 => 'EAC3_7_1_C', |
7214
|
|
|
|
|
|
|
163 => 'EAC3_7_1_D', |
7215
|
|
|
|
|
|
|
164 => 'EAC3_7_1_E', |
7216
|
|
|
|
|
|
|
165 => 'EAC3_7_1_F', |
7217
|
|
|
|
|
|
|
166 => 'EAC3_7_1_G', |
7218
|
|
|
|
|
|
|
167 => 'EAC3_7_1_H', |
7219
|
|
|
|
|
|
|
168 => 'DTS_3_1', |
7220
|
|
|
|
|
|
|
169 => 'DTS_4_1', |
7221
|
|
|
|
|
|
|
170 => 'DTS_6_0_A', |
7222
|
|
|
|
|
|
|
171 => 'DTS_6_0_B', |
7223
|
|
|
|
|
|
|
172 => 'DTS_6_0_C', |
7224
|
|
|
|
|
|
|
173 => 'DTS_6_1_A', |
7225
|
|
|
|
|
|
|
174 => 'DTS_6_1_B', |
7226
|
|
|
|
|
|
|
175 => 'DTS_6_1_C', |
7227
|
|
|
|
|
|
|
176 => 'DTS_7_0', |
7228
|
|
|
|
|
|
|
177 => 'DTS_7_1', |
7229
|
|
|
|
|
|
|
178 => 'DTS_8_0_A', |
7230
|
|
|
|
|
|
|
179 => 'DTS_8_0_B', |
7231
|
|
|
|
|
|
|
180 => 'DTS_8_1_A', |
7232
|
|
|
|
|
|
|
181 => 'DTS_8_1_B', |
7233
|
|
|
|
|
|
|
182 => 'DTS_6_1_D', |
7234
|
|
|
|
|
|
|
183 => 'AAC_7_1_B', |
7235
|
|
|
|
|
|
|
0xffff => 'Unknown', |
7236
|
|
|
|
|
|
|
}, |
7237
|
|
|
|
|
|
|
}, |
7238
|
|
|
|
|
|
|
6 => { |
7239
|
|
|
|
|
|
|
Name => 'AudioChannels', |
7240
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} != 0 and $$self{LayoutFlags} != 1', |
7241
|
|
|
|
|
|
|
Format => 'int16u', |
7242
|
|
|
|
|
|
|
}, |
7243
|
|
|
|
|
|
|
8 => { |
7244
|
|
|
|
|
|
|
Name => 'AudioChannelTypes', |
7245
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1', |
7246
|
|
|
|
|
|
|
Format => 'int32u', |
7247
|
|
|
|
|
|
|
PrintConv => { BITMASK => { |
7248
|
|
|
|
|
|
|
0 => 'Left', |
7249
|
|
|
|
|
|
|
1 => 'Right', |
7250
|
|
|
|
|
|
|
2 => 'Center', |
7251
|
|
|
|
|
|
|
3 => 'LFEScreen', |
7252
|
|
|
|
|
|
|
4 => 'LeftSurround', |
7253
|
|
|
|
|
|
|
5 => 'RightSurround', |
7254
|
|
|
|
|
|
|
6 => 'LeftCenter', |
7255
|
|
|
|
|
|
|
7 => 'RightCenter', |
7256
|
|
|
|
|
|
|
8 => 'CenterSurround', |
7257
|
|
|
|
|
|
|
9 => 'LeftSurroundDirect', |
7258
|
|
|
|
|
|
|
10 => 'RightSurroundDirect', |
7259
|
|
|
|
|
|
|
11 => 'TopCenterSurround', |
7260
|
|
|
|
|
|
|
12 => 'VerticalHeightLeft', |
7261
|
|
|
|
|
|
|
13 => 'VerticalHeightCenter', |
7262
|
|
|
|
|
|
|
14 => 'VerticalHeightRight', |
7263
|
|
|
|
|
|
|
15 => 'TopBackLeft', |
7264
|
|
|
|
|
|
|
16 => 'TopBackCenter', |
7265
|
|
|
|
|
|
|
17 => 'TopBackRight', |
7266
|
|
|
|
|
|
|
}}, |
7267
|
|
|
|
|
|
|
}, |
7268
|
|
|
|
|
|
|
12 => { |
7269
|
|
|
|
|
|
|
Name => 'NumChannelDescriptions', |
7270
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1', |
7271
|
|
|
|
|
|
|
Format => 'int32u', |
7272
|
|
|
|
|
|
|
RawConv => '$$self{NumChannelDescriptions} = $val', |
7273
|
|
|
|
|
|
|
}, |
7274
|
|
|
|
|
|
|
16 => { |
7275
|
|
|
|
|
|
|
Name => 'Channel1Label', |
7276
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0', |
7277
|
|
|
|
|
|
|
Format => 'int32u', |
7278
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7279
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7280
|
|
|
|
|
|
|
}, |
7281
|
|
|
|
|
|
|
20 => { |
7282
|
|
|
|
|
|
|
Name => 'Channel1Flags', |
7283
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0', |
7284
|
|
|
|
|
|
|
Format => 'int32u', |
7285
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7286
|
|
|
|
|
|
|
}, |
7287
|
|
|
|
|
|
|
24 => { |
7288
|
|
|
|
|
|
|
Name => 'Channel1Coordinates', |
7289
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0', |
7290
|
|
|
|
|
|
|
Notes => q{ |
7291
|
|
|
|
|
|
|
3 numbers: for rectangular coordinates left/right, back/front, down/up; for |
7292
|
|
|
|
|
|
|
spherical coordinates left/right degrees, down/up degrees, distance |
7293
|
|
|
|
|
|
|
}, |
7294
|
|
|
|
|
|
|
Format => 'float[3]', |
7295
|
|
|
|
|
|
|
}, |
7296
|
|
|
|
|
|
|
36 => { |
7297
|
|
|
|
|
|
|
Name => 'Channel2Label', |
7298
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1', |
7299
|
|
|
|
|
|
|
Format => 'int32u', |
7300
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7301
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7302
|
|
|
|
|
|
|
}, |
7303
|
|
|
|
|
|
|
40 => { |
7304
|
|
|
|
|
|
|
Name => 'Channel2Flags', |
7305
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1', |
7306
|
|
|
|
|
|
|
Format => 'int32u', |
7307
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7308
|
|
|
|
|
|
|
}, |
7309
|
|
|
|
|
|
|
44 => { |
7310
|
|
|
|
|
|
|
Name => 'Channel2Coordinates', |
7311
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1', |
7312
|
|
|
|
|
|
|
Format => 'float[3]', |
7313
|
|
|
|
|
|
|
}, |
7314
|
|
|
|
|
|
|
56 => { |
7315
|
|
|
|
|
|
|
Name => 'Channel3Label', |
7316
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2', |
7317
|
|
|
|
|
|
|
Format => 'int32u', |
7318
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7319
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7320
|
|
|
|
|
|
|
}, |
7321
|
|
|
|
|
|
|
60 => { |
7322
|
|
|
|
|
|
|
Name => 'Channel3Flags', |
7323
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2', |
7324
|
|
|
|
|
|
|
Format => 'int32u', |
7325
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7326
|
|
|
|
|
|
|
}, |
7327
|
|
|
|
|
|
|
64 => { |
7328
|
|
|
|
|
|
|
Name => 'Channel3Coordinates', |
7329
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2', |
7330
|
|
|
|
|
|
|
Format => 'float[3]', |
7331
|
|
|
|
|
|
|
}, |
7332
|
|
|
|
|
|
|
76 => { |
7333
|
|
|
|
|
|
|
Name => 'Channel4Label', |
7334
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3', |
7335
|
|
|
|
|
|
|
Format => 'int32u', |
7336
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7337
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7338
|
|
|
|
|
|
|
}, |
7339
|
|
|
|
|
|
|
80 => { |
7340
|
|
|
|
|
|
|
Name => 'Channel4Flags', |
7341
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3', |
7342
|
|
|
|
|
|
|
Format => 'int32u', |
7343
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7344
|
|
|
|
|
|
|
}, |
7345
|
|
|
|
|
|
|
84 => { |
7346
|
|
|
|
|
|
|
Name => 'Channel4Coordinates', |
7347
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3', |
7348
|
|
|
|
|
|
|
Format => 'float[3]', |
7349
|
|
|
|
|
|
|
}, |
7350
|
|
|
|
|
|
|
96 => { |
7351
|
|
|
|
|
|
|
Name => 'Channel5Label', |
7352
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4', |
7353
|
|
|
|
|
|
|
Format => 'int32u', |
7354
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7355
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7356
|
|
|
|
|
|
|
}, |
7357
|
|
|
|
|
|
|
100 => { |
7358
|
|
|
|
|
|
|
Name => 'Channel5Flags', |
7359
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4', |
7360
|
|
|
|
|
|
|
Format => 'int32u', |
7361
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7362
|
|
|
|
|
|
|
}, |
7363
|
|
|
|
|
|
|
104 => { |
7364
|
|
|
|
|
|
|
Name => 'Channel5Coordinates', |
7365
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4', |
7366
|
|
|
|
|
|
|
Format => 'float[3]', |
7367
|
|
|
|
|
|
|
}, |
7368
|
|
|
|
|
|
|
116 => { |
7369
|
|
|
|
|
|
|
Name => 'Channel6Label', |
7370
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5', |
7371
|
|
|
|
|
|
|
Format => 'int32u', |
7372
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7373
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7374
|
|
|
|
|
|
|
}, |
7375
|
|
|
|
|
|
|
120 => { |
7376
|
|
|
|
|
|
|
Name => 'Channel6Flags', |
7377
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5', |
7378
|
|
|
|
|
|
|
Format => 'int32u', |
7379
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7380
|
|
|
|
|
|
|
}, |
7381
|
|
|
|
|
|
|
124 => { |
7382
|
|
|
|
|
|
|
Name => 'Channel6Coordinates', |
7383
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5', |
7384
|
|
|
|
|
|
|
Format => 'float[3]', |
7385
|
|
|
|
|
|
|
}, |
7386
|
|
|
|
|
|
|
136 => { |
7387
|
|
|
|
|
|
|
Name => 'Channel7Label', |
7388
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6', |
7389
|
|
|
|
|
|
|
Format => 'int32u', |
7390
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7391
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7392
|
|
|
|
|
|
|
}, |
7393
|
|
|
|
|
|
|
140 => { |
7394
|
|
|
|
|
|
|
Name => 'Channel7Flags', |
7395
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6', |
7396
|
|
|
|
|
|
|
Format => 'int32u', |
7397
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7398
|
|
|
|
|
|
|
}, |
7399
|
|
|
|
|
|
|
144 => { |
7400
|
|
|
|
|
|
|
Name => 'Channel7Coordinates', |
7401
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6', |
7402
|
|
|
|
|
|
|
Format => 'float[3]', |
7403
|
|
|
|
|
|
|
}, |
7404
|
|
|
|
|
|
|
156 => { |
7405
|
|
|
|
|
|
|
Name => 'Channel8Label', |
7406
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7', |
7407
|
|
|
|
|
|
|
Format => 'int32u', |
7408
|
|
|
|
|
|
|
SeparateTable => 'ChannelLabel', |
7409
|
|
|
|
|
|
|
PrintConv => \%channelLabel, |
7410
|
|
|
|
|
|
|
}, |
7411
|
|
|
|
|
|
|
160 => { |
7412
|
|
|
|
|
|
|
Name => 'Channel8Flags', |
7413
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7', |
7414
|
|
|
|
|
|
|
Format => 'int32u', |
7415
|
|
|
|
|
|
|
PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }}, |
7416
|
|
|
|
|
|
|
}, |
7417
|
|
|
|
|
|
|
164 => { |
7418
|
|
|
|
|
|
|
Name => 'Channel8Coordinates', |
7419
|
|
|
|
|
|
|
Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7', |
7420
|
|
|
|
|
|
|
Format => 'float[3]', |
7421
|
|
|
|
|
|
|
}, |
7422
|
|
|
|
|
|
|
# (arbitrarily decode only first 8 channels) |
7423
|
|
|
|
|
|
|
); |
7424
|
|
|
|
|
|
|
|
7425
|
|
|
|
|
|
|
# scheme type atom |
7426
|
|
|
|
|
|
|
# ref http://xhelmboyx.tripod.com/formats/mp4-layout.txt |
7427
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::SchemeType = ( |
7428
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
7429
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
7430
|
|
|
|
|
|
|
# 0 - 4 bytes version |
7431
|
|
|
|
|
|
|
4 => { Name => 'SchemeType', Format => 'undef[4]' }, |
7432
|
|
|
|
|
|
|
8 => { Name => 'SchemeVersion', Format => 'int16u' }, |
7433
|
|
|
|
|
|
|
10 => { Name => 'SchemeURL', Format => 'string[$size-10]' }, |
7434
|
|
|
|
|
|
|
); |
7435
|
|
|
|
|
|
|
|
7436
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::SchemeInfo = ( |
7437
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7438
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
7439
|
|
|
|
|
|
|
user => { |
7440
|
|
|
|
|
|
|
Name => 'UserID', |
7441
|
|
|
|
|
|
|
Groups => { 2 => 'Author' }, |
7442
|
|
|
|
|
|
|
ValueConv => '"0x" . unpack("H*",$val)', |
7443
|
|
|
|
|
|
|
}, |
7444
|
|
|
|
|
|
|
cert => { # ref http://www.onvif.org/specs/stream/ONVIF-ExportFileFormat-Spec-v100.pdf |
7445
|
|
|
|
|
|
|
Name => 'Certificate', |
7446
|
|
|
|
|
|
|
ValueConv => '"0x" . unpack("H*",$val)', |
7447
|
|
|
|
|
|
|
}, |
7448
|
|
|
|
|
|
|
'key ' => { |
7449
|
|
|
|
|
|
|
Name => 'KeyID', |
7450
|
|
|
|
|
|
|
ValueConv => '"0x" . unpack("H*",$val)', |
7451
|
|
|
|
|
|
|
}, |
7452
|
|
|
|
|
|
|
iviv => { |
7453
|
|
|
|
|
|
|
Name => 'InitializationVector', |
7454
|
|
|
|
|
|
|
ValueConv => 'unpack("H*",$val)', |
7455
|
|
|
|
|
|
|
}, |
7456
|
|
|
|
|
|
|
righ => { |
7457
|
|
|
|
|
|
|
Name => 'Rights', |
7458
|
|
|
|
|
|
|
Groups => { 2 => 'Author' }, |
7459
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Rights' }, |
7460
|
|
|
|
|
|
|
}, |
7461
|
|
|
|
|
|
|
name => { Name => 'UserName', Groups => { 2 => 'Author' } }, |
7462
|
|
|
|
|
|
|
# chtb |
7463
|
|
|
|
|
|
|
# priv - private data |
7464
|
|
|
|
|
|
|
# sign |
7465
|
|
|
|
|
|
|
# adkm - Adobe DRM key management system (ref http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf) |
7466
|
|
|
|
|
|
|
# iKMS |
7467
|
|
|
|
|
|
|
# iSFM |
7468
|
|
|
|
|
|
|
# iSLT |
7469
|
|
|
|
|
|
|
); |
7470
|
|
|
|
|
|
|
|
7471
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Rights = ( |
7472
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessRights, |
7473
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
7474
|
|
|
|
|
|
|
veID => 'ItemVendorID', #PH ("VendorID" ref 19) |
7475
|
|
|
|
|
|
|
plat => 'Platform', #18? |
7476
|
|
|
|
|
|
|
aver => 'VersionRestrictions', #19 ("appversion?" ref 18) |
7477
|
|
|
|
|
|
|
tran => 'TransactionID', #18 |
7478
|
|
|
|
|
|
|
song => 'ItemID', #19 ("appid" ref 18) |
7479
|
|
|
|
|
|
|
tool => { |
7480
|
|
|
|
|
|
|
Name => 'ItemTool', #PH (guess) ("itunes build?" ref 18) |
7481
|
|
|
|
|
|
|
Format => 'string', |
7482
|
|
|
|
|
|
|
}, |
7483
|
|
|
|
|
|
|
medi => 'MediaFlags', #PH (?) |
7484
|
|
|
|
|
|
|
mode => 'ModeFlags', #PH (?) 0x04 is HD flag (https://compilr.com/heksesang/requiem-mac/UnDrm.java) |
7485
|
|
|
|
|
|
|
); |
7486
|
|
|
|
|
|
|
|
7487
|
|
|
|
|
|
|
# MP4 hint sample description box (ref 5) |
7488
|
|
|
|
|
|
|
# (ref https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-SW1) |
7489
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::HintSampleDesc = ( |
7490
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessHybrid, |
7491
|
|
|
|
|
|
|
VARS => { ID_LABEL => 'ID/Index' }, |
7492
|
|
|
|
|
|
|
NOTES => 'MP4 hint sample description.', |
7493
|
|
|
|
|
|
|
4 => { Name => 'HintFormat', Format => 'undef[4]' }, |
7494
|
|
|
|
|
|
|
# 14 - int16u DataReferenceIndex |
7495
|
|
|
|
|
|
|
16 => { Name => 'HintTrackVersion', Format => 'int16u' }, |
7496
|
|
|
|
|
|
|
# 18 - int16u LastCompatibleHintTrackVersion |
7497
|
|
|
|
|
|
|
20 => { Name => 'MaxPacketSize', Format => 'int32u' }, |
7498
|
|
|
|
|
|
|
# |
7499
|
|
|
|
|
|
|
# Observed offsets for child atoms of various HintFormat types: |
7500
|
|
|
|
|
|
|
# |
7501
|
|
|
|
|
|
|
# HintFormat Offset Child atoms |
7502
|
|
|
|
|
|
|
# ----------- ------ ---------------- |
7503
|
|
|
|
|
|
|
# "rtp " 24 tims |
7504
|
|
|
|
|
|
|
# |
7505
|
|
|
|
|
|
|
tims => { Name => 'RTPTimeScale', Format => 'int32u' }, |
7506
|
|
|
|
|
|
|
tsro => { Name => 'TimestampRandomOffset', Format => 'int32u' }, |
7507
|
|
|
|
|
|
|
snro => { Name => 'SequenceNumberRandomOffset', Format => 'int32u' }, |
7508
|
|
|
|
|
|
|
); |
7509
|
|
|
|
|
|
|
|
7510
|
|
|
|
|
|
|
# MP4 metadata sample description box |
7511
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::MetaSampleDesc = ( |
7512
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessHybrid, |
7513
|
|
|
|
|
|
|
NOTES => 'MP4 metadata sample description.', |
7514
|
|
|
|
|
|
|
4 => { |
7515
|
|
|
|
|
|
|
Name => 'MetaFormat', |
7516
|
|
|
|
|
|
|
Format => 'undef[4]', |
7517
|
|
|
|
|
|
|
RawConv => '$$self{MetaFormat} = $val', |
7518
|
|
|
|
|
|
|
}, |
7519
|
|
|
|
|
|
|
# |
7520
|
|
|
|
|
|
|
# Observed offsets for child atoms of various MetaFormat types: |
7521
|
|
|
|
|
|
|
# |
7522
|
|
|
|
|
|
|
# MetaFormat Offset Child atoms |
7523
|
|
|
|
|
|
|
# ----------- ------ ---------------- |
7524
|
|
|
|
|
|
|
# mebx 24 keys,btrt,lidp,lidl |
7525
|
|
|
|
|
|
|
# fdsc - - |
7526
|
|
|
|
|
|
|
# gpmd - - |
7527
|
|
|
|
|
|
|
# rtmd - - |
7528
|
|
|
|
|
|
|
# CTMD - - |
7529
|
|
|
|
|
|
|
# |
7530
|
|
|
|
|
|
|
'keys' => { #PH (iPhone7+ hevc) |
7531
|
|
|
|
|
|
|
Name => 'Keys', |
7532
|
|
|
|
|
|
|
SubDirectory => { |
7533
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Keys', |
7534
|
|
|
|
|
|
|
ProcessProc => \&ProcessMetaKeys, |
7535
|
|
|
|
|
|
|
}, |
7536
|
|
|
|
|
|
|
}, |
7537
|
|
|
|
|
|
|
btrt => { |
7538
|
|
|
|
|
|
|
Name => 'BitrateInfo', |
7539
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Bitrate' }, |
7540
|
|
|
|
|
|
|
}, |
7541
|
|
|
|
|
|
|
); |
7542
|
|
|
|
|
|
|
|
7543
|
|
|
|
|
|
|
# MP4 generic sample description box |
7544
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::OtherSampleDesc = ( |
7545
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessHybrid, |
7546
|
|
|
|
|
|
|
4 => { |
7547
|
|
|
|
|
|
|
Name => 'OtherFormat', |
7548
|
|
|
|
|
|
|
Format => 'undef[4]', |
7549
|
|
|
|
|
|
|
RawConv => '$$self{MetaFormat} = $val', # (yes, use MetaFormat for this too) |
7550
|
|
|
|
|
|
|
}, |
7551
|
|
|
|
|
|
|
# |
7552
|
|
|
|
|
|
|
# Observed offsets for child atoms of various OtherFormat types: |
7553
|
|
|
|
|
|
|
# |
7554
|
|
|
|
|
|
|
# OtherFormat Offset Child atoms |
7555
|
|
|
|
|
|
|
# ----------- ------ ---------------- |
7556
|
|
|
|
|
|
|
# avc1 86 avcC |
7557
|
|
|
|
|
|
|
# mp4a 36 esds |
7558
|
|
|
|
|
|
|
# mp4s 16 esds |
7559
|
|
|
|
|
|
|
# tmcd 34 name |
7560
|
|
|
|
|
|
|
# data - - |
7561
|
|
|
|
|
|
|
# |
7562
|
|
|
|
|
|
|
ftab => { Name => 'FontTable', Format => 'undef', ValueConv => 'substr($val, 5)' }, |
7563
|
|
|
|
|
|
|
name => { Name => 'OtherName', Format => 'undef', ValueConv => 'substr($val, 4)' }, |
7564
|
|
|
|
|
|
|
# mrlh = GM header? |
7565
|
|
|
|
|
|
|
# mrlv = GM data |
7566
|
|
|
|
|
|
|
# mrld = GM data (448-byte records): |
7567
|
|
|
|
|
|
|
# 0 - int32u count |
7568
|
|
|
|
|
|
|
# 4 - int32u ? (related to units) 0=none,1=m/km,2=L,3=kph,4=C,7=deg,8=rpm,9=kPa,10=G,11=V,15=Nm,16=% |
7569
|
|
|
|
|
|
|
# 8 - int32u ? (0,1,3,4,5) |
7570
|
|
|
|
|
|
|
# 12 - string[64] units |
7571
|
|
|
|
|
|
|
# 76 - int32u ? (1,3,7,15) |
7572
|
|
|
|
|
|
|
# 80 - int32u 0 |
7573
|
|
|
|
|
|
|
# 84 - undef[4] ? |
7574
|
|
|
|
|
|
|
# 88 - int16u[6] ? |
7575
|
|
|
|
|
|
|
# 100 - undef[32] ? |
7576
|
|
|
|
|
|
|
# 132 - string[64] measurement name |
7577
|
|
|
|
|
|
|
# 196 - string[64] measurement name |
7578
|
|
|
|
|
|
|
); |
7579
|
|
|
|
|
|
|
|
7580
|
|
|
|
|
|
|
# MP4 data information box (ref 5) |
7581
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::DataInfo = ( |
7582
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7583
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, # (necessary to parse dref even though we don't change it) |
7584
|
|
|
|
|
|
|
NOTES => 'MP4 data information box.', |
7585
|
|
|
|
|
|
|
dref => { |
7586
|
|
|
|
|
|
|
Name => 'DataRef', |
7587
|
|
|
|
|
|
|
SubDirectory => { |
7588
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::DataRef', |
7589
|
|
|
|
|
|
|
Start => 8, |
7590
|
|
|
|
|
|
|
}, |
7591
|
|
|
|
|
|
|
}, |
7592
|
|
|
|
|
|
|
); |
7593
|
|
|
|
|
|
|
|
7594
|
|
|
|
|
|
|
# Generic media header |
7595
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::GenMediaHeader = ( |
7596
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7597
|
|
|
|
|
|
|
gmin => { |
7598
|
|
|
|
|
|
|
Name => 'GenMediaInfo', |
7599
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::GenMediaInfo' }, |
7600
|
|
|
|
|
|
|
}, |
7601
|
|
|
|
|
|
|
text => { |
7602
|
|
|
|
|
|
|
Name => 'Text', |
7603
|
|
|
|
|
|
|
Flags => ['Binary','Unknown'], |
7604
|
|
|
|
|
|
|
}, |
7605
|
|
|
|
|
|
|
tmcd => { |
7606
|
|
|
|
|
|
|
Name => 'TimeCode', |
7607
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TimeCode' }, |
7608
|
|
|
|
|
|
|
}, |
7609
|
|
|
|
|
|
|
); |
7610
|
|
|
|
|
|
|
|
7611
|
|
|
|
|
|
|
# TimeCode header |
7612
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::TimeCode = ( |
7613
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7614
|
|
|
|
|
|
|
tcmi => { |
7615
|
|
|
|
|
|
|
Name => 'TCMediaInfo', |
7616
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TCMediaInfo' }, |
7617
|
|
|
|
|
|
|
}, |
7618
|
|
|
|
|
|
|
); |
7619
|
|
|
|
|
|
|
|
7620
|
|
|
|
|
|
|
# TimeCode media info (ref 12) |
7621
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::TCMediaInfo = ( |
7622
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
7623
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
7624
|
|
|
|
|
|
|
4 => { |
7625
|
|
|
|
|
|
|
Name => 'TextFont', |
7626
|
|
|
|
|
|
|
Format => 'int16u', |
7627
|
|
|
|
|
|
|
PrintConv => { 0 => 'System' }, |
7628
|
|
|
|
|
|
|
}, |
7629
|
|
|
|
|
|
|
6 => { |
7630
|
|
|
|
|
|
|
Name => 'TextFace', |
7631
|
|
|
|
|
|
|
Format => 'int16u', |
7632
|
|
|
|
|
|
|
PrintConv => { |
7633
|
|
|
|
|
|
|
0 => 'Plain', |
7634
|
|
|
|
|
|
|
BITMASK => { |
7635
|
|
|
|
|
|
|
0 => 'Bold', |
7636
|
|
|
|
|
|
|
1 => 'Italic', |
7637
|
|
|
|
|
|
|
2 => 'Underline', |
7638
|
|
|
|
|
|
|
3 => 'Outline', |
7639
|
|
|
|
|
|
|
4 => 'Shadow', |
7640
|
|
|
|
|
|
|
5 => 'Condense', |
7641
|
|
|
|
|
|
|
6 => 'Extend', |
7642
|
|
|
|
|
|
|
}, |
7643
|
|
|
|
|
|
|
}, |
7644
|
|
|
|
|
|
|
}, |
7645
|
|
|
|
|
|
|
8 => { |
7646
|
|
|
|
|
|
|
Name => 'TextSize', |
7647
|
|
|
|
|
|
|
Format => 'int16u', |
7648
|
|
|
|
|
|
|
}, |
7649
|
|
|
|
|
|
|
# 10 - reserved |
7650
|
|
|
|
|
|
|
12 => { |
7651
|
|
|
|
|
|
|
Name => 'TextColor', |
7652
|
|
|
|
|
|
|
Format => 'int16u[3]', |
7653
|
|
|
|
|
|
|
}, |
7654
|
|
|
|
|
|
|
18 => { |
7655
|
|
|
|
|
|
|
Name => 'BackgroundColor', |
7656
|
|
|
|
|
|
|
Format => 'int16u[3]', |
7657
|
|
|
|
|
|
|
}, |
7658
|
|
|
|
|
|
|
24 => { |
7659
|
|
|
|
|
|
|
Name => 'FontName', |
7660
|
|
|
|
|
|
|
Format => 'pstring', |
7661
|
|
|
|
|
|
|
ValueConv => '$self->Decode($val, $self->Options("CharsetQuickTime"))', |
7662
|
|
|
|
|
|
|
}, |
7663
|
|
|
|
|
|
|
); |
7664
|
|
|
|
|
|
|
|
7665
|
|
|
|
|
|
|
# Generic media info (ref http://sourceforge.jp/cvs/view/ntvrec/ntvrec/libqtime/gmin.h?view=co) |
7666
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::GenMediaInfo = ( |
7667
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
7668
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
7669
|
|
|
|
|
|
|
0 => 'GenMediaVersion', |
7670
|
|
|
|
|
|
|
1 => { Name => 'GenFlags', Format => 'int8u[3]' }, |
7671
|
|
|
|
|
|
|
4 => { Name => 'GenGraphicsMode', |
7672
|
|
|
|
|
|
|
Format => 'int16u', |
7673
|
|
|
|
|
|
|
PrintHex => 1, |
7674
|
|
|
|
|
|
|
SeparateTable => 'GraphicsMode', |
7675
|
|
|
|
|
|
|
PrintConv => \%graphicsMode, |
7676
|
|
|
|
|
|
|
}, |
7677
|
|
|
|
|
|
|
6 => { Name => 'GenOpColor', Format => 'int16u[3]' }, |
7678
|
|
|
|
|
|
|
12 => { Name => 'GenBalance', Format => 'fixed16s' }, |
7679
|
|
|
|
|
|
|
); |
7680
|
|
|
|
|
|
|
|
7681
|
|
|
|
|
|
|
# MP4 data reference box (ref 5) |
7682
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::DataRef = ( |
7683
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7684
|
|
|
|
|
|
|
WRITE_PROC => \&WriteQuickTime, # (necessary to parse dref even though we don't change it) |
7685
|
|
|
|
|
|
|
NOTES => 'MP4 data reference box.', |
7686
|
|
|
|
|
|
|
'url ' => { |
7687
|
|
|
|
|
|
|
Name => 'URL', |
7688
|
|
|
|
|
|
|
Format => 'undef', # (necessary to prevent decoding as string!) |
7689
|
|
|
|
|
|
|
RawConv => q{ |
7690
|
|
|
|
|
|
|
# ignore if self-contained (flags bit 0 set) |
7691
|
|
|
|
|
|
|
return undef if unpack("N",$val) & 0x01; |
7692
|
|
|
|
|
|
|
$_ = substr($val,4); s/\0.*//s; $_; |
7693
|
|
|
|
|
|
|
}, |
7694
|
|
|
|
|
|
|
}, |
7695
|
|
|
|
|
|
|
"url\0" => { # (written by GoPro) |
7696
|
|
|
|
|
|
|
Name => 'URL', |
7697
|
|
|
|
|
|
|
Format => 'undef', # (necessary to prevent decoding as string!) |
7698
|
|
|
|
|
|
|
RawConv => q{ |
7699
|
|
|
|
|
|
|
# ignore if self-contained (flags bit 0 set) |
7700
|
|
|
|
|
|
|
return undef if unpack("N",$val) & 0x01; |
7701
|
|
|
|
|
|
|
$_ = substr($val,4); s/\0.*//s; $_; |
7702
|
|
|
|
|
|
|
}, |
7703
|
|
|
|
|
|
|
}, |
7704
|
|
|
|
|
|
|
'urn ' => { |
7705
|
|
|
|
|
|
|
Name => 'URN', |
7706
|
|
|
|
|
|
|
Format => 'undef', # (necessary to prevent decoding as string!) |
7707
|
|
|
|
|
|
|
RawConv => q{ |
7708
|
|
|
|
|
|
|
return undef if unpack("N",$val) & 0x01; |
7709
|
|
|
|
|
|
|
$_ = substr($val,4); s/\0+/; /; s/\0.*//s; $_; |
7710
|
|
|
|
|
|
|
}, |
7711
|
|
|
|
|
|
|
}, |
7712
|
|
|
|
|
|
|
); |
7713
|
|
|
|
|
|
|
|
7714
|
|
|
|
|
|
|
# MP4 handler box (ref 5) |
7715
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Handler = ( |
7716
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
7717
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
7718
|
|
|
|
|
|
|
4 => { #PH |
7719
|
|
|
|
|
|
|
Name => 'HandlerClass', |
7720
|
|
|
|
|
|
|
Format => 'undef[4]', |
7721
|
|
|
|
|
|
|
RawConv => '$val eq "\0\0\0\0" ? undef : $val', |
7722
|
|
|
|
|
|
|
PrintConv => { |
7723
|
|
|
|
|
|
|
mhlr => 'Media Handler', |
7724
|
|
|
|
|
|
|
dhlr => 'Data Handler', |
7725
|
|
|
|
|
|
|
}, |
7726
|
|
|
|
|
|
|
}, |
7727
|
|
|
|
|
|
|
8 => { |
7728
|
|
|
|
|
|
|
Name => 'HandlerType', |
7729
|
|
|
|
|
|
|
Format => 'undef[4]', |
7730
|
|
|
|
|
|
|
RawConv => q{ |
7731
|
|
|
|
|
|
|
$$self{HandlerType} = $val unless $val eq 'alis' or $val eq 'url '; |
7732
|
|
|
|
|
|
|
$$self{HasHandler}{$val} = 1; # remember all our handlers |
7733
|
|
|
|
|
|
|
return $val; |
7734
|
|
|
|
|
|
|
}, |
7735
|
|
|
|
|
|
|
PrintConvColumns => 2, |
7736
|
|
|
|
|
|
|
PrintConv => { |
7737
|
|
|
|
|
|
|
alis => 'Alias Data', #PH |
7738
|
|
|
|
|
|
|
crsm => 'Clock Reference', #3 |
7739
|
|
|
|
|
|
|
hint => 'Hint Track', |
7740
|
|
|
|
|
|
|
ipsm => 'IPMP', #3 |
7741
|
|
|
|
|
|
|
m7sm => 'MPEG-7 Stream', #3 |
7742
|
|
|
|
|
|
|
meta => 'NRT Metadata', #PH |
7743
|
|
|
|
|
|
|
mdir => 'Metadata', #3 |
7744
|
|
|
|
|
|
|
mdta => 'Metadata Tags', #PH |
7745
|
|
|
|
|
|
|
mjsm => 'MPEG-J', #3 |
7746
|
|
|
|
|
|
|
ocsm => 'Object Content', #3 |
7747
|
|
|
|
|
|
|
odsm => 'Object Descriptor', #3 |
7748
|
|
|
|
|
|
|
priv => 'Private', #PH |
7749
|
|
|
|
|
|
|
sdsm => 'Scene Description', #3 |
7750
|
|
|
|
|
|
|
soun => 'Audio Track', |
7751
|
|
|
|
|
|
|
text => 'Text', #PH (but what type? subtitle?) |
7752
|
|
|
|
|
|
|
tmcd => 'Time Code', #PH |
7753
|
|
|
|
|
|
|
'url '=> 'URL', #3 |
7754
|
|
|
|
|
|
|
vide => 'Video Track', |
7755
|
|
|
|
|
|
|
subp => 'Subpicture', #http://www.google.nl/patents/US7778526 |
7756
|
|
|
|
|
|
|
nrtm => 'Non-Real Time Metadata', #PH (Sony ILCE-7S) [how is this different from "meta"?] |
7757
|
|
|
|
|
|
|
pict => 'Picture', # (HEIC images) |
7758
|
|
|
|
|
|
|
camm => 'Camera Metadata', # (Insta360 MP4) |
7759
|
|
|
|
|
|
|
psmd => 'Panasonic Static Metadata', #PH (Leica C-Lux CAM-DC25) |
7760
|
|
|
|
|
|
|
data => 'Data', #PH (GPS and G-sensor data from DataKam) |
7761
|
|
|
|
|
|
|
sbtl => 'Subtitle', #PH (TomTom Bandit Action Cam) |
7762
|
|
|
|
|
|
|
}, |
7763
|
|
|
|
|
|
|
}, |
7764
|
|
|
|
|
|
|
12 => { #PH |
7765
|
|
|
|
|
|
|
Name => 'HandlerVendorID', |
7766
|
|
|
|
|
|
|
Format => 'undef[4]', |
7767
|
|
|
|
|
|
|
RawConv => '$val eq "\0\0\0\0" ? undef : $val', |
7768
|
|
|
|
|
|
|
PrintConv => \%vendorID, |
7769
|
|
|
|
|
|
|
SeparateTable => 'VendorID', |
7770
|
|
|
|
|
|
|
}, |
7771
|
|
|
|
|
|
|
24 => { |
7772
|
|
|
|
|
|
|
Name => 'HandlerDescription', |
7773
|
|
|
|
|
|
|
Format => 'string', |
7774
|
|
|
|
|
|
|
# (sometimes this is a Pascal string, and sometimes it is a C string) |
7775
|
|
|
|
|
|
|
RawConv => q{ |
7776
|
|
|
|
|
|
|
$val=substr($val,1,ord($1)) if $val=~/^([\0-\x1f])/ and ord($1)
|
7777
|
|
|
|
|
|
|
length $val ? $val : undef; |
7778
|
|
|
|
|
|
|
}, |
7779
|
|
|
|
|
|
|
}, |
7780
|
|
|
|
|
|
|
); |
7781
|
|
|
|
|
|
|
|
7782
|
|
|
|
|
|
|
# Flip uuid data (ref PH) |
7783
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Flip = ( |
7784
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
7785
|
|
|
|
|
|
|
FORMAT => 'int32u', |
7786
|
|
|
|
|
|
|
FIRST_ENTRY => 0, |
7787
|
|
|
|
|
|
|
NOTES => 'Found in MP4 files from Flip Video cameras.', |
7788
|
|
|
|
|
|
|
GROUPS => { 1 => 'MakerNotes', 2 => 'Image' }, |
7789
|
|
|
|
|
|
|
1 => 'PreviewImageWidth', |
7790
|
|
|
|
|
|
|
2 => 'PreviewImageHeight', |
7791
|
|
|
|
|
|
|
13 => 'PreviewImageLength', |
7792
|
|
|
|
|
|
|
14 => { # (confirmed for FlipVideoMinoHD) |
7793
|
|
|
|
|
|
|
Name => 'SerialNumber', |
7794
|
|
|
|
|
|
|
Groups => { 2 => 'Camera' }, |
7795
|
|
|
|
|
|
|
Format => 'string[16]', |
7796
|
|
|
|
|
|
|
}, |
7797
|
|
|
|
|
|
|
28 => { |
7798
|
|
|
|
|
|
|
Name => 'PreviewImage', |
7799
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
7800
|
|
|
|
|
|
|
Format => 'undef[$val{13}]', |
7801
|
|
|
|
|
|
|
RawConv => '$self->ValidateImage(\$val, $tag)', |
7802
|
|
|
|
|
|
|
}, |
7803
|
|
|
|
|
|
|
); |
7804
|
|
|
|
|
|
|
|
7805
|
|
|
|
|
|
|
# atoms in Pittasoft "free" atom |
7806
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Pittasoft = ( |
7807
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessMOV, |
7808
|
|
|
|
|
|
|
NOTES => 'Tags found in Pittasoft Blackvue dashcam "free" data.', |
7809
|
|
|
|
|
|
|
cprt => 'Copyright', |
7810
|
|
|
|
|
|
|
thum => { |
7811
|
|
|
|
|
|
|
Name => 'PreviewImage', |
7812
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
7813
|
|
|
|
|
|
|
Binary => 1, |
7814
|
|
|
|
|
|
|
RawConv => q{ |
7815
|
|
|
|
|
|
|
return undef unless length $val > 4; |
7816
|
|
|
|
|
|
|
my $len = unpack('N', $val); |
7817
|
|
|
|
|
|
|
return undef unless length $val >= 4 + $len; |
7818
|
|
|
|
|
|
|
return substr($val, 4, $len); |
7819
|
|
|
|
|
|
|
}, |
7820
|
|
|
|
|
|
|
}, |
7821
|
|
|
|
|
|
|
ptnm => { |
7822
|
|
|
|
|
|
|
Name => 'OriginalFileName', |
7823
|
|
|
|
|
|
|
ValueConv => 'substr($val, 4, -1)', |
7824
|
|
|
|
|
|
|
}, |
7825
|
|
|
|
|
|
|
ptrh => { |
7826
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Pittasoft' }, |
7827
|
|
|
|
|
|
|
# contains these atoms: |
7828
|
|
|
|
|
|
|
# ptvi - 27 bytes: '..avc1...' |
7829
|
|
|
|
|
|
|
# ptso - 16 bytes: '..mp4a...' |
7830
|
|
|
|
|
|
|
}, |
7831
|
|
|
|
|
|
|
'gps ' => { |
7832
|
|
|
|
|
|
|
Name => 'GPSLog', |
7833
|
|
|
|
|
|
|
Binary => 1, # (ASCII NMEA track log with leading timestamps) |
7834
|
|
|
|
|
|
|
Notes => 'parsed to extract GPS separately when ExtractEmbedded is used', |
7835
|
|
|
|
|
|
|
RawConv => q{ |
7836
|
|
|
|
|
|
|
$val =~ s/\0+$//; # remove trailing nulls |
7837
|
|
|
|
|
|
|
if (length $val and $$self{OPTIONS}{ExtractEmbedded}) { |
7838
|
|
|
|
|
|
|
my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream'); |
7839
|
|
|
|
|
|
|
Image::ExifTool::QuickTime::ProcessGPSLog($self, { DataPt => \$val }, $tagTbl); |
7840
|
|
|
|
|
|
|
} |
7841
|
|
|
|
|
|
|
return $val; |
7842
|
|
|
|
|
|
|
}, |
7843
|
|
|
|
|
|
|
}, |
7844
|
|
|
|
|
|
|
'3gf ' => { |
7845
|
|
|
|
|
|
|
Name => 'AccelData', |
7846
|
|
|
|
|
|
|
SubDirectory => { |
7847
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
7848
|
|
|
|
|
|
|
ProcessProc => \&Process_3gf, |
7849
|
|
|
|
|
|
|
}, |
7850
|
|
|
|
|
|
|
}, |
7851
|
|
|
|
|
|
|
sttm => { |
7852
|
|
|
|
|
|
|
Name => 'StartTime', |
7853
|
|
|
|
|
|
|
Format => 'int64u', |
7854
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
7855
|
|
|
|
|
|
|
RawConv => '$$self{StartTime} = $val', |
7856
|
|
|
|
|
|
|
# (ms since Jan 1, 1970, in local time zone - PH) |
7857
|
|
|
|
|
|
|
ValueConv => q{ |
7858
|
|
|
|
|
|
|
my $secs = int($val / 1000); |
7859
|
|
|
|
|
|
|
return ConvertUnixTime($secs) . sprintf(".%03d",$val - $secs * 1000); |
7860
|
|
|
|
|
|
|
}, |
7861
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
7862
|
|
|
|
|
|
|
}, |
7863
|
|
|
|
|
|
|
); |
7864
|
|
|
|
|
|
|
|
7865
|
|
|
|
|
|
|
# QuickTime composite tags |
7866
|
|
|
|
|
|
|
%Image::ExifTool::QuickTime::Composite = ( |
7867
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
7868
|
|
|
|
|
|
|
Rotation => { |
7869
|
|
|
|
|
|
|
Notes => q{ |
7870
|
|
|
|
|
|
|
writing this tag updates QuickTime MatrixStructure for all tracks with a |
7871
|
|
|
|
|
|
|
non-zero image size |
7872
|
|
|
|
|
|
|
}, |
7873
|
|
|
|
|
|
|
Require => { |
7874
|
|
|
|
|
|
|
0 => 'QuickTime:MatrixStructure', |
7875
|
|
|
|
|
|
|
1 => 'QuickTime:HandlerType', |
7876
|
|
|
|
|
|
|
}, |
7877
|
|
|
|
|
|
|
Writable => 1, |
7878
|
|
|
|
|
|
|
Protected => 1, |
7879
|
|
|
|
|
|
|
WriteAlso => { |
7880
|
|
|
|
|
|
|
MatrixStructure => 'Image::ExifTool::QuickTime::GetRotationMatrix($val)', |
7881
|
|
|
|
|
|
|
}, |
7882
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::QuickTime::CalcRotation($self)', |
7883
|
|
|
|
|
|
|
ValueConvInv => '$val', |
7884
|
|
|
|
|
|
|
}, |
7885
|
|
|
|
|
|
|
AvgBitrate => { |
7886
|
|
|
|
|
|
|
Priority => 0, # let QuickTime::AvgBitrate take priority |
7887
|
|
|
|
|
|
|
Require => { |
7888
|
|
|
|
|
|
|
0 => 'QuickTime::MediaDataSize', |
7889
|
|
|
|
|
|
|
1 => 'QuickTime::Duration', |
7890
|
|
|
|
|
|
|
}, |
7891
|
|
|
|
|
|
|
RawConv => q{ |
7892
|
|
|
|
|
|
|
return undef unless $val[1]; |
7893
|
|
|
|
|
|
|
$val[1] /= $$self{TimeScale} if $$self{TimeScale}; |
7894
|
|
|
|
|
|
|
my $key = 'MediaDataSize'; |
7895
|
|
|
|
|
|
|
my $size = $val[0]; |
7896
|
|
|
|
|
|
|
for (;;) { |
7897
|
|
|
|
|
|
|
$key = $self->NextTagKey($key) or last; |
7898
|
|
|
|
|
|
|
$size += $self->GetValue($key, 'ValueConv'); |
7899
|
|
|
|
|
|
|
} |
7900
|
|
|
|
|
|
|
return int($size * 8 / $val[1] + 0.5); |
7901
|
|
|
|
|
|
|
}, |
7902
|
|
|
|
|
|
|
PrintConv => 'ConvertBitrate($val)', |
7903
|
|
|
|
|
|
|
}, |
7904
|
|
|
|
|
|
|
GPSLatitude => { |
7905
|
|
|
|
|
|
|
Require => 'QuickTime:GPSCoordinates', |
7906
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7907
|
|
|
|
|
|
|
ValueConv => 'my @c = split " ", $val; $c[0]', |
7908
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', |
7909
|
|
|
|
|
|
|
}, |
7910
|
|
|
|
|
|
|
GPSLongitude => { |
7911
|
|
|
|
|
|
|
Require => 'QuickTime:GPSCoordinates', |
7912
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7913
|
|
|
|
|
|
|
ValueConv => 'my @c = split " ", $val; $c[1]', |
7914
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', |
7915
|
|
|
|
|
|
|
}, |
7916
|
|
|
|
|
|
|
# split altitude into GPSAltitude/GPSAltitudeRef like EXIF and XMP |
7917
|
|
|
|
|
|
|
GPSAltitude => { |
7918
|
|
|
|
|
|
|
Require => 'QuickTime:GPSCoordinates', |
7919
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7920
|
|
|
|
|
|
|
Priority => 0, # (because it may not exist) |
7921
|
|
|
|
|
|
|
ValueConv => 'my @c = split " ", $val; defined $c[2] ? abs($c[2]) : undef', |
7922
|
|
|
|
|
|
|
PrintConv => '"$val m"', |
7923
|
|
|
|
|
|
|
}, |
7924
|
|
|
|
|
|
|
GPSAltitudeRef => { |
7925
|
|
|
|
|
|
|
Require => 'QuickTime:GPSCoordinates', |
7926
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7927
|
|
|
|
|
|
|
Priority => 0, # (because altitude information may not exist) |
7928
|
|
|
|
|
|
|
ValueConv => 'my @c = split " ", $val; defined $c[2] ? ($c[2] < 0 ? 1 : 0) : undef', |
7929
|
|
|
|
|
|
|
PrintConv => { |
7930
|
|
|
|
|
|
|
0 => 'Above Sea Level', |
7931
|
|
|
|
|
|
|
1 => 'Below Sea Level', |
7932
|
|
|
|
|
|
|
}, |
7933
|
|
|
|
|
|
|
}, |
7934
|
|
|
|
|
|
|
GPSLatitude2 => { |
7935
|
|
|
|
|
|
|
Name => 'GPSLatitude', |
7936
|
|
|
|
|
|
|
Require => 'QuickTime:LocationInformation', |
7937
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7938
|
|
|
|
|
|
|
ValueConv => '$val =~ /Lat=([-+.\d]+)/; $1', |
7939
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', |
7940
|
|
|
|
|
|
|
}, |
7941
|
|
|
|
|
|
|
GPSLongitude2 => { |
7942
|
|
|
|
|
|
|
Name => 'GPSLongitude', |
7943
|
|
|
|
|
|
|
Require => 'QuickTime:LocationInformation', |
7944
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7945
|
|
|
|
|
|
|
ValueConv => '$val =~ /Lon=([-+.\d]+)/; $1', |
7946
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', |
7947
|
|
|
|
|
|
|
}, |
7948
|
|
|
|
|
|
|
GPSAltitude2 => { |
7949
|
|
|
|
|
|
|
Name => 'GPSAltitude', |
7950
|
|
|
|
|
|
|
Require => 'QuickTime:LocationInformation', |
7951
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7952
|
|
|
|
|
|
|
ValueConv => '$val =~ /Alt=([-+.\d]+)/; abs($1)', |
7953
|
|
|
|
|
|
|
PrintConv => '"$val m"', |
7954
|
|
|
|
|
|
|
}, |
7955
|
|
|
|
|
|
|
GPSAltitudeRef2 => { |
7956
|
|
|
|
|
|
|
Name => 'GPSAltitudeRef', |
7957
|
|
|
|
|
|
|
Require => 'QuickTime:LocationInformation', |
7958
|
|
|
|
|
|
|
Groups => { 2 => 'Location' }, |
7959
|
|
|
|
|
|
|
ValueConv => '$val =~ /Alt=([-+.\d]+)/; $1 < 0 ? 1 : 0', |
7960
|
|
|
|
|
|
|
PrintConv => { |
7961
|
|
|
|
|
|
|
0 => 'Above Sea Level', |
7962
|
|
|
|
|
|
|
1 => 'Below Sea Level', |
7963
|
|
|
|
|
|
|
}, |
7964
|
|
|
|
|
|
|
}, |
7965
|
|
|
|
|
|
|
CDDBDiscPlayTime => { |
7966
|
|
|
|
|
|
|
Require => 'CDDB1Info', |
7967
|
|
|
|
|
|
|
Groups => { 2 => 'Audio' }, |
7968
|
|
|
|
|
|
|
ValueConv => '$val =~ /^..([a-z0-9]{4})/i ? hex($1) : undef', |
7969
|
|
|
|
|
|
|
PrintConv => 'ConvertDuration($val)', |
7970
|
|
|
|
|
|
|
}, |
7971
|
|
|
|
|
|
|
CDDBDiscTracks => { |
7972
|
|
|
|
|
|
|
Require => 'CDDB1Info', |
7973
|
|
|
|
|
|
|
Groups => { 2 => 'Audio' }, |
7974
|
|
|
|
|
|
|
ValueConv => '$val =~ /^.{6}([a-z0-9]{2})/i ? hex($1) : undef', |
7975
|
|
|
|
|
|
|
}, |
7976
|
|
|
|
|
|
|
); |
7977
|
|
|
|
|
|
|
|
7978
|
|
|
|
|
|
|
# add our composite tags |
7979
|
|
|
|
|
|
|
Image::ExifTool::AddCompositeTags('Image::ExifTool::QuickTime'); |
7980
|
|
|
|
|
|
|
|
7981
|
|
|
|
|
|
|
|
7982
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
7983
|
|
|
|
|
|
|
# AutoLoad our routines when necessary |
7984
|
|
|
|
|
|
|
# |
7985
|
|
|
|
|
|
|
sub AUTOLOAD |
7986
|
|
|
|
|
|
|
{ |
7987
|
|
|
|
|
|
|
# (Note: no need to autoload routines in QuickTimeStream that use Stream table) |
7988
|
22
|
50
|
|
22
|
|
110
|
if ($AUTOLOAD eq 'Image::ExifTool::QuickTime::Process_mebx') { |
7989
|
0
|
|
|
|
|
0
|
require 'Image/ExifTool/QuickTimeStream.pl'; |
7990
|
29
|
|
|
29
|
|
310
|
no strict 'refs'; |
|
29
|
|
|
|
|
64
|
|
|
29
|
|
|
|
|
316929
|
|
7991
|
0
|
|
|
|
|
0
|
return &$AUTOLOAD(@_); |
7992
|
|
|
|
|
|
|
} else { |
7993
|
22
|
|
|
|
|
123
|
return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_); |
7994
|
|
|
|
|
|
|
} |
7995
|
|
|
|
|
|
|
} |
7996
|
|
|
|
|
|
|
|
7997
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
7998
|
|
|
|
|
|
|
# Get rotation matrix |
7999
|
|
|
|
|
|
|
# Inputs: 0) angle in degrees |
8000
|
|
|
|
|
|
|
# Returns: 9-element rotation matrix as a string (with 0 x/y offsets) |
8001
|
|
|
|
|
|
|
sub GetRotationMatrix($) |
8002
|
|
|
|
|
|
|
{ |
8003
|
1
|
|
|
1
|
0
|
7
|
my $ang = 3.1415926536 * shift() / 180; |
8004
|
1
|
|
|
|
|
13
|
my $cos = cos $ang; |
8005
|
1
|
|
|
|
|
22
|
my $sin = sin $ang; |
8006
|
1
|
|
|
|
|
4
|
my $msn = -$sin; |
8007
|
1
|
|
|
|
|
26
|
return "$cos $sin 0 $msn $cos 0 0 0 1"; |
8008
|
|
|
|
|
|
|
} |
8009
|
|
|
|
|
|
|
|
8010
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8011
|
|
|
|
|
|
|
# Get rotation angle from a matrix |
8012
|
|
|
|
|
|
|
# Inputs: 0) rotation matrix as a string |
8013
|
|
|
|
|
|
|
# Return: positive rotation angle in degrees rounded to 3 decimal points, |
8014
|
|
|
|
|
|
|
# or undef on error |
8015
|
|
|
|
|
|
|
sub GetRotationAngle($) |
8016
|
|
|
|
|
|
|
{ |
8017
|
5
|
|
|
5
|
0
|
11
|
my $rotMatrix = shift; |
8018
|
5
|
|
|
|
|
27
|
my @a = split ' ', $rotMatrix; |
8019
|
5
|
50
|
66
|
|
|
26
|
return undef if $a[0]==0 and $a[1]==0; |
8020
|
|
|
|
|
|
|
# calculate the rotation angle (assume uniform rotation) |
8021
|
5
|
|
|
|
|
40
|
my $angle = atan2($a[1], $a[0]) * 180 / 3.14159; |
8022
|
5
|
100
|
|
|
|
15
|
$angle += 360 if $angle < 0; |
8023
|
5
|
|
|
|
|
56
|
return int($angle * 1000 + 0.5) / 1000; |
8024
|
|
|
|
|
|
|
} |
8025
|
|
|
|
|
|
|
|
8026
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8027
|
|
|
|
|
|
|
# Calculate rotation of video track |
8028
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref |
8029
|
|
|
|
|
|
|
# Returns: rotation angle or undef |
8030
|
|
|
|
|
|
|
sub CalcRotation($) |
8031
|
|
|
|
|
|
|
{ |
8032
|
5
|
|
|
5
|
0
|
14
|
my $et = shift; |
8033
|
5
|
|
|
|
|
13
|
my $value = $$et{VALUE}; |
8034
|
5
|
|
|
|
|
9
|
my ($i, $track); |
8035
|
|
|
|
|
|
|
# get the video track family 1 group (eg. "Track1"); |
8036
|
5
|
|
|
|
|
12
|
for ($i=0; ; ++$i) { |
8037
|
11
|
100
|
|
|
|
34
|
my $idx = $i ? " ($i)" : ''; |
8038
|
11
|
|
|
|
|
23
|
my $tag = "HandlerType$idx"; |
8039
|
11
|
100
|
|
|
|
28
|
last unless $$value{$tag}; |
8040
|
10
|
100
|
|
|
|
30
|
next unless $$value{$tag} eq 'vide'; |
8041
|
4
|
|
|
|
|
16
|
$track = $et->GetGroup($tag, 1); |
8042
|
4
|
|
|
|
|
10
|
last; |
8043
|
|
|
|
|
|
|
} |
8044
|
5
|
100
|
|
|
|
21
|
return undef unless $track; |
8045
|
|
|
|
|
|
|
# get the video track matrix |
8046
|
4
|
|
|
|
|
9
|
for ($i=0; ; ++$i) { |
8047
|
12
|
100
|
|
|
|
59
|
my $idx = $i ? " ($i)" : ''; |
8048
|
12
|
|
|
|
|
37
|
my $tag = "MatrixStructure$idx"; |
8049
|
12
|
50
|
|
|
|
29
|
last unless $$value{$tag}; |
8050
|
12
|
100
|
|
|
|
30
|
next unless $et->GetGroup($tag, 1) eq $track; |
8051
|
4
|
|
|
|
|
22
|
return GetRotationAngle($$value{$tag}); |
8052
|
|
|
|
|
|
|
} |
8053
|
0
|
|
|
|
|
0
|
return undef; |
8054
|
|
|
|
|
|
|
} |
8055
|
|
|
|
|
|
|
|
8056
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8057
|
|
|
|
|
|
|
# Get MatrixStructure for a given rotation angle |
8058
|
|
|
|
|
|
|
# Inputs: 0) rotation angle (deg), 1) ExifTool ref |
8059
|
|
|
|
|
|
|
# Returns: matrix structure as a string, or undef if it can't be rotated |
8060
|
|
|
|
|
|
|
# - requires ImageSizeLookahead to determine the video image size, and doesn't |
8061
|
|
|
|
|
|
|
# rotate matrix unless image size is valid |
8062
|
|
|
|
|
|
|
sub GetMatrixStructure($$) |
8063
|
|
|
|
|
|
|
{ |
8064
|
2
|
|
|
2
|
0
|
5
|
my ($val, $et) = @_; |
8065
|
2
|
|
|
|
|
11
|
my @a = split ' ', $val; |
8066
|
|
|
|
|
|
|
# pass straight through if it already has an offset |
8067
|
2
|
50
|
33
|
|
|
11
|
return $val unless $a[6] == 0 and $a[7] == 0; |
8068
|
2
|
|
|
|
|
39
|
my @s = split ' ', $$et{ImageSizeLookahead}; |
8069
|
2
|
|
|
|
|
8
|
my ($w, $h) = @s[12,13]; |
8070
|
2
|
100
|
66
|
|
|
14
|
return undef unless $w and $h; # don't rotate 0-sized track |
8071
|
1
|
|
|
|
|
7
|
$_ = Image::ExifTool::QuickTime::FixWrongFormat($_) foreach $w,$h; |
8072
|
|
|
|
|
|
|
# apply necessary offsets for the standard rotations |
8073
|
1
|
|
|
|
|
5
|
my $angle = GetRotationAngle($val); |
8074
|
1
|
50
|
|
|
|
5
|
return undef unless defined $angle; |
8075
|
1
|
50
|
|
|
|
8
|
if ($angle == 90) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
8076
|
0
|
|
|
|
|
0
|
@a[6,7] = ($h, 0); |
8077
|
|
|
|
|
|
|
} elsif ($angle == 180) { |
8078
|
0
|
|
|
|
|
0
|
@a[6,7] = ($w, $h); |
8079
|
|
|
|
|
|
|
} elsif ($angle == 270) { |
8080
|
1
|
|
|
|
|
3
|
@a[6,7] = (0, $w); |
8081
|
|
|
|
|
|
|
} |
8082
|
1
|
|
|
|
|
6
|
return "@a"; |
8083
|
|
|
|
|
|
|
} |
8084
|
|
|
|
|
|
|
|
8085
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8086
|
|
|
|
|
|
|
# Determine the average sample rate from a time-to-sample table |
8087
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) time-to-sample table data ref |
8088
|
|
|
|
|
|
|
# Returns: average sample rate (in Hz) |
8089
|
|
|
|
|
|
|
sub CalcSampleRate($$) |
8090
|
|
|
|
|
|
|
{ |
8091
|
21
|
|
|
21
|
0
|
70
|
my ($et, $valPt) = @_; |
8092
|
21
|
|
|
|
|
85
|
my @dat = unpack('N*', $$valPt); |
8093
|
21
|
|
|
|
|
57
|
my ($num, $dur) = (0, 0); |
8094
|
21
|
|
|
|
|
30
|
my $i; |
8095
|
21
|
|
|
|
|
83
|
for ($i=2; $i<@dat-1; $i+=2) { |
8096
|
21
|
|
|
|
|
54
|
$num += $dat[$i]; # total number of samples |
8097
|
21
|
|
|
|
|
80
|
$dur += $dat[$i] * $dat[$i+1]; # total sample duration |
8098
|
|
|
|
|
|
|
} |
8099
|
21
|
50
|
33
|
|
|
186
|
return undef unless $num and $dur and $$et{MediaTS}; |
|
|
|
33
|
|
|
|
|
8100
|
21
|
|
|
|
|
187
|
return $num * $$et{MediaTS} / $dur; |
8101
|
|
|
|
|
|
|
} |
8102
|
|
|
|
|
|
|
|
8103
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8104
|
|
|
|
|
|
|
# Fix incorrect format for ImageWidth/Height as written by Pentax |
8105
|
|
|
|
|
|
|
sub FixWrongFormat($) |
8106
|
|
|
|
|
|
|
{ |
8107
|
78
|
|
|
78
|
0
|
138
|
my $val = shift; |
8108
|
78
|
100
|
|
|
|
181
|
return undef unless $val; |
8109
|
44
|
50
|
|
|
|
226
|
return $val & 0xfff00000 ? unpack('n',pack('N',$val)) : $val; |
8110
|
|
|
|
|
|
|
} |
8111
|
|
|
|
|
|
|
|
8112
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8113
|
|
|
|
|
|
|
# Convert ISO 6709 string to standard lag/lon format |
8114
|
|
|
|
|
|
|
# Inputs: 0) ISO 6709 string (lat, lon, and optional alt) |
8115
|
|
|
|
|
|
|
# Returns: position in decimal degrees with altitude if available |
8116
|
|
|
|
|
|
|
# Notes: Wikipedia indicates altitude may be in feet -- how is this specified? |
8117
|
|
|
|
|
|
|
sub ConvertISO6709($) |
8118
|
|
|
|
|
|
|
{ |
8119
|
0
|
|
|
0
|
0
|
0
|
my $val = shift; |
8120
|
0
|
0
|
|
|
|
0
|
if ($val =~ /^([-+]\d{1,2}(?:\.\d*)?)([-+]\d{1,3}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
8121
|
|
|
|
|
|
|
# +DD.DDD+DDD.DDD+AA.AAA |
8122
|
0
|
|
|
|
|
0
|
$val = ($1 + 0) . ' ' . ($2 + 0); |
8123
|
0
|
0
|
|
|
|
0
|
$val .= ' ' . ($3 + 0) if $3; |
8124
|
|
|
|
|
|
|
} elsif ($val =~ /^([-+])(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) { |
8125
|
|
|
|
|
|
|
# +DDMM.MMM+DDDMM.MMM+AA.AAA |
8126
|
0
|
|
|
|
|
0
|
my $lat = $2 + $3 / 60; |
8127
|
0
|
0
|
|
|
|
0
|
$lat = -$lat if $1 eq '-'; |
8128
|
0
|
|
|
|
|
0
|
my $lon = $5 + $6 / 60; |
8129
|
0
|
0
|
|
|
|
0
|
$lon = -$lon if $4 eq '-'; |
8130
|
0
|
|
|
|
|
0
|
$val = "$lat $lon"; |
8131
|
0
|
0
|
|
|
|
0
|
$val .= ' ' . ($7 + 0) if $7; |
8132
|
|
|
|
|
|
|
} elsif ($val =~ /^([-+])(\d{2})(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2})(\d{2}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) { |
8133
|
|
|
|
|
|
|
# +DDMMSS.SSS+DDDMMSS.SSS+AA.AAA |
8134
|
0
|
|
|
|
|
0
|
my $lat = $2 + $3 / 60 + $4 / 3600; |
8135
|
0
|
0
|
|
|
|
0
|
$lat = -$lat if $1 eq '-'; |
8136
|
0
|
|
|
|
|
0
|
my $lon = $6 + $7 / 60 + $8 / 3600; |
8137
|
0
|
0
|
|
|
|
0
|
$lon = -$lon if $5 eq '-'; |
8138
|
0
|
|
|
|
|
0
|
$val = "$lat $lon"; |
8139
|
0
|
0
|
|
|
|
0
|
$val .= ' ' . ($9 + 0) if $9; |
8140
|
|
|
|
|
|
|
} |
8141
|
0
|
|
|
|
|
0
|
return $val; |
8142
|
|
|
|
|
|
|
} |
8143
|
|
|
|
|
|
|
|
8144
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8145
|
|
|
|
|
|
|
# Convert Nero chapter list (ref ffmpeg libavformat/movenc.c) |
8146
|
|
|
|
|
|
|
# Inputs: 0) binary chpl data |
8147
|
|
|
|
|
|
|
# Returns: chapter list |
8148
|
|
|
|
|
|
|
sub ConvertChapterList($) |
8149
|
|
|
|
|
|
|
{ |
8150
|
0
|
|
|
0
|
0
|
0
|
my $val = shift; |
8151
|
0
|
|
|
|
|
0
|
my $size = length $val; |
8152
|
0
|
0
|
|
|
|
0
|
return '' if $size < 9; |
8153
|
0
|
|
|
|
|
0
|
my $num = Get8u(\$val, 8); |
8154
|
0
|
|
|
|
|
0
|
my ($i, @chapters); |
8155
|
0
|
|
|
|
|
0
|
my $pos = 9; |
8156
|
0
|
|
|
|
|
0
|
for ($i=0; $i<$num; ++$i) { |
8157
|
0
|
0
|
|
|
|
0
|
last if $pos + 9 > $size; |
8158
|
0
|
|
|
|
|
0
|
my $dur = Get64u(\$val, $pos) / 10000000; |
8159
|
0
|
|
|
|
|
0
|
my $len = Get8u(\$val, $pos + 8); |
8160
|
0
|
0
|
|
|
|
0
|
last if $pos + 9 + $len > $size; |
8161
|
0
|
|
|
|
|
0
|
my $title = substr($val, $pos + 9, $len); |
8162
|
0
|
|
|
|
|
0
|
$pos += 9 + $len; |
8163
|
0
|
|
|
|
|
0
|
push @chapters, "$dur $title"; |
8164
|
|
|
|
|
|
|
} |
8165
|
0
|
|
|
|
|
0
|
return \@chapters; # return as a list |
8166
|
|
|
|
|
|
|
} |
8167
|
|
|
|
|
|
|
|
8168
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8169
|
|
|
|
|
|
|
# Print conversion for a Nero chapter list item |
8170
|
|
|
|
|
|
|
# Inputs: 0) ValueConv chapter string |
8171
|
|
|
|
|
|
|
# Returns: formatted chapter string |
8172
|
|
|
|
|
|
|
sub PrintChapter($) |
8173
|
|
|
|
|
|
|
{ |
8174
|
0
|
|
|
0
|
0
|
0
|
my $val = shift; |
8175
|
0
|
0
|
|
|
|
0
|
$val =~ /^(\S+) (.*)/ or return $val; |
8176
|
0
|
|
|
|
|
0
|
my ($dur, $title) = ($1, $2); |
8177
|
0
|
|
|
|
|
0
|
my $h = int($dur / 3600); |
8178
|
0
|
|
|
|
|
0
|
$dur -= $h * 3600; |
8179
|
0
|
|
|
|
|
0
|
my $m = int($dur / 60); |
8180
|
0
|
|
|
|
|
0
|
my $s = $dur - $m * 60; |
8181
|
0
|
|
|
|
|
0
|
my $ss = sprintf('%06.3f', $s); |
8182
|
0
|
0
|
|
|
|
0
|
if ($ss >= 60) { |
8183
|
0
|
|
|
|
|
0
|
$ss = '00.000'; |
8184
|
0
|
0
|
|
|
|
0
|
++$m >= 60 and $m -= 60, ++$h; |
8185
|
|
|
|
|
|
|
} |
8186
|
0
|
|
|
|
|
0
|
return sprintf("[%d:%.2d:%s] %s",$h,$m,$ss,$title); |
8187
|
|
|
|
|
|
|
} |
8188
|
|
|
|
|
|
|
|
8189
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8190
|
|
|
|
|
|
|
# Format GPSCoordinates for printing |
8191
|
|
|
|
|
|
|
# Inputs: 0) string with numerical lat, lon and optional alt, separated by spaces |
8192
|
|
|
|
|
|
|
# 1) ExifTool object reference |
8193
|
|
|
|
|
|
|
# Returns: PrintConv value |
8194
|
|
|
|
|
|
|
sub PrintGPSCoordinates($) |
8195
|
|
|
|
|
|
|
{ |
8196
|
0
|
|
|
0
|
0
|
0
|
my ($val, $et) = @_; |
8197
|
0
|
|
|
|
|
0
|
my @v = split ' ', $val; |
8198
|
0
|
|
|
|
|
0
|
my $prt = Image::ExifTool::GPS::ToDMS($et, $v[0], 1, "N") . ', ' . |
8199
|
|
|
|
|
|
|
Image::ExifTool::GPS::ToDMS($et, $v[1], 1, "E"); |
8200
|
0
|
0
|
|
|
|
0
|
if (defined $v[2]) { |
8201
|
0
|
0
|
|
|
|
0
|
$prt .= ', ' . ($v[2] < 0 ? -$v[2] . ' m Below' : $v[2] . ' m Above') . ' Sea Level'; |
8202
|
|
|
|
|
|
|
} |
8203
|
0
|
|
|
|
|
0
|
return $prt; |
8204
|
|
|
|
|
|
|
} |
8205
|
|
|
|
|
|
|
|
8206
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8207
|
|
|
|
|
|
|
# Unpack packed ISO 639/T language code |
8208
|
|
|
|
|
|
|
# Inputs: 0) packed language code (or undef/0), 1) true to not treat 'und' and 'eng' as default |
8209
|
|
|
|
|
|
|
# Returns: language code, or undef/0 for default language, or 'err' for format error |
8210
|
|
|
|
|
|
|
sub UnpackLang($;$) |
8211
|
|
|
|
|
|
|
{ |
8212
|
10
|
|
|
10
|
0
|
31
|
my ($lang, $noDef) = @_; |
8213
|
10
|
50
|
|
|
|
23
|
if ($lang) { |
8214
|
|
|
|
|
|
|
# language code is packed in 5-bit characters |
8215
|
10
|
|
|
|
|
18
|
$lang = pack 'C*', map { (($lang>>$_)&0x1f)+0x60 } 10, 5, 0; |
|
30
|
|
|
|
|
72
|
|
8216
|
|
|
|
|
|
|
# validate language code |
8217
|
10
|
50
|
|
|
|
40
|
if ($lang =~ /^[a-z]+$/) { |
8218
|
|
|
|
|
|
|
# treat 'eng' or 'und' as the default language |
8219
|
10
|
50
|
66
|
|
|
45
|
undef $lang if ($lang eq 'und' or $lang eq 'eng') and not $noDef; |
|
|
|
66
|
|
|
|
|
8220
|
|
|
|
|
|
|
} else { |
8221
|
0
|
|
|
|
|
0
|
$lang = 'err'; # invalid language code |
8222
|
|
|
|
|
|
|
} |
8223
|
|
|
|
|
|
|
} |
8224
|
10
|
|
|
|
|
20
|
return $lang; |
8225
|
|
|
|
|
|
|
} |
8226
|
|
|
|
|
|
|
|
8227
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8228
|
|
|
|
|
|
|
# Get language code string given QuickTime language and country codes |
8229
|
|
|
|
|
|
|
# Inputs: 0) numerical language code, 1) numerical country code, 2) no defaults |
8230
|
|
|
|
|
|
|
# Returns: language code string (ie. "fra-FR") or undef for default language |
8231
|
|
|
|
|
|
|
sub GetLangCode($;$$) |
8232
|
|
|
|
|
|
|
{ |
8233
|
6
|
|
|
6
|
0
|
14
|
my ($lang, $ctry, $noDef) = @_; |
8234
|
|
|
|
|
|
|
# ignore country ('ctry') and language lists ('lang') for now |
8235
|
6
|
50
|
66
|
|
|
19
|
undef $ctry if $ctry and $ctry <= 255; |
8236
|
6
|
50
|
33
|
|
|
22
|
undef $lang if $lang and $lang <= 255; |
8237
|
6
|
|
|
|
|
16
|
$lang = UnpackLang($lang, $noDef); |
8238
|
|
|
|
|
|
|
# add country code if specified |
8239
|
6
|
100
|
|
|
|
14
|
if ($ctry) { |
8240
|
1
|
|
|
|
|
4
|
$ctry = unpack('a2',pack('n',$ctry)); # unpack as ISO 3166-1 |
8241
|
|
|
|
|
|
|
# treat 'ZZ' like a default country (see ref 12) |
8242
|
1
|
50
|
|
|
|
4
|
undef $ctry if $ctry eq 'ZZ'; |
8243
|
1
|
50
|
33
|
|
|
8
|
if ($ctry and $ctry =~ /^[A-Z]{2}$/) { |
8244
|
1
|
50
|
|
|
|
3
|
$lang or $lang = 'und'; |
8245
|
1
|
|
|
|
|
3
|
$lang .= "-$ctry"; |
8246
|
|
|
|
|
|
|
} |
8247
|
|
|
|
|
|
|
} |
8248
|
6
|
|
|
|
|
17
|
return $lang; |
8249
|
|
|
|
|
|
|
} |
8250
|
|
|
|
|
|
|
|
8251
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8252
|
|
|
|
|
|
|
# Get langInfo hash and save details about alt-lang tags |
8253
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) tagInfo hash ref, 2) locale code |
8254
|
|
|
|
|
|
|
# Returns: new tagInfo hash ref, or undef if invalid |
8255
|
|
|
|
|
|
|
sub GetLangInfoQT($$$) |
8256
|
|
|
|
|
|
|
{ |
8257
|
1
|
|
|
1
|
0
|
3
|
my ($et, $tagInfo, $langCode) = @_; |
8258
|
1
|
|
|
|
|
6
|
my $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $langCode); |
8259
|
1
|
50
|
|
|
|
4
|
if ($langInfo) { |
8260
|
1
|
50
|
|
|
|
6
|
$$et{QTLang} or $$et{QTLang} = [ ]; |
8261
|
1
|
|
|
|
|
2
|
push @{$$et{QTLang}}, $$langInfo{Name}; |
|
1
|
|
|
|
|
5
|
|
8262
|
|
|
|
|
|
|
} |
8263
|
1
|
|
|
|
|
2
|
return $langInfo; |
8264
|
|
|
|
|
|
|
} |
8265
|
|
|
|
|
|
|
|
8266
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8267
|
|
|
|
|
|
|
# Get variable-length integer from data (used by ParseItemLocation) |
8268
|
|
|
|
|
|
|
# Inputs: 0) data ref, 1) start position, 2) integer size in bytes (0, 4 or 8), |
8269
|
|
|
|
|
|
|
# 3) default value |
8270
|
|
|
|
|
|
|
# Returns: integer value, and updates current position |
8271
|
|
|
|
|
|
|
sub GetVarInt($$$;$) |
8272
|
|
|
|
|
|
|
{ |
8273
|
78
|
|
|
78
|
0
|
118
|
my ($dataPt, $pos, $n, $default) = @_; |
8274
|
78
|
|
|
|
|
88
|
my $len = length $$dataPt; |
8275
|
78
|
|
|
|
|
88
|
$_[1] = $pos + $n; # update current position |
8276
|
78
|
50
|
|
|
|
119
|
return undef if $pos + $n > $len; |
8277
|
78
|
50
|
|
|
|
132
|
if ($n == 0) { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
8278
|
0
|
|
0
|
|
|
0
|
return $default || 0; |
8279
|
|
|
|
|
|
|
} elsif ($n == 4) { |
8280
|
78
|
|
|
|
|
136
|
return Get32u($dataPt, $pos); |
8281
|
|
|
|
|
|
|
} elsif ($n == 8) { |
8282
|
0
|
|
|
|
|
0
|
return Get64u($dataPt, $pos); |
8283
|
|
|
|
|
|
|
} |
8284
|
0
|
|
|
|
|
0
|
return undef; |
8285
|
|
|
|
|
|
|
} |
8286
|
|
|
|
|
|
|
|
8287
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8288
|
|
|
|
|
|
|
# Get null-terminated string from binary data (used by ParseItemInfoEntry) |
8289
|
|
|
|
|
|
|
# Inputs: 0) data ref, 1) start position |
8290
|
|
|
|
|
|
|
# Returns: string, and updates current position |
8291
|
|
|
|
|
|
|
sub GetString($$) |
8292
|
|
|
|
|
|
|
{ |
8293
|
30
|
|
|
30
|
0
|
53
|
my ($dataPt, $pos) = @_; |
8294
|
30
|
|
|
|
|
38
|
my $len = length $$dataPt; |
8295
|
30
|
|
|
|
|
43
|
my $str = ''; |
8296
|
30
|
|
|
|
|
48
|
while ($pos < $len) { |
8297
|
240
|
|
|
|
|
283
|
my $ch = substr($$dataPt, $pos, 1); |
8298
|
240
|
|
|
|
|
241
|
++$pos; |
8299
|
240
|
100
|
|
|
|
355
|
last if ord($ch) == 0; |
8300
|
215
|
|
|
|
|
297
|
$str .= $ch; |
8301
|
|
|
|
|
|
|
} |
8302
|
30
|
|
|
|
|
38
|
$_[1] = $pos; # update current position |
8303
|
30
|
|
|
|
|
70
|
return $str; |
8304
|
|
|
|
|
|
|
} |
8305
|
|
|
|
|
|
|
|
8306
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8307
|
|
|
|
|
|
|
# Get a printable version of the tag ID |
8308
|
|
|
|
|
|
|
# Inputs: 0) tag ID, 1) Flag: 0x01 - print as 4- or 8-digit hex value if necessary |
8309
|
|
|
|
|
|
|
# 0x02 - put leading backslash before escaped character |
8310
|
|
|
|
|
|
|
# Returns: Printable tag ID |
8311
|
|
|
|
|
|
|
sub PrintableTagID($;$) |
8312
|
|
|
|
|
|
|
{ |
8313
|
22
|
|
|
22
|
0
|
38
|
my $tag = $_[0]; |
8314
|
22
|
|
|
|
|
57
|
my $n = ($tag =~ s/([\x00-\x1f\x7f-\xff])/'x'.unpack('H*',$1)/eg); |
|
0
|
|
|
|
|
0
|
|
8315
|
22
|
0
|
33
|
|
|
62
|
if ($n and $_[1]) { |
8316
|
0
|
0
|
0
|
|
|
0
|
if ($n > 2 and $_[1] & 0x01) { |
|
|
0
|
|
|
|
|
|
8317
|
0
|
|
|
|
|
0
|
$tag = '0x' . unpack('H8', $_[0]); |
8318
|
0
|
|
|
|
|
0
|
$tag =~ s/^0x0000/0x/; |
8319
|
|
|
|
|
|
|
} elsif ($_[1] & 0x02) { |
8320
|
0
|
|
|
|
|
0
|
($tag = $_[0]) =~ s/([\x00-\x1f\x7f-\xff])/'\\x'.unpack('H*',$1)/eg; |
|
0
|
|
|
|
|
0
|
|
8321
|
|
|
|
|
|
|
} |
8322
|
|
|
|
|
|
|
} |
8323
|
22
|
|
|
|
|
52
|
return $tag; |
8324
|
|
|
|
|
|
|
} |
8325
|
|
|
|
|
|
|
|
8326
|
|
|
|
|
|
|
#============================================================================== |
8327
|
|
|
|
|
|
|
# The following ParseXxx routines parse various boxes to extract this |
8328
|
|
|
|
|
|
|
# information about embedded items in a $$et{ItemInfo} hash, keyed by item ID: |
8329
|
|
|
|
|
|
|
# |
8330
|
|
|
|
|
|
|
# iloc: |
8331
|
|
|
|
|
|
|
# ConstructionMethod - offset type: 0=file, 1=idat, 2=item |
8332
|
|
|
|
|
|
|
# DataReferenceIndex - 0 for "this file", otherwise index in dref box |
8333
|
|
|
|
|
|
|
# BaseOffset - base for file offsets |
8334
|
|
|
|
|
|
|
# Extents - list of details for data in file: |
8335
|
|
|
|
|
|
|
# 0) index (extent_index) |
8336
|
|
|
|
|
|
|
# 1) offset (extent_offset) |
8337
|
|
|
|
|
|
|
# 2) length (extent_length) |
8338
|
|
|
|
|
|
|
# 3) nlen (length_size) |
8339
|
|
|
|
|
|
|
# 4) lenPt (pointer to length word) |
8340
|
|
|
|
|
|
|
# infe: |
8341
|
|
|
|
|
|
|
# ProtectionIndex - index if item is protected (0 for unprotected) |
8342
|
|
|
|
|
|
|
# Name - item name |
8343
|
|
|
|
|
|
|
# ContentType - mime type of item |
8344
|
|
|
|
|
|
|
# ContentEncoding - item encoding |
8345
|
|
|
|
|
|
|
# URI - URI of a 'uri '-type item |
8346
|
|
|
|
|
|
|
# ipma: |
8347
|
|
|
|
|
|
|
# Association - list of associated properties in the ipco container |
8348
|
|
|
|
|
|
|
# Essential - list of "essential" flags for the associated properties |
8349
|
|
|
|
|
|
|
# cdsc: |
8350
|
|
|
|
|
|
|
# RefersTo - hash lookup of flags based on referred item ID |
8351
|
|
|
|
|
|
|
# other: |
8352
|
|
|
|
|
|
|
# DocNum - exiftool document number for this item |
8353
|
|
|
|
|
|
|
# |
8354
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8355
|
|
|
|
|
|
|
# Parse item location (iloc) box (ref ISO 14496-12:2015 pg.79) |
8356
|
|
|
|
|
|
|
# Inputs: 0) iloc data, 1) ExifTool ref |
8357
|
|
|
|
|
|
|
# Returns: undef, and fills in ExifTool ItemInfo hash |
8358
|
|
|
|
|
|
|
# Notes: see also Handle_iloc() in WriteQuickTime.pl |
8359
|
|
|
|
|
|
|
sub ParseItemLocation($$) |
8360
|
|
|
|
|
|
|
{ |
8361
|
6
|
|
|
6
|
0
|
18
|
my ($val, $et) = @_; |
8362
|
6
|
|
|
|
|
16
|
my ($i, $j, $num, $pos, $id); |
8363
|
6
|
|
|
|
|
0
|
my ($extent_index, $extent_offset, $extent_length); |
8364
|
|
|
|
|
|
|
|
8365
|
6
|
100
|
|
|
|
22
|
my $verbose = $$et{IsWriting} ? 0 : $et->Options('Verbose'); |
8366
|
6
|
|
50
|
|
|
29
|
my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { }); |
8367
|
6
|
|
|
|
|
10
|
my $len = length $val; |
8368
|
6
|
50
|
|
|
|
17
|
return undef if $len < 8; |
8369
|
6
|
|
|
|
|
16
|
my $ver = Get8u(\$val, 0); |
8370
|
6
|
|
|
|
|
15
|
my $siz = Get16u(\$val, 4); |
8371
|
6
|
|
|
|
|
35
|
my $noff = ($siz >> 12); |
8372
|
6
|
|
|
|
|
13
|
my $nlen = ($siz >> 8) & 0x0f; |
8373
|
6
|
|
|
|
|
9
|
my $nbas = ($siz >> 4) & 0x0f; |
8374
|
6
|
|
|
|
|
11
|
my $nind = $siz & 0x0f; |
8375
|
6
|
50
|
|
|
|
12
|
if ($ver < 2) { |
8376
|
6
|
|
|
|
|
16
|
$num = Get16u(\$val, 6); |
8377
|
6
|
|
|
|
|
16
|
$pos = 8; |
8378
|
|
|
|
|
|
|
} else { |
8379
|
0
|
0
|
|
|
|
0
|
return undef if $len < 10; |
8380
|
0
|
|
|
|
|
0
|
$num = Get32u(\$val, 6); |
8381
|
0
|
|
|
|
|
0
|
$pos = 10; |
8382
|
|
|
|
|
|
|
} |
8383
|
6
|
|
|
|
|
20
|
for ($i=0; $i<$num; ++$i) { |
8384
|
20
|
50
|
|
|
|
30
|
if ($ver < 2) { |
8385
|
20
|
50
|
|
|
|
33
|
return undef if $pos + 2 > $len; |
8386
|
20
|
|
|
|
|
37
|
$id = Get16u(\$val, $pos); |
8387
|
20
|
|
|
|
|
27
|
$pos += 2; |
8388
|
|
|
|
|
|
|
} else { |
8389
|
0
|
0
|
|
|
|
0
|
return undef if $pos + 4 > $len; |
8390
|
0
|
|
|
|
|
0
|
$id = Get32u(\$val, $pos); |
8391
|
0
|
|
|
|
|
0
|
$pos += 4; |
8392
|
|
|
|
|
|
|
} |
8393
|
20
|
50
|
33
|
|
|
62
|
if ($ver == 1 or $ver == 2) { |
8394
|
0
|
0
|
|
|
|
0
|
return undef if $pos + 2 > $len; |
8395
|
0
|
|
|
|
|
0
|
$$items{$id}{ConstructionMethod} = Get16u(\$val, $pos) & 0x0f; |
8396
|
0
|
|
|
|
|
0
|
$pos += 2; |
8397
|
|
|
|
|
|
|
} |
8398
|
20
|
50
|
|
|
|
36
|
return undef if $pos + 2 > $len; |
8399
|
20
|
|
|
|
|
34
|
$$items{$id}{DataReferenceIndex} = Get16u(\$val, $pos); |
8400
|
20
|
|
|
|
|
26
|
$pos += 2; |
8401
|
20
|
|
|
|
|
36
|
$$items{$id}{BaseOffset} = GetVarInt(\$val, $pos, $nbas); |
8402
|
20
|
50
|
|
|
|
42
|
return undef if $pos + 2 > $len; |
8403
|
20
|
|
|
|
|
60
|
my $ext_num = Get16u(\$val, $pos); |
8404
|
20
|
|
|
|
|
22
|
$pos += 2; |
8405
|
20
|
|
|
|
|
27
|
my @extents; |
8406
|
20
|
|
|
|
|
36
|
for ($j=0; $j<$ext_num; ++$j) { |
8407
|
20
|
50
|
33
|
|
|
54
|
if ($ver == 1 or $ver == 2) { |
8408
|
0
|
|
|
|
|
0
|
$extent_index = GetVarInt(\$val, $pos, $nind, 1); |
8409
|
|
|
|
|
|
|
} |
8410
|
20
|
|
|
|
|
33
|
$extent_offset = GetVarInt(\$val, $pos, $noff); |
8411
|
20
|
|
|
|
|
31
|
$extent_length = GetVarInt(\$val, $pos, $nlen); |
8412
|
20
|
50
|
|
|
|
35
|
return undef unless defined $extent_length; |
8413
|
|
|
|
|
|
|
$et->VPrint(1, "$$et{INDENT} Item $id: const_meth=", |
8414
|
|
|
|
|
|
|
defined $$items{$id}{ConstructionMethod} ? $$items{$id}{ConstructionMethod} : '', |
8415
|
|
|
|
|
|
|
sprintf(" base=0x%x offset=0x%x len=0x%x\n", $$items{$id}{BaseOffset}, |
8416
|
20
|
0
|
|
|
|
36
|
$extent_offset, $extent_length)) if $verbose; |
|
|
50
|
|
|
|
|
|
8417
|
20
|
|
|
|
|
58
|
push @extents, [ $extent_index, $extent_offset, $extent_length, $nlen, $pos-$nlen ]; |
8418
|
|
|
|
|
|
|
} |
8419
|
|
|
|
|
|
|
# save item location information keyed on 1-based item ID: |
8420
|
20
|
|
|
|
|
52
|
$$items{$id}{Extents} = \@extents; |
8421
|
|
|
|
|
|
|
} |
8422
|
6
|
|
|
|
|
15
|
return undef; |
8423
|
|
|
|
|
|
|
} |
8424
|
|
|
|
|
|
|
|
8425
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8426
|
|
|
|
|
|
|
# Parse content describes entry (cdsc) box |
8427
|
|
|
|
|
|
|
# Inputs: 0) cdsc data, 1) ExifTool ref |
8428
|
|
|
|
|
|
|
# Returns: undef, and fills in ExifTool ItemInfo hash |
8429
|
|
|
|
|
|
|
sub ParseContentDescribes($$) |
8430
|
|
|
|
|
|
|
{ |
8431
|
8
|
|
|
8
|
0
|
19
|
my ($val, $et) = @_; |
8432
|
8
|
|
|
|
|
15
|
my ($id, $count, @to); |
8433
|
8
|
50
|
|
|
|
19
|
if ($$et{ItemRefVersion}) { |
8434
|
0
|
0
|
|
|
|
0
|
return undef if length $val < 10; |
8435
|
0
|
|
|
|
|
0
|
($id, $count, @to) = unpack('NnN*', $val); |
8436
|
|
|
|
|
|
|
} else { |
8437
|
8
|
50
|
|
|
|
19
|
return undef if length $val < 6; |
8438
|
8
|
|
|
|
|
20
|
($id, $count, @to) = unpack('nnn*', $val); |
8439
|
|
|
|
|
|
|
} |
8440
|
8
|
50
|
|
|
|
29
|
if ($count > @to) { |
|
|
50
|
|
|
|
|
|
8441
|
0
|
|
|
|
|
0
|
my $str = 'Missing values in ContentDescribes box'; |
8442
|
0
|
0
|
|
|
|
0
|
$$et{IsWriting} ? $et->Error($str) : $et->Warn($str); |
8443
|
|
|
|
|
|
|
} elsif ($count < @to) { |
8444
|
0
|
|
|
|
|
0
|
$et->Warn('Ignored extra values in ContentDescribes box', 1); |
8445
|
0
|
|
|
|
|
0
|
@to = $count; |
8446
|
|
|
|
|
|
|
} |
8447
|
|
|
|
|
|
|
# add all referenced item ID's to a "RefersTo" lookup |
8448
|
8
|
|
|
|
|
35
|
$$et{ItemInfo}{$id}{RefersTo}{$_} = 1 foreach @to; |
8449
|
8
|
|
|
|
|
21
|
return undef; |
8450
|
|
|
|
|
|
|
} |
8451
|
|
|
|
|
|
|
|
8452
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8453
|
|
|
|
|
|
|
# Parse item information entry (infe) box (ref ISO 14496-12:2015 pg.82) |
8454
|
|
|
|
|
|
|
# Inputs: 0) infe data, 1) ExifTool ref |
8455
|
|
|
|
|
|
|
# Returns: undef, and fills in ExifTool ItemInfo hash |
8456
|
|
|
|
|
|
|
sub ParseItemInfoEntry($$) |
8457
|
|
|
|
|
|
|
{ |
8458
|
20
|
|
|
20
|
0
|
37
|
my ($val, $et) = @_; |
8459
|
20
|
|
|
|
|
29
|
my $id; |
8460
|
|
|
|
|
|
|
|
8461
|
20
|
100
|
|
|
|
64
|
my $verbose = $$et{IsWriting} ? 0 : $et->Options('Verbose'); |
8462
|
20
|
|
50
|
|
|
42
|
my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { }); |
8463
|
20
|
|
|
|
|
28
|
my $len = length $val; |
8464
|
20
|
50
|
|
|
|
32
|
return undef if $len < 4; |
8465
|
20
|
|
|
|
|
40
|
my $ver = Get8u(\$val, 0); |
8466
|
20
|
|
|
|
|
38
|
my $pos = 4; |
8467
|
20
|
50
|
|
|
|
41
|
return undef if $pos + 4 > $len; |
8468
|
20
|
50
|
33
|
|
|
63
|
if ($ver == 0 or $ver == 1) { |
8469
|
0
|
|
|
|
|
0
|
$id = Get16u(\$val, $pos); |
8470
|
0
|
|
|
|
|
0
|
$$items{$id}{ProtectionIndex} = Get16u(\$val, $pos + 2); |
8471
|
0
|
|
|
|
|
0
|
$pos += 4; |
8472
|
0
|
|
|
|
|
0
|
$$items{$id}{Name} = GetString(\$val, $pos); |
8473
|
0
|
|
|
|
|
0
|
$$items{$id}{ContentType} = GetString(\$val, $pos); |
8474
|
0
|
|
|
|
|
0
|
$$items{$id}{ContentEncoding} = GetString(\$val, $pos); |
8475
|
|
|
|
|
|
|
} else { |
8476
|
20
|
50
|
|
|
|
31
|
if ($ver == 2) { |
|
|
0
|
|
|
|
|
|
8477
|
20
|
|
|
|
|
42
|
$id = Get16u(\$val, $pos); |
8478
|
20
|
|
|
|
|
33
|
$pos += 2; |
8479
|
|
|
|
|
|
|
} elsif ($ver == 3) { |
8480
|
0
|
|
|
|
|
0
|
$id = Get32u(\$val, $pos); |
8481
|
0
|
|
|
|
|
0
|
$pos += 4; |
8482
|
|
|
|
|
|
|
} |
8483
|
20
|
50
|
|
|
|
43
|
return undef if $pos + 6 > $len; |
8484
|
20
|
|
|
|
|
50
|
$$items{$id}{ProtectionIndex} = Get16u(\$val, $pos); |
8485
|
20
|
|
|
|
|
39
|
my $type = substr($val, $pos + 2, 4); |
8486
|
20
|
|
|
|
|
38
|
$$items{$id}{Type} = $type; |
8487
|
20
|
|
|
|
|
26
|
$pos += 6; |
8488
|
20
|
|
|
|
|
45
|
$$items{$id}{Name} = GetString(\$val, $pos); |
8489
|
20
|
100
|
|
|
|
52
|
if ($type eq 'mime') { |
|
|
50
|
|
|
|
|
|
8490
|
5
|
|
|
|
|
15
|
$$items{$id}{ContentType} = GetString(\$val, $pos); |
8491
|
5
|
|
|
|
|
12
|
$$items{$id}{ContentEncoding} = GetString(\$val, $pos); |
8492
|
|
|
|
|
|
|
} elsif ($type eq 'uri ') { |
8493
|
0
|
|
|
|
|
0
|
$$items{$id}{URI} = GetString(\$val, $pos); |
8494
|
|
|
|
|
|
|
} |
8495
|
|
|
|
|
|
|
} |
8496
|
|
|
|
|
|
|
$et->VPrint(1, "$$et{INDENT} Item $id: Type=", $$items{$id}{Type} || '', |
8497
|
|
|
|
|
|
|
' Name=', $$items{$id}{Name} || '', |
8498
|
20
|
50
|
0
|
|
|
39
|
' ContentType=', $$items{$id}{ContentType} || '', |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
8499
|
|
|
|
|
|
|
"\n") if $verbose > 1; |
8500
|
20
|
|
|
|
|
36
|
return undef; |
8501
|
|
|
|
|
|
|
} |
8502
|
|
|
|
|
|
|
|
8503
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8504
|
|
|
|
|
|
|
# Parse item property association (ipma) box (ref https://github.com/gpac/gpac/blob/master/src/isomedia/iff.c) |
8505
|
|
|
|
|
|
|
# Inputs: 0) ipma data, 1) ExifTool ref |
8506
|
|
|
|
|
|
|
# Returns: undef, and fills in ExifTool ItemInfo hash |
8507
|
|
|
|
|
|
|
sub ParseItemPropAssoc($$) |
8508
|
|
|
|
|
|
|
{ |
8509
|
6
|
|
|
6
|
0
|
16
|
my ($val, $et) = @_; |
8510
|
6
|
|
|
|
|
10
|
my ($i, $j, $id); |
8511
|
|
|
|
|
|
|
|
8512
|
6
|
100
|
|
|
|
23
|
my $verbose = $$et{IsWriting} ? 0 : $et->Options('Verbose'); |
8513
|
6
|
|
50
|
|
|
19
|
my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { }); |
8514
|
6
|
|
|
|
|
9
|
my $len = length $val; |
8515
|
6
|
50
|
|
|
|
13
|
return undef if $len < 8; |
8516
|
6
|
|
|
|
|
16
|
my $ver = Get8u(\$val, 0); |
8517
|
6
|
|
|
|
|
15
|
my $flg = Get32u(\$val, 0); |
8518
|
6
|
|
|
|
|
16
|
my $num = Get32u(\$val, 4); |
8519
|
6
|
|
|
|
|
7
|
my $pos = 8; |
8520
|
6
|
|
|
|
|
19
|
for ($i=0; $i<$num; ++$i) { |
8521
|
12
|
50
|
|
|
|
23
|
if ($ver == 0) { |
8522
|
12
|
50
|
|
|
|
26
|
return undef if $pos + 3 > $len; |
8523
|
12
|
|
|
|
|
24
|
$id = Get16u(\$val, $pos); |
8524
|
12
|
|
|
|
|
18
|
$pos += 2; |
8525
|
|
|
|
|
|
|
} else { |
8526
|
0
|
0
|
|
|
|
0
|
return undef if $pos + 5 > $len; |
8527
|
0
|
|
|
|
|
0
|
$id = Get32u(\$val, $pos); |
8528
|
0
|
|
|
|
|
0
|
$pos += 4; |
8529
|
|
|
|
|
|
|
} |
8530
|
12
|
|
|
|
|
25
|
my $n = Get8u(\$val, $pos++); |
8531
|
12
|
|
|
|
|
19
|
my (@association, @essential); |
8532
|
12
|
50
|
|
|
|
26
|
if ($flg & 0x01) { |
8533
|
0
|
0
|
|
|
|
0
|
return undef if $pos + $n * 2 > $len; |
8534
|
0
|
|
|
|
|
0
|
for ($j=0; $j<$n; ++$j) { |
8535
|
0
|
|
|
|
|
0
|
my $tmp = Get16u(\$val, $pos + $j * 2); |
8536
|
0
|
|
|
|
|
0
|
push @association, $tmp & 0x7fff; |
8537
|
0
|
0
|
|
|
|
0
|
push @essential, ($tmp & 0x8000) ? 1 : 0; |
8538
|
|
|
|
|
|
|
} |
8539
|
0
|
|
|
|
|
0
|
$pos += $n * 2; |
8540
|
|
|
|
|
|
|
} else { |
8541
|
12
|
50
|
|
|
|
25
|
return undef if $pos + $n > $len; |
8542
|
12
|
|
|
|
|
25
|
for ($j=0; $j<$n; ++$j) { |
8543
|
24
|
|
|
|
|
47
|
my $tmp = Get8u(\$val, $pos + $j); |
8544
|
24
|
|
|
|
|
41
|
push @association, $tmp & 0x7f; |
8545
|
24
|
100
|
|
|
|
56
|
push @essential, ($tmp & 0x80) ? 1 : 0; |
8546
|
|
|
|
|
|
|
} |
8547
|
12
|
|
|
|
|
16
|
$pos += $n; |
8548
|
|
|
|
|
|
|
} |
8549
|
12
|
|
|
|
|
26
|
$$items{$id}{Association} = \@association; |
8550
|
12
|
|
|
|
|
33
|
$$items{$id}{Essential} = \@essential; |
8551
|
12
|
50
|
|
|
|
38
|
$et->VPrint(1, "$$et{INDENT} Item $id properties: @association\n") if $verbose > 1; |
8552
|
|
|
|
|
|
|
} |
8553
|
6
|
|
|
|
|
12
|
return undef; |
8554
|
|
|
|
|
|
|
} |
8555
|
|
|
|
|
|
|
|
8556
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8557
|
|
|
|
|
|
|
# Process item information now |
8558
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref |
8559
|
|
|
|
|
|
|
sub HandleItemInfo($) |
8560
|
|
|
|
|
|
|
{ |
8561
|
45
|
|
|
45
|
0
|
84
|
my $et = shift; |
8562
|
45
|
|
|
|
|
76
|
my $raf = $$et{RAF}; |
8563
|
45
|
|
|
|
|
84
|
my $items = $$et{ItemInfo}; |
8564
|
45
|
|
|
|
|
135
|
my $verbose = $et->Options('Verbose'); |
8565
|
45
|
|
|
|
|
75
|
my $buff; |
8566
|
|
|
|
|
|
|
|
8567
|
|
|
|
|
|
|
# extract information from EXIF/XMP metadata items |
8568
|
45
|
100
|
66
|
|
|
134
|
if ($items and $raf) { |
8569
|
3
|
|
|
|
|
6
|
push @{$$et{PATH}}, 'ItemInformation'; |
|
3
|
|
|
|
|
8
|
|
8570
|
3
|
|
|
|
|
9
|
my $curPos = $raf->Tell(); |
8571
|
3
|
|
|
|
|
7
|
my $primary = $$et{PrimaryItem}; |
8572
|
3
|
|
|
|
|
3
|
my $id; |
8573
|
3
|
|
|
|
|
20
|
$et->VerboseDir('Processing items from ItemInformation', scalar(keys %$items)); |
8574
|
3
|
|
|
|
|
15
|
foreach $id (sort { $a <=> $b } keys %$items) { |
|
13
|
|
|
|
|
26
|
|
8575
|
11
|
|
|
|
|
18
|
my $item = $$items{$id}; |
8576
|
11
|
|
50
|
|
|
39
|
my $type = $$item{ContentType} || $$item{Type} || next; |
8577
|
11
|
50
|
|
|
|
23
|
if ($verbose) { |
8578
|
|
|
|
|
|
|
# add up total length of this item for the verbose output |
8579
|
0
|
|
|
|
|
0
|
my $len = 0; |
8580
|
0
|
0
|
0
|
|
|
0
|
if ($$item{Extents} and @{$$item{Extents}}) { |
|
0
|
|
|
|
|
0
|
|
8581
|
0
|
|
|
|
|
0
|
$len += $$_[2] foreach @{$$item{Extents}}; |
|
0
|
|
|
|
|
0
|
|
8582
|
|
|
|
|
|
|
} |
8583
|
0
|
|
|
|
|
0
|
$et->VPrint(0, "$$et{INDENT}Item $id) '${type}' ($len bytes)\n"); |
8584
|
|
|
|
|
|
|
} |
8585
|
|
|
|
|
|
|
# get ExifTool name for this item |
8586
|
11
|
|
100
|
|
|
41
|
my $name = { Exif => 'EXIF', 'application/rdf+xml' => 'XMP' }->{$type} || ''; |
8587
|
11
|
|
|
|
|
27
|
my ($warn, $extent); |
8588
|
11
|
50
|
|
|
|
19
|
$warn = "Can't currently decode encoded $type metadata" if $$item{ContentEncoding}; |
8589
|
11
|
50
|
|
|
|
560
|
$warn = "Can't currently decode protected $type metadata" if $$item{ProtectionIndex}; |
8590
|
11
|
50
|
|
|
|
24
|
$warn = "Can't currently extract $type with construction method $$item{ConstructionMethod}" if $$item{ConstructionMethod}; |
8591
|
11
|
50
|
33
|
|
|
20
|
$et->WarnOnce($warn) if $warn and $name; |
8592
|
11
|
50
|
|
|
|
22
|
$warn = 'Not this file' if $$item{DataReferenceIndex}; # (can only extract from "this file") |
8593
|
11
|
50
|
33
|
|
|
20
|
unless (($$item{Extents} and @{$$item{Extents}}) or $warn) { |
|
11
|
|
33
|
|
|
32
|
|
8594
|
0
|
|
|
|
|
0
|
$warn = "No Extents for $type item"; |
8595
|
0
|
0
|
|
|
|
0
|
$et->WarnOnce($warn) if $name; |
8596
|
|
|
|
|
|
|
} |
8597
|
11
|
50
|
|
|
|
19
|
if ($warn) { |
8598
|
0
|
0
|
|
|
|
0
|
$et->VPrint(0, "$$et{INDENT} [not extracted] ($warn)\n") if $verbose > 2; |
8599
|
0
|
|
|
|
|
0
|
next; |
8600
|
|
|
|
|
|
|
} |
8601
|
11
|
|
100
|
|
|
27
|
my $base = $$item{BaseOffset} || 0; |
8602
|
11
|
50
|
|
|
|
19
|
if ($verbose > 2) { |
8603
|
|
|
|
|
|
|
# do verbose hex dump |
8604
|
0
|
|
|
|
|
0
|
my $len = 0; |
8605
|
0
|
|
|
|
|
0
|
undef $buff; |
8606
|
0
|
|
|
|
|
0
|
my $val = ''; |
8607
|
0
|
0
|
|
|
|
0
|
my $maxLen = $verbose > 3 ? 2048 : 96; |
8608
|
0
|
|
|
|
|
0
|
foreach $extent (@{$$item{Extents}}) { |
|
0
|
|
|
|
|
0
|
|
8609
|
0
|
|
|
|
|
0
|
my $n = $$extent[2]; |
8610
|
0
|
|
|
|
|
0
|
my $more = $maxLen - $len; |
8611
|
0
|
0
|
0
|
|
|
0
|
if ($more > 0 and $n) { |
8612
|
0
|
0
|
|
|
|
0
|
$more = $n if $more > $n; |
8613
|
0
|
0
|
|
|
|
0
|
$val .= $buff if defined $buff; |
8614
|
0
|
0
|
|
|
|
0
|
$raf->Seek($$extent[1] + $base, 0) or last; |
8615
|
0
|
0
|
|
|
|
0
|
$raf->Read($buff, $more) or last; |
8616
|
|
|
|
|
|
|
} |
8617
|
0
|
|
|
|
|
0
|
$len += $n; |
8618
|
|
|
|
|
|
|
} |
8619
|
0
|
0
|
|
|
|
0
|
if (defined $buff) { |
8620
|
0
|
0
|
|
|
|
0
|
$buff = $val . $buff if length $val; |
8621
|
0
|
|
|
|
|
0
|
$et->VerboseDump(\$buff, DataPos => $$item{Extents}[0][1] + $base); |
8622
|
0
|
|
|
|
|
0
|
my $snip = $len - length $buff; |
8623
|
0
|
0
|
|
|
|
0
|
$et->VPrint(0, "$$et{INDENT} [snip $snip bytes]\n") if $snip; |
8624
|
|
|
|
|
|
|
} |
8625
|
|
|
|
|
|
|
} |
8626
|
11
|
100
|
|
|
|
22
|
next unless $name; |
8627
|
|
|
|
|
|
|
# assemble the data for this item |
8628
|
5
|
|
|
|
|
9
|
undef $buff; |
8629
|
5
|
|
|
|
|
8
|
my $val = ''; |
8630
|
5
|
|
|
|
|
7
|
foreach $extent (@{$$item{Extents}}) { |
|
5
|
|
|
|
|
11
|
|
8631
|
5
|
50
|
|
|
|
11
|
$val .= $buff if defined $buff; |
8632
|
5
|
50
|
|
|
|
19
|
$raf->Seek($$extent[1] + $base, 0) or last; |
8633
|
5
|
100
|
|
|
|
20
|
$raf->Read($buff, $$extent[2]) or last; |
8634
|
|
|
|
|
|
|
} |
8635
|
5
|
50
|
|
|
|
13
|
next unless defined $buff; |
8636
|
5
|
50
|
|
|
|
10
|
$buff = $val . $buff if length $val; |
8637
|
5
|
100
|
|
|
|
12
|
next unless length $buff; # ignore empty directories |
8638
|
4
|
|
|
|
|
5
|
my ($start, $subTable, $proc); |
8639
|
4
|
|
|
|
|
11
|
my $pos = $$item{Extents}[0][1] + $base; |
8640
|
4
|
100
|
66
|
|
|
19
|
if ($name eq 'EXIF' and length $buff >= 4) { |
8641
|
2
|
50
|
|
|
|
17
|
if ($buff =~ /^(MM\0\x2a|II\x2a\0)/) { |
|
|
50
|
|
|
|
|
|
8642
|
0
|
|
|
|
|
0
|
$et->Warn('Missing Exif header'); |
8643
|
0
|
|
|
|
|
0
|
$start = 0; |
8644
|
|
|
|
|
|
|
} elsif ($buff =~ /^Exif\0\0/) { |
8645
|
|
|
|
|
|
|
# (haven't seen this yet, but it is just a matter of time |
8646
|
|
|
|
|
|
|
# until someone screws it up like this) |
8647
|
0
|
|
|
|
|
0
|
$et->Warn('Missing Exif header size'); |
8648
|
0
|
|
|
|
|
0
|
$start = 6; |
8649
|
|
|
|
|
|
|
} else { |
8650
|
2
|
|
|
|
|
7
|
my $n = unpack('N', $buff); |
8651
|
2
|
|
|
|
|
5
|
$start = 4 + $n; # skip "Exif\0\0" header if it exists |
8652
|
2
|
50
|
|
|
|
6
|
if ($start > length($buff)) { |
8653
|
0
|
|
|
|
|
0
|
$et->Warn('Invalid EXIF header'); |
8654
|
0
|
|
|
|
|
0
|
next; |
8655
|
|
|
|
|
|
|
} |
8656
|
2
|
50
|
|
|
|
5
|
if ($$et{HTML_DUMP}) { |
8657
|
0
|
|
|
|
|
0
|
$et->HDump($pos, 4, 'Exif header length', "Value: $n"); |
8658
|
0
|
0
|
|
|
|
0
|
$et->HDump($pos+4, $start-4, 'Exif header') if $n; |
8659
|
|
|
|
|
|
|
} |
8660
|
|
|
|
|
|
|
} |
8661
|
2
|
|
|
|
|
7
|
$subTable = GetTagTable('Image::ExifTool::Exif::Main'); |
8662
|
2
|
|
|
|
|
5
|
$proc = \&Image::ExifTool::ProcessTIFF; |
8663
|
|
|
|
|
|
|
} else { |
8664
|
2
|
|
|
|
|
5
|
$start = 0; |
8665
|
2
|
|
|
|
|
5
|
$subTable = GetTagTable('Image::ExifTool::XMP::Main'); |
8666
|
|
|
|
|
|
|
} |
8667
|
4
|
|
|
|
|
27
|
my %dirInfo = ( |
8668
|
|
|
|
|
|
|
DataPt => \$buff, |
8669
|
|
|
|
|
|
|
DataLen => length $buff, |
8670
|
|
|
|
|
|
|
DirStart => $start, |
8671
|
|
|
|
|
|
|
DirLen => length($buff) - $start, |
8672
|
|
|
|
|
|
|
DataPos => $pos, |
8673
|
|
|
|
|
|
|
Base => $pos + $start, # (needed for HtmlDump and IsOffset tags in binary data) |
8674
|
|
|
|
|
|
|
); |
8675
|
|
|
|
|
|
|
# handle processing of metadata for sub-documents |
8676
|
4
|
50
|
33
|
|
|
30
|
if (defined $primary and $$item{RefersTo} and not $$item{RefersTo}{$primary}) { |
|
|
|
33
|
|
|
|
|
8677
|
|
|
|
|
|
|
# set document number if this doesn't refer to the primary document |
8678
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT}; |
8679
|
|
|
|
|
|
|
# associate this document number with the lowest item index |
8680
|
0
|
|
|
|
|
0
|
my ($lowest) = sort { $a <=> $b } keys %{$$item{RefersTo}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
8681
|
0
|
|
|
|
|
0
|
$$items{$lowest}{DocNum} = $$et{DOC_NUM}; |
8682
|
|
|
|
|
|
|
} |
8683
|
4
|
|
|
|
|
16
|
$et->ProcessDirectory(\%dirInfo, $subTable, $proc); |
8684
|
4
|
|
|
|
|
14
|
delete $$et{DOC_NUM}; |
8685
|
|
|
|
|
|
|
} |
8686
|
3
|
|
|
|
|
20
|
$raf->Seek($curPos, 0); # seek back to original position |
8687
|
3
|
|
|
|
|
5
|
pop @{$$et{PATH}}; |
|
3
|
|
|
|
|
10
|
|
8688
|
|
|
|
|
|
|
} |
8689
|
|
|
|
|
|
|
# process the item properties now that we should know their associations and document numbers |
8690
|
45
|
100
|
|
|
|
114
|
if ($$et{ItemPropertyContainer}) { |
8691
|
3
|
|
|
|
|
6
|
my ($dirInfo, $subTable, $proc) = @{$$et{ItemPropertyContainer}}; |
|
3
|
|
|
|
|
7
|
|
8692
|
3
|
|
|
|
|
10
|
$$et{IsItemProperty} = 1; # set item property flag |
8693
|
3
|
|
|
|
|
11
|
$et->ProcessDirectory($dirInfo, $subTable, $proc); |
8694
|
3
|
|
|
|
|
9
|
delete $$et{ItemPropertyContainer}; |
8695
|
3
|
|
|
|
|
6
|
delete $$et{IsItemProperty}; |
8696
|
3
|
|
|
|
|
16
|
delete $$et{DOC_NUM}; |
8697
|
|
|
|
|
|
|
} |
8698
|
45
|
|
|
|
|
106
|
delete $$et{ItemInfo}; |
8699
|
|
|
|
|
|
|
} |
8700
|
|
|
|
|
|
|
|
8701
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8702
|
|
|
|
|
|
|
# Warn if ExtractEmbedded option isn't used |
8703
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref |
8704
|
|
|
|
|
|
|
sub EEWarn($) |
8705
|
|
|
|
|
|
|
{ |
8706
|
0
|
|
|
0
|
0
|
0
|
my $et = shift; |
8707
|
0
|
|
|
|
|
0
|
$et->WarnOnce('The ExtractEmbedded option may find more tags in the media data',3); |
8708
|
|
|
|
|
|
|
} |
8709
|
|
|
|
|
|
|
|
8710
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8711
|
|
|
|
|
|
|
# Get quicktime format from flags word |
8712
|
|
|
|
|
|
|
# Inputs: 0) quicktime atom flags, 1) data length |
8713
|
|
|
|
|
|
|
# Returns: ExifTool format string |
8714
|
|
|
|
|
|
|
sub QuickTimeFormat($$) |
8715
|
|
|
|
|
|
|
{ |
8716
|
12
|
|
|
12
|
0
|
31
|
my ($flags, $len) = @_; |
8717
|
12
|
|
|
|
|
17
|
my $format; |
8718
|
12
|
50
|
33
|
|
|
103
|
if ($flags == 0x15 or $flags == 0x16) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
8719
|
0
|
|
|
|
|
0
|
$format = { 1=>'int8', 2=>'int16', 4=>'int32', 8=>'int64' }->{$len}; |
8720
|
0
|
0
|
|
|
|
0
|
$format .= $flags == 0x15 ? 's' : 'u' if $format; |
|
|
0
|
|
|
|
|
|
8721
|
|
|
|
|
|
|
} elsif ($flags == 0x17) { |
8722
|
0
|
|
|
|
|
0
|
$format = 'float'; |
8723
|
|
|
|
|
|
|
} elsif ($flags == 0x18) { |
8724
|
0
|
|
|
|
|
0
|
$format = 'double'; |
8725
|
|
|
|
|
|
|
} elsif ($flags == 0x00) { |
8726
|
0
|
|
|
|
|
0
|
$format = { 1=>'int8u', 2=>'int16u' }->{$len}; |
8727
|
|
|
|
|
|
|
} |
8728
|
12
|
|
|
|
|
26
|
return $format; |
8729
|
|
|
|
|
|
|
} |
8730
|
|
|
|
|
|
|
|
8731
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8732
|
|
|
|
|
|
|
# Process MPEG-4 MTDT atom (ref 11) |
8733
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
8734
|
|
|
|
|
|
|
# Returns: 1 on success |
8735
|
|
|
|
|
|
|
sub ProcessMetaData($$$) |
8736
|
|
|
|
|
|
|
{ |
8737
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
8738
|
0
|
|
|
|
|
0
|
my $dataPt = $$dirInfo{DataPt}; |
8739
|
0
|
|
|
|
|
0
|
my $dirLen = length $$dataPt; |
8740
|
0
|
|
|
|
|
0
|
my $verbose = $et->Options('Verbose'); |
8741
|
0
|
0
|
|
|
|
0
|
return 0 unless $dirLen >= 2; |
8742
|
0
|
|
|
|
|
0
|
my $count = Get16u($dataPt, 0); |
8743
|
0
|
0
|
|
|
|
0
|
$verbose and $et->VerboseDir('MetaData', $count); |
8744
|
0
|
|
|
|
|
0
|
my $i; |
8745
|
0
|
|
|
|
|
0
|
my $pos = 2; |
8746
|
0
|
|
|
|
|
0
|
for ($i=0; $i<$count; ++$i) { |
8747
|
0
|
0
|
|
|
|
0
|
last if $pos + 10 > $dirLen; |
8748
|
0
|
|
|
|
|
0
|
my $size = Get16u($dataPt, $pos); |
8749
|
0
|
0
|
0
|
|
|
0
|
last if $size < 10 or $size + $pos > $dirLen; |
8750
|
0
|
|
|
|
|
0
|
my $tag = Get32u($dataPt, $pos + 2); |
8751
|
0
|
|
|
|
|
0
|
my $lang = Get16u($dataPt, $pos + 6); |
8752
|
0
|
|
|
|
|
0
|
my $enc = Get16u($dataPt, $pos + 8); |
8753
|
0
|
|
|
|
|
0
|
my $val = substr($$dataPt, $pos + 10, $size); |
8754
|
0
|
|
|
|
|
0
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); |
8755
|
0
|
0
|
|
|
|
0
|
if ($tagInfo) { |
8756
|
|
|
|
|
|
|
# convert language code to ASCII (ignore read-only bit) |
8757
|
0
|
|
|
|
|
0
|
$lang = UnpackLang($lang); |
8758
|
|
|
|
|
|
|
# handle alternate languages |
8759
|
0
|
0
|
|
|
|
0
|
if ($lang) { |
8760
|
0
|
|
|
|
|
0
|
my $langInfo = GetLangInfoQT($et, $tagInfo, $lang); |
8761
|
0
|
0
|
|
|
|
0
|
$tagInfo = $langInfo if $langInfo; |
8762
|
|
|
|
|
|
|
} |
8763
|
0
|
0
|
|
|
|
0
|
$verbose and $et->VerboseInfo($tag, $tagInfo, |
8764
|
|
|
|
|
|
|
Value => $val, |
8765
|
|
|
|
|
|
|
DataPt => $dataPt, |
8766
|
|
|
|
|
|
|
Start => $pos + 10, |
8767
|
|
|
|
|
|
|
Size => $size - 10, |
8768
|
|
|
|
|
|
|
); |
8769
|
|
|
|
|
|
|
# convert from UTF-16 BE if necessary |
8770
|
0
|
0
|
|
|
|
0
|
$val = $et->Decode($val, 'UCS2') if $enc == 1; |
8771
|
0
|
0
|
0
|
|
|
0
|
if ($enc == 0 and $$tagInfo{Unknown}) { |
8772
|
|
|
|
|
|
|
# binary data |
8773
|
0
|
|
|
|
|
0
|
$et->FoundTag($tagInfo, \$val); |
8774
|
|
|
|
|
|
|
} else { |
8775
|
0
|
|
|
|
|
0
|
$et->FoundTag($tagInfo, $val); |
8776
|
|
|
|
|
|
|
} |
8777
|
|
|
|
|
|
|
} |
8778
|
0
|
|
|
|
|
0
|
$pos += $size; |
8779
|
|
|
|
|
|
|
} |
8780
|
0
|
|
|
|
|
0
|
return 1; |
8781
|
|
|
|
|
|
|
} |
8782
|
|
|
|
|
|
|
|
8783
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8784
|
|
|
|
|
|
|
# Process sample description table |
8785
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
8786
|
|
|
|
|
|
|
# Returns: 1 on success |
8787
|
|
|
|
|
|
|
# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691) |
8788
|
|
|
|
|
|
|
sub ProcessSampleDesc($$$) |
8789
|
|
|
|
|
|
|
{ |
8790
|
38
|
|
|
38
|
0
|
89
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
8791
|
38
|
|
|
|
|
77
|
my $dataPt = $$dirInfo{DataPt}; |
8792
|
38
|
|
50
|
|
|
146
|
my $pos = $$dirInfo{DirStart} || 0; |
8793
|
38
|
|
33
|
|
|
100
|
my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $pos); |
8794
|
38
|
50
|
|
|
|
97
|
return 0 if $pos + 8 > $dirLen; |
8795
|
|
|
|
|
|
|
|
8796
|
38
|
|
|
|
|
107
|
my $num = Get32u($dataPt, 4); # get number of sample entries in table |
8797
|
38
|
|
|
|
|
82
|
$pos += 8; |
8798
|
38
|
|
|
|
|
59
|
my ($i, $err); |
8799
|
38
|
|
|
|
|
124
|
for ($i=0; $i<$num; ++$i) { # loop through sample entries |
8800
|
38
|
50
|
|
|
|
104
|
$pos + 8 > $dirLen and $err = 1, last; |
8801
|
38
|
|
|
|
|
102
|
my $size = Get32u($dataPt, $pos); |
8802
|
38
|
50
|
|
|
|
104
|
$pos + $size > $dirLen and $err = 1, last; |
8803
|
38
|
|
|
|
|
99
|
$$dirInfo{DirStart} = $pos; |
8804
|
38
|
|
|
|
|
73
|
$$dirInfo{DirLen} = $size; |
8805
|
38
|
|
|
|
|
132
|
ProcessHybrid($et, $dirInfo, $tagTablePtr); |
8806
|
38
|
|
|
|
|
108
|
$pos += $size; |
8807
|
|
|
|
|
|
|
} |
8808
|
38
|
0
|
33
|
|
|
89
|
if ($err and $$et{HandlerType}) { |
8809
|
0
|
|
0
|
|
|
0
|
my $grp = $$et{SET_GROUP1} || $$dirInfo{Parent} || 'unknown'; |
8810
|
0
|
|
|
|
|
0
|
$et->Warn("Truncated $$et{HandlerType} sample table for $grp"); |
8811
|
|
|
|
|
|
|
} |
8812
|
38
|
|
|
|
|
102
|
return 1; |
8813
|
|
|
|
|
|
|
} |
8814
|
|
|
|
|
|
|
|
8815
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8816
|
|
|
|
|
|
|
# Process hybrid binary data + QuickTime container (ref PH) |
8817
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
8818
|
|
|
|
|
|
|
# Returns: 1 on success |
8819
|
|
|
|
|
|
|
sub ProcessHybrid($$$) |
8820
|
|
|
|
|
|
|
{ |
8821
|
38
|
|
|
38
|
0
|
90
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
8822
|
|
|
|
|
|
|
# brute-force search for child atoms after first 8 bytes of binary data |
8823
|
38
|
|
|
|
|
79
|
my $dataPt = $$dirInfo{DataPt}; |
8824
|
38
|
|
50
|
|
|
104
|
my $dirStart = $$dirInfo{DirStart} || 0; |
8825
|
38
|
|
33
|
|
|
99
|
my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart; |
8826
|
38
|
|
|
|
|
62
|
my $end = $dirStart + $dirLen; |
8827
|
38
|
|
|
|
|
68
|
my $pos = $dirStart + 8; # skip length/version |
8828
|
38
|
|
|
|
|
60
|
my $try = $pos; |
8829
|
38
|
|
|
|
|
52
|
my $childPos; |
8830
|
|
|
|
|
|
|
|
8831
|
38
|
|
|
|
|
95
|
while ($pos <= $end - 8) { |
8832
|
2204
|
|
|
|
|
3005
|
my $tag = substr($$dataPt, $try+4, 4); |
8833
|
|
|
|
|
|
|
# look only for well-behaved tag ID's |
8834
|
2204
|
100
|
|
|
|
4848
|
$tag =~ /[^\w ]/ and $try = ++$pos, next; |
8835
|
94
|
|
|
|
|
181
|
my $size = Get32u($dataPt, $try); |
8836
|
94
|
100
|
|
|
|
197
|
if ($size + $try == $end) { |
8837
|
|
|
|
|
|
|
# the atom ends exactly at the end of the parent -- this must be it |
8838
|
16
|
|
|
|
|
38
|
$childPos = $pos; |
8839
|
16
|
|
|
|
|
37
|
$$dirInfo{DirLen} = $pos; # the binary data ends at the first child atom |
8840
|
16
|
|
|
|
|
35
|
last; |
8841
|
|
|
|
|
|
|
} |
8842
|
78
|
100
|
100
|
|
|
255
|
if ($size < 8 or $size + $try > $end - 8) { |
8843
|
58
|
|
|
|
|
109
|
$try = ++$pos; # fail. try next position |
8844
|
|
|
|
|
|
|
} else { |
8845
|
20
|
|
|
|
|
46
|
$try += $size; # could be another atom following this |
8846
|
|
|
|
|
|
|
} |
8847
|
|
|
|
|
|
|
} |
8848
|
|
|
|
|
|
|
# process binary data |
8849
|
38
|
|
|
|
|
106
|
$$dirInfo{MixedTags} = 1; # ignore non-integer tag ID's |
8850
|
38
|
|
|
|
|
139
|
$et->ProcessBinaryData($dirInfo, $tagTablePtr); |
8851
|
|
|
|
|
|
|
# process child atoms if found |
8852
|
38
|
100
|
|
|
|
121
|
if ($childPos) { |
8853
|
16
|
|
|
|
|
40
|
$$dirInfo{DirStart} = $childPos; |
8854
|
16
|
|
|
|
|
36
|
$$dirInfo{DirLen} = $end - $childPos; |
8855
|
16
|
|
|
|
|
58
|
ProcessMOV($et, $dirInfo, $tagTablePtr); |
8856
|
|
|
|
|
|
|
} |
8857
|
38
|
|
|
|
|
89
|
return 1; |
8858
|
|
|
|
|
|
|
} |
8859
|
|
|
|
|
|
|
|
8860
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8861
|
|
|
|
|
|
|
# Process iTunes 'righ' atom (ref PH) |
8862
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
8863
|
|
|
|
|
|
|
# Returns: 1 on success |
8864
|
|
|
|
|
|
|
sub ProcessRights($$$) |
8865
|
|
|
|
|
|
|
{ |
8866
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
8867
|
0
|
|
|
|
|
0
|
my $dataPt = $$dirInfo{DataPt}; |
8868
|
0
|
|
|
|
|
0
|
my $dataPos = $$dirInfo{Base}; |
8869
|
0
|
|
|
|
|
0
|
my $dirLen = length $$dataPt; |
8870
|
0
|
|
0
|
|
|
0
|
my $unknown = $$et{OPTIONS}{Unknown} || $$et{OPTIONS}{Verbose}; |
8871
|
0
|
|
|
|
|
0
|
my $pos; |
8872
|
0
|
|
|
|
|
0
|
$et->VerboseDir('righ', $dirLen / 8); |
8873
|
0
|
|
|
|
|
0
|
for ($pos = 0; $pos + 8 <= $dirLen; $pos += 8) { |
8874
|
0
|
|
|
|
|
0
|
my $tag = substr($$dataPt, $pos, 4); |
8875
|
0
|
0
|
|
|
|
0
|
last if $tag eq "\0\0\0\0"; |
8876
|
0
|
|
|
|
|
0
|
my $val = substr($$dataPt, $pos + 4, 4); |
8877
|
0
|
|
|
|
|
0
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); |
8878
|
0
|
0
|
|
|
|
0
|
unless ($tagInfo) { |
8879
|
0
|
0
|
|
|
|
0
|
next unless $unknown; |
8880
|
0
|
|
|
|
|
0
|
my $name = PrintableTagID($tag); |
8881
|
0
|
|
|
|
|
0
|
$tagInfo = { |
8882
|
|
|
|
|
|
|
Name => "Unknown_$name", |
8883
|
|
|
|
|
|
|
Description => "Unknown $name", |
8884
|
|
|
|
|
|
|
Unknown => 1, |
8885
|
|
|
|
|
|
|
}, |
8886
|
|
|
|
|
|
|
AddTagToTable($tagTablePtr, $tag, $tagInfo); |
8887
|
|
|
|
|
|
|
} |
8888
|
0
|
0
|
|
|
|
0
|
$val = '0x' . unpack('H*', $val) unless $$tagInfo{Format}; |
8889
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTablePtr, $tag, $val, |
8890
|
|
|
|
|
|
|
DataPt => $dataPt, |
8891
|
|
|
|
|
|
|
DataPos => $dataPos, |
8892
|
|
|
|
|
|
|
Start => $pos + 4, |
8893
|
|
|
|
|
|
|
Size => 4, |
8894
|
|
|
|
|
|
|
); |
8895
|
|
|
|
|
|
|
} |
8896
|
0
|
|
|
|
|
0
|
return 1; |
8897
|
|
|
|
|
|
|
} |
8898
|
|
|
|
|
|
|
|
8899
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8900
|
|
|
|
|
|
|
# Process iTunes Encoding Params (ref PH) |
8901
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
8902
|
|
|
|
|
|
|
# Returns: 1 on success |
8903
|
|
|
|
|
|
|
sub ProcessEncodingParams($$$) |
8904
|
|
|
|
|
|
|
{ |
8905
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
8906
|
0
|
|
|
|
|
0
|
my $dataPt = $$dirInfo{DataPt}; |
8907
|
0
|
|
|
|
|
0
|
my $dirLen = length $$dataPt; |
8908
|
0
|
|
|
|
|
0
|
my $pos; |
8909
|
0
|
|
|
|
|
0
|
$et->VerboseDir('Encoding Params', $dirLen / 8); |
8910
|
0
|
|
|
|
|
0
|
for ($pos = 0; $pos + 8 <= $dirLen; $pos += 8) { |
8911
|
0
|
|
|
|
|
0
|
my ($tag, $val) = unpack("x${pos}a4N", $$dataPt); |
8912
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTablePtr, $tag, $val); |
8913
|
|
|
|
|
|
|
} |
8914
|
0
|
|
|
|
|
0
|
return 1; |
8915
|
|
|
|
|
|
|
} |
8916
|
|
|
|
|
|
|
|
8917
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8918
|
|
|
|
|
|
|
# Read Meta Keys and add tags to ItemList table ('mdta' handler) (ref PH) |
8919
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
8920
|
|
|
|
|
|
|
# Returns: 1 on success |
8921
|
|
|
|
|
|
|
sub ProcessKeys($$$) |
8922
|
|
|
|
|
|
|
{ |
8923
|
9
|
|
|
9
|
0
|
18
|
local $_; |
8924
|
9
|
|
|
|
|
25
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
8925
|
9
|
|
|
|
|
21
|
my $dataPt = $$dirInfo{DataPt}; |
8926
|
9
|
|
|
|
|
17
|
my $dirLen = length $$dataPt; |
8927
|
9
|
|
|
|
|
11
|
my $out; |
8928
|
9
|
50
|
|
|
|
32
|
if ($et->Options('Verbose')) { |
8929
|
0
|
|
|
|
|
0
|
$et->VerboseDir('Keys'); |
8930
|
0
|
|
|
|
|
0
|
$out = $et->Options('TextOut'); |
8931
|
|
|
|
|
|
|
} |
8932
|
9
|
|
|
|
|
21
|
my $pos = 8; |
8933
|
9
|
|
|
|
|
17
|
my $index = 1; |
8934
|
9
|
|
|
|
|
19
|
++$$et{KeysCount}; # increment key count for this directory |
8935
|
9
|
|
|
|
|
23
|
my $itemList = GetTagTable('Image::ExifTool::QuickTime::ItemList'); |
8936
|
9
|
|
|
|
|
33
|
my $userData = GetTagTable('Image::ExifTool::QuickTime::UserData'); |
8937
|
9
|
|
|
|
|
43
|
while ($pos < $dirLen - 4) { |
8938
|
22
|
|
|
|
|
70
|
my $len = unpack("x${pos}N", $$dataPt); |
8939
|
22
|
50
|
33
|
|
|
104
|
last if $len < 8 or $pos + $len > $dirLen; |
8940
|
22
|
|
|
|
|
42
|
delete $$tagTablePtr{$index}; |
8941
|
22
|
|
|
|
|
55
|
my $ns = substr($$dataPt, $pos + 4, 4); |
8942
|
22
|
|
|
|
|
46
|
my $tag = substr($$dataPt, $pos + 8, $len - 8); |
8943
|
22
|
|
|
|
|
52
|
$tag =~ s/\0.*//s; # truncate at null |
8944
|
22
|
|
|
|
|
32
|
my $full = $tag; |
8945
|
22
|
50
|
|
|
|
114
|
$tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain |
8946
|
22
|
50
|
|
|
|
51
|
$tag = "Tag_$ns" unless $tag; |
8947
|
22
|
|
|
|
|
38
|
my $short = $tag; |
8948
|
22
|
|
|
|
|
26
|
my $tagInfo; |
8949
|
22
|
|
|
|
|
31
|
for (;;) { |
8950
|
22
|
50
|
|
|
|
51
|
$tagInfo = $et->GetTagInfo($tagTablePtr, $tag) and last; |
8951
|
|
|
|
|
|
|
# also try ItemList and UserData tables |
8952
|
0
|
0
|
|
|
|
0
|
$tagInfo = $et->GetTagInfo($itemList, $tag) and last; |
8953
|
0
|
0
|
|
|
|
0
|
$tagInfo = $et->GetTagInfo($userData, $tag) and last; |
8954
|
|
|
|
|
|
|
# (I have some samples where the tag is a reversed ItemList or UserData tag ID) |
8955
|
0
|
0
|
|
|
|
0
|
if ($tag =~ /^\w{3}\xa9$/) { |
8956
|
0
|
|
|
|
|
0
|
$tag = pack('N', unpack('V', $tag)); |
8957
|
0
|
0
|
|
|
|
0
|
$tagInfo = $et->GetTagInfo($itemList, $tag) and last; |
8958
|
0
|
|
|
|
|
0
|
$tagInfo = $et->GetTagInfo($userData, $tag); |
8959
|
0
|
|
|
|
|
0
|
last; |
8960
|
|
|
|
|
|
|
} |
8961
|
0
|
0
|
|
|
|
0
|
if ($tag eq $full) { |
8962
|
0
|
|
|
|
|
0
|
$tag = $short; |
8963
|
0
|
|
|
|
|
0
|
last; |
8964
|
|
|
|
|
|
|
} |
8965
|
0
|
|
|
|
|
0
|
$tag = $full; |
8966
|
|
|
|
|
|
|
} |
8967
|
22
|
|
|
|
|
50
|
my ($newInfo, $msg); |
8968
|
22
|
50
|
0
|
|
|
61
|
if ($tagInfo) { |
|
|
0
|
|
|
|
|
|
8969
|
|
|
|
|
|
|
# copy tag information into new Keys tag |
8970
|
|
|
|
|
|
|
$newInfo = { |
8971
|
|
|
|
|
|
|
Name => $$tagInfo{Name}, |
8972
|
|
|
|
|
|
|
Format => $$tagInfo{Format}, |
8973
|
|
|
|
|
|
|
ValueConv => $$tagInfo{ValueConv}, |
8974
|
|
|
|
|
|
|
ValueConvInv => $$tagInfo{ValueConvInv}, |
8975
|
|
|
|
|
|
|
PrintConv => $$tagInfo{PrintConv}, |
8976
|
|
|
|
|
|
|
PrintConvInv => $$tagInfo{PrintConvInv}, |
8977
|
|
|
|
|
|
|
Writable => defined $$tagInfo{Writable} ? $$tagInfo{Writable} : 1, |
8978
|
|
|
|
|
|
|
SubDirectory => $$tagInfo{SubDirectory}, |
8979
|
22
|
50
|
|
|
|
189
|
}; |
8980
|
22
|
|
|
|
|
46
|
my $groups = $$tagInfo{Groups}; |
8981
|
22
|
100
|
|
|
|
100
|
$$newInfo{Groups} = $groups ? { %$groups } : { }; |
8982
|
22
|
|
66
|
|
|
162
|
$$newInfo{Groups}{$_} or $$newInfo{Groups}{$_} = $$tagTablePtr{GROUPS}{$_} foreach 0..2; |
8983
|
22
|
|
|
|
|
51
|
$$newInfo{Groups}{1} = 'Keys'; |
8984
|
|
|
|
|
|
|
} elsif ($tag =~ /^[-\w. ]+$/ or $tag =~ /\w{4}/) { |
8985
|
|
|
|
|
|
|
# create info for tags with reasonable id's |
8986
|
0
|
|
|
|
|
0
|
my $name = ucfirst $tag; |
8987
|
0
|
|
|
|
|
0
|
$name =~ tr/-0-9a-zA-Z_. //dc; |
8988
|
0
|
|
|
|
|
0
|
$name =~ s/[. ]+(.?)/\U$1/g; |
8989
|
0
|
|
|
|
|
0
|
$name =~ s/_([a-z])/_\U$1/g; |
8990
|
0
|
|
|
|
|
0
|
$name =~ s/([a-z])_([A-Z])/$1$2/g; |
8991
|
0
|
0
|
|
|
|
0
|
$name = "Tag_$name" if length $name < 2; |
8992
|
0
|
|
|
|
|
0
|
$newInfo = { Name => $name, Groups => { 1 => 'Keys' } }; |
8993
|
0
|
|
|
|
|
0
|
$msg = ' (Unknown)'; |
8994
|
|
|
|
|
|
|
} |
8995
|
|
|
|
|
|
|
# substitute this tag in the ItemList table with the given index |
8996
|
22
|
|
|
|
|
57
|
my $id = $$et{KeysCount} . '.' . $index; |
8997
|
22
|
100
|
|
|
|
69
|
if (ref $$itemList{$id} eq 'HASH') { |
8998
|
|
|
|
|
|
|
# delete other languages too if they exist |
8999
|
18
|
|
|
|
|
37
|
my $oldInfo = $$itemList{$id}; |
9000
|
18
|
50
|
|
|
|
49
|
if ($$oldInfo{OtherLang}) { |
9001
|
0
|
|
|
|
|
0
|
delete $$itemList{$_} foreach @{$$oldInfo{OtherLang}}; |
|
0
|
|
|
|
|
0
|
|
9002
|
|
|
|
|
|
|
} |
9003
|
18
|
|
|
|
|
119
|
delete $$itemList{$id}; |
9004
|
|
|
|
|
|
|
} |
9005
|
22
|
50
|
|
|
|
42
|
if ($newInfo) { |
9006
|
22
|
|
|
|
|
47
|
$$newInfo{KeysID} = $tag; # save original ID for use in family 7 group name |
9007
|
22
|
|
|
|
|
61
|
AddTagToTable($itemList, $id, $newInfo); |
9008
|
22
|
50
|
|
|
|
41
|
$msg or $msg = ''; |
9009
|
22
|
50
|
|
|
|
47
|
$out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n"; |
9010
|
|
|
|
|
|
|
} |
9011
|
22
|
|
|
|
|
35
|
$pos += $len; |
9012
|
22
|
|
|
|
|
64
|
++$index; |
9013
|
|
|
|
|
|
|
} |
9014
|
9
|
|
|
|
|
26
|
return 1; |
9015
|
|
|
|
|
|
|
} |
9016
|
|
|
|
|
|
|
|
9017
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
9018
|
|
|
|
|
|
|
# Process keys in MetaSampleDesc directory |
9019
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
9020
|
|
|
|
|
|
|
# Returns: 1 on success |
9021
|
|
|
|
|
|
|
sub ProcessMetaKeys($$$) |
9022
|
|
|
|
|
|
|
{ |
9023
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
9024
|
|
|
|
|
|
|
# save this information to decode timed metadata samples when ExtractEmbedded is used |
9025
|
0
|
0
|
|
|
|
0
|
SaveMetaKeys($et, $dirInfo, $tagTablePtr) if $$et{OPTIONS}{ExtractEmbedded}; |
9026
|
0
|
|
|
|
|
0
|
return 1; |
9027
|
|
|
|
|
|
|
} |
9028
|
|
|
|
|
|
|
|
9029
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
9030
|
|
|
|
|
|
|
# Process a QuickTime atom |
9031
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) optional tag table ref |
9032
|
|
|
|
|
|
|
# Returns: 1 on success |
9033
|
|
|
|
|
|
|
sub ProcessMOV($$;$) |
9034
|
|
|
|
|
|
|
{ |
9035
|
383
|
|
|
383
|
0
|
573
|
local $_; |
9036
|
383
|
|
|
|
|
673
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
9037
|
383
|
|
|
|
|
614
|
my $raf = $$dirInfo{RAF}; |
9038
|
383
|
|
|
|
|
577
|
my $dataPt = $$dirInfo{DataPt}; |
9039
|
383
|
|
|
|
|
988
|
my $verbose = $et->Options('Verbose'); |
9040
|
383
|
|
|
|
|
725
|
my $validate = $$et{OPTIONS}{Validate}; |
9041
|
383
|
|
100
|
|
|
823
|
my $dataPos = $$dirInfo{Base} || 0; |
9042
|
383
|
|
100
|
|
|
851
|
my $dirID = $$dirInfo{DirID} || ''; |
9043
|
383
|
|
|
|
|
690
|
my $charsetQuickTime = $et->Options('CharsetQuickTime'); |
9044
|
383
|
|
|
|
|
934
|
my ($buff, $tag, $size, $track, $isUserData, %triplet, $doDefaultLang, $index); |
9045
|
383
|
|
|
|
|
0
|
my ($dirEnd, $unkOpt, %saveOptions, $atomCount); |
9046
|
|
|
|
|
|
|
|
9047
|
383
|
|
|
|
|
618
|
my $topLevel = not $$et{InQuickTime}; |
9048
|
383
|
|
|
|
|
551
|
$$et{InQuickTime} = 1; |
9049
|
383
|
100
|
|
|
|
829
|
$$et{HandlerType} = $$et{MetaFormat} = '' unless defined $$et{HandlerType}; |
9050
|
|
|
|
|
|
|
|
9051
|
383
|
100
|
|
|
|
715
|
unless (defined $$et{KeysCount}) { |
9052
|
20
|
|
|
|
|
49
|
$$et{KeysCount} = 0; # initialize ItemList key directory count |
9053
|
20
|
|
|
|
|
42
|
$doDefaultLang = 1; # flag to generate default language tags |
9054
|
|
|
|
|
|
|
} |
9055
|
|
|
|
|
|
|
# more convenient to package data as a RandomAccess file |
9056
|
383
|
100
|
|
|
|
730
|
unless ($raf) { |
9057
|
363
|
|
|
|
|
998
|
$raf = new File::RandomAccess($dataPt); |
9058
|
363
|
50
|
100
|
|
|
1405
|
$dirEnd = $dataPos + $$dirInfo{DirLen} + ($$dirInfo{DirStart} || 0) if $$dirInfo{DirLen}; |
9059
|
|
|
|
|
|
|
} |
9060
|
|
|
|
|
|
|
# skip leading bytes if necessary |
9061
|
383
|
100
|
|
|
|
773
|
if ($$dirInfo{DirStart}) { |
9062
|
94
|
50
|
|
|
|
296
|
$raf->Seek($$dirInfo{DirStart}, 1) or return 0; |
9063
|
94
|
|
|
|
|
172
|
$dataPos += $$dirInfo{DirStart}; |
9064
|
|
|
|
|
|
|
} |
9065
|
|
|
|
|
|
|
# read size/tag name atom header |
9066
|
383
|
50
|
|
|
|
799
|
$raf->Read($buff,8) == 8 or return 0; |
9067
|
383
|
|
|
|
|
582
|
$dataPos += 8; |
9068
|
383
|
100
|
|
|
|
614
|
if ($tagTablePtr) { |
9069
|
363
|
|
|
|
|
919
|
$isUserData = ($tagTablePtr eq \%Image::ExifTool::QuickTime::UserData); |
9070
|
|
|
|
|
|
|
} else { |
9071
|
20
|
|
|
|
|
60
|
$tagTablePtr = GetTagTable('Image::ExifTool::QuickTime::Main'); |
9072
|
|
|
|
|
|
|
} |
9073
|
383
|
|
|
|
|
1299
|
($size, $tag) = unpack('Na4', $buff); |
9074
|
383
|
100
|
|
|
|
753
|
if ($dataPt) { |
9075
|
363
|
50
|
|
|
|
685
|
$verbose and $et->VerboseDir($$dirInfo{DirName}); |
9076
|
|
|
|
|
|
|
} else { |
9077
|
|
|
|
|
|
|
# check on file type if called with a RAF |
9078
|
20
|
50
|
|
|
|
73
|
$$tagTablePtr{$tag} or return 0; |
9079
|
20
|
100
|
66
|
|
|
100
|
if ($tag eq 'ftyp' and $size >= 12) { |
9080
|
|
|
|
|
|
|
# read ftyp atom to see what type of file this is |
9081
|
11
|
|
|
|
|
27
|
my $fileType; |
9082
|
11
|
50
|
|
|
|
40
|
if ($raf->Read($buff, $size-8) == $size-8) { |
9083
|
11
|
|
|
|
|
45
|
$raf->Seek(-($size-8), 1); |
9084
|
11
|
|
|
|
|
45
|
my $type = substr($buff, 0, 4); |
9085
|
11
|
|
|
|
|
38
|
$$et{save_ftyp} = $type; |
9086
|
|
|
|
|
|
|
# see if we know the extension for this file type |
9087
|
11
|
50
|
33
|
|
|
124
|
if ($ftypLookup{$type} and $ftypLookup{$type} =~ /\(\.(\w+)/) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
9088
|
11
|
|
|
|
|
44
|
$fileType = $1; |
9089
|
|
|
|
|
|
|
# check compatible brands |
9090
|
|
|
|
|
|
|
} elsif ($buff =~ /^.{8}(.{4})+(mp41|mp42|avc1)/s) { |
9091
|
0
|
|
|
|
|
0
|
$fileType = 'MP4'; |
9092
|
|
|
|
|
|
|
} elsif ($buff =~ /^.{8}(.{4})+(f4v )/s) { |
9093
|
0
|
|
|
|
|
0
|
$fileType = 'F4V'; |
9094
|
|
|
|
|
|
|
} elsif ($buff =~ /^.{8}(.{4})+(qt )/s) { |
9095
|
0
|
|
|
|
|
0
|
$fileType = 'MOV'; |
9096
|
|
|
|
|
|
|
} |
9097
|
|
|
|
|
|
|
} |
9098
|
11
|
50
|
|
|
|
37
|
$fileType or $fileType = 'MP4'; # default to MP4 |
9099
|
11
|
|
50
|
|
|
80
|
$et->SetFileType($fileType, $mimeLookup{$fileType} || 'video/mp4'); |
9100
|
|
|
|
|
|
|
# temporarily set ExtractEmbedded option for CRX files |
9101
|
11
|
100
|
|
|
|
54
|
$saveOptions{ExtractEmbedded} = $et->Options(ExtractEmbedded => 1) if $fileType eq 'CRX'; |
9102
|
|
|
|
|
|
|
} else { |
9103
|
9
|
|
|
|
|
37
|
$et->SetFileType(); # MOV |
9104
|
|
|
|
|
|
|
} |
9105
|
20
|
|
|
|
|
78
|
SetByteOrder('MM'); |
9106
|
20
|
|
|
|
|
56
|
$$et{PRIORITY_DIR} = 'XMP'; # have XMP take priority |
9107
|
|
|
|
|
|
|
} |
9108
|
383
|
50
|
|
|
|
915
|
$$raf{NoBuffer} = 1 if $et->Options('FastScan'); # disable buffering in FastScan mode |
9109
|
|
|
|
|
|
|
|
9110
|
383
|
|
|
|
|
710
|
my $ee = $$et{OPTIONS}{ExtractEmbedded}; |
9111
|
383
|
100
|
|
|
|
639
|
if ($ee) { |
9112
|
134
|
|
|
|
|
261
|
$unkOpt = $$et{OPTIONS}{Unknown}; |
9113
|
134
|
|
|
|
|
2436
|
require 'Image/ExifTool/QuickTimeStream.pl'; |
9114
|
|
|
|
|
|
|
} |
9115
|
383
|
100
|
|
|
|
869
|
if ($$tagTablePtr{VARS}) { |
9116
|
22
|
|
|
|
|
51
|
$index = $$tagTablePtr{VARS}{START_INDEX}; |
9117
|
22
|
|
|
|
|
45
|
$atomCount = $$tagTablePtr{VARS}{ATOM_COUNT}; |
9118
|
|
|
|
|
|
|
} |
9119
|
383
|
|
|
|
|
446
|
for (;;) { |
9120
|
1253
|
|
|
|
|
1782
|
my ($eeTag, $ignore); |
9121
|
1253
|
50
|
33
|
|
|
2327
|
last if defined $atomCount and --$atomCount < 0; |
9122
|
1253
|
100
|
|
|
|
1974
|
if ($size < 8) { |
9123
|
4
|
50
|
|
|
|
16
|
if ($size == 0) { |
9124
|
0
|
0
|
|
|
|
0
|
if ($dataPt) { |
9125
|
|
|
|
|
|
|
# a zero size isn't legal for contained atoms, but Canon uses it to |
9126
|
|
|
|
|
|
|
# terminate the CNTH atom (eg. CanonEOS100D.mov), so tolerate it here |
9127
|
0
|
|
|
|
|
0
|
my $pos = $raf->Tell() - 4; |
9128
|
0
|
|
|
|
|
0
|
$raf->Seek(0,2); |
9129
|
0
|
|
|
|
|
0
|
my $str = $$dirInfo{DirName} . ' with ' . ($raf->Tell() - $pos) . ' bytes'; |
9130
|
0
|
|
|
|
|
0
|
$et->VPrint(0,"$$et{INDENT}\[Terminator found in $str remaining]"); |
9131
|
|
|
|
|
|
|
} else { |
9132
|
0
|
|
|
|
|
0
|
my $t = PrintableTagID($tag,2); |
9133
|
0
|
|
|
|
|
0
|
$et->VPrint(0,"$$et{INDENT}Tag '${t}' extends to end of file"); |
9134
|
0
|
0
|
|
|
|
0
|
if ($$tagTablePtr{"$tag-size"}) { |
9135
|
0
|
|
|
|
|
0
|
my $pos = $raf->Tell(); |
9136
|
0
|
|
|
|
|
0
|
$raf->Seek(0, 2); |
9137
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTablePtr, "$tag-size", $raf->Tell() - $pos); |
9138
|
0
|
0
|
|
|
|
0
|
$et->HandleTag($tagTablePtr, "$tag-offset", $pos) if $$tagTablePtr{"$tag-offset"}; |
9139
|
|
|
|
|
|
|
} |
9140
|
|
|
|
|
|
|
} |
9141
|
0
|
|
|
|
|
0
|
last; |
9142
|
|
|
|
|
|
|
} |
9143
|
4
|
50
|
|
|
|
15
|
$size == 1 or $et->Warn('Invalid atom size'), last; |
9144
|
|
|
|
|
|
|
# read extended atom size |
9145
|
4
|
50
|
|
|
|
13
|
$raf->Read($buff, 8) == 8 or $et->Warn('Truncated atom header'), last; |
9146
|
4
|
|
|
|
|
9
|
$dataPos += 8; |
9147
|
4
|
|
|
|
|
14
|
my ($hi, $lo) = unpack('NN', $buff); |
9148
|
4
|
50
|
33
|
|
|
110
|
if ($hi or $lo > 0x7fffffff) { |
9149
|
0
|
0
|
|
|
|
0
|
if ($hi > 0x7fffffff) { |
|
|
0
|
|
|
|
|
|
9150
|
0
|
|
|
|
|
0
|
$et->Warn('Invalid atom size'); |
9151
|
0
|
|
|
|
|
0
|
last; |
9152
|
|
|
|
|
|
|
} elsif (not $et->Options('LargeFileSupport')) { |
9153
|
0
|
|
|
|
|
0
|
$et->Warn('End of processing at large atom (LargeFileSupport not enabled)'); |
9154
|
0
|
|
|
|
|
0
|
last; |
9155
|
|
|
|
|
|
|
} |
9156
|
|
|
|
|
|
|
} |
9157
|
4
|
|
|
|
|
13
|
$size = $hi * 4294967296 + $lo - 16; |
9158
|
4
|
50
|
|
|
|
15
|
$size < 0 and $et->Warn('Invalid extended size'), last; |
9159
|
|
|
|
|
|
|
} else { |
9160
|
1249
|
|
|
|
|
1613
|
$size -= 8; |
9161
|
|
|
|
|
|
|
} |
9162
|
1253
|
50
|
|
|
|
2040
|
if ($validate) { |
9163
|
0
|
0
|
|
|
|
0
|
$$et{ValidatePath} or $$et{ValidatePath} = { }; |
9164
|
0
|
|
|
|
|
0
|
my $path = join('-', @{$$et{PATH}}, $tag); |
|
0
|
|
|
|
|
0
|
|
9165
|
0
|
0
|
|
|
|
0
|
$path =~ s/-Track-/-$$et{SET_GROUP1}-/ if $$et{SET_GROUP1}; |
9166
|
0
|
0
|
0
|
|
|
0
|
if ($$et{ValidatePath}{$path} and not $dupTagOK{$tag} and not $dupDirOK{$dirID}) { |
|
|
|
0
|
|
|
|
|
9167
|
0
|
|
|
|
|
0
|
my $i = Get32u(\$tag,0); |
9168
|
0
|
0
|
|
|
|
0
|
my $str = $i < 255 ? "index $i" : "tag '" . PrintableTagID($tag,2) . "'"; |
9169
|
0
|
|
|
|
|
0
|
$et->WarnOnce("Duplicate $str at " . join('-', @{$$et{PATH}})); |
|
0
|
|
|
|
|
0
|
|
9170
|
0
|
0
|
|
|
|
0
|
$$et{ValidatePath} = { } if $path eq 'MOV-moov'; # avoid warnings for all contained dups |
9171
|
|
|
|
|
|
|
} |
9172
|
0
|
|
|
|
|
0
|
$$et{ValidatePath}{$path} = 1; |
9173
|
|
|
|
|
|
|
} |
9174
|
1253
|
50
|
66
|
|
|
2231
|
if ($isUserData and $$et{SET_GROUP1}) { |
9175
|
0
|
|
|
|
|
0
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); |
9176
|
|
|
|
|
|
|
# add track name to UserData tags inside tracks |
9177
|
0
|
|
|
|
|
0
|
$tag = $$et{SET_GROUP1} . $tag; |
9178
|
0
|
0
|
0
|
|
|
0
|
if (not $$tagTablePtr{$tag} and $tagInfo) { |
9179
|
0
|
|
|
|
|
0
|
my %newInfo = %$tagInfo; |
9180
|
0
|
|
|
|
|
0
|
foreach ('Name', 'Description') { |
9181
|
0
|
0
|
|
|
|
0
|
next unless $$tagInfo{$_}; |
9182
|
0
|
|
|
|
|
0
|
$newInfo{$_} = $$et{SET_GROUP1} . $$tagInfo{$_}; |
9183
|
0
|
|
|
|
|
0
|
$newInfo{$_} =~ s/^(Track\d+)Track/$1/; # remove duplicate "Track" in name |
9184
|
|
|
|
|
|
|
} |
9185
|
0
|
|
|
|
|
0
|
AddTagToTable($tagTablePtr, $tag, \%newInfo); |
9186
|
|
|
|
|
|
|
} |
9187
|
|
|
|
|
|
|
} |
9188
|
|
|
|
|
|
|
# set flag to store additional information for ExtractEmbedded option |
9189
|
1253
|
|
|
|
|
2372
|
my $handlerType = $$et{HandlerType}; |
9190
|
1253
|
100
|
100
|
|
|
5281
|
if ($eeBox{$handlerType} and $eeBox{$handlerType}{$tag}) { |
|
|
50
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
0
|
|
|
|
|
9191
|
104
|
100
|
33
|
|
|
268
|
if ($ee) { |
|
|
50
|
|
|
|
|
|
9192
|
|
|
|
|
|
|
# (there is another 'gps ' box with a track log that doesn't contain offsets) |
9193
|
68
|
50
|
33
|
|
|
161
|
if ($tag ne 'gps ' or $eeBox{$handlerType}{$tag} eq $dirID) { |
9194
|
68
|
|
|
|
|
83
|
$eeTag = 1; |
9195
|
68
|
|
|
|
|
121
|
$$et{OPTIONS}{Unknown} = 1; # temporarily enable "Unknown" option |
9196
|
|
|
|
|
|
|
} |
9197
|
|
|
|
|
|
|
} elsif ($handlerType ne 'vide' and not $$et{OPTIONS}{Validate}) { |
9198
|
0
|
|
|
|
|
0
|
EEWarn($et); |
9199
|
|
|
|
|
|
|
} |
9200
|
|
|
|
|
|
|
} elsif ($ee and $ee > 1 and $eeBox2{$handlerType} and $eeBox2{$handlerType}{$tag}) { |
9201
|
0
|
|
|
|
|
0
|
$eeTag = 1; |
9202
|
0
|
|
|
|
|
0
|
$$et{OPTIONS}{Unknown} = 1; |
9203
|
|
|
|
|
|
|
} |
9204
|
1253
|
|
|
|
|
2878
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); |
9205
|
|
|
|
|
|
|
|
9206
|
1253
|
100
|
|
|
|
2585
|
$$et{OPTIONS}{Unknown} = $unkOpt if $eeTag; # restore Unknown option |
9207
|
|
|
|
|
|
|
|
9208
|
|
|
|
|
|
|
# allow numerical tag ID's |
9209
|
1253
|
100
|
|
|
|
2152
|
unless ($tagInfo) { |
9210
|
160
|
|
|
|
|
538
|
my $id = $$et{KeysCount} . '.' . unpack('N', $tag); |
9211
|
160
|
100
|
|
|
|
422
|
if ($$tagTablePtr{$id}) { |
9212
|
22
|
|
|
|
|
54
|
$tagInfo = $et->GetTagInfo($tagTablePtr, $id); |
9213
|
22
|
|
|
|
|
47
|
$tag = $id; |
9214
|
|
|
|
|
|
|
} |
9215
|
|
|
|
|
|
|
} |
9216
|
|
|
|
|
|
|
# generate tagInfo if Unknown option set |
9217
|
1253
|
50
|
66
|
|
|
2596
|
if (not defined $tagInfo and ($$et{OPTIONS}{Unknown} or |
|
|
|
66
|
|
|
|
|
9218
|
|
|
|
|
|
|
$verbose or $tag =~ /^\xa9/)) |
9219
|
|
|
|
|
|
|
{ |
9220
|
13
|
|
|
|
|
39
|
my $name = PrintableTagID($tag,1); |
9221
|
13
|
50
|
|
|
|
43
|
if ($name =~ /^xa9(.*)/) { |
9222
|
0
|
|
|
|
|
0
|
$tagInfo = { |
9223
|
|
|
|
|
|
|
Name => "UserData_$1", |
9224
|
|
|
|
|
|
|
Description => "User Data $1", |
9225
|
|
|
|
|
|
|
}; |
9226
|
|
|
|
|
|
|
} else { |
9227
|
13
|
|
|
|
|
86
|
$tagInfo = { |
9228
|
|
|
|
|
|
|
Name => "Unknown_$name", |
9229
|
|
|
|
|
|
|
Description => "Unknown $name", |
9230
|
|
|
|
|
|
|
%unknownInfo, |
9231
|
|
|
|
|
|
|
}; |
9232
|
|
|
|
|
|
|
} |
9233
|
13
|
|
|
|
|
44
|
AddTagToTable($tagTablePtr, $tag, $tagInfo); |
9234
|
|
|
|
|
|
|
} |
9235
|
|
|
|
|
|
|
# save required tag sizes |
9236
|
1253
|
100
|
|
|
|
3039
|
if ($$tagTablePtr{"$tag-size"}) { |
9237
|
23
|
|
|
|
|
119
|
$et->HandleTag($tagTablePtr, "$tag-size", $size); |
9238
|
23
|
50
|
|
|
|
172
|
$et->HandleTag($tagTablePtr, "$tag-offset", $raf->Tell()) if $$tagTablePtr{"$tag-offset"}; |
9239
|
|
|
|
|
|
|
} |
9240
|
|
|
|
|
|
|
# load values only if associated with a tag (or verbose) and not too big |
9241
|
1253
|
50
|
|
|
|
2149
|
if ($size > 0x2000000) { # start to get worried above 32 MB |
9242
|
|
|
|
|
|
|
# check for RIFF trailer (written by Auto-Vox dashcam) |
9243
|
0
|
0
|
|
|
|
0
|
if ($buff =~ /^(gpsa|gps0|gsen|gsea)...\0/s) { # (yet seen only gpsa as first record) |
9244
|
0
|
|
|
|
|
0
|
$et->VPrint(0, "Found RIFF trailer"); |
9245
|
0
|
0
|
|
|
|
0
|
if ($et->Options('ExtractEmbedded')) { |
9246
|
0
|
0
|
|
|
|
0
|
$raf->Seek(-8, 1) or last; # seek back to start of trailer |
9247
|
0
|
|
|
|
|
0
|
my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream'); |
9248
|
0
|
|
|
|
|
0
|
ProcessRIFFTrailer($et, { RAF => $raf }, $tbl); |
9249
|
|
|
|
|
|
|
} else { |
9250
|
0
|
|
|
|
|
0
|
EEWarn($et); |
9251
|
|
|
|
|
|
|
} |
9252
|
0
|
|
|
|
|
0
|
last; |
9253
|
|
|
|
|
|
|
} |
9254
|
0
|
|
|
|
|
0
|
$ignore = 1; |
9255
|
0
|
0
|
0
|
|
|
0
|
if ($tagInfo and not $$tagInfo{Unknown} and not $eeTag) { |
|
|
|
0
|
|
|
|
|
9256
|
0
|
|
|
|
|
0
|
my $t = PrintableTagID($tag,2); |
9257
|
0
|
0
|
|
|
|
0
|
if ($size > 0x8000000) { |
9258
|
0
|
|
|
|
|
0
|
$et->Warn("Skipping '${t}' atom > 128 MB", 1); |
9259
|
|
|
|
|
|
|
} else { |
9260
|
0
|
0
|
|
|
|
0
|
$et->Warn("Skipping '${t}' atom > 32 MB", 2) or $ignore = 0; |
9261
|
|
|
|
|
|
|
} |
9262
|
|
|
|
|
|
|
} |
9263
|
|
|
|
|
|
|
} |
9264
|
1253
|
100
|
66
|
|
|
3208
|
if (defined $tagInfo and not $ignore) { |
9265
|
|
|
|
|
|
|
# set document number for this item property if necessary |
9266
|
1165
|
100
|
|
|
|
2184
|
if ($$et{IsItemProperty}) { |
9267
|
12
|
|
|
|
|
19
|
my $items = $$et{ItemInfo}; |
9268
|
12
|
|
|
|
|
19
|
my ($id, $prop, $docNum, $lowest); |
9269
|
12
|
|
50
|
|
|
27
|
my $primary = $$et{PrimaryItem} || 0; |
9270
|
12
|
|
|
|
|
33
|
ItemID: foreach $id (keys %$items) { |
9271
|
34
|
100
|
|
|
|
66
|
next unless $$items{$id}{Association}; |
9272
|
20
|
|
|
|
|
28
|
my $item = $$items{$id}; |
9273
|
20
|
|
|
|
|
26
|
foreach $prop (@{$$item{Association}}) { |
|
20
|
|
|
|
|
33
|
|
9274
|
37
|
100
|
|
|
|
63
|
next unless $prop == $index; |
9275
|
12
|
100
|
0
|
|
|
66
|
if ($id == $primary or (not $dontInherit{$tag} and |
|
|
100
|
33
|
|
|
|
|
|
|
50
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
9276
|
|
|
|
|
|
|
(not $$item{RefersTo} or $$item{RefersTo}{$primary}))) |
9277
|
|
|
|
|
|
|
{ |
9278
|
|
|
|
|
|
|
# this is associated with the primary item or an item describing |
9279
|
|
|
|
|
|
|
# the primary item, so consider this part of the main document |
9280
|
6
|
|
|
|
|
7
|
undef $docNum; |
9281
|
6
|
|
|
|
|
9
|
undef $lowest; |
9282
|
6
|
|
|
|
|
11
|
last ItemID; |
9283
|
|
|
|
|
|
|
} elsif ($$item{DocNum}) { |
9284
|
|
|
|
|
|
|
# this property is already associated with an item that has |
9285
|
|
|
|
|
|
|
# an ExifTool document number, so use the lowest associated DocNum |
9286
|
3
|
50
|
33
|
|
|
14
|
$docNum = $$item{DocNum} if not defined $docNum or $docNum > $$item{DocNum}; |
9287
|
|
|
|
|
|
|
} elsif (not defined $lowest or $lowest > $id) { |
9288
|
|
|
|
|
|
|
# keep track of the lowest associated item ID |
9289
|
3
|
|
|
|
|
7
|
$lowest = $id; |
9290
|
|
|
|
|
|
|
} |
9291
|
|
|
|
|
|
|
} |
9292
|
|
|
|
|
|
|
} |
9293
|
12
|
100
|
100
|
|
|
41
|
if (not defined $docNum and defined $lowest) { |
9294
|
|
|
|
|
|
|
# this is the first time we've seen metadata from this item, |
9295
|
|
|
|
|
|
|
# so use a new document number |
9296
|
3
|
|
|
|
|
4
|
$docNum = ++$$et{DOC_COUNT}; |
9297
|
3
|
|
|
|
|
6
|
$$items{$lowest}{DocNum} = $docNum; |
9298
|
|
|
|
|
|
|
} |
9299
|
12
|
|
|
|
|
24
|
$$et{DOC_NUM} = $docNum; |
9300
|
|
|
|
|
|
|
} |
9301
|
1165
|
|
|
|
|
1384
|
my $val; |
9302
|
1165
|
|
|
|
|
2439
|
my $missing = $size - $raf->Read($val, $size); |
9303
|
1165
|
50
|
|
|
|
2059
|
if ($missing) { |
9304
|
0
|
|
|
|
|
0
|
my $t = PrintableTagID($tag,2); |
9305
|
0
|
|
|
|
|
0
|
$et->Warn("Truncated '${t}' data (missing $missing bytes)"); |
9306
|
0
|
|
|
|
|
0
|
last; |
9307
|
|
|
|
|
|
|
} |
9308
|
|
|
|
|
|
|
# use value to get tag info if necessary |
9309
|
1165
|
100
|
|
|
|
2052
|
$tagInfo or $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val); |
9310
|
1165
|
|
66
|
|
|
2881
|
my $hasData = ($$dirInfo{HasData} and $val =~ /\0...data\0/s); |
9311
|
1165
|
50
|
33
|
|
|
2271
|
if ($verbose and not $hasData) { |
9312
|
0
|
|
|
|
|
0
|
my $tval; |
9313
|
0
|
0
|
0
|
|
|
0
|
if ($tagInfo and $$tagInfo{Format}) { |
9314
|
0
|
|
|
|
|
0
|
$tval = ReadValue(\$val, 0, $$tagInfo{Format}, $$tagInfo{Count}, length($val)); |
9315
|
|
|
|
|
|
|
} |
9316
|
|
|
|
|
|
|
$et->VerboseInfo($tag, $tagInfo, |
9317
|
|
|
|
|
|
|
Value => $tval, |
9318
|
|
|
|
|
|
|
DataPt => \$val, |
9319
|
|
|
|
|
|
|
DataPos => $dataPos, |
9320
|
|
|
|
|
|
|
Size => $size, |
9321
|
|
|
|
|
|
|
Format => $tagInfo ? $$tagInfo{Format} : undef, |
9322
|
0
|
0
|
|
|
|
0
|
Index => $index, |
9323
|
|
|
|
|
|
|
); |
9324
|
|
|
|
|
|
|
# print iref item ID numbers |
9325
|
0
|
0
|
|
|
|
0
|
if ($dirID eq 'iref') { |
9326
|
0
|
|
|
|
|
0
|
my ($id, $count, @to, $i); |
9327
|
0
|
0
|
|
|
|
0
|
if ($$et{ItemRefVersion}) { |
9328
|
0
|
0
|
|
|
|
0
|
($id, $count, @to) = unpack('NnN*', $val) if length $val >= 10; |
9329
|
|
|
|
|
|
|
} else { |
9330
|
0
|
0
|
|
|
|
0
|
($id, $count, @to) = unpack('nnn*', $val) if length $val >= 6; |
9331
|
|
|
|
|
|
|
} |
9332
|
0
|
0
|
|
|
|
0
|
defined $id or $id = '', $count = 0; |
9333
|
0
|
0
|
|
|
|
0
|
$id .= " (wrong count: $count)" if $count != @to; |
9334
|
|
|
|
|
|
|
# convert sequential numbers to a range |
9335
|
0
|
|
|
|
|
0
|
for ($i=1; $i<@to; ) { |
9336
|
0
|
0
|
0
|
|
|
0
|
$to[$i-1] =~ /(\d+)$/ and $to[$i] == $1 + 1 or ++$i, next; |
9337
|
0
|
|
|
|
|
0
|
$to[$i-1] =~ s/(-.*)?$/-$to[$i]/; |
9338
|
0
|
|
|
|
|
0
|
splice @to, $i, 1; |
9339
|
|
|
|
|
|
|
} |
9340
|
0
|
|
|
|
|
0
|
$et->VPrint(1, "$$et{INDENT} Item $id refers to: ",join(',',@to),"\n"); |
9341
|
|
|
|
|
|
|
} |
9342
|
|
|
|
|
|
|
} |
9343
|
|
|
|
|
|
|
# extract metadata from stream if ExtractEmbedded option is enabled |
9344
|
1165
|
100
|
|
|
|
1961
|
if ($eeTag) { |
9345
|
68
|
|
|
|
|
220
|
ParseTag($et, $tag, \$val); |
9346
|
|
|
|
|
|
|
# forget this tag if we generated it only for ExtractEmbedded |
9347
|
68
|
100
|
66
|
|
|
320
|
undef $tagInfo if $tagInfo and $$tagInfo{Unknown} and not $unkOpt; |
|
|
|
100
|
|
|
|
|
9348
|
|
|
|
|
|
|
} |
9349
|
|
|
|
|
|
|
|
9350
|
|
|
|
|
|
|
# handle iTunesInfo mean/name/data triplets |
9351
|
1165
|
100
|
100
|
|
|
3533
|
if ($tagInfo and $$tagInfo{Triplet}) { |
9352
|
9
|
100
|
66
|
|
|
44
|
if ($tag eq 'data' and $triplet{mean} and $triplet{name}) { |
|
|
|
33
|
|
|
|
|
9353
|
3
|
|
|
|
|
7
|
$tag = $triplet{name}; |
9354
|
|
|
|
|
|
|
# add 'mean' to name unless it is 'com.apple.iTunes' |
9355
|
3
|
50
|
|
|
|
12
|
$tag = $triplet{mean} . '/' . $tag unless $triplet{mean} eq 'com.apple.iTunes'; |
9356
|
3
|
|
|
|
|
9
|
$tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val); |
9357
|
3
|
50
|
|
|
|
11
|
unless ($tagInfo) { |
9358
|
0
|
|
|
|
|
0
|
my $name = $triplet{name}; |
9359
|
0
|
|
|
|
|
0
|
my $desc = $name; |
9360
|
0
|
|
|
|
|
0
|
$name =~ tr/-_a-zA-Z0-9//dc; |
9361
|
0
|
|
|
|
|
0
|
$desc =~ tr/_/ /; |
9362
|
0
|
|
|
|
|
0
|
$tagInfo = { |
9363
|
|
|
|
|
|
|
Name => $name, |
9364
|
|
|
|
|
|
|
Description => $desc, |
9365
|
|
|
|
|
|
|
}; |
9366
|
0
|
|
|
|
|
0
|
$et->VPrint(0, $$et{INDENT}, "[adding QuickTime:$name]\n"); |
9367
|
0
|
|
|
|
|
0
|
AddTagToTable($tagTablePtr, $tag, $tagInfo); |
9368
|
|
|
|
|
|
|
} |
9369
|
|
|
|
|
|
|
# ignore 8-byte header |
9370
|
3
|
50
|
|
|
|
13
|
$val = substr($val, 8) if length($val) >= 8; |
9371
|
3
|
50
|
33
|
|
|
18
|
unless ($$tagInfo{Format} or $$tagInfo{SubDirectory}) { |
9372
|
|
|
|
|
|
|
# extract as binary if it contains any non-ASCII or control characters |
9373
|
3
|
50
|
|
|
|
17
|
if ($val =~ /[^\x20-\x7e]/) { |
9374
|
0
|
|
|
|
|
0
|
my $buff = $val; |
9375
|
0
|
|
|
|
|
0
|
$val = \$buff; |
9376
|
|
|
|
|
|
|
} |
9377
|
|
|
|
|
|
|
} |
9378
|
3
|
|
|
|
|
11
|
$$tagInfo{List} = 1; # (allow any of these tags to have multiple data elements) |
9379
|
3
|
50
|
|
|
|
61
|
$et->VerboseInfo($tag, $tagInfo, Value => $val) if $verbose; |
9380
|
|
|
|
|
|
|
} else { |
9381
|
6
|
50
|
|
|
|
25
|
$triplet{$tag} = substr($val,4) if length($val) > 4; |
9382
|
6
|
|
|
|
|
9
|
undef $tagInfo; # don't store this tag |
9383
|
|
|
|
|
|
|
} |
9384
|
|
|
|
|
|
|
} |
9385
|
1165
|
100
|
|
|
|
1888
|
if ($tagInfo) { |
9386
|
1131
|
|
|
|
|
1641
|
my $subdir = $$tagInfo{SubDirectory}; |
9387
|
1131
|
100
|
66
|
|
|
2763
|
if ($subdir) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
9388
|
674
|
|
100
|
|
|
1844
|
my $start = $$subdir{Start} || 0; |
9389
|
674
|
|
|
|
|
1111
|
my ($base, $dPos) = ($dataPos, 0); |
9390
|
674
|
50
|
|
|
|
1324
|
if ($$subdir{Base}) { |
9391
|
0
|
|
|
|
|
0
|
$dPos -= eval $$subdir{Base}; |
9392
|
0
|
|
|
|
|
0
|
$base -= $dPos; |
9393
|
|
|
|
|
|
|
} |
9394
|
|
|
|
|
|
|
my %dirInfo = ( |
9395
|
|
|
|
|
|
|
DataPt => \$val, |
9396
|
|
|
|
|
|
|
DataLen => $size, |
9397
|
|
|
|
|
|
|
DirStart => $start, |
9398
|
|
|
|
|
|
|
DirLen => $size - $start, |
9399
|
|
|
|
|
|
|
DirName => $$subdir{DirName} || $$tagInfo{Name}, |
9400
|
|
|
|
|
|
|
DirID => $tag, |
9401
|
|
|
|
|
|
|
HasData => $$subdir{HasData}, |
9402
|
|
|
|
|
|
|
Multi => $$subdir{Multi}, |
9403
|
|
|
|
|
|
|
IgnoreProp => $$subdir{IgnoreProp}, # (XML hack) |
9404
|
674
|
|
66
|
|
|
4932
|
DataPos => $dPos, |
9405
|
|
|
|
|
|
|
Base => $base, # (needed for IsOffset tags in binary data) |
9406
|
|
|
|
|
|
|
); |
9407
|
674
|
50
|
|
|
|
1395
|
$dirInfo{BlockInfo} = $tagInfo if $$tagInfo{BlockExtract}; |
9408
|
674
|
100
|
66
|
|
|
1423
|
if ($$subdir{ByteOrder} and $$subdir{ByteOrder} =~ /^Little/) { |
9409
|
6
|
|
|
|
|
43
|
SetByteOrder('II'); |
9410
|
|
|
|
|
|
|
} |
9411
|
674
|
|
|
|
|
997
|
my $oldGroup1 = $$et{SET_GROUP1}; |
9412
|
674
|
100
|
33
|
|
|
3035
|
if ($$tagInfo{SubDirectory} and $$tagInfo{SubDirectory}{TagTable} and |
|
|
|
66
|
|
|
|
|
9413
|
|
|
|
|
|
|
$$tagInfo{SubDirectory}{TagTable} eq 'Image::ExifTool::QuickTime::Track') |
9414
|
|
|
|
|
|
|
{ |
9415
|
38
|
100
|
|
|
|
107
|
$track or $track = 0; |
9416
|
38
|
|
|
|
|
108
|
$$et{SET_GROUP1} = 'Track' . (++$track); |
9417
|
|
|
|
|
|
|
} |
9418
|
674
|
|
|
|
|
1721
|
my $subTable = GetTagTable($$subdir{TagTable}); |
9419
|
674
|
|
|
|
|
1050
|
my $proc = $$subdir{ProcessProc}; |
9420
|
|
|
|
|
|
|
# make ProcessMOV() the default processing procedure for subdirectories |
9421
|
674
|
100
|
100
|
|
|
2320
|
$proc = \&ProcessMOV unless $proc or $$subTable{PROCESS_PROC}; |
9422
|
674
|
50
|
|
|
|
1216
|
if ($size > $start) { |
9423
|
|
|
|
|
|
|
# delay processing of ipco box until after all other boxes |
9424
|
674
|
100
|
66
|
|
|
1473
|
if ($tag eq 'ipco' and not $$et{IsItemProperty}) { |
9425
|
3
|
|
|
|
|
919
|
$$et{ItemPropertyContainer} = [ \%dirInfo, $subTable, $proc ]; |
9426
|
3
|
|
|
|
|
15
|
$et->VPrint(0,"$$et{INDENT}\[Process ipco box later]"); |
9427
|
|
|
|
|
|
|
} else { |
9428
|
671
|
|
|
|
|
1813
|
$et->ProcessDirectory(\%dirInfo, $subTable, $proc); |
9429
|
|
|
|
|
|
|
} |
9430
|
|
|
|
|
|
|
} |
9431
|
674
|
100
|
|
|
|
1709
|
if ($tag eq 'stbl') { |
|
|
100
|
|
|
|
|
|
9432
|
|
|
|
|
|
|
# process sample data when exiting SampleTable box if extracting embedded |
9433
|
38
|
100
|
|
|
|
132
|
ProcessSamples($et) if $ee; |
9434
|
|
|
|
|
|
|
} elsif ($tag eq 'minf') { |
9435
|
38
|
|
|
|
|
87
|
$$et{HandlerType} = ''; # reset handler type at end of media info box |
9436
|
|
|
|
|
|
|
} |
9437
|
674
|
|
|
|
|
1130
|
$$et{SET_GROUP1} = $oldGroup1; |
9438
|
674
|
|
|
|
|
1220
|
SetByteOrder('MM'); |
9439
|
|
|
|
|
|
|
} elsif ($hasData) { |
9440
|
|
|
|
|
|
|
# handle atoms containing 'data' tags |
9441
|
|
|
|
|
|
|
# (currently ignore contained atoms: 'itif', 'name', etc.) |
9442
|
157
|
|
|
|
|
220
|
my $pos = 0; |
9443
|
157
|
|
|
|
|
180
|
for (;;) { |
9444
|
318
|
100
|
|
|
|
640
|
last if $pos + 16 > $size; |
9445
|
161
|
|
|
|
|
632
|
my ($len, $type, $flags, $ctry, $lang) = unpack("x${pos}Na4Nnn", $val); |
9446
|
161
|
50
|
33
|
|
|
535
|
last if $pos + $len > $size or not $len; |
9447
|
161
|
|
|
|
|
246
|
my ($value, $langInfo, $oldDir); |
9448
|
161
|
|
|
|
|
254
|
my $format = $$tagInfo{Format}; |
9449
|
161
|
50
|
33
|
|
|
456
|
if ($type eq 'data' and $len >= 16) { |
9450
|
161
|
|
|
|
|
196
|
$pos += 16; |
9451
|
161
|
|
|
|
|
189
|
$len -= 16; |
9452
|
161
|
|
|
|
|
292
|
$value = substr($val, $pos, $len); |
9453
|
|
|
|
|
|
|
# format flags (ref 12): |
9454
|
|
|
|
|
|
|
# 0x0=binary, 0x1=UTF-8, 0x2=UTF-16, 0x3=ShiftJIS, |
9455
|
|
|
|
|
|
|
# 0x4=UTF-8 0x5=UTF-16, 0xd=JPEG, 0xe=PNG, |
9456
|
|
|
|
|
|
|
# 0x15=signed int, 0x16=unsigned int, 0x17=float, |
9457
|
|
|
|
|
|
|
# 0x18=double, 0x1b=BMP, 0x1c='meta' atom |
9458
|
161
|
100
|
|
|
|
318
|
if ($stringEncoding{$flags}) { |
9459
|
|
|
|
|
|
|
# handle all string formats |
9460
|
116
|
|
|
|
|
327
|
$value = $et->Decode($value, $stringEncoding{$flags}); |
9461
|
|
|
|
|
|
|
# (shouldn't be null terminated, but some software writes it anyway) |
9462
|
116
|
50
|
|
|
|
320
|
$value =~ s/\0$// unless $$tagInfo{Binary}; |
9463
|
|
|
|
|
|
|
} else { |
9464
|
45
|
100
|
|
|
|
166
|
if (not $format) { |
|
|
100
|
|
|
|
|
|
9465
|
12
|
|
|
|
|
35
|
$format = QuickTimeFormat($flags, $len); |
9466
|
|
|
|
|
|
|
} elsif ($format =~ /^int\d+([us])$/) { |
9467
|
|
|
|
|
|
|
# adjust integer to available length (but not int64) |
9468
|
15
|
|
|
|
|
71
|
my $fmt = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len}; |
9469
|
15
|
50
|
|
|
|
71
|
$format = $fmt . $1 if defined $fmt; |
9470
|
|
|
|
|
|
|
} |
9471
|
45
|
100
|
|
|
|
100
|
if ($format) { |
|
|
50
|
|
|
|
|
|
9472
|
33
|
|
|
|
|
130
|
$value = ReadValue(\$value, 0, $format, $$tagInfo{Count}, $len); |
9473
|
|
|
|
|
|
|
} elsif (not $$tagInfo{ValueConv}) { |
9474
|
|
|
|
|
|
|
# make binary data a scalar reference unless a ValueConv exists |
9475
|
12
|
|
|
|
|
21
|
my $buf = $value; |
9476
|
12
|
|
|
|
|
26
|
$value = \$buf; |
9477
|
|
|
|
|
|
|
} |
9478
|
|
|
|
|
|
|
} |
9479
|
|
|
|
|
|
|
} |
9480
|
161
|
100
|
66
|
|
|
483
|
if ($ctry or $lang) { |
9481
|
1
|
|
|
|
|
5
|
my $langCode = GetLangCode($lang, $ctry); |
9482
|
1
|
50
|
|
|
|
5
|
if ($langCode) { |
9483
|
|
|
|
|
|
|
# get tagInfo for other language |
9484
|
1
|
|
|
|
|
4
|
$langInfo = GetLangInfoQT($et, $tagInfo, $langCode); |
9485
|
|
|
|
|
|
|
# save other language tag ID's so we can delete later if necessary |
9486
|
1
|
50
|
|
|
|
3
|
if ($langInfo) { |
9487
|
1
|
50
|
|
|
|
6
|
$$tagInfo{OtherLang} or $$tagInfo{OtherLang} = [ ]; |
9488
|
1
|
|
|
|
|
2
|
push @{$$tagInfo{OtherLang}}, $$langInfo{TagID}; |
|
1
|
|
|
|
|
3
|
|
9489
|
|
|
|
|
|
|
} |
9490
|
|
|
|
|
|
|
} |
9491
|
|
|
|
|
|
|
} |
9492
|
161
|
100
|
|
|
|
315
|
$langInfo or $langInfo = $tagInfo; |
9493
|
161
|
0
|
|
|
|
248
|
$et->VerboseInfo($tag, $langInfo, |
|
|
50
|
|
|
|
|
|
9494
|
|
|
|
|
|
|
Value => ref $value ? $$value : $value, |
9495
|
|
|
|
|
|
|
DataPt => \$val, |
9496
|
|
|
|
|
|
|
DataPos => $dataPos, |
9497
|
|
|
|
|
|
|
Start => $pos, |
9498
|
|
|
|
|
|
|
Size => $len, |
9499
|
|
|
|
|
|
|
Format => $format, |
9500
|
|
|
|
|
|
|
Index => $index, |
9501
|
|
|
|
|
|
|
Extra => sprintf(", Type='${type}', Flags=0x%x, Lang=0x%.4x",$flags,$lang), |
9502
|
|
|
|
|
|
|
) if $verbose; |
9503
|
|
|
|
|
|
|
# use "Keys" in path instead of ItemList if this was defined by a Keys tag |
9504
|
161
|
|
100
|
|
|
769
|
my $isKey = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys'; |
9505
|
161
|
100
|
|
|
|
286
|
if ($isKey) { |
9506
|
22
|
|
|
|
|
43
|
$oldDir = $$et{PATH}[-1]; |
9507
|
22
|
|
|
|
|
43
|
$$et{PATH}[-1] = 'Keys'; |
9508
|
|
|
|
|
|
|
} |
9509
|
161
|
50
|
|
|
|
500
|
$et->FoundTag($langInfo, $value) if defined $value; |
9510
|
161
|
100
|
|
|
|
280
|
$$et{PATH}[-1] = $oldDir if $isKey; |
9511
|
161
|
|
|
|
|
272
|
$pos += $len; |
9512
|
|
|
|
|
|
|
} |
9513
|
|
|
|
|
|
|
} elsif ($tag =~ /^\xa9/ or $$tagInfo{IText}) { |
9514
|
|
|
|
|
|
|
# parse international text to extract all languages |
9515
|
49
|
|
|
|
|
83
|
my $pos = 0; |
9516
|
49
|
50
|
|
|
|
109
|
if ($$tagInfo{Format}) { |
9517
|
0
|
|
|
|
|
0
|
$et->FoundTag($tagInfo, ReadValue(\$val, 0, $$tagInfo{Format}, undef, length($val))); |
9518
|
0
|
|
|
|
|
0
|
$pos = $size; |
9519
|
|
|
|
|
|
|
} |
9520
|
49
|
|
|
|
|
61
|
for (;;) { |
9521
|
98
|
|
|
|
|
132
|
my ($len, $lang); |
9522
|
98
|
100
|
66
|
|
|
213
|
if ($$tagInfo{IText} and $$tagInfo{IText} >= 6) { |
9523
|
4
|
100
|
|
|
|
13
|
last if $pos + $$tagInfo{IText} > $size; |
9524
|
2
|
|
|
|
|
5
|
$pos += $$tagInfo{IText} - 2; |
9525
|
2
|
|
|
|
|
7
|
$lang = unpack("x${pos}n", $val); |
9526
|
2
|
|
|
|
|
3
|
$pos += 2; |
9527
|
2
|
|
|
|
|
3
|
$len = $size - $pos; |
9528
|
|
|
|
|
|
|
} else { |
9529
|
94
|
100
|
|
|
|
202
|
last if $pos + 4 > $size; |
9530
|
47
|
|
|
|
|
137
|
($len, $lang) = unpack("x${pos}nn", $val); |
9531
|
47
|
|
|
|
|
128
|
$pos += 4; |
9532
|
|
|
|
|
|
|
# according to the QuickTime spec (ref 12), $len should include |
9533
|
|
|
|
|
|
|
# 4 bytes for length and type words, but nobody (including |
9534
|
|
|
|
|
|
|
# Apple, Pentax and Kodak) seems to add these in, so try |
9535
|
|
|
|
|
|
|
# to allow for either |
9536
|
47
|
50
|
|
|
|
111
|
if ($pos + $len > $size) { |
9537
|
0
|
|
|
|
|
0
|
$len -= 4; |
9538
|
0
|
0
|
0
|
|
|
0
|
last if $pos + $len > $size or $len < 0; |
9539
|
|
|
|
|
|
|
} |
9540
|
|
|
|
|
|
|
} |
9541
|
|
|
|
|
|
|
# ignore any empty entries (or null padding) after the first |
9542
|
49
|
50
|
33
|
|
|
102
|
next if not $len and $pos; |
9543
|
49
|
|
|
|
|
105
|
my $str = substr($val, $pos, $len); |
9544
|
49
|
|
|
|
|
61
|
my ($langInfo, $enc); |
9545
|
49
|
50
|
33
|
|
|
212
|
if (($lang < 0x400 or $lang == 0x7fff) and $str !~ /^\xfe\xff/) { |
|
|
|
33
|
|
|
|
|
9546
|
|
|
|
|
|
|
# this is a Macintosh language code |
9547
|
|
|
|
|
|
|
# a language code of 0 is Macintosh english, so treat as default |
9548
|
49
|
50
|
|
|
|
93
|
if ($lang) { |
9549
|
0
|
0
|
|
|
|
0
|
if ($lang == 0x7fff) { |
9550
|
|
|
|
|
|
|
# technically, ISO 639-2 doesn't have a 2-character |
9551
|
|
|
|
|
|
|
# equivalent for 'und', but use 'un' anyway |
9552
|
0
|
|
|
|
|
0
|
$lang = 'un'; |
9553
|
|
|
|
|
|
|
} else { |
9554
|
|
|
|
|
|
|
# use Font.pm to look up language string |
9555
|
0
|
|
|
|
|
0
|
require Image::ExifTool::Font; |
9556
|
0
|
|
|
|
|
0
|
$lang = $Image::ExifTool::Font::ttLang{Macintosh}{$lang}; |
9557
|
|
|
|
|
|
|
} |
9558
|
|
|
|
|
|
|
} |
9559
|
|
|
|
|
|
|
# the spec says only "Macintosh text encoding", but |
9560
|
|
|
|
|
|
|
# allow this to be configured by the user |
9561
|
49
|
|
|
|
|
70
|
$enc = $charsetQuickTime; |
9562
|
|
|
|
|
|
|
} else { |
9563
|
|
|
|
|
|
|
# convert language code to ASCII (ignore read-only bit) |
9564
|
0
|
|
|
|
|
0
|
$lang = UnpackLang($lang); |
9565
|
|
|
|
|
|
|
# may be either UTF-8 or UTF-16BE |
9566
|
0
|
0
|
|
|
|
0
|
$enc = $str=~s/^\xfe\xff// ? 'UTF16' : 'UTF8'; |
9567
|
|
|
|
|
|
|
} |
9568
|
49
|
100
|
|
|
|
102
|
unless ($$tagInfo{NoDecode}) { |
9569
|
48
|
|
|
|
|
131
|
$str = $et->Decode($str, $enc); |
9570
|
48
|
|
|
|
|
95
|
$str =~ s/\0+$//; # remove any trailing nulls (eg. 3gp tags) |
9571
|
|
|
|
|
|
|
} |
9572
|
49
|
100
|
100
|
|
|
130
|
if ($$tagInfo{IText} and $$tagInfo{IText} > 6) { |
9573
|
1
|
|
|
|
|
8
|
my $n = $$tagInfo{IText} - 6; |
9574
|
|
|
|
|
|
|
# add back extra bytes (eg. 'rtng' box) |
9575
|
1
|
|
|
|
|
6
|
$str = substr($val, $pos-$n-2, $n) . $str; |
9576
|
|
|
|
|
|
|
} |
9577
|
49
|
50
|
|
|
|
77
|
$langInfo = GetLangInfoQT($et, $tagInfo, $lang) if $lang; |
9578
|
49
|
|
33
|
|
|
205
|
$et->FoundTag($langInfo || $tagInfo, $str); |
9579
|
49
|
|
|
|
|
105
|
$pos += $len; |
9580
|
|
|
|
|
|
|
} |
9581
|
|
|
|
|
|
|
} else { |
9582
|
251
|
|
|
|
|
393
|
my $format = $$tagInfo{Format}; |
9583
|
251
|
100
|
|
|
|
432
|
if ($format) { |
9584
|
68
|
|
|
|
|
293
|
$val = ReadValue(\$val, 0, $format, $$tagInfo{Count}, length($val)); |
9585
|
|
|
|
|
|
|
} |
9586
|
251
|
|
|
|
|
340
|
my $oldBase; |
9587
|
251
|
50
|
|
|
|
512
|
if ($$tagInfo{SetBase}) { |
9588
|
0
|
|
|
|
|
0
|
$oldBase = $$et{BASE}; |
9589
|
0
|
|
|
|
|
0
|
$$et{BASE} = $dataPos; |
9590
|
|
|
|
|
|
|
} |
9591
|
251
|
|
|
|
|
609
|
my $key = $et->FoundTag($tagInfo, $val); |
9592
|
251
|
50
|
|
|
|
568
|
$$et{BASE} = $oldBase if defined $oldBase; |
9593
|
|
|
|
|
|
|
# decode if necessary (NOTE: must be done after RawConv) |
9594
|
251
|
50
|
66
|
|
|
1420
|
if (defined $key and (not $format or $format =~ /^string/) and |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
9595
|
|
|
|
|
|
|
not $$tagInfo{Unknown} and not $$tagInfo{ValueConv} and |
9596
|
|
|
|
|
|
|
not $$tagInfo{Binary} and defined $$et{VALUE}{$key} and not ref $val) |
9597
|
|
|
|
|
|
|
{ |
9598
|
20
|
|
|
|
|
50
|
my $vp = \$$et{VALUE}{$key}; |
9599
|
20
|
50
|
66
|
|
|
147
|
if (not ref $$vp and length($$vp) <= 65536 and $$vp =~ /[\x80-\xff]/) { |
|
|
|
66
|
|
|
|
|
9600
|
|
|
|
|
|
|
# the encoding of this is not specified, so use CharsetQuickTime |
9601
|
|
|
|
|
|
|
# unless the string is valid UTF-8 |
9602
|
0
|
|
|
|
|
0
|
require Image::ExifTool::XMP; |
9603
|
0
|
0
|
|
|
|
0
|
my $enc = Image::ExifTool::XMP::IsUTF8($vp) > 0 ? 'UTF8' : $charsetQuickTime; |
9604
|
0
|
|
|
|
|
0
|
$$vp = $et->Decode($$vp, $enc); |
9605
|
|
|
|
|
|
|
} |
9606
|
|
|
|
|
|
|
} |
9607
|
|
|
|
|
|
|
} |
9608
|
|
|
|
|
|
|
} |
9609
|
|
|
|
|
|
|
} else { |
9610
|
88
|
50
|
|
|
|
150
|
$et->VerboseInfo($tag, $tagInfo, |
9611
|
|
|
|
|
|
|
Size => $size, |
9612
|
|
|
|
|
|
|
Extra => sprintf(' at offset 0x%.4x', $raf->Tell()), |
9613
|
|
|
|
|
|
|
) if $verbose; |
9614
|
88
|
50
|
33
|
|
|
302
|
if ($size and (not $raf->Seek($size-1, 1) or $raf->Read($buff, 1) != 1)) { |
|
|
|
66
|
|
|
|
|
9615
|
0
|
|
|
|
|
0
|
my $t = PrintableTagID($tag,2); |
9616
|
0
|
|
|
|
|
0
|
$et->Warn("Truncated '${t}' data"); |
9617
|
0
|
|
|
|
|
0
|
last; |
9618
|
|
|
|
|
|
|
} |
9619
|
|
|
|
|
|
|
} |
9620
|
1253
|
|
|
|
|
1788
|
$dataPos += $size + 8; # point to start of next atom data |
9621
|
1253
|
100
|
100
|
|
|
3545
|
last if $dirEnd and $dataPos >= $dirEnd; # (note: ignores last value if 0 bytes) |
9622
|
890
|
100
|
|
|
|
2180
|
$raf->Read($buff, 8) == 8 or last; |
9623
|
870
|
|
|
|
|
2667
|
($size, $tag) = unpack('Na4', $buff); |
9624
|
870
|
100
|
|
|
|
1925
|
++$index if defined $index; |
9625
|
|
|
|
|
|
|
} |
9626
|
|
|
|
|
|
|
# tweak file type based on track content ("iso*" and "dash" ftyp only) |
9627
|
383
|
0
|
66
|
|
|
872
|
if ($topLevel and $$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
9628
|
|
|
|
|
|
|
$$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^(iso|dash)/ and |
9629
|
|
|
|
|
|
|
$$et{HasHandler}{soun} and not $$et{HasHandler}{vide}) |
9630
|
|
|
|
|
|
|
{ |
9631
|
0
|
|
|
|
|
0
|
$et->OverrideFileType('M4A', 'audio/mp4'); |
9632
|
|
|
|
|
|
|
} |
9633
|
|
|
|
|
|
|
# fill in missing defaults for alternate language tags |
9634
|
|
|
|
|
|
|
# (the first language is taken as the default) |
9635
|
383
|
100
|
100
|
|
|
696
|
if ($doDefaultLang and $$et{QTLang}) { |
9636
|
1
|
|
|
|
|
3
|
QTLang: foreach $tag (@{$$et{QTLang}}) { |
|
1
|
|
|
|
|
4
|
|
9637
|
1
|
50
|
|
|
|
4
|
next unless defined $$et{VALUE}{$tag}; |
9638
|
1
|
50
|
|
|
|
5
|
my $langInfo = $$et{TAG_INFO}{$tag} or next; |
9639
|
1
|
50
|
|
|
|
5
|
my $tagInfo = $$langInfo{SrcTagInfo} or next; |
9640
|
1
|
|
|
|
|
3
|
my $infoHash = $$et{TAG_INFO}; |
9641
|
1
|
|
|
|
|
2
|
my $name = $$tagInfo{Name}; |
9642
|
|
|
|
|
|
|
# loop through all instances of this tag name and generate the default-language |
9643
|
|
|
|
|
|
|
# version only if we don't already have a QuickTime tag with this name |
9644
|
1
|
|
|
|
|
3
|
my ($i, $key); |
9645
|
1
|
|
|
|
|
5
|
for ($i=0, $key=$name; $$infoHash{$key}; ++$i, $key="$name ($i)") { |
9646
|
1
|
50
|
|
|
|
6
|
next QTLang if $et->GetGroup($key, 0) eq 'QuickTime'; |
9647
|
|
|
|
|
|
|
} |
9648
|
0
|
|
|
|
|
0
|
$et->FoundTag($tagInfo, $$et{VALUE}{$tag}); |
9649
|
|
|
|
|
|
|
} |
9650
|
1
|
|
|
|
|
4
|
delete $$et{QTLang}; |
9651
|
|
|
|
|
|
|
} |
9652
|
|
|
|
|
|
|
# process item information now that we are done processing its 'meta' container |
9653
|
383
|
100
|
100
|
|
|
1158
|
HandleItemInfo($et) if $topLevel or $dirID eq 'meta'; |
9654
|
|
|
|
|
|
|
|
9655
|
383
|
100
|
100
|
|
|
840
|
ScanMediaData($et) if $ee and $topLevel; # brute force scan for metadata embedded in media data |
9656
|
|
|
|
|
|
|
|
9657
|
|
|
|
|
|
|
# restore any changed options |
9658
|
383
|
|
|
|
|
786
|
$et->Options($_ => $saveOptions{$_}) foreach keys %saveOptions; |
9659
|
383
|
|
|
|
|
1448
|
return 1; |
9660
|
|
|
|
|
|
|
} |
9661
|
|
|
|
|
|
|
|
9662
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
9663
|
|
|
|
|
|
|
# Process a QuickTime Image File |
9664
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object reference, 1) directory information reference |
9665
|
|
|
|
|
|
|
# Returns: 1 on success |
9666
|
|
|
|
|
|
|
sub ProcessQTIF($$) |
9667
|
|
|
|
|
|
|
{ |
9668
|
0
|
|
|
0
|
0
|
|
my ($et, $dirInfo) = @_; |
9669
|
0
|
|
|
|
|
|
my $table = GetTagTable('Image::ExifTool::QuickTime::ImageFile'); |
9670
|
0
|
|
|
|
|
|
return ProcessMOV($et, $dirInfo, $table); |
9671
|
|
|
|
|
|
|
} |
9672
|
|
|
|
|
|
|
|
9673
|
|
|
|
|
|
|
1; # end |
9674
|
|
|
|
|
|
|
|
9675
|
|
|
|
|
|
|
__END__ |