| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
2
|
|
|
|
|
|
|
# File: RIFF.pm |
|
3
|
|
|
|
|
|
|
# |
|
4
|
|
|
|
|
|
|
# Description: Read RIFF/AVI/WAV meta information |
|
5
|
|
|
|
|
|
|
# |
|
6
|
|
|
|
|
|
|
# Revisions: 09/14/2005 - P. Harvey Created |
|
7
|
|
|
|
|
|
|
# 06/28/2017 - PH Added MBWF/RF64 support |
|
8
|
|
|
|
|
|
|
# |
|
9
|
|
|
|
|
|
|
# References: 1) http://www.exif.org/Exif2-2.PDF |
|
10
|
|
|
|
|
|
|
# 2) http://www.vlsi.fi/datasheets/vs1011.pdf |
|
11
|
|
|
|
|
|
|
# 3) http://www.music-center.com.br/spec_rif.htm |
|
12
|
|
|
|
|
|
|
# 4) http://www.codeproject.com/audio/wavefiles.asp |
|
13
|
|
|
|
|
|
|
# 5) http://msdn.microsoft.com/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp |
|
14
|
|
|
|
|
|
|
# 6) http://research.microsoft.com/invisible/tests/riff.h.htm |
|
15
|
|
|
|
|
|
|
# 7) http://www.onicos.com/staff/iz/formats/wav.html |
|
16
|
|
|
|
|
|
|
# 8) http://graphics.cs.uni-sb.de/NMM/dist-0.9.1/Docs/Doxygen/html/mmreg_8h-source.html |
|
17
|
|
|
|
|
|
|
# 9) http://developers.videolan.org/vlc/vlc/doc/doxygen/html/codecs_8h-source.html |
|
18
|
|
|
|
|
|
|
# 10) http://wiki.multimedia.cx/index.php?title=TwoCC |
|
19
|
|
|
|
|
|
|
# 11) Andreas Winter (SCLive) private communication |
|
20
|
|
|
|
|
|
|
# 12) http://abcavi.kibi.ru/infotags.htm |
|
21
|
|
|
|
|
|
|
# 13) http://tech.ebu.ch/docs/tech/tech3285.pdf |
|
22
|
|
|
|
|
|
|
# 14) https://developers.google.com/speed/webp/docs/riff_container |
|
23
|
|
|
|
|
|
|
# 15) https://tech.ebu.ch/docs/tech/tech3306-2009.pdf |
|
24
|
|
|
|
|
|
|
# 16) https://sites.google.com/site/musicgapi/technical-documents/wav-file-format |
|
25
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
package Image::ExifTool::RIFF; |
|
28
|
|
|
|
|
|
|
|
|
29
|
9
|
|
|
9
|
|
3614
|
use strict; |
|
|
9
|
|
|
|
|
20
|
|
|
|
9
|
|
|
|
|
258
|
|
|
30
|
9
|
|
|
9
|
|
45
|
use vars qw($VERSION); |
|
|
9
|
|
|
|
|
21
|
|
|
|
9
|
|
|
|
|
315
|
|
|
31
|
9
|
|
|
9
|
|
42
|
use Image::ExifTool qw(:DataAccess :Utils); |
|
|
9
|
|
|
|
|
16
|
|
|
|
9
|
|
|
|
|
50464
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
$VERSION = '1.59'; |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub ConvertTimecode($); |
|
36
|
|
|
|
|
|
|
sub ProcessSGLT($$$); |
|
37
|
|
|
|
|
|
|
sub ProcessSLLT($$$); |
|
38
|
|
|
|
|
|
|
sub ProcessLucas($$$); |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# recognized RIFF variants |
|
41
|
|
|
|
|
|
|
my %riffType = ( |
|
42
|
|
|
|
|
|
|
'WAVE' => 'WAV', 'AVI ' => 'AVI', 'WEBP' => 'WEBP', |
|
43
|
|
|
|
|
|
|
'LA02' => 'LA', 'LA03' => 'LA', 'LA04' => 'LA', |
|
44
|
|
|
|
|
|
|
'OFR ' => 'OFR', 'LPAC' => 'PAC', 'wvpk' => 'WV', |
|
45
|
|
|
|
|
|
|
); |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# MIME types of recognized RIFF-format files |
|
48
|
|
|
|
|
|
|
my %riffMimeType = ( |
|
49
|
|
|
|
|
|
|
WAV => 'audio/x-wav', |
|
50
|
|
|
|
|
|
|
AVI => 'video/x-msvideo', |
|
51
|
|
|
|
|
|
|
WEBP => 'image/webp', |
|
52
|
|
|
|
|
|
|
LA => 'audio/x-nspaudio', |
|
53
|
|
|
|
|
|
|
OFR => 'audio/x-ofr', |
|
54
|
|
|
|
|
|
|
PAC => 'audio/x-lpac', |
|
55
|
|
|
|
|
|
|
WV => 'audio/x-wavpack', |
|
56
|
|
|
|
|
|
|
); |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# character sets for recognized Windows code pages |
|
59
|
|
|
|
|
|
|
my %code2charset = ( |
|
60
|
|
|
|
|
|
|
0 => 'Latin', |
|
61
|
|
|
|
|
|
|
65001 => 'UTF8', |
|
62
|
|
|
|
|
|
|
1252 => 'Latin', |
|
63
|
|
|
|
|
|
|
1250 => 'Latin2', |
|
64
|
|
|
|
|
|
|
1251 => 'Cyrillic', |
|
65
|
|
|
|
|
|
|
1253 => 'Greek', |
|
66
|
|
|
|
|
|
|
1254 => 'Turkish', |
|
67
|
|
|
|
|
|
|
1255 => 'Hebrew', |
|
68
|
|
|
|
|
|
|
1256 => 'Arabic', |
|
69
|
|
|
|
|
|
|
1257 => 'Baltic', |
|
70
|
|
|
|
|
|
|
1258 => 'Vietnam', |
|
71
|
|
|
|
|
|
|
874 => 'Thai', |
|
72
|
|
|
|
|
|
|
10000 => 'MacRoman', |
|
73
|
|
|
|
|
|
|
10029 => 'MacLatin2', |
|
74
|
|
|
|
|
|
|
10007 => 'MacCyrillic', |
|
75
|
|
|
|
|
|
|
10006 => 'MacGreek', |
|
76
|
|
|
|
|
|
|
10081 => 'MacTurkish', |
|
77
|
|
|
|
|
|
|
10010 => 'MacRomanian', |
|
78
|
|
|
|
|
|
|
10079 => 'MacIceland', |
|
79
|
|
|
|
|
|
|
10082 => 'MacCroatian', |
|
80
|
|
|
|
|
|
|
); |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::audioEncoding = ( #2 |
|
83
|
|
|
|
|
|
|
Notes => 'These "TwoCC" audio encoding codes are used in RIFF and ASF files.', |
|
84
|
|
|
|
|
|
|
0x01 => 'Microsoft PCM', |
|
85
|
|
|
|
|
|
|
0x02 => 'Microsoft ADPCM', |
|
86
|
|
|
|
|
|
|
0x03 => 'Microsoft IEEE float', |
|
87
|
|
|
|
|
|
|
0x04 => 'Compaq VSELP', #4 |
|
88
|
|
|
|
|
|
|
0x05 => 'IBM CVSD', #4 |
|
89
|
|
|
|
|
|
|
0x06 => 'Microsoft a-Law', |
|
90
|
|
|
|
|
|
|
0x07 => 'Microsoft u-Law', |
|
91
|
|
|
|
|
|
|
0x08 => 'Microsoft DTS', #4 |
|
92
|
|
|
|
|
|
|
0x09 => 'DRM', #4 |
|
93
|
|
|
|
|
|
|
0x0a => 'WMA 9 Speech', #9 |
|
94
|
|
|
|
|
|
|
0x0b => 'Microsoft Windows Media RT Voice', #10 |
|
95
|
|
|
|
|
|
|
0x10 => 'OKI-ADPCM', |
|
96
|
|
|
|
|
|
|
0x11 => 'Intel IMA/DVI-ADPCM', |
|
97
|
|
|
|
|
|
|
0x12 => 'Videologic Mediaspace ADPCM', #4 |
|
98
|
|
|
|
|
|
|
0x13 => 'Sierra ADPCM', #4 |
|
99
|
|
|
|
|
|
|
0x14 => 'Antex G.723 ADPCM', #4 |
|
100
|
|
|
|
|
|
|
0x15 => 'DSP Solutions DIGISTD', |
|
101
|
|
|
|
|
|
|
0x16 => 'DSP Solutions DIGIFIX', |
|
102
|
|
|
|
|
|
|
0x17 => 'Dialoic OKI ADPCM', #6 |
|
103
|
|
|
|
|
|
|
0x18 => 'Media Vision ADPCM', #6 |
|
104
|
|
|
|
|
|
|
0x19 => 'HP CU', #7 |
|
105
|
|
|
|
|
|
|
0x1a => 'HP Dynamic Voice', #10 |
|
106
|
|
|
|
|
|
|
0x20 => 'Yamaha ADPCM', #6 |
|
107
|
|
|
|
|
|
|
0x21 => 'SONARC Speech Compression', #6 |
|
108
|
|
|
|
|
|
|
0x22 => 'DSP Group True Speech', #6 |
|
109
|
|
|
|
|
|
|
0x23 => 'Echo Speech Corp.', #6 |
|
110
|
|
|
|
|
|
|
0x24 => 'Virtual Music Audiofile AF36', #6 |
|
111
|
|
|
|
|
|
|
0x25 => 'Audio Processing Tech.', #6 |
|
112
|
|
|
|
|
|
|
0x26 => 'Virtual Music Audiofile AF10', #6 |
|
113
|
|
|
|
|
|
|
0x27 => 'Aculab Prosody 1612', #7 |
|
114
|
|
|
|
|
|
|
0x28 => 'Merging Tech. LRC', #7 |
|
115
|
|
|
|
|
|
|
0x30 => 'Dolby AC2', |
|
116
|
|
|
|
|
|
|
0x31 => 'Microsoft GSM610', |
|
117
|
|
|
|
|
|
|
0x32 => 'MSN Audio', #6 |
|
118
|
|
|
|
|
|
|
0x33 => 'Antex ADPCME', #6 |
|
119
|
|
|
|
|
|
|
0x34 => 'Control Resources VQLPC', #6 |
|
120
|
|
|
|
|
|
|
0x35 => 'DSP Solutions DIGIREAL', #6 |
|
121
|
|
|
|
|
|
|
0x36 => 'DSP Solutions DIGIADPCM', #6 |
|
122
|
|
|
|
|
|
|
0x37 => 'Control Resources CR10', #6 |
|
123
|
|
|
|
|
|
|
0x38 => 'Natural MicroSystems VBX ADPCM', #6 |
|
124
|
|
|
|
|
|
|
0x39 => 'Crystal Semiconductor IMA ADPCM', #6 |
|
125
|
|
|
|
|
|
|
0x3a => 'Echo Speech ECHOSC3', #6 |
|
126
|
|
|
|
|
|
|
0x3b => 'Rockwell ADPCM', |
|
127
|
|
|
|
|
|
|
0x3c => 'Rockwell DIGITALK', |
|
128
|
|
|
|
|
|
|
0x3d => 'Xebec Multimedia', #6 |
|
129
|
|
|
|
|
|
|
0x40 => 'Antex G.721 ADPCM', |
|
130
|
|
|
|
|
|
|
0x41 => 'Antex G.728 CELP', |
|
131
|
|
|
|
|
|
|
0x42 => 'Microsoft MSG723', #7 |
|
132
|
|
|
|
|
|
|
0x43 => 'IBM AVC ADPCM', #10 |
|
133
|
|
|
|
|
|
|
0x45 => 'ITU-T G.726', #9 |
|
134
|
|
|
|
|
|
|
0x50 => 'Microsoft MPEG', |
|
135
|
|
|
|
|
|
|
0x51 => 'RT23 or PAC', #7 |
|
136
|
|
|
|
|
|
|
0x52 => 'InSoft RT24', #4 |
|
137
|
|
|
|
|
|
|
0x53 => 'InSoft PAC', #4 |
|
138
|
|
|
|
|
|
|
0x55 => 'MP3', |
|
139
|
|
|
|
|
|
|
0x59 => 'Cirrus', #7 |
|
140
|
|
|
|
|
|
|
0x60 => 'Cirrus Logic', #6 |
|
141
|
|
|
|
|
|
|
0x61 => 'ESS Tech. PCM', #6 |
|
142
|
|
|
|
|
|
|
0x62 => 'Voxware Inc.', #6 |
|
143
|
|
|
|
|
|
|
0x63 => 'Canopus ATRAC', #6 |
|
144
|
|
|
|
|
|
|
0x64 => 'APICOM G.726 ADPCM', |
|
145
|
|
|
|
|
|
|
0x65 => 'APICOM G.722 ADPCM', |
|
146
|
|
|
|
|
|
|
0x66 => 'Microsoft DSAT', #6 |
|
147
|
|
|
|
|
|
|
0x67 => 'Microsoft DSAT DISPLAY', #6 |
|
148
|
|
|
|
|
|
|
0x69 => 'Voxware Byte Aligned', #7 |
|
149
|
|
|
|
|
|
|
0x70 => 'Voxware AC8', #7 |
|
150
|
|
|
|
|
|
|
0x71 => 'Voxware AC10', #7 |
|
151
|
|
|
|
|
|
|
0x72 => 'Voxware AC16', #7 |
|
152
|
|
|
|
|
|
|
0x73 => 'Voxware AC20', #7 |
|
153
|
|
|
|
|
|
|
0x74 => 'Voxware MetaVoice', #7 |
|
154
|
|
|
|
|
|
|
0x75 => 'Voxware MetaSound', #7 |
|
155
|
|
|
|
|
|
|
0x76 => 'Voxware RT29HW', #7 |
|
156
|
|
|
|
|
|
|
0x77 => 'Voxware VR12', #7 |
|
157
|
|
|
|
|
|
|
0x78 => 'Voxware VR18', #7 |
|
158
|
|
|
|
|
|
|
0x79 => 'Voxware TQ40', #7 |
|
159
|
|
|
|
|
|
|
0x7a => 'Voxware SC3', #10 |
|
160
|
|
|
|
|
|
|
0x7b => 'Voxware SC3', #10 |
|
161
|
|
|
|
|
|
|
0x80 => 'Soundsoft', #6 |
|
162
|
|
|
|
|
|
|
0x81 => 'Voxware TQ60', #7 |
|
163
|
|
|
|
|
|
|
0x82 => 'Microsoft MSRT24', #7 |
|
164
|
|
|
|
|
|
|
0x83 => 'AT&T G.729A', #7 |
|
165
|
|
|
|
|
|
|
0x84 => 'Motion Pixels MVI MV12', #7 |
|
166
|
|
|
|
|
|
|
0x85 => 'DataFusion G.726', #7 |
|
167
|
|
|
|
|
|
|
0x86 => 'DataFusion GSM610', #7 |
|
168
|
|
|
|
|
|
|
0x88 => 'Iterated Systems Audio', #7 |
|
169
|
|
|
|
|
|
|
0x89 => 'Onlive', #7 |
|
170
|
|
|
|
|
|
|
0x8a => 'Multitude, Inc. FT SX20', #10 |
|
171
|
|
|
|
|
|
|
0x8b => 'Infocom ITS A/S G.721 ADPCM', #10 |
|
172
|
|
|
|
|
|
|
0x8c => 'Convedia G729', #10 |
|
173
|
|
|
|
|
|
|
0x8d => 'Not specified congruency, Inc.', #10 |
|
174
|
|
|
|
|
|
|
0x91 => 'Siemens SBC24', #7 |
|
175
|
|
|
|
|
|
|
0x92 => 'Sonic Foundry Dolby AC3 APDIF', #7 |
|
176
|
|
|
|
|
|
|
0x93 => 'MediaSonic G.723', #8 |
|
177
|
|
|
|
|
|
|
0x94 => 'Aculab Prosody 8kbps', #8 |
|
178
|
|
|
|
|
|
|
0x97 => 'ZyXEL ADPCM', #7, |
|
179
|
|
|
|
|
|
|
0x98 => 'Philips LPCBB', #7 |
|
180
|
|
|
|
|
|
|
0x99 => 'Studer Professional Audio Packed', #7 |
|
181
|
|
|
|
|
|
|
0xa0 => 'Malden PhonyTalk', #8 |
|
182
|
|
|
|
|
|
|
0xa1 => 'Racal Recorder GSM', #10 |
|
183
|
|
|
|
|
|
|
0xa2 => 'Racal Recorder G720.a', #10 |
|
184
|
|
|
|
|
|
|
0xa3 => 'Racal G723.1', #10 |
|
185
|
|
|
|
|
|
|
0xa4 => 'Racal Tetra ACELP', #10 |
|
186
|
|
|
|
|
|
|
0xb0 => 'NEC AAC NEC Corporation', #10 |
|
187
|
|
|
|
|
|
|
0xff => 'AAC', #10 |
|
188
|
|
|
|
|
|
|
0x100 => 'Rhetorex ADPCM', #6 |
|
189
|
|
|
|
|
|
|
0x101 => 'IBM u-Law', #3 |
|
190
|
|
|
|
|
|
|
0x102 => 'IBM a-Law', #3 |
|
191
|
|
|
|
|
|
|
0x103 => 'IBM ADPCM', #3 |
|
192
|
|
|
|
|
|
|
0x111 => 'Vivo G.723', #7 |
|
193
|
|
|
|
|
|
|
0x112 => 'Vivo Siren', #7 |
|
194
|
|
|
|
|
|
|
0x120 => 'Philips Speech Processing CELP', #10 |
|
195
|
|
|
|
|
|
|
0x121 => 'Philips Speech Processing GRUNDIG', #10 |
|
196
|
|
|
|
|
|
|
0x123 => 'Digital G.723', #7 |
|
197
|
|
|
|
|
|
|
0x125 => 'Sanyo LD ADPCM', #8 |
|
198
|
|
|
|
|
|
|
0x130 => 'Sipro Lab ACEPLNET', #8 |
|
199
|
|
|
|
|
|
|
0x131 => 'Sipro Lab ACELP4800', #8 |
|
200
|
|
|
|
|
|
|
0x132 => 'Sipro Lab ACELP8V3', #8 |
|
201
|
|
|
|
|
|
|
0x133 => 'Sipro Lab G.729', #8 |
|
202
|
|
|
|
|
|
|
0x134 => 'Sipro Lab G.729A', #8 |
|
203
|
|
|
|
|
|
|
0x135 => 'Sipro Lab Kelvin', #8 |
|
204
|
|
|
|
|
|
|
0x136 => 'VoiceAge AMR', #10 |
|
205
|
|
|
|
|
|
|
0x140 => 'Dictaphone G.726 ADPCM', #8 |
|
206
|
|
|
|
|
|
|
0x150 => 'Qualcomm PureVoice', #8 |
|
207
|
|
|
|
|
|
|
0x151 => 'Qualcomm HalfRate', #8 |
|
208
|
|
|
|
|
|
|
0x155 => 'Ring Zero Systems TUBGSM', #8 |
|
209
|
|
|
|
|
|
|
0x160 => 'Microsoft Audio1', #8 |
|
210
|
|
|
|
|
|
|
0x161 => 'Windows Media Audio V2 V7 V8 V9 / DivX audio (WMA) / Alex AC3 Audio', #10 |
|
211
|
|
|
|
|
|
|
0x162 => 'Windows Media Audio Professional V9', #10 |
|
212
|
|
|
|
|
|
|
0x163 => 'Windows Media Audio Lossless V9', #10 |
|
213
|
|
|
|
|
|
|
0x164 => 'WMA Pro over S/PDIF', #10 |
|
214
|
|
|
|
|
|
|
0x170 => 'UNISYS NAP ADPCM', #10 |
|
215
|
|
|
|
|
|
|
0x171 => 'UNISYS NAP ULAW', #10 |
|
216
|
|
|
|
|
|
|
0x172 => 'UNISYS NAP ALAW', #10 |
|
217
|
|
|
|
|
|
|
0x173 => 'UNISYS NAP 16K', #10 |
|
218
|
|
|
|
|
|
|
0x174 => 'MM SYCOM ACM SYC008 SyCom Technologies', #10 |
|
219
|
|
|
|
|
|
|
0x175 => 'MM SYCOM ACM SYC701 G726L SyCom Technologies', #10 |
|
220
|
|
|
|
|
|
|
0x176 => 'MM SYCOM ACM SYC701 CELP54 SyCom Technologies', #10 |
|
221
|
|
|
|
|
|
|
0x177 => 'MM SYCOM ACM SYC701 CELP68 SyCom Technologies', #10 |
|
222
|
|
|
|
|
|
|
0x178 => 'Knowledge Adventure ADPCM', #10 |
|
223
|
|
|
|
|
|
|
0x180 => 'Fraunhofer IIS MPEG2AAC', #10 |
|
224
|
|
|
|
|
|
|
0x190 => 'Digital Theater Systems DTS DS', #10 |
|
225
|
|
|
|
|
|
|
0x200 => 'Creative Labs ADPCM', #6 |
|
226
|
|
|
|
|
|
|
0x202 => 'Creative Labs FASTSPEECH8', #6 |
|
227
|
|
|
|
|
|
|
0x203 => 'Creative Labs FASTSPEECH10', #6 |
|
228
|
|
|
|
|
|
|
0x210 => 'UHER ADPCM', #8 |
|
229
|
|
|
|
|
|
|
0x215 => 'Ulead DV ACM', #10 |
|
230
|
|
|
|
|
|
|
0x216 => 'Ulead DV ACM', #10 |
|
231
|
|
|
|
|
|
|
0x220 => 'Quarterdeck Corp.', #6 |
|
232
|
|
|
|
|
|
|
0x230 => 'I-Link VC', #8 |
|
233
|
|
|
|
|
|
|
0x240 => 'Aureal Semiconductor Raw Sport', #8 |
|
234
|
|
|
|
|
|
|
0x241 => 'ESST AC3', #10 |
|
235
|
|
|
|
|
|
|
0x250 => 'Interactive Products HSX', #8 |
|
236
|
|
|
|
|
|
|
0x251 => 'Interactive Products RPELP', #8 |
|
237
|
|
|
|
|
|
|
0x260 => 'Consistent CS2', #8 |
|
238
|
|
|
|
|
|
|
0x270 => 'Sony SCX', #8 |
|
239
|
|
|
|
|
|
|
0x271 => 'Sony SCY', #10 |
|
240
|
|
|
|
|
|
|
0x272 => 'Sony ATRAC3', #10 |
|
241
|
|
|
|
|
|
|
0x273 => 'Sony SPC', #10 |
|
242
|
|
|
|
|
|
|
0x280 => 'TELUM Telum Inc.', #10 |
|
243
|
|
|
|
|
|
|
0x281 => 'TELUMIA Telum Inc.', #10 |
|
244
|
|
|
|
|
|
|
0x285 => 'Norcom Voice Systems ADPCM', #10 |
|
245
|
|
|
|
|
|
|
0x300 => 'Fujitsu FM TOWNS SND', #6 |
|
246
|
|
|
|
|
|
|
0x301 => 'Fujitsu (not specified)', #10 |
|
247
|
|
|
|
|
|
|
0x302 => 'Fujitsu (not specified)', #10 |
|
248
|
|
|
|
|
|
|
0x303 => 'Fujitsu (not specified)', #10 |
|
249
|
|
|
|
|
|
|
0x304 => 'Fujitsu (not specified)', #10 |
|
250
|
|
|
|
|
|
|
0x305 => 'Fujitsu (not specified)', #10 |
|
251
|
|
|
|
|
|
|
0x306 => 'Fujitsu (not specified)', #10 |
|
252
|
|
|
|
|
|
|
0x307 => 'Fujitsu (not specified)', #10 |
|
253
|
|
|
|
|
|
|
0x308 => 'Fujitsu (not specified)', #10 |
|
254
|
|
|
|
|
|
|
0x350 => 'Micronas Semiconductors, Inc. Development', #10 |
|
255
|
|
|
|
|
|
|
0x351 => 'Micronas Semiconductors, Inc. CELP833', #10 |
|
256
|
|
|
|
|
|
|
0x400 => 'Brooktree Digital', #6 |
|
257
|
|
|
|
|
|
|
0x401 => 'Intel Music Coder (IMC)', #10 |
|
258
|
|
|
|
|
|
|
0x402 => 'Ligos Indeo Audio', #10 |
|
259
|
|
|
|
|
|
|
0x450 => 'QDesign Music', #8 |
|
260
|
|
|
|
|
|
|
0x500 => 'On2 VP7 On2 Technologies', #10 |
|
261
|
|
|
|
|
|
|
0x501 => 'On2 VP6 On2 Technologies', #10 |
|
262
|
|
|
|
|
|
|
0x680 => 'AT&T VME VMPCM', #7 |
|
263
|
|
|
|
|
|
|
0x681 => 'AT&T TCP', #8 |
|
264
|
|
|
|
|
|
|
0x700 => 'YMPEG Alpha (dummy for MPEG-2 compressor)', #10 |
|
265
|
|
|
|
|
|
|
0x8ae => 'ClearJump LiteWave (lossless)', #10 |
|
266
|
|
|
|
|
|
|
0x1000 => 'Olivetti GSM', #6 |
|
267
|
|
|
|
|
|
|
0x1001 => 'Olivetti ADPCM', #6 |
|
268
|
|
|
|
|
|
|
0x1002 => 'Olivetti CELP', #6 |
|
269
|
|
|
|
|
|
|
0x1003 => 'Olivetti SBC', #6 |
|
270
|
|
|
|
|
|
|
0x1004 => 'Olivetti OPR', #6 |
|
271
|
|
|
|
|
|
|
0x1100 => 'Lernout & Hauspie', #6 |
|
272
|
|
|
|
|
|
|
0x1101 => 'Lernout & Hauspie CELP codec', #10 |
|
273
|
|
|
|
|
|
|
0x1102 => 'Lernout & Hauspie SBC codec', #10 |
|
274
|
|
|
|
|
|
|
0x1103 => 'Lernout & Hauspie SBC codec', #10 |
|
275
|
|
|
|
|
|
|
0x1104 => 'Lernout & Hauspie SBC codec', #10 |
|
276
|
|
|
|
|
|
|
0x1400 => 'Norris Comm. Inc.', #6 |
|
277
|
|
|
|
|
|
|
0x1401 => 'ISIAudio', #7 |
|
278
|
|
|
|
|
|
|
0x1500 => 'AT&T Soundspace Music Compression', #7 |
|
279
|
|
|
|
|
|
|
0x181c => 'VoxWare RT24 speech codec', #10 |
|
280
|
|
|
|
|
|
|
0x181e => 'Lucent elemedia AX24000P Music codec', #10 |
|
281
|
|
|
|
|
|
|
0x1971 => 'Sonic Foundry LOSSLESS', #10 |
|
282
|
|
|
|
|
|
|
0x1979 => 'Innings Telecom Inc. ADPCM', #10 |
|
283
|
|
|
|
|
|
|
0x1c07 => 'Lucent SX8300P speech codec', #10 |
|
284
|
|
|
|
|
|
|
0x1c0c => 'Lucent SX5363S G.723 compliant codec', #10 |
|
285
|
|
|
|
|
|
|
0x1f03 => 'CUseeMe DigiTalk (ex-Rocwell)', #10 |
|
286
|
|
|
|
|
|
|
0x1fc4 => 'NCT Soft ALF2CD ACM', #10 |
|
287
|
|
|
|
|
|
|
0x2000 => 'FAST Multimedia DVM', #7 |
|
288
|
|
|
|
|
|
|
0x2001 => 'Dolby DTS (Digital Theater System)', #10 |
|
289
|
|
|
|
|
|
|
0x2002 => 'RealAudio 1 / 2 14.4', #10 |
|
290
|
|
|
|
|
|
|
0x2003 => 'RealAudio 1 / 2 28.8', #10 |
|
291
|
|
|
|
|
|
|
0x2004 => 'RealAudio G2 / 8 Cook (low bitrate)', #10 |
|
292
|
|
|
|
|
|
|
0x2005 => 'RealAudio 3 / 4 / 5 Music (DNET)', #10 |
|
293
|
|
|
|
|
|
|
0x2006 => 'RealAudio 10 AAC (RAAC)', #10 |
|
294
|
|
|
|
|
|
|
0x2007 => 'RealAudio 10 AAC+ (RACP)', #10 |
|
295
|
|
|
|
|
|
|
0x2500 => 'Reserved range to 0x2600 Microsoft', #10 |
|
296
|
|
|
|
|
|
|
0x3313 => 'makeAVIS (ffvfw fake AVI sound from AviSynth scripts)', #10 |
|
297
|
|
|
|
|
|
|
0x4143 => 'Divio MPEG-4 AAC audio', #10 |
|
298
|
|
|
|
|
|
|
0x4201 => 'Nokia adaptive multirate', #10 |
|
299
|
|
|
|
|
|
|
0x4243 => 'Divio G726 Divio, Inc.', #10 |
|
300
|
|
|
|
|
|
|
0x434c => 'LEAD Speech', #10 |
|
301
|
|
|
|
|
|
|
0x564c => 'LEAD Vorbis', #10 |
|
302
|
|
|
|
|
|
|
0x5756 => 'WavPack Audio', #10 |
|
303
|
|
|
|
|
|
|
0x674f => 'Ogg Vorbis (mode 1)', #10 |
|
304
|
|
|
|
|
|
|
0x6750 => 'Ogg Vorbis (mode 2)', #10 |
|
305
|
|
|
|
|
|
|
0x6751 => 'Ogg Vorbis (mode 3)', #10 |
|
306
|
|
|
|
|
|
|
0x676f => 'Ogg Vorbis (mode 1+)', #10 |
|
307
|
|
|
|
|
|
|
0x6770 => 'Ogg Vorbis (mode 2+)', #10 |
|
308
|
|
|
|
|
|
|
0x6771 => 'Ogg Vorbis (mode 3+)', #10 |
|
309
|
|
|
|
|
|
|
0x7000 => '3COM NBX 3Com Corporation', #10 |
|
310
|
|
|
|
|
|
|
0x706d => 'FAAD AAC', #10 |
|
311
|
|
|
|
|
|
|
0x7a21 => 'GSM-AMR (CBR, no SID)', #10 |
|
312
|
|
|
|
|
|
|
0x7a22 => 'GSM-AMR (VBR, including SID)', #10 |
|
313
|
|
|
|
|
|
|
0xa100 => 'Comverse Infosys Ltd. G723 1', #10 |
|
314
|
|
|
|
|
|
|
0xa101 => 'Comverse Infosys Ltd. AVQSBC', #10 |
|
315
|
|
|
|
|
|
|
0xa102 => 'Comverse Infosys Ltd. OLDSBC', #10 |
|
316
|
|
|
|
|
|
|
0xa103 => 'Symbol Technologies G729A', #10 |
|
317
|
|
|
|
|
|
|
0xa104 => 'VoiceAge AMR WB VoiceAge Corporation', #10 |
|
318
|
|
|
|
|
|
|
0xa105 => 'Ingenient Technologies Inc. G726', #10 |
|
319
|
|
|
|
|
|
|
0xa106 => 'ISO/MPEG-4 advanced audio Coding', #10 |
|
320
|
|
|
|
|
|
|
0xa107 => 'Encore Software Ltd G726', #10 |
|
321
|
|
|
|
|
|
|
0xa109 => 'Speex ACM Codec xiph.org', #10 |
|
322
|
|
|
|
|
|
|
0xdfac => 'DebugMode SonicFoundry Vegas FrameServer ACM Codec', #10 |
|
323
|
|
|
|
|
|
|
0xe708 => 'Unknown -', #10 |
|
324
|
|
|
|
|
|
|
0xf1ac => 'Free Lossless Audio Codec FLAC', #10 |
|
325
|
|
|
|
|
|
|
0xfffe => 'Extensible', #7 |
|
326
|
|
|
|
|
|
|
0xffff => 'Development', #4 |
|
327
|
|
|
|
|
|
|
); |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# RIFF info |
|
330
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Main = ( |
|
331
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, |
|
332
|
|
|
|
|
|
|
NOTES => q{ |
|
333
|
|
|
|
|
|
|
The RIFF container format is used various types of fines including AVI, WAV, |
|
334
|
|
|
|
|
|
|
WEBP, LA, OFR, PAC and WV. According to the EXIF specification, Meta |
|
335
|
|
|
|
|
|
|
information is embedded in two types of RIFF C chunks: C and |
|
336
|
|
|
|
|
|
|
C, and information about the audio content is stored in the C |
|
337
|
|
|
|
|
|
|
chunk. As well as this information, some video information and proprietary |
|
338
|
|
|
|
|
|
|
manufacturer-specific information is also extracted. |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
Large AVI videos may be a concatenation of two or more RIFF chunks. For |
|
341
|
|
|
|
|
|
|
these files, information is extracted from subsequent RIFF chunks as |
|
342
|
|
|
|
|
|
|
sub-documents, but the Duration is calculated for the full video. |
|
343
|
|
|
|
|
|
|
}, |
|
344
|
|
|
|
|
|
|
# (not 100% sure that the concatenation technique mentioned above is valid - PH) |
|
345
|
|
|
|
|
|
|
'fmt ' => { |
|
346
|
|
|
|
|
|
|
Name => 'AudioFormat', |
|
347
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AudioFormat' }, |
|
348
|
|
|
|
|
|
|
}, |
|
349
|
|
|
|
|
|
|
'bext' => { |
|
350
|
|
|
|
|
|
|
Name => 'BroadcastExtension', |
|
351
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::BroadcastExt' }, |
|
352
|
|
|
|
|
|
|
}, |
|
353
|
|
|
|
|
|
|
ds64 => { #15 |
|
354
|
|
|
|
|
|
|
Name => 'DataSize64', |
|
355
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::DS64' }, |
|
356
|
|
|
|
|
|
|
}, |
|
357
|
|
|
|
|
|
|
list => 'ListType', #15 |
|
358
|
|
|
|
|
|
|
labl => { #16 (in 'adtl' chunk) |
|
359
|
|
|
|
|
|
|
Name => 'CuePointLabel', |
|
360
|
|
|
|
|
|
|
Priority => 0, # (so they are stored in sequence) |
|
361
|
|
|
|
|
|
|
ValueConv => 'my $str=substr($val,4); $str=~s/\0+$//; unpack("V",$val) . " " . $str', |
|
362
|
|
|
|
|
|
|
}, |
|
363
|
|
|
|
|
|
|
note => { #16 (in 'adtl' chunk) |
|
364
|
|
|
|
|
|
|
Name => 'CuePointNote', |
|
365
|
|
|
|
|
|
|
Priority => 0, # (so they are stored in sequence) |
|
366
|
|
|
|
|
|
|
ValueConv => 'my $str=substr($val,4); $str=~s/\0+$//; unpack("V",$val) . " " . $str', |
|
367
|
|
|
|
|
|
|
}, |
|
368
|
|
|
|
|
|
|
ltxt => { #16 (in 'adtl' chunk) |
|
369
|
|
|
|
|
|
|
Name => 'LabeledText', |
|
370
|
|
|
|
|
|
|
Notes => 'CuePointID Length Purpose Country Language Dialect Codepage Text', |
|
371
|
|
|
|
|
|
|
Priority => 0, # (so they are stored in sequence) |
|
372
|
|
|
|
|
|
|
ValueConv => q{ |
|
373
|
|
|
|
|
|
|
my @a = unpack('VVa4vvvv', $val); |
|
374
|
|
|
|
|
|
|
$a[2] = "'$a[2]'"; |
|
375
|
|
|
|
|
|
|
my $txt = substr($val, 18); |
|
376
|
|
|
|
|
|
|
$txt =~ s/\0+$//; # remove null terminator |
|
377
|
|
|
|
|
|
|
return join(' ', @a, $txt); |
|
378
|
|
|
|
|
|
|
}, |
|
379
|
|
|
|
|
|
|
}, |
|
380
|
|
|
|
|
|
|
smpl => { #16 |
|
381
|
|
|
|
|
|
|
Name => 'Sampler', |
|
382
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Sampler' }, |
|
383
|
|
|
|
|
|
|
}, |
|
384
|
|
|
|
|
|
|
inst => { #16 |
|
385
|
|
|
|
|
|
|
Name => 'Instrument', |
|
386
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Instrument' }, |
|
387
|
|
|
|
|
|
|
}, |
|
388
|
|
|
|
|
|
|
LIST_INFO => { |
|
389
|
|
|
|
|
|
|
Name => 'Info', |
|
390
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Info' }, |
|
391
|
|
|
|
|
|
|
}, |
|
392
|
|
|
|
|
|
|
LIST_exif => { |
|
393
|
|
|
|
|
|
|
Name => 'Exif', |
|
394
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Exif' }, |
|
395
|
|
|
|
|
|
|
}, |
|
396
|
|
|
|
|
|
|
LIST_hdrl => { # AVI header LIST chunk |
|
397
|
|
|
|
|
|
|
Name => 'Hdrl', |
|
398
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Hdrl' }, |
|
399
|
|
|
|
|
|
|
}, |
|
400
|
|
|
|
|
|
|
LIST_Tdat => { #PH (Adobe CS3 Bridge) |
|
401
|
|
|
|
|
|
|
Name => 'Tdat', |
|
402
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Tdat' }, |
|
403
|
|
|
|
|
|
|
}, |
|
404
|
|
|
|
|
|
|
LIST_ncdt => { #PH (Nikon metadata) |
|
405
|
|
|
|
|
|
|
Name => 'NikonData', |
|
406
|
|
|
|
|
|
|
SubDirectory => { |
|
407
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Nikon::AVI', |
|
408
|
|
|
|
|
|
|
# define ProcessProc here so we don't need to load RIFF.pm from Nikon.pm |
|
409
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, |
|
410
|
|
|
|
|
|
|
}, |
|
411
|
|
|
|
|
|
|
}, |
|
412
|
|
|
|
|
|
|
LIST_hydt => { #PH (Pentax metadata) |
|
413
|
|
|
|
|
|
|
Name => 'PentaxData', |
|
414
|
|
|
|
|
|
|
SubDirectory => { |
|
415
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::AVI', |
|
416
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, |
|
417
|
|
|
|
|
|
|
}, |
|
418
|
|
|
|
|
|
|
}, |
|
419
|
|
|
|
|
|
|
LIST_pntx => { #Andras Salamon (Q-S1 AVI) |
|
420
|
|
|
|
|
|
|
Name => 'PentaxData2', |
|
421
|
|
|
|
|
|
|
SubDirectory => { |
|
422
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Pentax::AVI', |
|
423
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, |
|
424
|
|
|
|
|
|
|
}, |
|
425
|
|
|
|
|
|
|
}, |
|
426
|
|
|
|
|
|
|
LIST_adtl => { #PH (ref 16, forum12387) |
|
427
|
|
|
|
|
|
|
Name => 'AssociatedDataList', |
|
428
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Main' }, |
|
429
|
|
|
|
|
|
|
}, |
|
430
|
|
|
|
|
|
|
# seen LIST_JUNK |
|
431
|
|
|
|
|
|
|
JUNK => [ |
|
432
|
|
|
|
|
|
|
{ |
|
433
|
|
|
|
|
|
|
Name => 'OlympusJunk', |
|
434
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^OLYMDigital Camera/', |
|
435
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Olympus::AVI' }, |
|
436
|
|
|
|
|
|
|
}, |
|
437
|
|
|
|
|
|
|
{ |
|
438
|
|
|
|
|
|
|
Name => 'CasioJunk', |
|
439
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^QVMI/', |
|
440
|
|
|
|
|
|
|
# Casio stores standard EXIF-format information in AVI videos (EX-S600) |
|
441
|
|
|
|
|
|
|
SubDirectory => { |
|
442
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Exif::Main', |
|
443
|
|
|
|
|
|
|
DirName => 'IFD0', |
|
444
|
|
|
|
|
|
|
Multi => 0, # (IFD1 is not written) |
|
445
|
|
|
|
|
|
|
Start => 10, |
|
446
|
|
|
|
|
|
|
ByteOrder => 'BigEndian', |
|
447
|
|
|
|
|
|
|
}, |
|
448
|
|
|
|
|
|
|
}, |
|
449
|
|
|
|
|
|
|
{ |
|
450
|
|
|
|
|
|
|
Name => 'RicohJunk', |
|
451
|
|
|
|
|
|
|
# the Ricoh Caplio GX stores sub-chunks in here |
|
452
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^ucmt/', |
|
453
|
|
|
|
|
|
|
SubDirectory => { |
|
454
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Ricoh::AVI', |
|
455
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks, |
|
456
|
|
|
|
|
|
|
}, |
|
457
|
|
|
|
|
|
|
}, |
|
458
|
|
|
|
|
|
|
{ |
|
459
|
|
|
|
|
|
|
Name => 'PentaxJunk', # (Optio RS1000) |
|
460
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^IIII\x01\0/', |
|
461
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Pentax::Junk' }, |
|
462
|
|
|
|
|
|
|
}, |
|
463
|
|
|
|
|
|
|
{ |
|
464
|
|
|
|
|
|
|
Name => 'PentaxJunk2', # (Optio RZ18) |
|
465
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^PENTDigital Camera/', |
|
466
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Pentax::Junk2' }, |
|
467
|
|
|
|
|
|
|
}, |
|
468
|
|
|
|
|
|
|
{ |
|
469
|
|
|
|
|
|
|
Name => 'LucasJunk', # (Lucas LK-7900 Ace) |
|
470
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^0G(DA|PS)/', |
|
471
|
|
|
|
|
|
|
SubDirectory => { |
|
472
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
|
473
|
|
|
|
|
|
|
ProcessProc => \&ProcessLucas, |
|
474
|
|
|
|
|
|
|
}, |
|
475
|
|
|
|
|
|
|
}, |
|
476
|
|
|
|
|
|
|
{ |
|
477
|
|
|
|
|
|
|
Name => 'TextJunk', |
|
478
|
|
|
|
|
|
|
# try to interpret unknown junk as an ASCII string |
|
479
|
|
|
|
|
|
|
RawConv => '$val =~ /^([^\0-\x1f\x7f-\xff]+)\0*$/ ? $1 : undef', |
|
480
|
|
|
|
|
|
|
} |
|
481
|
|
|
|
|
|
|
], |
|
482
|
|
|
|
|
|
|
_PMX => { #PH (Adobe CS3 Bridge) |
|
483
|
|
|
|
|
|
|
Name => 'XMP', |
|
484
|
|
|
|
|
|
|
Notes => 'AVI and WAV files', |
|
485
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, |
|
486
|
|
|
|
|
|
|
}, |
|
487
|
|
|
|
|
|
|
JUNQ => { #PH (Adobe CS3 Bridge) |
|
488
|
|
|
|
|
|
|
# old XMP is preserved when metadata is replaced in Bridge |
|
489
|
|
|
|
|
|
|
Name => 'OldXMP', |
|
490
|
|
|
|
|
|
|
Binary => 1, |
|
491
|
|
|
|
|
|
|
}, |
|
492
|
|
|
|
|
|
|
olym => { |
|
493
|
|
|
|
|
|
|
Name => 'Olym', |
|
494
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Olympus::WAV' }, |
|
495
|
|
|
|
|
|
|
}, |
|
496
|
|
|
|
|
|
|
fact => { |
|
497
|
|
|
|
|
|
|
Name => 'NumberOfSamples', |
|
498
|
|
|
|
|
|
|
RawConv => 'Get32u(\$val, 0)', |
|
499
|
|
|
|
|
|
|
}, |
|
500
|
|
|
|
|
|
|
'cue '=> { |
|
501
|
|
|
|
|
|
|
Name => 'CuePoints', |
|
502
|
|
|
|
|
|
|
Binary => 1, |
|
503
|
|
|
|
|
|
|
Notes => q{ |
|
504
|
|
|
|
|
|
|
config_files/cutepointlist.config from full distribution will decode this |
|
505
|
|
|
|
|
|
|
and generate a list of cue points with labels |
|
506
|
|
|
|
|
|
|
}, |
|
507
|
|
|
|
|
|
|
}, |
|
508
|
|
|
|
|
|
|
plst => { Name => 'Playlist', Binary => 1 }, #16 |
|
509
|
|
|
|
|
|
|
afsp => { }, |
|
510
|
|
|
|
|
|
|
IDIT => { |
|
511
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
|
512
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
|
513
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
|
514
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::RIFF::ConvertRIFFDate($val)', |
|
515
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
|
516
|
|
|
|
|
|
|
}, |
|
517
|
|
|
|
|
|
|
CSET => { |
|
518
|
|
|
|
|
|
|
Name => 'CharacterSet', |
|
519
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::CSET' }, |
|
520
|
|
|
|
|
|
|
}, |
|
521
|
|
|
|
|
|
|
# tx_ tags are generated based on the Codec used for the txts stream |
|
522
|
|
|
|
|
|
|
tx_USER => { |
|
523
|
|
|
|
|
|
|
Name => 'UserText', |
|
524
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::UserText' }, |
|
525
|
|
|
|
|
|
|
}, |
|
526
|
|
|
|
|
|
|
tx_Unknown => { # (untested) |
|
527
|
|
|
|
|
|
|
Name => 'Text', |
|
528
|
|
|
|
|
|
|
Notes => 'streamed text, extracted when the ExtractEmbedded option is used', |
|
529
|
|
|
|
|
|
|
}, |
|
530
|
|
|
|
|
|
|
'id3 ' => { |
|
531
|
|
|
|
|
|
|
Name => 'ID3', |
|
532
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::ID3::Main' }, |
|
533
|
|
|
|
|
|
|
}, |
|
534
|
|
|
|
|
|
|
# |
|
535
|
|
|
|
|
|
|
# WebP-specific tags |
|
536
|
|
|
|
|
|
|
# |
|
537
|
|
|
|
|
|
|
EXIF => [{ # (WebP) |
|
538
|
|
|
|
|
|
|
Name => 'EXIF', |
|
539
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^(II\x2a\0|MM\0\x2a)/', |
|
540
|
|
|
|
|
|
|
Notes => 'WebP files', |
|
541
|
|
|
|
|
|
|
SubDirectory => { |
|
542
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Exif::Main', |
|
543
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::ProcessTIFF, |
|
544
|
|
|
|
|
|
|
}, |
|
545
|
|
|
|
|
|
|
},{ # (WebP) - have also seen with "Exif\0\0" header - PH |
|
546
|
|
|
|
|
|
|
Name => 'EXIF', |
|
547
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^Exif\0\0(II\x2a\0|MM\0\x2a)/', |
|
548
|
|
|
|
|
|
|
SubDirectory => { |
|
549
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Exif::Main', |
|
550
|
|
|
|
|
|
|
ProcessProc => \&Image::ExifTool::ProcessTIFF, |
|
551
|
|
|
|
|
|
|
Start => 6, |
|
552
|
|
|
|
|
|
|
}, |
|
553
|
|
|
|
|
|
|
},{ |
|
554
|
|
|
|
|
|
|
Name => 'UnknownEXIF', |
|
555
|
|
|
|
|
|
|
Binary => 1, |
|
556
|
|
|
|
|
|
|
}], |
|
557
|
|
|
|
|
|
|
'XMP ' => { #14 (WebP) |
|
558
|
|
|
|
|
|
|
Name => 'XMP', |
|
559
|
|
|
|
|
|
|
Notes => 'WebP files', |
|
560
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' }, |
|
561
|
|
|
|
|
|
|
}, |
|
562
|
|
|
|
|
|
|
ICCP => { #14 (WebP) |
|
563
|
|
|
|
|
|
|
Name => 'ICC_Profile', |
|
564
|
|
|
|
|
|
|
Notes => 'WebP files', |
|
565
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' }, |
|
566
|
|
|
|
|
|
|
}, |
|
567
|
|
|
|
|
|
|
'VP8 ' => { # (WebP lossy) |
|
568
|
|
|
|
|
|
|
Name => 'VP8Bitstream', |
|
569
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^...\x9d\x01\x2a/s', |
|
570
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::VP8' }, |
|
571
|
|
|
|
|
|
|
}, |
|
572
|
|
|
|
|
|
|
VP8L => { #14 (WebP lossless) |
|
573
|
|
|
|
|
|
|
Name => 'VP8L', |
|
574
|
|
|
|
|
|
|
Condition => '$$valPt =~ /^\x2f/', |
|
575
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::VP8L' }, |
|
576
|
|
|
|
|
|
|
}, |
|
577
|
|
|
|
|
|
|
VP8X => { #14 (WebP extended) |
|
578
|
|
|
|
|
|
|
Name => 'VP8X', |
|
579
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::VP8X' }, |
|
580
|
|
|
|
|
|
|
}, |
|
581
|
|
|
|
|
|
|
ANIM => { #14 (WebP animation) |
|
582
|
|
|
|
|
|
|
Name => 'ANIM', |
|
583
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ANIM' }, |
|
584
|
|
|
|
|
|
|
}, |
|
585
|
|
|
|
|
|
|
ANMF => { #14 (WebP animation frame) |
|
586
|
|
|
|
|
|
|
Name => 'ANMF', |
|
587
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ANMF' }, |
|
588
|
|
|
|
|
|
|
}, |
|
589
|
|
|
|
|
|
|
ALPH => { #14 (WebP alpha) |
|
590
|
|
|
|
|
|
|
Name => 'ALPH', |
|
591
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ALPH' }, |
|
592
|
|
|
|
|
|
|
}, |
|
593
|
|
|
|
|
|
|
SGLT => { #PH (BikeBro) |
|
594
|
|
|
|
|
|
|
Name => 'BikeBroAccel', |
|
595
|
|
|
|
|
|
|
SubDirectory => { |
|
596
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
|
597
|
|
|
|
|
|
|
ProcessProc => \&ProcessSGLT, |
|
598
|
|
|
|
|
|
|
}, |
|
599
|
|
|
|
|
|
|
}, |
|
600
|
|
|
|
|
|
|
SLLT => { #PH (BikeBro) |
|
601
|
|
|
|
|
|
|
Name => 'BikeBroGPS', |
|
602
|
|
|
|
|
|
|
SubDirectory => { |
|
603
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
|
604
|
|
|
|
|
|
|
ProcessProc => \&ProcessSLLT, |
|
605
|
|
|
|
|
|
|
}, |
|
606
|
|
|
|
|
|
|
}, |
|
607
|
|
|
|
|
|
|
iXML => { #PH |
|
608
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::XML' }, |
|
609
|
|
|
|
|
|
|
}, |
|
610
|
|
|
|
|
|
|
aXML => { #PH |
|
611
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::XMP::XML' }, |
|
612
|
|
|
|
|
|
|
}, |
|
613
|
|
|
|
|
|
|
# |
|
614
|
|
|
|
|
|
|
# tags found in an AlphaImagingTech AVI video - PH |
|
615
|
|
|
|
|
|
|
# |
|
616
|
|
|
|
|
|
|
LIST_INF0 => { # ('0' instead of 'O' -- odd) |
|
617
|
|
|
|
|
|
|
Name => 'Info', |
|
618
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Info' }, |
|
619
|
|
|
|
|
|
|
}, |
|
620
|
|
|
|
|
|
|
gps0 => { |
|
621
|
|
|
|
|
|
|
Name => 'GPSTrack', |
|
622
|
|
|
|
|
|
|
SetGroups => 'RIFF', # (moves "QuickTime" tags to the "RIFF" group) |
|
623
|
|
|
|
|
|
|
SubDirectory => { |
|
624
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
|
625
|
|
|
|
|
|
|
# (don't use code ref here or get "Prototype mismatch" warning with some Perl versions) |
|
626
|
|
|
|
|
|
|
ProcessProc => 'Image::ExifTool::QuickTime::Process_gps0', |
|
627
|
|
|
|
|
|
|
}, |
|
628
|
|
|
|
|
|
|
}, |
|
629
|
|
|
|
|
|
|
gsen => { |
|
630
|
|
|
|
|
|
|
Name => 'GSensor', |
|
631
|
|
|
|
|
|
|
SetGroups => 'RIFF', # (moves "QuickTime" tags to the "RIFF" group) |
|
632
|
|
|
|
|
|
|
SubDirectory => { |
|
633
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::QuickTime::Stream', |
|
634
|
|
|
|
|
|
|
ProcessProc => 'Image::ExifTool::QuickTime::Process_gsen', |
|
635
|
|
|
|
|
|
|
}, |
|
636
|
|
|
|
|
|
|
}, |
|
637
|
|
|
|
|
|
|
# gpsa - seen hex "01 20 00 00", same as QuickTime |
|
638
|
|
|
|
|
|
|
# gsea - 16 bytes hex "04 08 02 00 20 02 00 00 1f 03 00 00 01 00 00 00" |
|
639
|
|
|
|
|
|
|
); |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
# the maker notes used by some digital cameras |
|
642
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Junk = ( |
|
643
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
644
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
645
|
|
|
|
|
|
|
); |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
# Format and Audio Stream Format chunk data |
|
648
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::AudioFormat = ( |
|
649
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
650
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
651
|
|
|
|
|
|
|
FORMAT => 'int16u', |
|
652
|
|
|
|
|
|
|
0 => { |
|
653
|
|
|
|
|
|
|
Name => 'Encoding', |
|
654
|
|
|
|
|
|
|
PrintHex => 1, |
|
655
|
|
|
|
|
|
|
PrintConv => \%Image::ExifTool::RIFF::audioEncoding, |
|
656
|
|
|
|
|
|
|
SeparateTable => 'AudioEncoding', |
|
657
|
|
|
|
|
|
|
}, |
|
658
|
|
|
|
|
|
|
1 => 'NumChannels', |
|
659
|
|
|
|
|
|
|
2 => { |
|
660
|
|
|
|
|
|
|
Name => 'SampleRate', |
|
661
|
|
|
|
|
|
|
Format => 'int32u', |
|
662
|
|
|
|
|
|
|
}, |
|
663
|
|
|
|
|
|
|
4 => { |
|
664
|
|
|
|
|
|
|
Name => 'AvgBytesPerSec', |
|
665
|
|
|
|
|
|
|
Format => 'int32u', |
|
666
|
|
|
|
|
|
|
}, |
|
667
|
|
|
|
|
|
|
# uninteresting |
|
668
|
|
|
|
|
|
|
# 6 => 'BlockAlignment', |
|
669
|
|
|
|
|
|
|
7 => 'BitsPerSample', |
|
670
|
|
|
|
|
|
|
); |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
# Broadcast Audio Extension 'bext' information (ref 13) |
|
673
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::BroadcastExt = ( |
|
674
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
675
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
676
|
|
|
|
|
|
|
NOTES => q{ |
|
677
|
|
|
|
|
|
|
Information found in the Broadcast Audio Extension chunk (see |
|
678
|
|
|
|
|
|
|
L). |
|
679
|
|
|
|
|
|
|
}, |
|
680
|
|
|
|
|
|
|
0 => { |
|
681
|
|
|
|
|
|
|
Name => 'Description', |
|
682
|
|
|
|
|
|
|
Format => 'string[256]', |
|
683
|
|
|
|
|
|
|
}, |
|
684
|
|
|
|
|
|
|
256 => { |
|
685
|
|
|
|
|
|
|
Name => 'Originator', |
|
686
|
|
|
|
|
|
|
Format => 'string[32]', |
|
687
|
|
|
|
|
|
|
}, |
|
688
|
|
|
|
|
|
|
288 => { |
|
689
|
|
|
|
|
|
|
Name => 'OriginatorReference', |
|
690
|
|
|
|
|
|
|
Format => 'string[32]', |
|
691
|
|
|
|
|
|
|
}, |
|
692
|
|
|
|
|
|
|
320 => { |
|
693
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
|
694
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
|
695
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
|
696
|
|
|
|
|
|
|
Format => 'string[18]', |
|
697
|
|
|
|
|
|
|
ValueConv => '$_=$val; tr/-/:/; s/^(\d{4}:\d{2}:\d{2})/$1 /; $_', |
|
698
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
|
699
|
|
|
|
|
|
|
}, |
|
700
|
|
|
|
|
|
|
338 => { |
|
701
|
|
|
|
|
|
|
Name => 'TimeReference', |
|
702
|
|
|
|
|
|
|
Notes => 'first sample count since midnight', |
|
703
|
|
|
|
|
|
|
Format => 'int32u[2]', |
|
704
|
|
|
|
|
|
|
ValueConv => 'my @v=split(" ",$val); $v[0] + $v[1] * 4294967296', |
|
705
|
|
|
|
|
|
|
}, |
|
706
|
|
|
|
|
|
|
346 => { |
|
707
|
|
|
|
|
|
|
Name => 'BWFVersion', |
|
708
|
|
|
|
|
|
|
Format => 'int16u', |
|
709
|
|
|
|
|
|
|
}, |
|
710
|
|
|
|
|
|
|
348 => { |
|
711
|
|
|
|
|
|
|
Name => 'BWF_UMID', |
|
712
|
|
|
|
|
|
|
Format => 'undef[64]', |
|
713
|
|
|
|
|
|
|
ValueConv => '$_=unpack("H*",$val); s/0{64}$//; uc $_', |
|
714
|
|
|
|
|
|
|
}, |
|
715
|
|
|
|
|
|
|
# 412 - int8u[190] - reserved |
|
716
|
|
|
|
|
|
|
602 => { |
|
717
|
|
|
|
|
|
|
Name => 'CodingHistory', |
|
718
|
|
|
|
|
|
|
Format => 'string[$size-602]', |
|
719
|
|
|
|
|
|
|
}, |
|
720
|
|
|
|
|
|
|
); |
|
721
|
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
# 64-bit chunk sizes (ref 15) |
|
723
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::DS64 = ( |
|
724
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
725
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
726
|
|
|
|
|
|
|
FORMAT => 'int64u', |
|
727
|
|
|
|
|
|
|
NOTES => q{ |
|
728
|
|
|
|
|
|
|
64-bit data sizes for MBWF/RF64 files. See |
|
729
|
|
|
|
|
|
|
L for the specification. |
|
730
|
|
|
|
|
|
|
}, |
|
731
|
|
|
|
|
|
|
0 => { |
|
732
|
|
|
|
|
|
|
Name => 'RIFFSize64', |
|
733
|
|
|
|
|
|
|
PrintConv => \&Image::ExifTool::ConvertFileSize, |
|
734
|
|
|
|
|
|
|
}, |
|
735
|
|
|
|
|
|
|
1 => { |
|
736
|
|
|
|
|
|
|
Name => 'DataSize64', |
|
737
|
|
|
|
|
|
|
DataMember => 'DataSize64', |
|
738
|
|
|
|
|
|
|
RawConv => '$$self{DataSize64} = $val', |
|
739
|
|
|
|
|
|
|
PrintConv => \&Image::ExifTool::ConvertFileSize, |
|
740
|
|
|
|
|
|
|
}, |
|
741
|
|
|
|
|
|
|
2 => 'NumberOfSamples64', |
|
742
|
|
|
|
|
|
|
# (after this comes a table of size overrides for chunk |
|
743
|
|
|
|
|
|
|
# types other than 'data', but since these are currently |
|
744
|
|
|
|
|
|
|
# very unlikely, support for these is not yet implemented) |
|
745
|
|
|
|
|
|
|
); |
|
746
|
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
# Sampler chunk (ref 16) |
|
748
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Sampler = ( |
|
749
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
750
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
751
|
|
|
|
|
|
|
FORMAT => 'int32u', |
|
752
|
|
|
|
|
|
|
0 => 'Manufacturer', |
|
753
|
|
|
|
|
|
|
1 => 'Product', |
|
754
|
|
|
|
|
|
|
2 => 'SamplePeriod', |
|
755
|
|
|
|
|
|
|
3 => 'MIDIUnityNote', |
|
756
|
|
|
|
|
|
|
4 => 'MIDIPitchFraction', |
|
757
|
|
|
|
|
|
|
5 => { |
|
758
|
|
|
|
|
|
|
Name => 'SMPTEFormat', |
|
759
|
|
|
|
|
|
|
PrintConv => { |
|
760
|
|
|
|
|
|
|
0 => 'none', |
|
761
|
|
|
|
|
|
|
24 => '24 fps', |
|
762
|
|
|
|
|
|
|
25 => '25 fps', |
|
763
|
|
|
|
|
|
|
29 => '29 fps', |
|
764
|
|
|
|
|
|
|
30 => '30 fps', |
|
765
|
|
|
|
|
|
|
}, |
|
766
|
|
|
|
|
|
|
}, |
|
767
|
|
|
|
|
|
|
6 => { |
|
768
|
|
|
|
|
|
|
Name => 'SMPTEOffset', |
|
769
|
|
|
|
|
|
|
Notes => 'HH:MM:SS:FF', |
|
770
|
|
|
|
|
|
|
ValueConv => q{ |
|
771
|
|
|
|
|
|
|
my $str = sprintf('%.8x', $val); |
|
772
|
|
|
|
|
|
|
$str =~ s/(..)(..)(..)(..)/$1:$2:$3:$4/; |
|
773
|
|
|
|
|
|
|
return $str; |
|
774
|
|
|
|
|
|
|
}, |
|
775
|
|
|
|
|
|
|
}, |
|
776
|
|
|
|
|
|
|
7 => 'NumSampleLoops', |
|
777
|
|
|
|
|
|
|
8 => 'SamplerDataLen', |
|
778
|
|
|
|
|
|
|
9 => { Name => 'SamplerData', Format => 'undef[$size-40]', Binary => 1 }, |
|
779
|
|
|
|
|
|
|
); |
|
780
|
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
# Instrument chunk (ref 16) |
|
782
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Instrument = ( |
|
783
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
784
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
785
|
|
|
|
|
|
|
FORMAT => 'int8s', |
|
786
|
|
|
|
|
|
|
0 => 'UnshiftedNote', |
|
787
|
|
|
|
|
|
|
1 => 'FineTune', |
|
788
|
|
|
|
|
|
|
2 => 'Gain', |
|
789
|
|
|
|
|
|
|
3 => 'LowNote', |
|
790
|
|
|
|
|
|
|
4 => 'HighNote', |
|
791
|
|
|
|
|
|
|
5 => 'LowVelocity', |
|
792
|
|
|
|
|
|
|
6 => 'HighVelocity', |
|
793
|
|
|
|
|
|
|
); |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
# Sub chunks of INFO LIST chunk |
|
796
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Info = ( |
|
797
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, |
|
798
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
799
|
|
|
|
|
|
|
FORMAT => 'string', |
|
800
|
|
|
|
|
|
|
NOTES => q{ |
|
801
|
|
|
|
|
|
|
RIFF INFO tags found in AVI video and WAV audio files. Tags which are part |
|
802
|
|
|
|
|
|
|
of the EXIF 2.3 specification have an underlined Tag Name in the HTML |
|
803
|
|
|
|
|
|
|
version of this documentation. Other tags are found in AVI files generated |
|
804
|
|
|
|
|
|
|
by some software. |
|
805
|
|
|
|
|
|
|
}, |
|
806
|
|
|
|
|
|
|
IARL => 'ArchivalLocation', |
|
807
|
|
|
|
|
|
|
IART => { Name => 'Artist', Groups => { 2 => 'Author' } }, |
|
808
|
|
|
|
|
|
|
ICMS => 'Commissioned', |
|
809
|
|
|
|
|
|
|
ICMT => 'Comment', |
|
810
|
|
|
|
|
|
|
ICOP => { Name => 'Copyright', Groups => { 2 => 'Author' } }, |
|
811
|
|
|
|
|
|
|
ICRD => { |
|
812
|
|
|
|
|
|
|
Name => 'DateCreated', |
|
813
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
|
814
|
|
|
|
|
|
|
ValueConv => '$_=$val; s/-/:/g; $_', |
|
815
|
|
|
|
|
|
|
}, |
|
816
|
|
|
|
|
|
|
ICRP => 'Cropped', |
|
817
|
|
|
|
|
|
|
IDIM => 'Dimensions', |
|
818
|
|
|
|
|
|
|
IDPI => 'DotsPerInch', |
|
819
|
|
|
|
|
|
|
IENG => 'Engineer', |
|
820
|
|
|
|
|
|
|
IGNR => 'Genre', |
|
821
|
|
|
|
|
|
|
IKEY => 'Keywords', |
|
822
|
|
|
|
|
|
|
ILGT => 'Lightness', |
|
823
|
|
|
|
|
|
|
IMED => 'Medium', |
|
824
|
|
|
|
|
|
|
INAM => 'Title', |
|
825
|
|
|
|
|
|
|
ITRK => 'TrackNumber', |
|
826
|
|
|
|
|
|
|
IPLT => 'NumColors', |
|
827
|
|
|
|
|
|
|
IPRD => 'Product', |
|
828
|
|
|
|
|
|
|
ISBJ => 'Subject', |
|
829
|
|
|
|
|
|
|
ISFT => { |
|
830
|
|
|
|
|
|
|
Name => 'Software', |
|
831
|
|
|
|
|
|
|
# remove trailing nulls/spaces and split at first null |
|
832
|
|
|
|
|
|
|
# (Casio writes "CASIO" in unicode after the first null) |
|
833
|
|
|
|
|
|
|
ValueConv => '$_=$val; s/(\s*\0)+$//; s/(\s*\0)/, /; s/\0+//g; $_', |
|
834
|
|
|
|
|
|
|
}, |
|
835
|
|
|
|
|
|
|
ISHP => 'Sharpness', |
|
836
|
|
|
|
|
|
|
ISRC => 'Source', |
|
837
|
|
|
|
|
|
|
ISRF => 'SourceForm', |
|
838
|
|
|
|
|
|
|
ITCH => 'Technician', |
|
839
|
|
|
|
|
|
|
# |
|
840
|
|
|
|
|
|
|
# 3rd party tags |
|
841
|
|
|
|
|
|
|
# |
|
842
|
|
|
|
|
|
|
# internet movie database (ref 12) |
|
843
|
|
|
|
|
|
|
ISGN => 'SecondaryGenre', |
|
844
|
|
|
|
|
|
|
IWRI => 'WrittenBy', |
|
845
|
|
|
|
|
|
|
IPRO => 'ProducedBy', |
|
846
|
|
|
|
|
|
|
ICNM => 'Cinematographer', |
|
847
|
|
|
|
|
|
|
IPDS => 'ProductionDesigner', |
|
848
|
|
|
|
|
|
|
IEDT => 'EditedBy', |
|
849
|
|
|
|
|
|
|
ICDS => 'CostumeDesigner', |
|
850
|
|
|
|
|
|
|
IMUS => 'MusicBy', |
|
851
|
|
|
|
|
|
|
ISTD => 'ProductionStudio', |
|
852
|
|
|
|
|
|
|
IDST => 'DistributedBy', |
|
853
|
|
|
|
|
|
|
ICNT => 'Country', |
|
854
|
|
|
|
|
|
|
ILNG => 'Language', |
|
855
|
|
|
|
|
|
|
IRTD => 'Rating', |
|
856
|
|
|
|
|
|
|
ISTR => 'Starring', |
|
857
|
|
|
|
|
|
|
# MovieID (ref12) |
|
858
|
|
|
|
|
|
|
TITL => 'Title', |
|
859
|
|
|
|
|
|
|
DIRC => 'Directory', |
|
860
|
|
|
|
|
|
|
YEAR => 'Year', |
|
861
|
|
|
|
|
|
|
GENR => 'Genre', |
|
862
|
|
|
|
|
|
|
COMM => 'Comments', |
|
863
|
|
|
|
|
|
|
LANG => 'Language', |
|
864
|
|
|
|
|
|
|
AGES => 'Rated', |
|
865
|
|
|
|
|
|
|
STAR => 'Starring', |
|
866
|
|
|
|
|
|
|
CODE => 'EncodedBy', |
|
867
|
|
|
|
|
|
|
PRT1 => 'Part', |
|
868
|
|
|
|
|
|
|
PRT2 => 'NumberOfParts', |
|
869
|
|
|
|
|
|
|
# Morgan Multimedia INFO tags (ref 12) |
|
870
|
|
|
|
|
|
|
IAS1 => 'FirstLanguage', |
|
871
|
|
|
|
|
|
|
IAS2 => 'SecondLanguage', |
|
872
|
|
|
|
|
|
|
IAS3 => 'ThirdLanguage', |
|
873
|
|
|
|
|
|
|
IAS4 => 'FourthLanguage', |
|
874
|
|
|
|
|
|
|
IAS5 => 'FifthLanguage', |
|
875
|
|
|
|
|
|
|
IAS6 => 'SixthLanguage', |
|
876
|
|
|
|
|
|
|
IAS7 => 'SeventhLanguage', |
|
877
|
|
|
|
|
|
|
IAS8 => 'EighthLanguage', |
|
878
|
|
|
|
|
|
|
IAS9 => 'NinthLanguage', |
|
879
|
|
|
|
|
|
|
ICAS => 'DefaultAudioStream', |
|
880
|
|
|
|
|
|
|
IBSU => 'BaseURL', |
|
881
|
|
|
|
|
|
|
ILGU => 'LogoURL', |
|
882
|
|
|
|
|
|
|
ILIU => 'LogoIconURL', |
|
883
|
|
|
|
|
|
|
IWMU => 'WatermarkURL', |
|
884
|
|
|
|
|
|
|
IMIU => 'MoreInfoURL', |
|
885
|
|
|
|
|
|
|
IMBI => 'MoreInfoBannerImage', |
|
886
|
|
|
|
|
|
|
IMBU => 'MoreInfoBannerURL', |
|
887
|
|
|
|
|
|
|
IMIT => 'MoreInfoText', |
|
888
|
|
|
|
|
|
|
# GSpot INFO tags (ref 12) |
|
889
|
|
|
|
|
|
|
IENC => 'EncodedBy', |
|
890
|
|
|
|
|
|
|
IRIP => 'RippedBy', |
|
891
|
|
|
|
|
|
|
# Sound Forge Pro tags |
|
892
|
|
|
|
|
|
|
DISP => 'SoundSchemeTitle', |
|
893
|
|
|
|
|
|
|
TLEN => { Name => 'Length', ValueConv => '$val/1000', PrintConv => '"$val s"' }, |
|
894
|
|
|
|
|
|
|
TRCK => 'TrackNumber', |
|
895
|
|
|
|
|
|
|
TURL => 'URL', |
|
896
|
|
|
|
|
|
|
TVER => 'Version', |
|
897
|
|
|
|
|
|
|
LOCA => 'Location', |
|
898
|
|
|
|
|
|
|
TORG => 'Organization', |
|
899
|
|
|
|
|
|
|
# Sony Vegas AVI tags, also used by SCLive and Adobe Premier (ref 11) |
|
900
|
|
|
|
|
|
|
TAPE => { |
|
901
|
|
|
|
|
|
|
Name => 'TapeName', |
|
902
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
903
|
|
|
|
|
|
|
}, |
|
904
|
|
|
|
|
|
|
TCOD => { |
|
905
|
|
|
|
|
|
|
Name => 'StartTimecode', |
|
906
|
|
|
|
|
|
|
# this is the tape time code for the start of the video |
|
907
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
908
|
|
|
|
|
|
|
ValueConv => '$val * 1e-7', |
|
909
|
|
|
|
|
|
|
PrintConv => \&ConvertTimecode, |
|
910
|
|
|
|
|
|
|
}, |
|
911
|
|
|
|
|
|
|
TCDO => { |
|
912
|
|
|
|
|
|
|
Name => 'EndTimecode', |
|
913
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
914
|
|
|
|
|
|
|
ValueConv => '$val * 1e-7', |
|
915
|
|
|
|
|
|
|
PrintConv => \&ConvertTimecode, |
|
916
|
|
|
|
|
|
|
}, |
|
917
|
|
|
|
|
|
|
VMAJ => { |
|
918
|
|
|
|
|
|
|
Name => 'VegasVersionMajor', |
|
919
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
920
|
|
|
|
|
|
|
}, |
|
921
|
|
|
|
|
|
|
VMIN => { |
|
922
|
|
|
|
|
|
|
Name => 'VegasVersionMinor', |
|
923
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
924
|
|
|
|
|
|
|
}, |
|
925
|
|
|
|
|
|
|
CMNT => { |
|
926
|
|
|
|
|
|
|
Name => 'Comment', |
|
927
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
928
|
|
|
|
|
|
|
}, |
|
929
|
|
|
|
|
|
|
RATE => { |
|
930
|
|
|
|
|
|
|
Name => 'Rate', #? (video? units?) |
|
931
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
932
|
|
|
|
|
|
|
}, |
|
933
|
|
|
|
|
|
|
STAT => { |
|
934
|
|
|
|
|
|
|
Name => 'Statistics', |
|
935
|
|
|
|
|
|
|
Groups => { 2 => 'Video' }, |
|
936
|
|
|
|
|
|
|
# ("7318 0 3.430307 1", "0 0 3500.000000 1", "7 0 3.433228 1") |
|
937
|
|
|
|
|
|
|
PrintConv => [ |
|
938
|
|
|
|
|
|
|
'"$val frames captured"', |
|
939
|
|
|
|
|
|
|
'"$val dropped"', |
|
940
|
|
|
|
|
|
|
'"Data rate $val"', |
|
941
|
|
|
|
|
|
|
{ 0 => 'Bad', 1 => 'OK' }, # capture OK? |
|
942
|
|
|
|
|
|
|
], |
|
943
|
|
|
|
|
|
|
}, |
|
944
|
|
|
|
|
|
|
DTIM => { |
|
945
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
|
946
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
|
947
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
|
948
|
|
|
|
|
|
|
ValueConv => q{ |
|
949
|
|
|
|
|
|
|
my @v = split ' ', $val; |
|
950
|
|
|
|
|
|
|
return undef unless @v == 2; |
|
951
|
|
|
|
|
|
|
# the Kodak EASYSHARE Sport stores this incorrectly as a string: |
|
952
|
|
|
|
|
|
|
return $val if $val =~ /^\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2}$/; |
|
953
|
|
|
|
|
|
|
# get time in seconds |
|
954
|
|
|
|
|
|
|
$val = 1e-7 * ($v[0] * 4294967296 + $v[1]); |
|
955
|
|
|
|
|
|
|
# shift from Jan 1, 1601 to Jan 1, 1970 |
|
956
|
|
|
|
|
|
|
$val -= 134774 * 24 * 3600 if $val != 0; |
|
957
|
|
|
|
|
|
|
return Image::ExifTool::ConvertUnixTime($val); |
|
958
|
|
|
|
|
|
|
}, |
|
959
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
|
960
|
|
|
|
|
|
|
}, |
|
961
|
|
|
|
|
|
|
# not observed, but apparently part of the standard: |
|
962
|
|
|
|
|
|
|
IDIT => { |
|
963
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
|
964
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
|
965
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
|
966
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::RIFF::ConvertRIFFDate($val)', |
|
967
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
|
968
|
|
|
|
|
|
|
}, |
|
969
|
|
|
|
|
|
|
ISMP => 'TimeCode', |
|
970
|
|
|
|
|
|
|
); |
|
971
|
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
# Sub chunks of EXIF LIST chunk |
|
973
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Exif = ( |
|
974
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, |
|
975
|
|
|
|
|
|
|
GROUPS => { 2 => 'Audio' }, |
|
976
|
|
|
|
|
|
|
NOTES => 'These tags are part of the EXIF 2.3 specification for WAV audio files.', |
|
977
|
|
|
|
|
|
|
ever => 'ExifVersion', |
|
978
|
|
|
|
|
|
|
erel => 'RelatedImageFile', |
|
979
|
|
|
|
|
|
|
etim => { Name => 'TimeCreated', Groups => { 2 => 'Time' } }, |
|
980
|
|
|
|
|
|
|
ecor => { Name => 'Make', Groups => { 2 => 'Camera' } }, |
|
981
|
|
|
|
|
|
|
emdl => { Name => 'Model', Groups => { 2 => 'Camera' }, Description => 'Camera Model Name' }, |
|
982
|
|
|
|
|
|
|
emnt => { Name => 'MakerNotes', Binary => 1 }, |
|
983
|
|
|
|
|
|
|
eucm => { |
|
984
|
|
|
|
|
|
|
Name => 'UserComment', |
|
985
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,"RIFF:UserComment")', |
|
986
|
|
|
|
|
|
|
}, |
|
987
|
|
|
|
|
|
|
); |
|
988
|
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
# Sub chunks of hdrl LIST chunk |
|
990
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Hdrl = ( |
|
991
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, |
|
992
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
993
|
|
|
|
|
|
|
avih => { |
|
994
|
|
|
|
|
|
|
Name => 'AVIHeader', |
|
995
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AVIHeader' }, |
|
996
|
|
|
|
|
|
|
}, |
|
997
|
|
|
|
|
|
|
IDIT => { |
|
998
|
|
|
|
|
|
|
Name => 'DateTimeOriginal', |
|
999
|
|
|
|
|
|
|
Description => 'Date/Time Original', |
|
1000
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
|
1001
|
|
|
|
|
|
|
ValueConv => 'Image::ExifTool::RIFF::ConvertRIFFDate($val)', |
|
1002
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
|
1003
|
|
|
|
|
|
|
}, |
|
1004
|
|
|
|
|
|
|
ISMP => 'TimeCode', |
|
1005
|
|
|
|
|
|
|
LIST_strl => { |
|
1006
|
|
|
|
|
|
|
Name => 'Stream', |
|
1007
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Stream' }, |
|
1008
|
|
|
|
|
|
|
}, |
|
1009
|
|
|
|
|
|
|
LIST_odml => { |
|
1010
|
|
|
|
|
|
|
Name => 'OpenDML', |
|
1011
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::OpenDML' }, |
|
1012
|
|
|
|
|
|
|
}, |
|
1013
|
|
|
|
|
|
|
); |
|
1014
|
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
# Sub chunks of Tdat LIST chunk (ref PH) |
|
1016
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Tdat = ( |
|
1017
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, |
|
1018
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
|
1019
|
|
|
|
|
|
|
# (have seen tc_O, tc_A, rn_O and rn_A) |
|
1020
|
|
|
|
|
|
|
); |
|
1021
|
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
# RIFF character set chunk |
|
1023
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::CSET = ( |
|
1024
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1025
|
|
|
|
|
|
|
GROUPS => { 2 => 'Other' }, |
|
1026
|
|
|
|
|
|
|
FORMAT => 'int16u', |
|
1027
|
|
|
|
|
|
|
0 => { |
|
1028
|
|
|
|
|
|
|
Name => 'CodePage', |
|
1029
|
|
|
|
|
|
|
RawConv => '$$self{CodePage} = $val', |
|
1030
|
|
|
|
|
|
|
}, |
|
1031
|
|
|
|
|
|
|
1 => 'CountryCode', |
|
1032
|
|
|
|
|
|
|
2 => 'LanguageCode', |
|
1033
|
|
|
|
|
|
|
3 => 'Dialect', |
|
1034
|
|
|
|
|
|
|
); |
|
1035
|
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::AVIHeader = ( |
|
1037
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1038
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
|
1039
|
|
|
|
|
|
|
FORMAT => 'int32u', |
|
1040
|
|
|
|
|
|
|
FIRST_ENTRY => 0, |
|
1041
|
|
|
|
|
|
|
0 => { |
|
1042
|
|
|
|
|
|
|
Name => 'FrameRate', |
|
1043
|
|
|
|
|
|
|
# (must use RawConv because raw value used in Composite tag) |
|
1044
|
|
|
|
|
|
|
RawConv => '$val ? 1e6 / $val : undef', |
|
1045
|
|
|
|
|
|
|
PrintConv => 'int($val * 1000 + 0.5) / 1000', |
|
1046
|
|
|
|
|
|
|
}, |
|
1047
|
|
|
|
|
|
|
1 => { |
|
1048
|
|
|
|
|
|
|
Name => 'MaxDataRate', |
|
1049
|
|
|
|
|
|
|
PrintConv => 'sprintf("%.4g kB/s",$val / 1024)', |
|
1050
|
|
|
|
|
|
|
}, |
|
1051
|
|
|
|
|
|
|
# 2 => 'PaddingGranularity', |
|
1052
|
|
|
|
|
|
|
# 3 => 'Flags', |
|
1053
|
|
|
|
|
|
|
4 => 'FrameCount', |
|
1054
|
|
|
|
|
|
|
# 5 => 'InitialFrames', |
|
1055
|
|
|
|
|
|
|
6 => 'StreamCount', |
|
1056
|
|
|
|
|
|
|
# 7 => 'SuggestedBufferSize', |
|
1057
|
|
|
|
|
|
|
8 => 'ImageWidth', |
|
1058
|
|
|
|
|
|
|
9 => 'ImageHeight', |
|
1059
|
|
|
|
|
|
|
); |
|
1060
|
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Stream = ( |
|
1062
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, |
|
1063
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
1064
|
|
|
|
|
|
|
strh => { |
|
1065
|
|
|
|
|
|
|
Name => 'StreamHeader', |
|
1066
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::StreamHeader' }, |
|
1067
|
|
|
|
|
|
|
}, |
|
1068
|
|
|
|
|
|
|
strn => 'StreamName', |
|
1069
|
|
|
|
|
|
|
strd => { #PH |
|
1070
|
|
|
|
|
|
|
Name => 'StreamData', |
|
1071
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::StreamData' }, |
|
1072
|
|
|
|
|
|
|
}, |
|
1073
|
|
|
|
|
|
|
strf => [ |
|
1074
|
|
|
|
|
|
|
{ |
|
1075
|
|
|
|
|
|
|
Name => 'AudioFormat', |
|
1076
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "auds"', |
|
1077
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AudioFormat' }, |
|
1078
|
|
|
|
|
|
|
}, |
|
1079
|
|
|
|
|
|
|
{ |
|
1080
|
|
|
|
|
|
|
Name => 'VideoFormat', |
|
1081
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "vids"', |
|
1082
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::BMP::Main' }, |
|
1083
|
|
|
|
|
|
|
}, |
|
1084
|
|
|
|
|
|
|
{ |
|
1085
|
|
|
|
|
|
|
Name => 'TextFormat', |
|
1086
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "txts"', |
|
1087
|
|
|
|
|
|
|
Hidden => 1, |
|
1088
|
|
|
|
|
|
|
RawConv => '$self->Options("ExtractEmbedded") or $self->WarnOnce("Use ExtractEmbedded option to extract timed text",3); undef', |
|
1089
|
|
|
|
|
|
|
}, |
|
1090
|
|
|
|
|
|
|
], |
|
1091
|
|
|
|
|
|
|
); |
|
1092
|
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
# Open DML tags (ref http://www.morgan-multimedia.com/download/odmlff2.pdf) |
|
1094
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::OpenDML = ( |
|
1095
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks, |
|
1096
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
|
1097
|
|
|
|
|
|
|
dmlh => { |
|
1098
|
|
|
|
|
|
|
Name => 'ExtendedAVIHeader', |
|
1099
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ExtAVIHdr' }, |
|
1100
|
|
|
|
|
|
|
}, |
|
1101
|
|
|
|
|
|
|
); |
|
1102
|
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
# Extended AVI Header tags (ref http://www.morgan-multimedia.com/download/odmlff2.pdf) |
|
1104
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::ExtAVIHdr = ( |
|
1105
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1106
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
|
1107
|
|
|
|
|
|
|
FORMAT => 'int32u', |
|
1108
|
|
|
|
|
|
|
0 => 'TotalFrameCount', |
|
1109
|
|
|
|
|
|
|
); |
|
1110
|
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::StreamHeader = ( |
|
1112
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1113
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
|
1114
|
|
|
|
|
|
|
FORMAT => 'int32u', |
|
1115
|
|
|
|
|
|
|
FIRST_ENTRY => 0, |
|
1116
|
|
|
|
|
|
|
PRIORITY => 0, # so we get values from the first stream |
|
1117
|
|
|
|
|
|
|
0 => { |
|
1118
|
|
|
|
|
|
|
Name => 'StreamType', |
|
1119
|
|
|
|
|
|
|
Format => 'string[4]', |
|
1120
|
|
|
|
|
|
|
RawConv => '$$self{RIFFStreamNum} = ($$self{RIFFStreamNum} || 0) + 1; $$self{RIFFStreamType} = $val', |
|
1121
|
|
|
|
|
|
|
PrintConv => { |
|
1122
|
|
|
|
|
|
|
auds => 'Audio', |
|
1123
|
|
|
|
|
|
|
mids => 'MIDI', |
|
1124
|
|
|
|
|
|
|
txts => 'Text', |
|
1125
|
|
|
|
|
|
|
vids => 'Video', |
|
1126
|
|
|
|
|
|
|
iavs => 'Interleaved Audio+Video', |
|
1127
|
|
|
|
|
|
|
}, |
|
1128
|
|
|
|
|
|
|
}, |
|
1129
|
|
|
|
|
|
|
1 => [ |
|
1130
|
|
|
|
|
|
|
{ |
|
1131
|
|
|
|
|
|
|
Name => 'AudioCodec', |
|
1132
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "auds"', |
|
1133
|
|
|
|
|
|
|
RawConv => '$$self{RIFFStreamCodec}[$$self{RIFFStreamNum}-1] = $val', |
|
1134
|
|
|
|
|
|
|
Format => 'string[4]', |
|
1135
|
|
|
|
|
|
|
}, |
|
1136
|
|
|
|
|
|
|
{ |
|
1137
|
|
|
|
|
|
|
Name => 'VideoCodec', |
|
1138
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "vids"', |
|
1139
|
|
|
|
|
|
|
RawConv => '$$self{RIFFStreamCodec}[$$self{RIFFStreamNum}-1] = $val', |
|
1140
|
|
|
|
|
|
|
Format => 'string[4]', |
|
1141
|
|
|
|
|
|
|
}, |
|
1142
|
|
|
|
|
|
|
{ |
|
1143
|
|
|
|
|
|
|
Name => 'Codec', |
|
1144
|
|
|
|
|
|
|
Format => 'string[4]', |
|
1145
|
|
|
|
|
|
|
RawConv => '$$self{RIFFStreamCodec}[$$self{RIFFStreamNum}-1] = $val', |
|
1146
|
|
|
|
|
|
|
}, |
|
1147
|
|
|
|
|
|
|
], |
|
1148
|
|
|
|
|
|
|
# 2 => 'StreamFlags', |
|
1149
|
|
|
|
|
|
|
# 3 => 'StreamPriority', |
|
1150
|
|
|
|
|
|
|
# 3.5 => 'Language', |
|
1151
|
|
|
|
|
|
|
# 4 => 'InitialFrames', |
|
1152
|
|
|
|
|
|
|
5 => [ |
|
1153
|
|
|
|
|
|
|
{ |
|
1154
|
|
|
|
|
|
|
Name => 'AudioSampleRate', |
|
1155
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "auds"', |
|
1156
|
|
|
|
|
|
|
Format => 'rational64u', |
|
1157
|
|
|
|
|
|
|
ValueConv => '$val ? 1/$val : 0', |
|
1158
|
|
|
|
|
|
|
PrintConv => 'int($val * 100 + 0.5) / 100', |
|
1159
|
|
|
|
|
|
|
}, |
|
1160
|
|
|
|
|
|
|
{ |
|
1161
|
|
|
|
|
|
|
Name => 'VideoFrameRate', |
|
1162
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "vids"', |
|
1163
|
|
|
|
|
|
|
Format => 'rational64u', |
|
1164
|
|
|
|
|
|
|
# (must use RawConv because raw value used in Composite tag) |
|
1165
|
|
|
|
|
|
|
RawConv => '$val ? 1/$val : undef', |
|
1166
|
|
|
|
|
|
|
PrintConv => 'int($val * 1000 + 0.5) / 1000', |
|
1167
|
|
|
|
|
|
|
}, |
|
1168
|
|
|
|
|
|
|
{ |
|
1169
|
|
|
|
|
|
|
Name => 'StreamSampleRate', |
|
1170
|
|
|
|
|
|
|
Format => 'rational64u', |
|
1171
|
|
|
|
|
|
|
ValueConv => '$val ? 1/$val : 0', |
|
1172
|
|
|
|
|
|
|
PrintConv => 'int($val * 1000 + 0.5) / 1000', |
|
1173
|
|
|
|
|
|
|
}, |
|
1174
|
|
|
|
|
|
|
], |
|
1175
|
|
|
|
|
|
|
# 7 => 'Start', |
|
1176
|
|
|
|
|
|
|
8 => [ |
|
1177
|
|
|
|
|
|
|
{ |
|
1178
|
|
|
|
|
|
|
Name => 'AudioSampleCount', |
|
1179
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "auds"', |
|
1180
|
|
|
|
|
|
|
}, |
|
1181
|
|
|
|
|
|
|
{ |
|
1182
|
|
|
|
|
|
|
Name => 'VideoFrameCount', |
|
1183
|
|
|
|
|
|
|
Condition => '$$self{RIFFStreamType} eq "vids"', |
|
1184
|
|
|
|
|
|
|
}, |
|
1185
|
|
|
|
|
|
|
{ |
|
1186
|
|
|
|
|
|
|
Name => 'StreamSampleCount', |
|
1187
|
|
|
|
|
|
|
}, |
|
1188
|
|
|
|
|
|
|
], |
|
1189
|
|
|
|
|
|
|
# 9 => 'SuggestedBufferSize', |
|
1190
|
|
|
|
|
|
|
10 => { |
|
1191
|
|
|
|
|
|
|
Name => 'Quality', |
|
1192
|
|
|
|
|
|
|
PrintConv => '$val eq 0xffffffff ? "Default" : $val', |
|
1193
|
|
|
|
|
|
|
}, |
|
1194
|
|
|
|
|
|
|
11 => { |
|
1195
|
|
|
|
|
|
|
Name => 'SampleSize', |
|
1196
|
|
|
|
|
|
|
PrintConv => '$val ? "$val byte" . ($val==1 ? "" : "s") : "Variable"', |
|
1197
|
|
|
|
|
|
|
}, |
|
1198
|
|
|
|
|
|
|
# 12 => { Name => 'Frame', Format => 'int16u[4]' }, |
|
1199
|
|
|
|
|
|
|
); |
|
1200
|
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::StreamData = ( #PH |
|
1202
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessStreamData, |
|
1203
|
|
|
|
|
|
|
GROUPS => { 2 => 'Video' }, |
|
1204
|
|
|
|
|
|
|
NOTES => q{ |
|
1205
|
|
|
|
|
|
|
This chunk is used to store proprietary information in AVI videos from some |
|
1206
|
|
|
|
|
|
|
cameras. The first 4 characters of the data are used as the Tag ID below. |
|
1207
|
|
|
|
|
|
|
}, |
|
1208
|
|
|
|
|
|
|
AVIF => { |
|
1209
|
|
|
|
|
|
|
Name => 'AVIF', |
|
1210
|
|
|
|
|
|
|
SubDirectory => { |
|
1211
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::Exif::Main', |
|
1212
|
|
|
|
|
|
|
DirName => 'IFD0', |
|
1213
|
|
|
|
|
|
|
Start => 8, |
|
1214
|
|
|
|
|
|
|
ByteOrder => 'LittleEndian', |
|
1215
|
|
|
|
|
|
|
}, |
|
1216
|
|
|
|
|
|
|
}, |
|
1217
|
|
|
|
|
|
|
CASI => { # (used by Casio GV-10) |
|
1218
|
|
|
|
|
|
|
Name => 'CasioData', |
|
1219
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::Casio::AVI' }, |
|
1220
|
|
|
|
|
|
|
}, |
|
1221
|
|
|
|
|
|
|
Zora => 'VendorName', # (Samsung PL90 AVI files) |
|
1222
|
|
|
|
|
|
|
unknown => { |
|
1223
|
|
|
|
|
|
|
Name => 'UnknownData', |
|
1224
|
|
|
|
|
|
|
# try to interpret unknown stream data as a string |
|
1225
|
|
|
|
|
|
|
RawConv => '$_=$val; /^[^\0-\x1f\x7f-\xff]+$/ ? $_ : undef', |
|
1226
|
|
|
|
|
|
|
}, |
|
1227
|
|
|
|
|
|
|
); |
|
1228
|
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
# VP8 bitstream (ref http://www.rfc-editor.org/rfc/pdfrfc/rfc6386.txt.pdf) |
|
1230
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::VP8 = ( |
|
1231
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1232
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
1233
|
|
|
|
|
|
|
NOTES => q{ |
|
1234
|
|
|
|
|
|
|
This chunk is found in simple-format (lossy) WebP files. See |
|
1235
|
|
|
|
|
|
|
L for the WebP |
|
1236
|
|
|
|
|
|
|
container specification. |
|
1237
|
|
|
|
|
|
|
}, |
|
1238
|
|
|
|
|
|
|
0 => { |
|
1239
|
|
|
|
|
|
|
Name => 'VP8Version', |
|
1240
|
|
|
|
|
|
|
Mask => 0x0e, |
|
1241
|
|
|
|
|
|
|
PrintConv => { |
|
1242
|
|
|
|
|
|
|
0 => '0 (bicubic reconstruction, normal loop)', |
|
1243
|
|
|
|
|
|
|
1 => '1 (bilinear reconstruction, simple loop)', |
|
1244
|
|
|
|
|
|
|
2 => '2 (bilinear reconstruction, no loop)', |
|
1245
|
|
|
|
|
|
|
3 => '3 (no reconstruction, no loop)', |
|
1246
|
|
|
|
|
|
|
}, |
|
1247
|
|
|
|
|
|
|
}, |
|
1248
|
|
|
|
|
|
|
6 => { |
|
1249
|
|
|
|
|
|
|
Name => 'ImageWidth', |
|
1250
|
|
|
|
|
|
|
Format => 'int16u', |
|
1251
|
|
|
|
|
|
|
Mask => 0x3fff, |
|
1252
|
|
|
|
|
|
|
}, |
|
1253
|
|
|
|
|
|
|
6.1 => { |
|
1254
|
|
|
|
|
|
|
Name => 'HorizontalScale', |
|
1255
|
|
|
|
|
|
|
Format => 'int16u', |
|
1256
|
|
|
|
|
|
|
Mask => 0xc000, |
|
1257
|
|
|
|
|
|
|
}, |
|
1258
|
|
|
|
|
|
|
8 => { |
|
1259
|
|
|
|
|
|
|
Name => 'ImageHeight', |
|
1260
|
|
|
|
|
|
|
Format => 'int16u', |
|
1261
|
|
|
|
|
|
|
Mask => 0x3fff, |
|
1262
|
|
|
|
|
|
|
}, |
|
1263
|
|
|
|
|
|
|
8.1 => { |
|
1264
|
|
|
|
|
|
|
Name => 'VerticalScale', |
|
1265
|
|
|
|
|
|
|
Format => 'int16u', |
|
1266
|
|
|
|
|
|
|
Mask => 0xc000, |
|
1267
|
|
|
|
|
|
|
}, |
|
1268
|
|
|
|
|
|
|
); |
|
1269
|
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
# WebP lossless info (ref 14) |
|
1271
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::VP8L = ( |
|
1272
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1273
|
|
|
|
|
|
|
NOTES => 'This chunk is found in lossless WebP files.', |
|
1274
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
1275
|
|
|
|
|
|
|
1 => { |
|
1276
|
|
|
|
|
|
|
Name => 'ImageWidth', |
|
1277
|
|
|
|
|
|
|
Format => 'int16u', |
|
1278
|
|
|
|
|
|
|
ValueConv => '($val & 0x3fff) + 1', |
|
1279
|
|
|
|
|
|
|
}, |
|
1280
|
|
|
|
|
|
|
2 => { |
|
1281
|
|
|
|
|
|
|
Name => 'ImageHeight', |
|
1282
|
|
|
|
|
|
|
Format => 'int32u', |
|
1283
|
|
|
|
|
|
|
ValueConv => '(($val >> 6) & 0x3fff) + 1', |
|
1284
|
|
|
|
|
|
|
}, |
|
1285
|
|
|
|
|
|
|
); |
|
1286
|
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
# WebP extended info (ref 14) |
|
1288
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::VP8X = ( |
|
1289
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1290
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
1291
|
|
|
|
|
|
|
NOTES => 'This chunk is found in extended WebP files.', |
|
1292
|
|
|
|
|
|
|
# 0 - bitmask: 2=ICC, 3=alpha, 4=EXIF, 5=XMP, 6=animation |
|
1293
|
|
|
|
|
|
|
4 => { |
|
1294
|
|
|
|
|
|
|
Name => 'ImageWidth', |
|
1295
|
|
|
|
|
|
|
Format => 'int32u', |
|
1296
|
|
|
|
|
|
|
ValueConv => '($val & 0xffffff) + 1', |
|
1297
|
|
|
|
|
|
|
}, |
|
1298
|
|
|
|
|
|
|
6 => { |
|
1299
|
|
|
|
|
|
|
Name => 'ImageHeight', |
|
1300
|
|
|
|
|
|
|
Format => 'int32u', |
|
1301
|
|
|
|
|
|
|
ValueConv => '($val >> 8) + 1', |
|
1302
|
|
|
|
|
|
|
}, |
|
1303
|
|
|
|
|
|
|
); |
|
1304
|
|
|
|
|
|
|
|
|
1305
|
|
|
|
|
|
|
# WebP animation info (ref 14) |
|
1306
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::ANIM = ( |
|
1307
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1308
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
1309
|
|
|
|
|
|
|
NOTES => 'WebP animation chunk.', |
|
1310
|
|
|
|
|
|
|
0 => { |
|
1311
|
|
|
|
|
|
|
Name => 'BackgroundColor', |
|
1312
|
|
|
|
|
|
|
Format => 'int8u[4]', |
|
1313
|
|
|
|
|
|
|
}, |
|
1314
|
|
|
|
|
|
|
4 => { |
|
1315
|
|
|
|
|
|
|
Name => 'AnimationLoopCount', |
|
1316
|
|
|
|
|
|
|
PrintConv => '$val || "inf"', |
|
1317
|
|
|
|
|
|
|
}, |
|
1318
|
|
|
|
|
|
|
); |
|
1319
|
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
# WebP animation frame info (ref 14) |
|
1321
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::ANMF = ( |
|
1322
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1323
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
1324
|
|
|
|
|
|
|
NOTES => 'WebP animation frame chunk.', |
|
1325
|
|
|
|
|
|
|
12 => { |
|
1326
|
|
|
|
|
|
|
Name => 'Duration', |
|
1327
|
|
|
|
|
|
|
Format => 'int32u', |
|
1328
|
|
|
|
|
|
|
Notes => 'extracted as the sum of durations of all animation frames', |
|
1329
|
|
|
|
|
|
|
RawConv => q{ |
|
1330
|
|
|
|
|
|
|
if (defined $$self{VALUE}{Duration}) { |
|
1331
|
|
|
|
|
|
|
$$self{VALUE}{Duration} += $val & 0x0fff; |
|
1332
|
|
|
|
|
|
|
return undef; |
|
1333
|
|
|
|
|
|
|
} |
|
1334
|
|
|
|
|
|
|
return $val & 0x0fff; |
|
1335
|
|
|
|
|
|
|
}, |
|
1336
|
|
|
|
|
|
|
ValueConv => '$val / 1000', |
|
1337
|
|
|
|
|
|
|
PrintConv => 'ConvertDuration($val)', |
|
1338
|
|
|
|
|
|
|
}, |
|
1339
|
|
|
|
|
|
|
); |
|
1340
|
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
# streamed USER txts written by Momento M6 dashcam (ref PH) |
|
1342
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::UserText = ( |
|
1343
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1344
|
|
|
|
|
|
|
GROUPS => { 2 => 'Location' }, |
|
1345
|
|
|
|
|
|
|
NOTES => q{ |
|
1346
|
|
|
|
|
|
|
Tags decoded from the USER-format txts stream written by Momento M6 dashcam. |
|
1347
|
|
|
|
|
|
|
Extracted only if the ExtractEmbedded option is used. |
|
1348
|
|
|
|
|
|
|
}, |
|
1349
|
|
|
|
|
|
|
# (little-endian) |
|
1350
|
|
|
|
|
|
|
# 0 - int32u: 32 |
|
1351
|
|
|
|
|
|
|
# 4 - int32u: sample number (starting from unknown offset) |
|
1352
|
|
|
|
|
|
|
# 8 - int8u[4]: "w x y z" ? (w 0=front cam, 1=rear cam, z mostly 5-8) |
|
1353
|
|
|
|
|
|
|
# 12 - int8u[4]: "0 x 1 0" ? (x incrementing once per second) |
|
1354
|
|
|
|
|
|
|
# 16 - int8u[4]: "0 32 0 x" ? |
|
1355
|
|
|
|
|
|
|
# 20 - int32u: 100-150(mostly), 250-300(once per second) |
|
1356
|
|
|
|
|
|
|
# 24 - int8u[4]: "0 x y 0" ? |
|
1357
|
|
|
|
|
|
|
28 => { Name => 'GPSAltitude', Format => 'int32u', ValueConv => '$val / 10' }, # (NC) |
|
1358
|
|
|
|
|
|
|
# 32 - int32u: 0(mostly), 23(once per second) |
|
1359
|
|
|
|
|
|
|
# 36 - int32u: 0 |
|
1360
|
|
|
|
|
|
|
40 => { Name => 'Accelerometer', Format => 'float[3]' }, |
|
1361
|
|
|
|
|
|
|
# 52 - int32u: 1 |
|
1362
|
|
|
|
|
|
|
56 => { Name => 'GPSSpeed', Format => 'float' }, # km/h |
|
1363
|
|
|
|
|
|
|
60 => { |
|
1364
|
|
|
|
|
|
|
Name => 'GPSLatitude', |
|
1365
|
|
|
|
|
|
|
Format => 'float', |
|
1366
|
|
|
|
|
|
|
# Note: these values are unsigned and I don't know where the hemisphere is stored, |
|
1367
|
|
|
|
|
|
|
# but my only sample is from the U.S., so assume a positive latitude (for now) |
|
1368
|
|
|
|
|
|
|
ValueConv => 'my $deg = int($val / 100); $deg + ($val - $deg * 100) / 60', |
|
1369
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")', |
|
1370
|
|
|
|
|
|
|
}, |
|
1371
|
|
|
|
|
|
|
64 => { |
|
1372
|
|
|
|
|
|
|
Name => 'GPSLongitude', |
|
1373
|
|
|
|
|
|
|
Format => 'float', |
|
1374
|
|
|
|
|
|
|
# Note: these values are unsigned and I don't know where the hemisphere is stored, |
|
1375
|
|
|
|
|
|
|
# but my only sample is from the U.S., so assume a negative longitude (for now) |
|
1376
|
|
|
|
|
|
|
ValueConv => 'my $deg = int($val / 100); -($deg + ($val - $deg * 100) / 60)', |
|
1377
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")', |
|
1378
|
|
|
|
|
|
|
}, |
|
1379
|
|
|
|
|
|
|
68 => { |
|
1380
|
|
|
|
|
|
|
Name => 'GPSDateTime', |
|
1381
|
|
|
|
|
|
|
Description => 'GPS Date/Time', |
|
1382
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
|
1383
|
|
|
|
|
|
|
Format => 'int32u', |
|
1384
|
|
|
|
|
|
|
ValueConv => 'ConvertUnixTime($val)', |
|
1385
|
|
|
|
|
|
|
# (likely local time, but clock seemed off by 3 hours in my sample) |
|
1386
|
|
|
|
|
|
|
PrintConv => '$self->ConvertDateTime($val)', |
|
1387
|
|
|
|
|
|
|
}, |
|
1388
|
|
|
|
|
|
|
); |
|
1389
|
|
|
|
|
|
|
|
|
1390
|
|
|
|
|
|
|
# WebP alpha info (ref 14) |
|
1391
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::ALPH = ( |
|
1392
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
|
1393
|
|
|
|
|
|
|
GROUPS => { 2 => 'Image' }, |
|
1394
|
|
|
|
|
|
|
NOTES => 'WebP alpha chunk.', |
|
1395
|
|
|
|
|
|
|
0 => { |
|
1396
|
|
|
|
|
|
|
Name => 'AlphaPreprocessing', |
|
1397
|
|
|
|
|
|
|
Mask => 0x03, |
|
1398
|
|
|
|
|
|
|
PrintConv => { |
|
1399
|
|
|
|
|
|
|
0 => 'none', |
|
1400
|
|
|
|
|
|
|
1 => 'Level Reduction', |
|
1401
|
|
|
|
|
|
|
}, |
|
1402
|
|
|
|
|
|
|
}, |
|
1403
|
|
|
|
|
|
|
0.1 => { |
|
1404
|
|
|
|
|
|
|
Name => 'AlphaFiltering', |
|
1405
|
|
|
|
|
|
|
Mask => 0x03, |
|
1406
|
|
|
|
|
|
|
PrintConv => { |
|
1407
|
|
|
|
|
|
|
0 => 'none', |
|
1408
|
|
|
|
|
|
|
1 => 'Horizontal', |
|
1409
|
|
|
|
|
|
|
2 => 'Vertical', |
|
1410
|
|
|
|
|
|
|
3 => 'Gradient', |
|
1411
|
|
|
|
|
|
|
}, |
|
1412
|
|
|
|
|
|
|
}, |
|
1413
|
|
|
|
|
|
|
0.2 => { |
|
1414
|
|
|
|
|
|
|
Name => 'AlphaCompression', |
|
1415
|
|
|
|
|
|
|
Mask => 0x03, |
|
1416
|
|
|
|
|
|
|
PrintConv => { |
|
1417
|
|
|
|
|
|
|
0 => 'none', |
|
1418
|
|
|
|
|
|
|
1 => 'Lossless', |
|
1419
|
|
|
|
|
|
|
}, |
|
1420
|
|
|
|
|
|
|
}, |
|
1421
|
|
|
|
|
|
|
); |
|
1422
|
|
|
|
|
|
|
|
|
1423
|
|
|
|
|
|
|
# RIFF composite tags |
|
1424
|
|
|
|
|
|
|
%Image::ExifTool::RIFF::Composite = ( |
|
1425
|
|
|
|
|
|
|
Duration => { |
|
1426
|
|
|
|
|
|
|
Require => { |
|
1427
|
|
|
|
|
|
|
0 => 'RIFF:FrameRate', |
|
1428
|
|
|
|
|
|
|
1 => 'RIFF:FrameCount', |
|
1429
|
|
|
|
|
|
|
}, |
|
1430
|
|
|
|
|
|
|
Desire => { |
|
1431
|
|
|
|
|
|
|
2 => 'VideoFrameRate', |
|
1432
|
|
|
|
|
|
|
3 => 'VideoFrameCount', |
|
1433
|
|
|
|
|
|
|
}, |
|
1434
|
|
|
|
|
|
|
RawConv => 'Image::ExifTool::RIFF::CalcDuration($self, @val)', |
|
1435
|
|
|
|
|
|
|
PrintConv => 'ConvertDuration($val)', |
|
1436
|
|
|
|
|
|
|
}, |
|
1437
|
|
|
|
|
|
|
Duration2 => { |
|
1438
|
|
|
|
|
|
|
Name => 'Duration', |
|
1439
|
|
|
|
|
|
|
Require => { |
|
1440
|
|
|
|
|
|
|
0 => 'RIFF:AvgBytesPerSec', |
|
1441
|
|
|
|
|
|
|
1 => 'FileSize', |
|
1442
|
|
|
|
|
|
|
}, |
|
1443
|
|
|
|
|
|
|
Desire => { |
|
1444
|
|
|
|
|
|
|
# check FrameCount because this calculation only applies |
|
1445
|
|
|
|
|
|
|
# to audio-only files (eg. WAV) |
|
1446
|
|
|
|
|
|
|
2 => 'FrameCount', |
|
1447
|
|
|
|
|
|
|
3 => 'VideoFrameCount', |
|
1448
|
|
|
|
|
|
|
}, |
|
1449
|
|
|
|
|
|
|
# (can't calculate duration like this for compressed audio types) |
|
1450
|
|
|
|
|
|
|
RawConv => q{ |
|
1451
|
|
|
|
|
|
|
return undef if $$self{VALUE}{FileType} =~ /^(LA|OFR|PAC|WV)$/; |
|
1452
|
|
|
|
|
|
|
return(($val[0] and not ($val[2] or $val[3])) ? $val[1] / $val[0] : undef); |
|
1453
|
|
|
|
|
|
|
}, |
|
1454
|
|
|
|
|
|
|
PrintConv => 'ConvertDuration($val)', |
|
1455
|
|
|
|
|
|
|
}, |
|
1456
|
|
|
|
|
|
|
); |
|
1457
|
|
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
# add our composite tags |
|
1459
|
|
|
|
|
|
|
Image::ExifTool::AddCompositeTags('Image::ExifTool::RIFF'); |
|
1460
|
|
|
|
|
|
|
|
|
1461
|
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1463
|
|
|
|
|
|
|
# Convert RIFF date to EXIF format |
|
1464
|
|
|
|
|
|
|
my %monthNum = ( |
|
1465
|
|
|
|
|
|
|
Jan=>1, Feb=>2, Mar=>3, Apr=>4, May=>5, Jun=>6, |
|
1466
|
|
|
|
|
|
|
Jul=>7, Aug=>8, Sep=>9, Oct=>10,Nov=>11,Dec=>12 |
|
1467
|
|
|
|
|
|
|
); |
|
1468
|
|
|
|
|
|
|
sub ConvertRIFFDate($) |
|
1469
|
|
|
|
|
|
|
{ |
|
1470
|
2
|
|
|
2
|
0
|
5
|
my $val = shift; |
|
1471
|
2
|
|
|
|
|
9
|
my @part = split ' ', $val; |
|
1472
|
2
|
|
|
|
|
4
|
my $mon; |
|
1473
|
2
|
100
|
66
|
|
|
21
|
if (@part >= 5 and $mon = $monthNum{ucfirst(lc($part[1]))}) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1474
|
|
|
|
|
|
|
# the standard AVI date format (eg. "Mon Mar 10 15:04:43 2003") |
|
1475
|
1
|
|
|
|
|
7
|
$val = sprintf("%.4d:%.2d:%.2d %s", $part[4], |
|
1476
|
|
|
|
|
|
|
$mon, $part[2], $part[3]); |
|
1477
|
|
|
|
|
|
|
} elsif ($val =~ m{(\d{4})/\s*(\d+)/\s*(\d+)/?\s+(\d+):\s*(\d+)\s*(P?)}) { |
|
1478
|
|
|
|
|
|
|
# but the Casio QV-3EX writes dates like "2001/ 1/27 1:42PM", |
|
1479
|
|
|
|
|
|
|
# and the Casio EX-Z30 writes "2005/11/28/ 09:19"... doh! |
|
1480
|
1
|
50
|
|
|
|
12
|
$val = sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00",$1,$2,$3,$4+($6?12:0),$5); |
|
1481
|
|
|
|
|
|
|
} elsif ($val =~ m{(\d{4})[-/](\d+)[-/](\d+)\s+(\d+:\d+:\d+)}) { |
|
1482
|
|
|
|
|
|
|
# the Konica KD500Z writes "2002-12-16 15:35:01\0\0" |
|
1483
|
0
|
|
|
|
|
0
|
$val = "$1:$2:$3 $4"; |
|
1484
|
|
|
|
|
|
|
} |
|
1485
|
2
|
|
|
|
|
15
|
return $val; |
|
1486
|
|
|
|
|
|
|
} |
|
1487
|
|
|
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1489
|
|
|
|
|
|
|
# Print time |
|
1490
|
|
|
|
|
|
|
# Inputs: 0) time in seconds |
|
1491
|
|
|
|
|
|
|
# Returns: time string |
|
1492
|
|
|
|
|
|
|
sub ConvertTimecode($) |
|
1493
|
|
|
|
|
|
|
{ |
|
1494
|
0
|
|
|
0
|
0
|
0
|
my $val = shift; |
|
1495
|
0
|
|
|
|
|
0
|
my $hr = int($val / 3600); |
|
1496
|
0
|
|
|
|
|
0
|
$val -= $hr * 3600; |
|
1497
|
0
|
|
|
|
|
0
|
my $min = int($val / 60); |
|
1498
|
0
|
|
|
|
|
0
|
$val -= $min * 60; |
|
1499
|
0
|
|
|
|
|
0
|
my $ss = sprintf('%05.2f', $val); |
|
1500
|
0
|
0
|
|
|
|
0
|
if ($ss >= 60) { # handle round-off problems |
|
1501
|
0
|
|
|
|
|
0
|
$ss = '00.00'; |
|
1502
|
0
|
0
|
|
|
|
0
|
++$min >= 60 and $min -= 60, ++$hr; |
|
1503
|
|
|
|
|
|
|
} |
|
1504
|
0
|
|
|
|
|
0
|
return sprintf('%d:%.2d:%s', $hr, $min, $ss); |
|
1505
|
|
|
|
|
|
|
} |
|
1506
|
|
|
|
|
|
|
|
|
1507
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1508
|
|
|
|
|
|
|
# Calculate duration of RIFF |
|
1509
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1/2) RIFF:FrameRate/Count, 2/3) VideoFrameRate/Count |
|
1510
|
|
|
|
|
|
|
# Returns: Duration in seconds or undef |
|
1511
|
|
|
|
|
|
|
# Notes: Sums duration of all sub-documents (concatenated AVI files) |
|
1512
|
|
|
|
|
|
|
sub CalcDuration($@) |
|
1513
|
|
|
|
|
|
|
{ |
|
1514
|
2
|
|
|
2
|
0
|
9
|
my ($et, @val) = @_; |
|
1515
|
2
|
|
|
|
|
5
|
my $totalDuration = 0; |
|
1516
|
2
|
|
|
|
|
4
|
my $subDoc = 0; |
|
1517
|
2
|
|
|
|
|
4
|
my @keyList; |
|
1518
|
2
|
|
|
|
|
3
|
for (;;) { |
|
1519
|
|
|
|
|
|
|
# this is annoying. Apparently (although I couldn't verify this), FrameCount |
|
1520
|
|
|
|
|
|
|
# in the RIFF header includes multiple video tracks if they exist (eg. with the |
|
1521
|
|
|
|
|
|
|
# FujiFilm REAL 3D AVI's), but the video stream information isn't reliable for |
|
1522
|
|
|
|
|
|
|
# some cameras (eg. Olympus FE models), so use the video stream information |
|
1523
|
|
|
|
|
|
|
# only if the RIFF header duration is 2 to 3 times longer |
|
1524
|
2
|
|
|
|
|
4
|
my $dur1; |
|
1525
|
2
|
50
|
|
|
|
10
|
$dur1 = $val[1] / $val[0] if $val[0]; |
|
1526
|
2
|
50
|
33
|
|
|
13
|
if ($val[2] and $val[3]) { |
|
1527
|
2
|
|
|
|
|
5
|
my $dur2 = $val[3] / $val[2]; |
|
1528
|
2
|
|
|
|
|
5
|
my $rat = $dur1 / $dur2; |
|
1529
|
2
|
50
|
33
|
|
|
16
|
$dur1 = $dur2 if $rat > 1.9 and $rat < 3.1; |
|
1530
|
|
|
|
|
|
|
} |
|
1531
|
2
|
50
|
|
|
|
8
|
$totalDuration += $dur1 if defined $dur1; |
|
1532
|
2
|
50
|
|
|
|
28
|
last unless $subDoc++ < $$et{DOC_COUNT}; |
|
1533
|
|
|
|
|
|
|
# get tag values for next sub-document |
|
1534
|
0
|
|
|
|
|
0
|
my @tags = qw(FrameRate FrameCount VideoFrameRate VideoFrameCount); |
|
1535
|
0
|
|
|
|
|
0
|
my $rawValue = $$et{VALUE}; |
|
1536
|
0
|
|
|
|
|
0
|
my ($i, $j, $key, $keys); |
|
1537
|
0
|
|
|
|
|
0
|
for ($i=0; $i<@tags; ++$i) { |
|
1538
|
0
|
0
|
|
|
|
0
|
if ($subDoc == 1) { |
|
1539
|
|
|
|
|
|
|
# generate list of available keys for each tag |
|
1540
|
0
|
|
|
|
|
0
|
$keys = $keyList[$i] = [ ]; |
|
1541
|
0
|
|
|
|
|
0
|
for ($j=0; ; ++$j) { |
|
1542
|
0
|
|
|
|
|
0
|
$key = $tags[$i]; |
|
1543
|
0
|
0
|
|
|
|
0
|
$key .= " ($j)" if $j; |
|
1544
|
0
|
0
|
|
|
|
0
|
last unless defined $$rawValue{$key}; |
|
1545
|
0
|
|
|
|
|
0
|
push @$keys, $key; |
|
1546
|
|
|
|
|
|
|
} |
|
1547
|
|
|
|
|
|
|
} else { |
|
1548
|
0
|
|
|
|
|
0
|
$keys = $keyList[$i]; |
|
1549
|
|
|
|
|
|
|
} |
|
1550
|
|
|
|
|
|
|
# find key for tag in this sub-document |
|
1551
|
0
|
|
|
|
|
0
|
my $grp = "Doc$subDoc"; |
|
1552
|
0
|
0
|
|
|
|
0
|
$grp .= ":RIFF" if $i < 2; # (tags 0 and 1 also in RIFF group) |
|
1553
|
0
|
|
|
|
|
0
|
$key = $et->GroupMatches($grp, $keys); |
|
1554
|
0
|
0
|
|
|
|
0
|
$val[$i] = $key ? $$rawValue{$key} : undef; |
|
1555
|
|
|
|
|
|
|
} |
|
1556
|
0
|
0
|
0
|
|
|
0
|
last unless defined $val[0] and defined $val[1]; # (Require'd tags) |
|
1557
|
|
|
|
|
|
|
} |
|
1558
|
2
|
|
|
|
|
19
|
return $totalDuration; |
|
1559
|
|
|
|
|
|
|
} |
|
1560
|
|
|
|
|
|
|
|
|
1561
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1562
|
|
|
|
|
|
|
# Process stream data |
|
1563
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo reference, 2) tag table ref |
|
1564
|
|
|
|
|
|
|
# Returns: 1 on success |
|
1565
|
|
|
|
|
|
|
sub ProcessStreamData($$$) |
|
1566
|
|
|
|
|
|
|
{ |
|
1567
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTbl) = @_; |
|
1568
|
0
|
|
|
|
|
0
|
my $dataPt = $$dirInfo{DataPt}; |
|
1569
|
0
|
|
|
|
|
0
|
my $start = $$dirInfo{DirStart}; |
|
1570
|
0
|
|
|
|
|
0
|
my $size = $$dirInfo{DirLen}; |
|
1571
|
0
|
0
|
|
|
|
0
|
return 0 if $size < 4; |
|
1572
|
0
|
0
|
|
|
|
0
|
if ($et->Options('Verbose')) { |
|
1573
|
0
|
|
|
|
|
0
|
$et->VerboseDir($$dirInfo{DirName}, 0, $size); |
|
1574
|
|
|
|
|
|
|
} |
|
1575
|
0
|
|
|
|
|
0
|
my $tag = substr($$dataPt, $start, 4); |
|
1576
|
0
|
|
|
|
|
0
|
my $tagInfo = $et->GetTagInfo($tagTbl, $tag); |
|
1577
|
0
|
0
|
|
|
|
0
|
unless ($tagInfo) { |
|
1578
|
0
|
|
|
|
|
0
|
$tagInfo = $et->GetTagInfo($tagTbl, 'unknown'); |
|
1579
|
0
|
0
|
|
|
|
0
|
return 1 unless $tagInfo; |
|
1580
|
|
|
|
|
|
|
} |
|
1581
|
0
|
|
|
|
|
0
|
my $subdir = $$tagInfo{SubDirectory}; |
|
1582
|
0
|
0
|
|
|
|
0
|
if ($$tagInfo{SubDirectory}) { |
|
1583
|
0
|
|
0
|
|
|
0
|
my $offset = $$subdir{Start} || 0; |
|
1584
|
0
|
|
|
|
|
0
|
my $baseShift = $$dirInfo{DataPos} + $$dirInfo{DirStart} + $offset; |
|
1585
|
|
|
|
|
|
|
my %subdirInfo = ( |
|
1586
|
|
|
|
|
|
|
DataPt => $dataPt, |
|
1587
|
|
|
|
|
|
|
DataPos => $$dirInfo{DataPos} - $baseShift, |
|
1588
|
|
|
|
|
|
|
Base => ($$dirInfo{Base} || 0) + $baseShift, |
|
1589
|
|
|
|
|
|
|
DataLen => $$dirInfo{DataLen}, |
|
1590
|
|
|
|
|
|
|
DirStart=> $$dirInfo{DirStart} + $offset, |
|
1591
|
|
|
|
|
|
|
DirLen => $$dirInfo{DirLen} - $offset, |
|
1592
|
|
|
|
|
|
|
DirName => $$subdir{DirName}, |
|
1593
|
|
|
|
|
|
|
Parent => $$dirInfo{DirName}, |
|
1594
|
0
|
|
0
|
|
|
0
|
); |
|
1595
|
0
|
0
|
|
|
|
0
|
unless ($offset) { |
|
1596
|
|
|
|
|
|
|
# allow processing of 2nd directory at the same address |
|
1597
|
0
|
|
|
|
|
0
|
my $addr = $subdirInfo{DirStart} + $subdirInfo{DataPos} + $subdirInfo{Base}; |
|
1598
|
0
|
|
|
|
|
0
|
delete $$et{PROCESSED}{$addr} |
|
1599
|
|
|
|
|
|
|
} |
|
1600
|
|
|
|
|
|
|
# (we could set FIRST_EXIF_POS to $subdirInfo{Base} here to make |
|
1601
|
|
|
|
|
|
|
# htmlDump offsets relative to EXIF base if we wanted...) |
|
1602
|
0
|
|
|
|
|
0
|
my $subTable = GetTagTable($$subdir{TagTable}); |
|
1603
|
0
|
|
|
|
|
0
|
$et->ProcessDirectory(\%subdirInfo, $subTable); |
|
1604
|
|
|
|
|
|
|
} else { |
|
1605
|
|
|
|
|
|
|
$et->HandleTag($tagTbl, $tag, undef, |
|
1606
|
|
|
|
|
|
|
DataPt => $dataPt, |
|
1607
|
|
|
|
|
|
|
DataPos => $$dirInfo{DataPos}, |
|
1608
|
0
|
|
|
|
|
0
|
Start => $start, |
|
1609
|
|
|
|
|
|
|
Size => $size, |
|
1610
|
|
|
|
|
|
|
TagInfo => $tagInfo, |
|
1611
|
|
|
|
|
|
|
); |
|
1612
|
|
|
|
|
|
|
} |
|
1613
|
0
|
|
|
|
|
0
|
return 1; |
|
1614
|
|
|
|
|
|
|
} |
|
1615
|
|
|
|
|
|
|
|
|
1616
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1617
|
|
|
|
|
|
|
# Make tag information hash for unknown tag |
|
1618
|
|
|
|
|
|
|
# Inputs: 0) Tag table ref, 1) tag ID |
|
1619
|
|
|
|
|
|
|
sub MakeTagInfo($$) |
|
1620
|
|
|
|
|
|
|
{ |
|
1621
|
0
|
|
|
0
|
0
|
0
|
my ($tagTbl, $tag) = @_; |
|
1622
|
0
|
|
|
|
|
0
|
my $name = $tag; |
|
1623
|
0
|
|
|
|
|
0
|
my $n = ($name =~ s/([\x00-\x1f\x7f-\xff])/'x'.unpack('H*',$1)/eg); |
|
|
0
|
|
|
|
|
0
|
|
|
1624
|
|
|
|
|
|
|
# print in hex if tag is numerical |
|
1625
|
0
|
0
|
|
|
|
0
|
$name = sprintf('0x%.4x',unpack('N',$tag)) if $n > 2; |
|
1626
|
0
|
|
|
|
|
0
|
AddTagToTable($tagTbl, $tag, { |
|
1627
|
|
|
|
|
|
|
Name => "Unknown_$name", |
|
1628
|
|
|
|
|
|
|
Description => "Unknown $name", |
|
1629
|
|
|
|
|
|
|
Unknown => 1, |
|
1630
|
|
|
|
|
|
|
Binary => 1, |
|
1631
|
|
|
|
|
|
|
}); |
|
1632
|
|
|
|
|
|
|
} |
|
1633
|
|
|
|
|
|
|
|
|
1634
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1635
|
|
|
|
|
|
|
# Process RIFF chunks |
|
1636
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref |
|
1637
|
|
|
|
|
|
|
# Returns: 1 on success |
|
1638
|
|
|
|
|
|
|
sub ProcessChunks($$$) |
|
1639
|
|
|
|
|
|
|
{ |
|
1640
|
13
|
|
|
13
|
0
|
30
|
my ($et, $dirInfo, $tagTbl) = @_; |
|
1641
|
13
|
|
|
|
|
28
|
my $dataPt = $$dirInfo{DataPt}; |
|
1642
|
13
|
|
|
|
|
18
|
my $start = $$dirInfo{DirStart}; |
|
1643
|
13
|
|
|
|
|
28
|
my $size = $$dirInfo{DirLen}; |
|
1644
|
13
|
|
|
|
|
18
|
my $end = $start + $size; |
|
1645
|
13
|
|
|
|
|
18
|
my $base = $$dirInfo{Base}; |
|
1646
|
13
|
|
|
|
|
43
|
my $verbose = $et->Options('Verbose'); |
|
1647
|
13
|
|
|
|
|
39
|
my $unknown = $et->Options('Unknown'); |
|
1648
|
13
|
|
|
|
|
29
|
my $charset = $et->Options('CharsetRIFF'); |
|
1649
|
|
|
|
|
|
|
|
|
1650
|
13
|
50
|
|
|
|
31
|
unless ($charset) { |
|
1651
|
13
|
50
|
33
|
|
|
72
|
if ($$et{CodePage}) { |
|
|
|
50
|
|
|
|
|
|
|
1652
|
0
|
|
|
|
|
0
|
$charset = $$et{CodePage}; |
|
1653
|
|
|
|
|
|
|
} elsif (defined $charset and $charset eq '0') { |
|
1654
|
13
|
|
|
|
|
24
|
$charset = 'Latin'; |
|
1655
|
|
|
|
|
|
|
} |
|
1656
|
|
|
|
|
|
|
} |
|
1657
|
|
|
|
|
|
|
|
|
1658
|
13
|
50
|
|
|
|
34
|
$et->VerboseDir($$dirInfo{DirName}, 0, $size) if $verbose; |
|
1659
|
|
|
|
|
|
|
|
|
1660
|
13
|
|
|
|
|
33
|
while ($start + 8 < $end) { |
|
1661
|
34
|
|
|
|
|
64
|
my $tag = substr($$dataPt, $start, 4); |
|
1662
|
34
|
|
|
|
|
77
|
my $len = Get32u($dataPt, $start + 4); |
|
1663
|
34
|
|
|
|
|
67
|
$start += 8; |
|
1664
|
34
|
50
|
|
|
|
74
|
if ($start + $len > $end) { |
|
1665
|
0
|
|
|
|
|
0
|
$et->Warn("Bad $tag chunk"); |
|
1666
|
0
|
|
|
|
|
0
|
return 0; |
|
1667
|
|
|
|
|
|
|
} |
|
1668
|
34
|
100
|
66
|
|
|
184
|
if ($tag eq 'LIST' and $len >= 4) { |
|
1669
|
5
|
|
|
|
|
14
|
$tag .= '_' . substr($$dataPt, $start, 4); |
|
1670
|
5
|
|
|
|
|
8
|
$len -= 4; |
|
1671
|
5
|
|
|
|
|
9
|
$start += 4; |
|
1672
|
|
|
|
|
|
|
} |
|
1673
|
34
|
|
|
|
|
79
|
my $tagInfo = $et->GetTagInfo($tagTbl, $tag); |
|
1674
|
34
|
|
|
|
|
50
|
my $baseShift = 0; |
|
1675
|
34
|
|
|
|
|
38
|
my $val; |
|
1676
|
34
|
100
|
33
|
|
|
71
|
if ($tagInfo) { |
|
|
|
50
|
|
|
|
|
|
|
1677
|
28
|
100
|
|
|
|
71
|
if ($$tagInfo{SubDirectory}) { |
|
|
|
100
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
# adjust base if necessary (needed for Ricoh maker notes) |
|
1679
|
17
|
|
|
|
|
30
|
my $newBase = $tagInfo->{SubDirectory}{Base}; |
|
1680
|
17
|
100
|
|
|
|
38
|
if (defined $newBase) { |
|
1681
|
|
|
|
|
|
|
# different than your average Base eval... |
|
1682
|
|
|
|
|
|
|
# here we use an absolute $start address |
|
1683
|
1
|
|
|
|
|
2
|
$start += $base; |
|
1684
|
|
|
|
|
|
|
#### eval Base ($start) |
|
1685
|
1
|
|
|
|
|
61
|
$newBase = eval $newBase; |
|
1686
|
1
|
|
|
|
|
3
|
$baseShift = $newBase - $base; |
|
1687
|
1
|
|
|
|
|
2
|
$start -= $base; |
|
1688
|
|
|
|
|
|
|
} |
|
1689
|
|
|
|
|
|
|
} elsif (not $$tagInfo{Binary}) { |
|
1690
|
10
|
|
66
|
|
|
36
|
my $format = $$tagInfo{Format} || $$tagTbl{FORMAT}; |
|
1691
|
10
|
100
|
66
|
|
|
30
|
if ($format and $format eq 'string') { |
|
1692
|
3
|
|
|
|
|
9
|
$val = substr($$dataPt, $start, $len); |
|
1693
|
3
|
|
|
|
|
20
|
$val =~ s/\0+$//; # remove trailing nulls from strings |
|
1694
|
|
|
|
|
|
|
# decode if necessary |
|
1695
|
3
|
50
|
|
|
|
14
|
$val = $et->Decode($val, $charset) if $charset; |
|
1696
|
|
|
|
|
|
|
} |
|
1697
|
|
|
|
|
|
|
} |
|
1698
|
|
|
|
|
|
|
} elsif ($verbose or $unknown) { |
|
1699
|
0
|
|
|
|
|
0
|
MakeTagInfo($tagTbl, $tag); |
|
1700
|
|
|
|
|
|
|
} |
|
1701
|
|
|
|
|
|
|
$et->HandleTag($tagTbl, $tag, $val, |
|
1702
|
|
|
|
|
|
|
DataPt => $dataPt, |
|
1703
|
34
|
|
|
|
|
162
|
DataPos => $$dirInfo{DataPos} - $baseShift, |
|
1704
|
|
|
|
|
|
|
Start => $start, |
|
1705
|
|
|
|
|
|
|
Size => $len, |
|
1706
|
|
|
|
|
|
|
Base => $base + $baseShift, |
|
1707
|
|
|
|
|
|
|
Addr => $base + $baseShift + $start, |
|
1708
|
|
|
|
|
|
|
); |
|
1709
|
34
|
100
|
|
|
|
80
|
++$len if $len & 0x01; # must account for padding if odd number of bytes |
|
1710
|
34
|
|
|
|
|
88
|
$start += $len; |
|
1711
|
|
|
|
|
|
|
} |
|
1712
|
13
|
|
|
|
|
32
|
return 1; |
|
1713
|
|
|
|
|
|
|
} |
|
1714
|
|
|
|
|
|
|
|
|
1715
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1716
|
|
|
|
|
|
|
# Process BikeBro SGLT chunk (accelerometer data) (ref PH) |
|
1717
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref |
|
1718
|
|
|
|
|
|
|
# Returns: 1 on success |
|
1719
|
|
|
|
|
|
|
sub ProcessSGLT($$$) |
|
1720
|
|
|
|
|
|
|
{ |
|
1721
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTbl) = @_; |
|
1722
|
0
|
|
|
|
|
0
|
my $dataPt = $$dirInfo{DataPt}; |
|
1723
|
0
|
|
|
|
|
0
|
my $dataLen = length $$dataPt; |
|
1724
|
0
|
|
|
|
|
0
|
my $ee = $et->Options('ExtractEmbedded'); |
|
1725
|
0
|
|
|
|
|
0
|
my $pos; |
|
1726
|
|
|
|
|
|
|
# example accelerometer record: |
|
1727
|
|
|
|
|
|
|
# 0 1 2 3 4 5 6 7 |
|
1728
|
|
|
|
|
|
|
# 00 00 00 24 02 00 00 01 17 04 00 00 00 00 00 00 00 00 9b 02 |
|
1729
|
|
|
|
|
|
|
# frame------ ?? Xs X---------- Ys Y---------- Zs Z---------- |
|
1730
|
0
|
|
|
|
|
0
|
$$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF'; |
|
1731
|
0
|
|
|
|
|
0
|
for ($pos=0; $pos<=$dataLen-20; $pos+=20) { |
|
1732
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT}; |
|
1733
|
0
|
|
|
|
|
0
|
my $buff = substr($$dataPt, $pos); |
|
1734
|
0
|
|
|
|
|
0
|
my @a = unpack('NCCNCNCN', $buff); |
|
1735
|
0
|
0
|
|
|
|
0
|
my @acc = ($a[3]*($a[2]?-1:1)/1e5, $a[5]*($a[4]?-1:1)/1e5, $a[7]*($a[6]?-1:1)/1e5); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1736
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, FrameNumber => $a[0]); |
|
1737
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, Accelerometer => "@acc"); |
|
1738
|
0
|
0
|
|
|
|
0
|
unless ($ee) { |
|
1739
|
0
|
|
|
|
|
0
|
$et->Warn('Use ExtractEmbedded option to extract all accelerometer data', 3); |
|
1740
|
0
|
|
|
|
|
0
|
last; |
|
1741
|
|
|
|
|
|
|
} |
|
1742
|
|
|
|
|
|
|
} |
|
1743
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP0}; |
|
1744
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP1}; |
|
1745
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = 0; |
|
1746
|
0
|
|
|
|
|
0
|
return 0; |
|
1747
|
|
|
|
|
|
|
} |
|
1748
|
|
|
|
|
|
|
|
|
1749
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1750
|
|
|
|
|
|
|
# Process BikeBro SLLT chunk (GPS information) (ref PH) |
|
1751
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref |
|
1752
|
|
|
|
|
|
|
# Returns: 1 on success |
|
1753
|
|
|
|
|
|
|
sub ProcessSLLT($$$) |
|
1754
|
|
|
|
|
|
|
{ |
|
1755
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTbl) = @_; |
|
1756
|
0
|
|
|
|
|
0
|
my $dataPt = $$dirInfo{DataPt}; |
|
1757
|
0
|
|
|
|
|
0
|
my $dataLen = length $$dataPt; |
|
1758
|
0
|
|
|
|
|
0
|
my $ee = $et->Options('ExtractEmbedded'); |
|
1759
|
0
|
|
|
|
|
0
|
my $pos; |
|
1760
|
|
|
|
|
|
|
# example GPS record: |
|
1761
|
|
|
|
|
|
|
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1762
|
|
|
|
|
|
|
# 00 00 00 17 01 00 00 03 fa 21 ec 00 35 01 6e c0 06 00 08 00 62 10 0b 1b 07 e2 03 0e 57 4e |
|
1763
|
|
|
|
|
|
|
# frame------ ?? lonDD lonDDDDDDDD latDD latDDDDDDDD alt-- spd-- hr mn sc yr--- mn dy EW NS |
|
1764
|
0
|
|
|
|
|
0
|
$$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF'; |
|
1765
|
0
|
|
|
|
|
0
|
for ($pos=0; $pos<=$dataLen-30; $pos+=30) { |
|
1766
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT}; |
|
1767
|
0
|
|
|
|
|
0
|
my $buff = substr($$dataPt, $pos); |
|
1768
|
0
|
|
|
|
|
0
|
my @a = unpack('NCnNnNnnCCCnCCaa', $buff); |
|
1769
|
|
|
|
|
|
|
# - is $a[1] perhaps GPSStatus? (only seen 1, or perhaps record type 1=GPS, 2=acc?) |
|
1770
|
0
|
|
|
|
|
0
|
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', @a[11..13, 8..10]); |
|
1771
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, FrameNumber => $a[0]); |
|
1772
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSDateTime => $time); |
|
1773
|
0
|
0
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSLatitude => ($a[4] + $a[5]/1e8) * ($a[15] eq 'S' ? -1 : 1)); |
|
1774
|
0
|
0
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSLongitude => ($a[2] + $a[3]/1e8) * ($a[14] eq 'W' ? -1 : 1)); |
|
1775
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSAltitude => $a[6]); |
|
1776
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSSpeed => $a[7]); |
|
1777
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSSpeedRef => 'K'); |
|
1778
|
0
|
0
|
|
|
|
0
|
unless ($ee) { |
|
1779
|
0
|
|
|
|
|
0
|
$et->Warn('Use ExtractEmbedded option to extract timed GPS', 3); |
|
1780
|
0
|
|
|
|
|
0
|
last; |
|
1781
|
|
|
|
|
|
|
} |
|
1782
|
|
|
|
|
|
|
} |
|
1783
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP0}; |
|
1784
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP1}; |
|
1785
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = 0; |
|
1786
|
0
|
|
|
|
|
0
|
return 1; |
|
1787
|
|
|
|
|
|
|
} |
|
1788
|
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1790
|
|
|
|
|
|
|
# Process Lucas streaming GPS information (Lucas LK-7900 Ace) (ref PH) |
|
1791
|
|
|
|
|
|
|
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref |
|
1792
|
|
|
|
|
|
|
# Returns: 1 on success |
|
1793
|
|
|
|
|
|
|
sub ProcessLucas($$$) |
|
1794
|
|
|
|
|
|
|
{ |
|
1795
|
0
|
|
|
0
|
0
|
0
|
my ($et, $dirInfo, $tagTbl) = @_; |
|
1796
|
0
|
|
|
|
|
0
|
my $dataPt = $$dirInfo{DataPt}; |
|
1797
|
0
|
|
|
|
|
0
|
my $dataLen = length $$dataPt; |
|
1798
|
|
|
|
|
|
|
|
|
1799
|
0
|
0
|
|
|
|
0
|
unless ($et->Options('ExtractEmbedded')) { |
|
1800
|
0
|
|
|
|
|
0
|
$et->Warn('Use ExtractEmbedded option to extract timed GPS', 3); |
|
1801
|
0
|
|
|
|
|
0
|
return 1; |
|
1802
|
|
|
|
|
|
|
} |
|
1803
|
0
|
|
|
|
|
0
|
my %recLen = ( # record lengths (not including 4-byte ID) |
|
1804
|
|
|
|
|
|
|
'0GDA' => 24, |
|
1805
|
|
|
|
|
|
|
'0GPS' => 48, |
|
1806
|
|
|
|
|
|
|
); |
|
1807
|
0
|
|
|
|
|
0
|
my ($date,$time,$lat,$lon,$alt,$spd,$sat,$dop,$ew,$ns); |
|
1808
|
0
|
|
|
|
|
0
|
$$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF'; |
|
1809
|
0
|
|
|
|
|
0
|
while ($$dataPt =~ /(0GDA|0GPS)/g) { |
|
1810
|
0
|
|
|
|
|
0
|
my ($rec, $pos) = ($1, pos $$dataPt); |
|
1811
|
0
|
0
|
|
|
|
0
|
$pos + $recLen{$rec} > $dataLen and $et->Warn("Truncated $1 record"), last; |
|
1812
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT}; |
|
1813
|
|
|
|
|
|
|
# records start with int64u sample date/time in ms since 1970 |
|
1814
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, SampleDateTime => Get64u($dataPt, $pos) / 1000); |
|
1815
|
0
|
0
|
|
|
|
0
|
if ($rec eq '0GPS') { |
|
1816
|
0
|
|
|
|
|
0
|
my $len = Get32u($dataPt, $pos+8); |
|
1817
|
0
|
|
|
|
|
0
|
my $endPos = $pos + $recLen{$rec} + $len; |
|
1818
|
0
|
0
|
|
|
|
0
|
$endPos > $dataLen and $et->Warn('Truncated 0GPS record'), last; |
|
1819
|
0
|
|
|
|
|
0
|
my $buff = substr($$dataPt, $pos+$recLen{$rec}, $len); |
|
1820
|
0
|
|
|
|
|
0
|
while ($buff =~ /\$(GC|GA),(\d+),/g) { |
|
1821
|
0
|
|
|
|
|
0
|
my $p = pos $buff; |
|
1822
|
0
|
|
|
|
|
0
|
$time = $2; |
|
1823
|
0
|
0
|
|
|
|
0
|
if ($1 eq 'GC') { |
|
1824
|
|
|
|
|
|
|
# time date dist ? sat dop alt A |
|
1825
|
|
|
|
|
|
|
# $GC,052350,180914,0000955,1,08,1.1,0017,,A*45\x0d\x0a\0 |
|
1826
|
0
|
0
|
|
|
|
0
|
if ($buff =~ /\G(\d+),\d*,\d*,(\d+),([-\d.]+),(\d+),\d*,A/g) { |
|
1827
|
0
|
|
|
|
|
0
|
($date,$sat,$dop,$alt) = ($1,$2,$3,$4); |
|
1828
|
|
|
|
|
|
|
} |
|
1829
|
|
|
|
|
|
|
} else { |
|
1830
|
|
|
|
|
|
|
# time A lat lon spd N W |
|
1831
|
|
|
|
|
|
|
# $GA,052351,A,0949.6626,07635.4439,049,N,E,*4C\x0d\x0a\0 |
|
1832
|
0
|
0
|
|
|
|
0
|
if ($buff =~ /\GA,([\d.]+),([\d.]+),(\d+),([NS]),([EW])/g) { |
|
1833
|
0
|
|
|
|
|
0
|
($lat,$lon,$spd,$ns,$ew) = ($1,$2,$3,$4,$5,$6); |
|
1834
|
|
|
|
|
|
|
# lat/long are in DDDMM.MMMM format |
|
1835
|
0
|
|
|
|
|
0
|
my $deg = int($lat / 100); |
|
1836
|
0
|
|
|
|
|
0
|
$lat = $deg + ($lat - $deg * 100) / 60; |
|
1837
|
0
|
|
|
|
|
0
|
$deg = int($lon / 100); |
|
1838
|
0
|
|
|
|
|
0
|
$lon = $deg + ($lon - $deg * 100) / 60; |
|
1839
|
0
|
0
|
|
|
|
0
|
$lat *= -1 if $ns eq 'S'; |
|
1840
|
0
|
0
|
|
|
|
0
|
$lon *= -1 if $ew eq 'W'; |
|
1841
|
|
|
|
|
|
|
} |
|
1842
|
|
|
|
|
|
|
} |
|
1843
|
|
|
|
|
|
|
# look ahead to next NMEA-like sentence, and store the fix |
|
1844
|
|
|
|
|
|
|
# now only if the next sentence is not at the same time |
|
1845
|
0
|
0
|
|
|
|
0
|
if ($buff !~ /\$(GC|GA),$time,/g) { |
|
1846
|
0
|
|
|
|
|
0
|
pos($$dataPt) = $endPos; |
|
1847
|
0
|
0
|
0
|
|
|
0
|
if ($$dataPt !~ /\$(GC|GA),(\d+)/ or $1 ne $time) { |
|
1848
|
0
|
|
|
|
|
0
|
$time =~ s/(\d{2})(\d{2})(\d{2})/$1:$2:$3Z/; |
|
1849
|
0
|
0
|
|
|
|
0
|
if ($date) { |
|
1850
|
0
|
|
|
|
|
0
|
$date =~ s/(\d{2})(\d{2})(\d{2})/20$3:$2:$1/; |
|
1851
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSDateTime => "$date $time"); |
|
1852
|
|
|
|
|
|
|
} else { |
|
1853
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSTimeStamp => $time); |
|
1854
|
|
|
|
|
|
|
} |
|
1855
|
0
|
0
|
|
|
|
0
|
if (defined $lat) { |
|
1856
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSLatitude => $lat); |
|
1857
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSLongitude => $lon); |
|
1858
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSSpeed => $spd); |
|
1859
|
|
|
|
|
|
|
} |
|
1860
|
0
|
0
|
|
|
|
0
|
if (defined $alt) { |
|
1861
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSAltitude => $alt); |
|
1862
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSSatellites => $sat); |
|
1863
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, GPSDOP => $dop); |
|
1864
|
|
|
|
|
|
|
} |
|
1865
|
0
|
|
|
|
|
0
|
undef $lat; |
|
1866
|
0
|
|
|
|
|
0
|
undef $alt; |
|
1867
|
|
|
|
|
|
|
} |
|
1868
|
|
|
|
|
|
|
} |
|
1869
|
0
|
|
|
|
|
0
|
pos($buff) = $p; |
|
1870
|
|
|
|
|
|
|
} |
|
1871
|
0
|
|
|
|
|
0
|
$pos += $len; |
|
1872
|
|
|
|
|
|
|
} else { # this is an accelerometer (0GDA) record |
|
1873
|
|
|
|
|
|
|
# record has 4 more int32s values (the last is always 57 or 58 -- |
|
1874
|
|
|
|
|
|
|
# maybe related to sample time in ms? -- not extracted) |
|
1875
|
0
|
|
|
|
|
0
|
my @acc = unpack('x'.($pos+8).'V3', $$dataPt); |
|
1876
|
|
|
|
|
|
|
# change to signed integer and divide by 256 |
|
1877
|
0
|
0
|
|
|
|
0
|
map { $_ = $_ - 4294967296 if $_ >= 0x80000000; $_ /= 256 } @acc; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
1878
|
0
|
|
|
|
|
0
|
$et->HandleTag($tagTbl, Accelerometer => "@acc"); |
|
1879
|
|
|
|
|
|
|
} |
|
1880
|
0
|
|
|
|
|
0
|
pos($$dataPt) = $pos + $recLen{$rec}; |
|
1881
|
|
|
|
|
|
|
} |
|
1882
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP0}; |
|
1883
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP1}; |
|
1884
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = 0; |
|
1885
|
0
|
|
|
|
|
0
|
return 1; |
|
1886
|
|
|
|
|
|
|
} |
|
1887
|
|
|
|
|
|
|
|
|
1888
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
|
1889
|
|
|
|
|
|
|
# Extract information from a RIFF file |
|
1890
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object reference, 1) DirInfo reference |
|
1891
|
|
|
|
|
|
|
# Returns: 1 on success, 0 if this wasn't a valid RIFF file |
|
1892
|
|
|
|
|
|
|
sub ProcessRIFF($$) |
|
1893
|
|
|
|
|
|
|
{ |
|
1894
|
4
|
|
|
4
|
0
|
10
|
my ($et, $dirInfo) = @_; |
|
1895
|
4
|
|
|
|
|
9
|
my $raf = $$dirInfo{RAF}; |
|
1896
|
4
|
|
|
|
|
7
|
my ($buff, $buf2, $type, $mime, $err, $rf64); |
|
1897
|
4
|
|
|
|
|
13
|
my $verbose = $et->Options('Verbose'); |
|
1898
|
4
|
|
|
|
|
9
|
my $unknown = $et->Options('Unknown'); |
|
1899
|
4
|
|
|
|
|
15
|
my $ee = $et->Options('ExtractEmbedded'); |
|
1900
|
|
|
|
|
|
|
|
|
1901
|
|
|
|
|
|
|
# verify this is a valid RIFF file |
|
1902
|
4
|
50
|
|
|
|
19
|
return 0 unless $raf->Read($buff, 12) == 12; |
|
1903
|
4
|
50
|
|
|
|
27
|
if ($buff =~ /^(RIFF|RF64)....(.{4})/s) { |
|
1904
|
4
|
|
|
|
|
15
|
$type = $riffType{$2}; |
|
1905
|
4
|
50
|
|
|
|
15
|
$rf64 = 1 if $1 eq 'RF64'; |
|
1906
|
|
|
|
|
|
|
} else { |
|
1907
|
|
|
|
|
|
|
# minimal support for a few obscure lossless audio formats... |
|
1908
|
0
|
0
|
0
|
|
|
0
|
return 0 unless $buff =~ /^(LA0[234]|OFR |LPAC|wvpk)/ and $raf->Read($buf2, 1024); |
|
1909
|
0
|
|
|
|
|
0
|
$type = $riffType{$1}; |
|
1910
|
0
|
|
|
|
|
0
|
$buff .= $buf2; |
|
1911
|
0
|
0
|
0
|
|
|
0
|
return 0 unless $buff =~ /WAVE(.{4})?fmt /sg and $raf->Seek(pos($buff) - 4, 0); |
|
1912
|
|
|
|
|
|
|
} |
|
1913
|
4
|
50
|
|
|
|
12
|
$$raf{NoBuffer} = 1 if $et->Options('FastScan'); # disable buffering in FastScan mode |
|
1914
|
4
|
50
|
|
|
|
14
|
$mime = $riffMimeType{$type} if $type; |
|
1915
|
4
|
|
|
|
|
30
|
$et->SetFileType($type, $mime); |
|
1916
|
4
|
50
|
|
|
|
10
|
$$et{VALUE}{FileType} .= ' (RF64)' if $rf64; |
|
1917
|
4
|
|
|
|
|
14
|
$$et{RIFFStreamType} = ''; # initialize stream type |
|
1918
|
4
|
|
|
|
|
8
|
$$et{RIFFStreamCodec} = []; # initialize codec array |
|
1919
|
4
|
|
|
|
|
14
|
SetByteOrder('II'); |
|
1920
|
4
|
|
|
|
|
10
|
my $tagTbl = GetTagTable('Image::ExifTool::RIFF::Main'); |
|
1921
|
4
|
|
|
|
|
9
|
my $pos = 12; |
|
1922
|
|
|
|
|
|
|
# |
|
1923
|
|
|
|
|
|
|
# Read chunks in RIFF image |
|
1924
|
|
|
|
|
|
|
# |
|
1925
|
4
|
|
|
|
|
7
|
for (;;) { |
|
1926
|
19
|
|
|
|
|
64
|
my $num = $raf->Read($buff, 8); |
|
1927
|
19
|
100
|
|
|
|
45
|
if ($num < 8) { |
|
1928
|
4
|
50
|
|
|
|
11
|
$err = 1 if $num; |
|
1929
|
4
|
|
|
|
|
8
|
last; |
|
1930
|
|
|
|
|
|
|
} |
|
1931
|
15
|
|
|
|
|
23
|
$pos += 8; |
|
1932
|
15
|
|
|
|
|
57
|
my ($tag, $len) = unpack('a4V', $buff); |
|
1933
|
|
|
|
|
|
|
# special case: construct new tag name from specific LIST type |
|
1934
|
15
|
100
|
66
|
|
|
49
|
if ($tag eq 'LIST') { |
|
|
|
50
|
33
|
|
|
|
|
|
1935
|
10
|
50
|
|
|
|
25
|
$raf->Read($buff, 4) == 4 or $err=1, last; |
|
1936
|
10
|
|
|
|
|
17
|
$pos += 4; |
|
1937
|
10
|
|
|
|
|
21
|
$tag .= "_$buff"; |
|
1938
|
10
|
|
|
|
|
19
|
$len -= 4; # already read 4 bytes (the LIST type) |
|
1939
|
|
|
|
|
|
|
} elsif ($tag eq 'data' and $len == 0xffffffff and $$et{DataSize64}) { |
|
1940
|
0
|
|
|
|
|
0
|
$len = $$et{DataSize64}; |
|
1941
|
|
|
|
|
|
|
} |
|
1942
|
15
|
|
|
|
|
72
|
$et->VPrint(0, "RIFF '${tag}' chunk ($len bytes of data):\n"); |
|
1943
|
15
|
100
|
|
|
|
36
|
if ($len <= 0) { |
|
1944
|
3
|
50
|
|
|
|
14
|
if ($len < 0) { |
|
|
|
50
|
|
|
|
|
|
|
1945
|
0
|
|
|
|
|
0
|
$et->Warn('Invalid chunk length'); |
|
1946
|
|
|
|
|
|
|
} elsif ($tag eq "\0\0\0\0") { |
|
1947
|
|
|
|
|
|
|
# avoid reading through corupted files filled with nulls because it takes forever |
|
1948
|
0
|
|
|
|
|
0
|
$et->Warn('Encountered empty null chunk. Processing aborted'); |
|
1949
|
|
|
|
|
|
|
} else { |
|
1950
|
3
|
|
|
|
|
5
|
next; |
|
1951
|
|
|
|
|
|
|
} |
|
1952
|
0
|
|
|
|
|
0
|
last; |
|
1953
|
|
|
|
|
|
|
} |
|
1954
|
|
|
|
|
|
|
# stop when we hit the audio data or AVI index or AVI movie data |
|
1955
|
|
|
|
|
|
|
# --> no more because Adobe Bridge stores XMP after this!! |
|
1956
|
|
|
|
|
|
|
# (so now we only do this on the FastScan option) |
|
1957
|
12
|
0
|
0
|
|
|
30
|
if ($et->Options('FastScan') and ($tag eq 'data' or $tag eq 'idx1' or |
|
|
|
|
33
|
|
|
|
|
|
1958
|
|
|
|
|
|
|
($tag eq 'LIST_movi' and not $ee))) |
|
1959
|
|
|
|
|
|
|
{ |
|
1960
|
0
|
|
|
|
|
0
|
$et->VPrint(0, "(end of parsing)\n"); |
|
1961
|
0
|
|
|
|
|
0
|
last; |
|
1962
|
|
|
|
|
|
|
} |
|
1963
|
|
|
|
|
|
|
# RIFF chunks are padded to an even number of bytes |
|
1964
|
12
|
|
|
|
|
26
|
my $len2 = $len + ($len & 0x01); |
|
1965
|
|
|
|
|
|
|
# change name of stream txts data depending on the Codec |
|
1966
|
12
|
50
|
33
|
|
|
31
|
if ($ee and $tag =~ /^(\d{2})tx$/) { |
|
1967
|
0
|
|
0
|
|
|
0
|
$tag = 'tx_' . ($$et{RIFFStreamCodec}[$1] || 'Unknown'); |
|
1968
|
0
|
0
|
|
|
|
0
|
$tag = "tx_Unknown" unless defined $$tagTbl{$tag}; |
|
1969
|
0
|
|
|
|
|
0
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT}; |
|
1970
|
|
|
|
|
|
|
} |
|
1971
|
12
|
|
|
|
|
28
|
my $tagInfo = $$tagTbl{$tag}; |
|
1972
|
12
|
50
|
0
|
|
|
32
|
if ($tagInfo or (($verbose or $unknown) and $tag !~ /^(data|idx1|LIST_movi|RIFF|\d{2}(db|dc|wb))$/)) { |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
33
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1973
|
12
|
50
|
|
|
|
28
|
$raf->Read($buff, $len2) == $len2 or $err=1, last; |
|
1974
|
12
|
|
|
|
|
19
|
my $setGroups; |
|
1975
|
12
|
50
|
66
|
|
|
70
|
if ($tagInfo and ref $tagInfo eq 'HASH' and $$tagInfo{SetGroups}) { |
|
|
|
|
66
|
|
|
|
|
|
1976
|
0
|
|
|
|
|
0
|
$setGroups = $$et{SET_GROUP0} = $$et{SET_GROUP1} = $$tagInfo{SetGroups}; |
|
1977
|
|
|
|
|
|
|
} |
|
1978
|
12
|
0
|
0
|
|
|
28
|
MakeTagInfo($tagTbl, $tag) if not $tagInfo and ($verbose or $unknown); |
|
|
|
|
33
|
|
|
|
|
|
1979
|
12
|
|
|
|
|
58
|
$et->HandleTag($tagTbl, $tag, $buff, |
|
1980
|
|
|
|
|
|
|
DataPt => \$buff, |
|
1981
|
|
|
|
|
|
|
DataPos => 0, # (relative to Base) |
|
1982
|
|
|
|
|
|
|
Start => 0, |
|
1983
|
|
|
|
|
|
|
Size => $len2, |
|
1984
|
|
|
|
|
|
|
Base => $pos, |
|
1985
|
|
|
|
|
|
|
); |
|
1986
|
12
|
50
|
|
|
|
27
|
if ($setGroups) { |
|
1987
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP0}; |
|
1988
|
0
|
|
|
|
|
0
|
delete $$et{SET_GROUP1}; |
|
1989
|
|
|
|
|
|
|
} |
|
1990
|
12
|
50
|
|
|
|
31
|
delete $$et{DOC_NUM} if $ee; |
|
1991
|
|
|
|
|
|
|
} elsif ($tag eq 'RIFF') { |
|
1992
|
|
|
|
|
|
|
# don't read into RIFF chunk (eg. concatenated video file) |
|
1993
|
0
|
0
|
|
|
|
0
|
$raf->Read($buff, 4) == 4 or $err=1, last; |
|
1994
|
|
|
|
|
|
|
# extract information from remaining file as an embedded file |
|
1995
|
|
|
|
|
|
|
$$et{DOC_NUM} = ++$$et{DOC_COUNT} |
|
1996
|
0
|
|
|
|
|
0
|
} elsif ($tag eq 'LIST_movi' and $ee) { |
|
1997
|
0
|
|
|
|
|
0
|
next; # parse into movi chunk |
|
1998
|
|
|
|
|
|
|
} else { |
|
1999
|
0
|
0
|
0
|
|
|
0
|
if ($len > 0x7fffffff and not $et->Options('LargeFileSupport')) { |
|
2000
|
0
|
|
|
|
|
0
|
$et->Warn("Stopped parsing at large $tag chunk (LargeFileSupport not set)"); |
|
2001
|
0
|
|
|
|
|
0
|
last; |
|
2002
|
|
|
|
|
|
|
} |
|
2003
|
0
|
0
|
|
|
|
0
|
$raf->Seek($len2, 1) or $err=1, last; |
|
2004
|
|
|
|
|
|
|
} |
|
2005
|
12
|
|
|
|
|
23
|
$pos += $len2; |
|
2006
|
|
|
|
|
|
|
} |
|
2007
|
4
|
|
|
|
|
9
|
delete $$et{DOC_NUM}; |
|
2008
|
4
|
50
|
|
|
|
11
|
$err and $et->Warn('Error reading RIFF file (corrupted?)'); |
|
2009
|
4
|
|
|
|
|
16
|
return 1; |
|
2010
|
|
|
|
|
|
|
} |
|
2011
|
|
|
|
|
|
|
|
|
2012
|
|
|
|
|
|
|
1; # end |
|
2013
|
|
|
|
|
|
|
|
|
2014
|
|
|
|
|
|
|
__END__ |