source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/RIFF.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

File size: 39.5 KB
Line 
1#------------------------------------------------------------------------------
2# File: RIFF.pm
3#
4# Description: Read RIFF/WAV/AVI meta information
5#
6# Revisions: 09/14/2005 - P. Harvey Created
7#
8# References: 1) http://www.exif.org/Exif2-2.PDF
9# 2) http://www.vlsi.fi/datasheets/vs1011.pdf
10# 3) http://www.music-center.com.br/spec_rif.htm
11# 4) http://www.codeproject.com/audio/wavefiles.asp
12# 5) http://msdn.microsoft.com/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp
13# 6) http://research.microsoft.com/invisible/tests/riff.h.htm
14# 7) http://www.onicos.com/staff/iz/formats/wav.html
15# 8) http://graphics.cs.uni-sb.de/NMM/dist-0.9.1/Docs/Doxygen/html/mmreg_8h-source.html
16# 9) http://developers.videolan.org/vlc/vlc/doc/doxygen/html/codecs_8h-source.html
17# 10) http://wiki.multimedia.cx/index.php?title=TwoCC
18# 11) Andreas Winter (SCLive) private communication
19# 12) http://abcavi.kibi.ru/infotags.htm
20# 13) http://tech.ebu.ch/docs/tech/tech3285.pdf
21#------------------------------------------------------------------------------
22
23package Image::ExifTool::RIFF;
24
25use strict;
26use vars qw($VERSION);
27use Image::ExifTool qw(:DataAccess :Utils);
28
29$VERSION = '1.28';
30
31sub ConvertTimecode($);
32
33# type of current stream
34$Image::ExifTool::RIFF::streamType = '';
35
36%Image::ExifTool::RIFF::audioEncoding = ( #2
37 Notes => 'These "TwoCC" audio encoding codes are used in RIFF and ASF files.',
38 0x01 => 'Microsoft PCM',
39 0x02 => 'Microsoft ADPCM',
40 0x03 => 'Microsoft IEEE float',
41 0x04 => 'Compaq VSELP', #4
42 0x05 => 'IBM CVSD', #4
43 0x06 => 'Microsoft a-Law',
44 0x07 => 'Microsoft u-Law',
45 0x08 => 'Microsoft DTS', #4
46 0x09 => 'DRM', #4
47 0x0a => 'WMA 9 Speech', #9
48 0x0b => 'Microsoft Windows Media RT Voice', #10
49 0x10 => 'OKI-ADPCM',
50 0x11 => 'Intel IMA/DVI-ADPCM',
51 0x12 => 'Videologic Mediaspace ADPCM', #4
52 0x13 => 'Sierra ADPCM', #4
53 0x14 => 'Antex G.723 ADPCM', #4
54 0x15 => 'DSP Solutions DIGISTD',
55 0x16 => 'DSP Solutions DIGIFIX',
56 0x17 => 'Dialoic OKI ADPCM', #6
57 0x18 => 'Media Vision ADPCM', #6
58 0x19 => 'HP CU', #7
59 0x1a => 'HP Dynamic Voice', #10
60 0x20 => 'Yamaha ADPCM', #6
61 0x21 => 'SONARC Speech Compression', #6
62 0x22 => 'DSP Group True Speech', #6
63 0x23 => 'Echo Speech Corp.', #6
64 0x24 => 'Virtual Music Audiofile AF36', #6
65 0x25 => 'Audio Processing Tech.', #6
66 0x26 => 'Virtual Music Audiofile AF10', #6
67 0x27 => 'Aculab Prosody 1612', #7
68 0x28 => 'Merging Tech. LRC', #7
69 0x30 => 'Dolby AC2',
70 0x31 => 'Microsoft GSM610',
71 0x32 => 'MSN Audio', #6
72 0x33 => 'Antex ADPCME', #6
73 0x34 => 'Control Resources VQLPC', #6
74 0x35 => 'DSP Solutions DIGIREAL', #6
75 0x36 => 'DSP Solutions DIGIADPCM', #6
76 0x37 => 'Control Resources CR10', #6
77 0x38 => 'Natural MicroSystems VBX ADPCM', #6
78 0x39 => 'Crystal Semiconductor IMA ADPCM', #6
79 0x3a => 'Echo Speech ECHOSC3', #6
80 0x3b => 'Rockwell ADPCM',
81 0x3c => 'Rockwell DIGITALK',
82 0x3d => 'Xebec Multimedia', #6
83 0x40 => 'Antex G.721 ADPCM',
84 0x41 => 'Antex G.728 CELP',
85 0x42 => 'Microsoft MSG723', #7
86 0x43 => 'IBM AVC ADPCM', #10
87 0x45 => 'ITU-T G.726', #9
88 0x50 => 'Microsoft MPEG',
89 0x51 => 'RT23 or PAC', #7
90 0x52 => 'InSoft RT24', #4
91 0x53 => 'InSoft PAC', #4
92 0x55 => 'MP3',
93 0x59 => 'Cirrus', #7
94 0x60 => 'Cirrus Logic', #6
95 0x61 => 'ESS Tech. PCM', #6
96 0x62 => 'Voxware Inc.', #6
97 0x63 => 'Canopus ATRAC', #6
98 0x64 => 'APICOM G.726 ADPCM',
99 0x65 => 'APICOM G.722 ADPCM',
100 0x66 => 'Microsoft DSAT', #6
101 0x67 => 'Micorsoft DSAT DISPLAY', #6
102 0x69 => 'Voxware Byte Aligned', #7
103 0x70 => 'Voxware AC8', #7
104 0x71 => 'Voxware AC10', #7
105 0x72 => 'Voxware AC16', #7
106 0x73 => 'Voxware AC20', #7
107 0x74 => 'Voxware MetaVoice', #7
108 0x75 => 'Voxware MetaSound', #7
109 0x76 => 'Voxware RT29HW', #7
110 0x77 => 'Voxware VR12', #7
111 0x78 => 'Voxware VR18', #7
112 0x79 => 'Voxware TQ40', #7
113 0x7a => 'Voxware SC3', #10
114 0x7b => 'Voxware SC3', #10
115 0x80 => 'Soundsoft', #6
116 0x81 => 'Voxware TQ60', #7
117 0x82 => 'Microsoft MSRT24', #7
118 0x83 => 'AT&T G.729A', #7
119 0x84 => 'Motion Pixels MVI MV12', #7
120 0x85 => 'DataFusion G.726', #7
121 0x86 => 'DataFusion GSM610', #7
122 0x88 => 'Iterated Systems Audio', #7
123 0x89 => 'Onlive', #7
124 0x8a => 'Multitude, Inc. FT SX20', #10
125 0x8b => 'Infocom ITS A/S G.721 ADPCM', #10
126 0x8c => 'Convedia G729', #10
127 0x8d => 'Not specified congruency, Inc.', #10
128 0x91 => 'Siemens SBC24', #7
129 0x92 => 'Sonic Foundry Dolby AC3 APDIF', #7
130 0x93 => 'MediaSonic G.723', #8
131 0x94 => 'Aculab Prosody 8kbps', #8
132 0x97 => 'ZyXEL ADPCM', #7,
133 0x98 => 'Philips LPCBB', #7
134 0x99 => 'Studer Professional Audio Packed', #7
135 0xa0 => 'Malden PhonyTalk', #8
136 0xa1 => 'Racal Recorder GSM', #10
137 0xa2 => 'Racal Recorder G720.a', #10
138 0xa3 => 'Racal G723.1', #10
139 0xa4 => 'Racal Tetra ACELP', #10
140 0xb0 => 'NEC AAC NEC Corporation', #10
141 0xff => 'AAC', #10
142 0x100 => 'Rhetorex ADPCM', #6
143 0x101 => 'IBM u-Law', #3
144 0x102 => 'IBM a-Law', #3
145 0x103 => 'IBM ADPCM', #3
146 0x111 => 'Vivo G.723', #7
147 0x112 => 'Vivo Siren', #7
148 0x120 => 'Philips Speech Processing CELP', #10
149 0x121 => 'Philips Speech Processing GRUNDIG', #10
150 0x123 => 'Digital G.723', #7
151 0x125 => 'Sanyo LD ADPCM', #8
152 0x130 => 'Sipro Lab ACEPLNET', #8
153 0x131 => 'Sipro Lab ACELP4800', #8
154 0x132 => 'Sipro Lab ACELP8V3', #8
155 0x133 => 'Sipro Lab G.729', #8
156 0x134 => 'Sipro Lab G.729A', #8
157 0x135 => 'Sipro Lab Kelvin', #8
158 0x136 => 'VoiceAge AMR', #10
159 0x140 => 'Dictaphone G.726 ADPCM', #8
160 0x150 => 'Qualcomm PureVoice', #8
161 0x151 => 'Qualcomm HalfRate', #8
162 0x155 => 'Ring Zero Systems TUBGSM', #8
163 0x160 => 'Microsoft Audio1', #8
164 0x161 => 'Windows Media Audio V2 V7 V8 V9 / DivX audio (WMA) / Alex AC3 Audio', #10
165 0x162 => 'Windows Media Audio Professional V9', #10
166 0x163 => 'Windows Media Audio Lossless V9', #10
167 0x164 => 'WMA Pro over S/PDIF', #10
168 0x170 => 'UNISYS NAP ADPCM', #10
169 0x171 => 'UNISYS NAP ULAW', #10
170 0x172 => 'UNISYS NAP ALAW', #10
171 0x173 => 'UNISYS NAP 16K', #10
172 0x174 => 'MM SYCOM ACM SYC008 SyCom Technologies', #10
173 0x175 => 'MM SYCOM ACM SYC701 G726L SyCom Technologies', #10
174 0x176 => 'MM SYCOM ACM SYC701 CELP54 SyCom Technologies', #10
175 0x177 => 'MM SYCOM ACM SYC701 CELP68 SyCom Technologies', #10
176 0x178 => 'Knowledge Adventure ADPCM', #10
177 0x180 => 'Fraunhofer IIS MPEG2AAC', #10
178 0x190 => 'Digital Theater Systems DTS DS', #10
179 0x200 => 'Creative Labs ADPCM', #6
180 0x202 => 'Creative Labs FASTSPEECH8', #6
181 0x203 => 'Creative Labs FASTSPEECH10', #6
182 0x210 => 'UHER ADPCM', #8
183 0x215 => 'Ulead DV ACM', #10
184 0x216 => 'Ulead DV ACM', #10
185 0x220 => 'Quarterdeck Corp.', #6
186 0x230 => 'I-Link VC', #8
187 0x240 => 'Aureal Semiconductor Raw Sport', #8
188 0x241 => 'ESST AC3', #10
189 0x250 => 'Interactive Products HSX', #8
190 0x251 => 'Interactive Products RPELP', #8
191 0x260 => 'Consistent CS2', #8
192 0x270 => 'Sony SCX', #8
193 0x271 => 'Sony SCY', #10
194 0x272 => 'Sony ATRAC3', #10
195 0x273 => 'Sony SPC', #10
196 0x280 => 'TELUM Telum Inc.', #10
197 0x281 => 'TELUMIA Telum Inc.', #10
198 0x285 => 'Norcom Voice Systems ADPCM', #10
199 0x300 => 'Fujitsu FM TOWNS SND', #6
200 0x301 => 'Fujitsu (not specified)', #10
201 0x302 => 'Fujitsu (not specified)', #10
202 0x303 => 'Fujitsu (not specified)', #10
203 0x304 => 'Fujitsu (not specified)', #10
204 0x305 => 'Fujitsu (not specified)', #10
205 0x306 => 'Fujitsu (not specified)', #10
206 0x307 => 'Fujitsu (not specified)', #10
207 0x308 => 'Fujitsu (not specified)', #10
208 0x350 => 'Micronas Semiconductors, Inc. Development', #10
209 0x351 => 'Micronas Semiconductors, Inc. CELP833', #10
210 0x400 => 'Brooktree Digital', #6
211 0x401 => 'Intel Music Coder (IMC)', #10
212 0x402 => 'Ligos Indeo Audio', #10
213 0x450 => 'QDesign Music', #8
214 0x500 => 'On2 VP7 On2 Technologies', #10
215 0x501 => 'On2 VP6 On2 Technologies', #10
216 0x680 => 'AT&T VME VMPCM', #7
217 0x681 => 'AT&T TCP', #8
218 0x700 => 'YMPEG Alpha (dummy for MPEG-2 compressor)', #10
219 0x8ae => 'ClearJump LiteWave (lossless)', #10
220 0x1000 => 'Olivetti GSM', #6
221 0x1001 => 'Olivetti ADPCM', #6
222 0x1002 => 'Olivetti CELP', #6
223 0x1003 => 'Olivetti SBC', #6
224 0x1004 => 'Olivetti OPR', #6
225 0x1100 => 'Lernout & Hauspie', #6
226 0x1101 => 'Lernout & Hauspie CELP codec', #10
227 0x1102 => 'Lernout & Hauspie SBC codec', #10
228 0x1103 => 'Lernout & Hauspie SBC codec', #10
229 0x1104 => 'Lernout & Hauspie SBC codec', #10
230 0x1400 => 'Norris Comm. Inc.', #6
231 0x1401 => 'ISIAudio', #7
232 0x1500 => 'AT&T Soundspace Music Compression', #7
233 0x181c => 'VoxWare RT24 speech codec', #10
234 0x181e => 'Lucent elemedia AX24000P Music codec', #10
235 0x1971 => 'Sonic Foundry LOSSLESS', #10
236 0x1979 => 'Innings Telecom Inc. ADPCM', #10
237 0x1c07 => 'Lucent SX8300P speech codec', #10
238 0x1c0c => 'Lucent SX5363S G.723 compliant codec', #10
239 0x1f03 => 'CUseeMe DigiTalk (ex-Rocwell)', #10
240 0x1fc4 => 'NCT Soft ALF2CD ACM', #10
241 0x2000 => 'FAST Multimedia DVM', #7
242 0x2001 => 'Dolby DTS (Digital Theater System)', #10
243 0x2002 => 'RealAudio 1 / 2 14.4', #10
244 0x2003 => 'RealAudio 1 / 2 28.8', #10
245 0x2004 => 'RealAudio G2 / 8 Cook (low bitrate)', #10
246 0x2005 => 'RealAudio 3 / 4 / 5 Music (DNET)', #10
247 0x2006 => 'RealAudio 10 AAC (RAAC)', #10
248 0x2007 => 'RealAudio 10 AAC+ (RACP)', #10
249 0x2500 => 'Reserved range to 0x2600 Microsoft', #10
250 0x3313 => 'makeAVIS (ffvfw fake AVI sound from AviSynth scripts)', #10
251 0x4143 => 'Divio MPEG-4 AAC audio', #10
252 0x4201 => 'Nokia adaptive multirate', #10
253 0x4243 => 'Divio G726 Divio, Inc.', #10
254 0x434c => 'LEAD Speech', #10
255 0x564c => 'LEAD Vorbis', #10
256 0x5756 => 'WavPack Audio', #10
257 0x674f => 'Ogg Vorbis (mode 1)', #10
258 0x6750 => 'Ogg Vorbis (mode 2)', #10
259 0x6751 => 'Ogg Vorbis (mode 3)', #10
260 0x676f => 'Ogg Vorbis (mode 1+)', #10
261 0x6770 => 'Ogg Vorbis (mode 2+)', #10
262 0x6771 => 'Ogg Vorbis (mode 3+)', #10
263 0x7000 => '3COM NBX 3Com Corporation', #10
264 0x706d => 'FAAD AAC', #10
265 0x7a21 => 'GSM-AMR (CBR, no SID)', #10
266 0x7a22 => 'GSM-AMR (VBR, including SID)', #10
267 0xa100 => 'Comverse Infosys Ltd. G723 1', #10
268 0xa101 => 'Comverse Infosys Ltd. AVQSBC', #10
269 0xa102 => 'Comverse Infosys Ltd. OLDSBC', #10
270 0xa103 => 'Symbol Technologies G729A', #10
271 0xa104 => 'VoiceAge AMR WB VoiceAge Corporation', #10
272 0xa105 => 'Ingenient Technologies Inc. G726', #10
273 0xa106 => 'ISO/MPEG-4 advanced audio Coding', #10
274 0xa107 => 'Encore Software Ltd G726', #10
275 0xa109 => 'Speex ACM Codec xiph.org', #10
276 0xdfac => 'DebugMode SonicFoundry Vegas FrameServer ACM Codec', #10
277 0xe708 => 'Unknown -', #10
278 0xf1ac => 'Free Lossless Audio Codec FLAC', #10
279 0xfffe => 'Extensible', #7
280 0xffff => 'Development', #4
281);
282
283# RIFF info
284%Image::ExifTool::RIFF::Main = (
285 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks,
286 NOTES => q{
287 The RIFF container format is used various types of fines including WAV, AVI
288 and WEBP. According to the EXIF specification, Meta information is embedded
289 in two types of RIFF C<LIST> chunks: C<INFO> and C<exif>, and information
290 about the audio content is stored in the C<fmt > chunk. As well as this
291 information, some video information and proprietary manufacturer-specific
292 information is also extracted.
293 },
294 'fmt ' => {
295 Name => 'AudioFormat',
296 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AudioFormat' },
297 },
298 'bext' => {
299 Name => 'BroadcastExtension',
300 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::BroadcastExt' },
301 },
302 LIST_INFO => {
303 Name => 'Info',
304 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Info' },
305 },
306 LIST_exif => {
307 Name => 'Exif',
308 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Exif' },
309 },
310 LIST_hdrl => { # AVI header LIST chunk
311 Name => 'Hdrl',
312 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Hdrl' },
313 },
314 LIST_Tdat => { #PH (Adobe CS3 Bridge)
315 Name => 'Tdat',
316 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Tdat' },
317 },
318 LIST_ncdt => { #PH (Nikon metadata)
319 Name => 'NikonData',
320 SubDirectory => {
321 TagTable => 'Image::ExifTool::Nikon::AVI',
322 # define ProcessProc here so we don't need to load RIFF.pm from Nikon.pm
323 ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks,
324 },
325 },
326 LIST_hydt => { #PH (Pentax metadata)
327 Name => 'PentaxData',
328 SubDirectory => {
329 TagTable => 'Image::ExifTool::Pentax::AVI',
330 ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks,
331 },
332 },
333 JUNK => [
334 {
335 Name => 'OlympusJunk',
336 Condition => '$$valPt =~ /^OLYMDigital Camera/',
337 SubDirectory => { TagTable => 'Image::ExifTool::Olympus::AVI' },
338 },
339 {
340 Name => 'CasioJunk',
341 Condition => '$$valPt =~ /^QVMI/',
342 # Casio stores standard EXIF-format information in AVI videos (EX-S600)
343 SubDirectory => {
344 TagTable => 'Image::ExifTool::Exif::Main',
345 DirName => 'IFD0',
346 Multi => 0, # (IFD1 is not written)
347 Start => 10,
348 ByteOrder => 'BigEndian',
349 },
350 },
351 {
352 Name => 'RicohJunk',
353 # the Ricoh Caplio GX stores sub-chunks in here
354 Condition => '$$valPt =~ /^ucmt/',
355 SubDirectory => {
356 TagTable => 'Image::ExifTool::Ricoh::AVI',
357 ProcessProc => \&Image::ExifTool::RIFF::ProcessChunks,
358 },
359 },
360 {
361 Name => 'PentaxJunk', # (Optio RS1000)
362 Condition => '$$valPt =~ /^IIII\x01\0/',
363 SubDirectory => { TagTable => 'Image::ExifTool::Pentax::Junk' },
364 },
365 {
366 Name => 'TextJunk',
367 # try to interpret unknown junk as an ASCII string
368 RawConv => '$val =~ /^([^\0-\x1f\x7f-\xff]+)\0*$/ ? $1 : undef',
369 }
370 ],
371 _PMX => { #PH (Adobe CS3 Bridge)
372 Name => 'XMP',
373 SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' },
374 },
375 JUNQ => { #PH (Adobe CS3 Bridge)
376 # old XMP is preserved when metadata is replaced in Bridge
377 Name => 'OldXMP',
378 Binary => 1,
379 },
380 olym => {
381 Name => 'Olym',
382 SubDirectory => { TagTable => 'Image::ExifTool::Olympus::WAV' },
383 },
384);
385
386# the maker notes used by some digital cameras
387%Image::ExifTool::RIFF::Junk = (
388 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
389 GROUPS => { 2 => 'Audio' },
390);
391
392# Format and Audio Stream Format chunk data
393%Image::ExifTool::RIFF::AudioFormat = (
394 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
395 GROUPS => { 2 => 'Audio' },
396 FORMAT => 'int16u',
397 0 => {
398 Name => 'Encoding',
399 PrintHex => 1,
400 PrintConv => \%Image::ExifTool::RIFF::audioEncoding,
401 SeparateTable => 'AudioEncoding',
402 },
403 1 => 'NumChannels',
404 2 => {
405 Name => 'SampleRate',
406 Format => 'int32u',
407 },
408 4 => {
409 Name => 'AvgBytesPerSec',
410 Format => 'int32u',
411 },
412 # uninteresting
413 # 6 => 'BlockAlignment',
414 7 => 'BitsPerSample',
415);
416
417# Broadcast Audio Extension 'bext' information (ref 13)
418%Image::ExifTool::RIFF::BroadcastExt = (
419 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
420 GROUPS => { 2 => 'Audio' },
421 NOTES => q{
422 Information found in the Broadcast Audio Extension chunk (see
423 L<http://tech.ebu.ch/docs/tech/tech3285.pdf>).
424 },
425 0 => {
426 Name => 'Description',
427 Format => 'string[256]',
428 },
429 256 => {
430 Name => 'Originator',
431 Format => 'string[32]',
432 },
433 288 => {
434 Name => 'OriginatorReference',
435 Format => 'string[32]',
436 },
437 320 => {
438 Name => 'DateTimeOriginal',
439 Description => 'Date/Time Original',
440 Groups => { 2 => 'Time' },
441 Format => 'string[18]',
442 ValueConv => '$_=$val; tr/-/:/; s/^(\d{4}:\d{2}:\d{2})/$1 /; $_',
443 PrintConv => '$self->ConvertDateTime($val)',
444 },
445 338 => {
446 Name => 'TimeReference',
447 Notes => 'first sample count since midnight',
448 Format => 'int32u[2]',
449 ValueConv => 'my @v=split(" ",$val); $v[0] + $v[1] * 4294967296',
450 },
451 346 => {
452 Name => 'BWFVersion',
453 Format => 'int16u',
454 },
455 # 348 - int8u[64] - SMPTE 330M UMID (Unique Material Identifier)
456 # 412 - int8u[190] - reserved
457 602 => {
458 Name => 'CodingHistory',
459 Format => 'string[$size-602]',
460 },
461);
462
463# Sub chunks of INFO LIST chunk
464%Image::ExifTool::RIFF::Info = (
465 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks,
466 GROUPS => { 2 => 'Audio' },
467 NOTES => q{
468 RIFF INFO tags found in WAV audio and AVI video files. Tags which are part
469 of the EXIF 2.3 specification have an underlined Tag Name in the HTML
470 version of this documentation. Other tags are found in AVI files generated
471 by some software.
472 },
473 IARL => 'ArchivalLocation',
474 IART => { Name => 'Artist', Groups => { 2 => 'Author' } },
475 ICMS => 'Commissioned',
476 ICMT => 'Comment',
477 ICOP => { Name => 'Copyright', Groups => { 2 => 'Author' } },
478 ICRD => {
479 Name => 'DateCreated',
480 Groups => { 2 => 'Time' },
481 ValueConv => '$_=$val; s/-/:/g; $_',
482 },
483 ICRP => 'Cropped',
484 IDIM => 'Dimensions',
485 IDPI => 'DotsPerInch',
486 IENG => 'Engineer',
487 IGNR => 'Genre',
488 IKEY => 'Keywords',
489 ILGT => 'Lightness',
490 IMED => 'Medium',
491 INAM => 'Title',
492 IPLT => 'NumColors',
493 IPRD => 'Product',
494 ISBJ => 'Subject',
495 ISFT => {
496 Name => 'Software',
497 # remove trailing nulls/spaces and split at first null
498 # (Casio writes "CASIO" in unicode after the first null)
499 ValueConv => '$_=$val; s/(\s*\0)+$//; s/(\s*\0)/, /; s/\0+//g; $_',
500 },
501 ISHP => 'Sharpness',
502 ISRC => 'Source',
503 ISRF => 'SourceForm',
504 ITCH => 'Technician',
505#
506# 3rd party tags
507#
508 # internet movie database (ref 12)
509 ISGN => 'SecondaryGenre',
510 IWRI => 'WrittenBy',
511 IPRO => 'ProducedBy',
512 ICNM => 'Cinematographer',
513 IPDS => 'ProductionDesigner',
514 IEDT => 'EditedBy',
515 ICDS => 'CostumeDesigner',
516 IMUS => 'MusicBy',
517 ISTD => 'ProductionStudio',
518 IDST => 'DistributedBy',
519 ICNT => 'Country',
520 ILNG => 'Language',
521 IRTD => 'Rating',
522 ISTR => 'Starring',
523 # MovieID (ref12)
524 TITL => 'Title',
525 DIRC => 'Directory',
526 YEAR => 'Year',
527 GENR => 'Genre',
528 COMM => 'Comments',
529 LANG => 'Language',
530 AGES => 'Rated',
531 STAR => 'Starring',
532 CODE => 'EncodedBy',
533 PRT1 => 'Part',
534 PRT2 => 'NumberOfParts',
535 # Morgan Multimedia INFO tags (ref 12)
536 IAS1 => 'FirstLanguage',
537 IAS2 => 'SecondLanguage',
538 IAS3 => 'ThirdLanguage',
539 IAS4 => 'FourthLanguage',
540 IAS5 => 'FifthLanguage',
541 IAS6 => 'SixthLanguage',
542 IAS7 => 'SeventhLanguage',
543 IAS8 => 'EighthLanguage',
544 IAS9 => 'NinthLanguage',
545 ICAS => 'DefaultAudioStream',
546 IBSU => 'BaseURL',
547 ILGU => 'LogoURL',
548 ILIU => 'LogoIconURL',
549 IWMU => 'WatermarkURL',
550 IMIU => 'MoreInfoURL',
551 IMBI => 'MoreInfoBannerImage',
552 IMBU => 'MoreInfoBannerURL',
553 IMIT => 'MoreInfoText',
554 # GSpot INFO tags (ref 12)
555 IENC => 'EncodedBy',
556 IRIP => 'RippedBy',
557 # Sound Forge Pro tags
558 DISP => 'SoundSchemeTitle',
559 TLEN => { Name => 'Length', ValueConv => '$val/1000', PrintConv => '"$val s"' },
560 TRCK => 'TrackNumber',
561 TURL => 'URL',
562 TVER => 'Version',
563 LOCA => 'Location',
564 TORG => 'Organization',
565 # Sony Vegas AVI tags, also used by SCLive and Adobe Premier (ref 11)
566 TAPE => {
567 Name => 'TapeName',
568 Groups => { 2 => 'Video' },
569 },
570 TCOD => {
571 Name => 'StartTimecode',
572 # this is the tape time code for the start of the video
573 Groups => { 2 => 'Video' },
574 ValueConv => '$val * 1e-7',
575 PrintConv => \&ConvertTimecode,
576 },
577 TCDO => {
578 Name => 'EndTimecode',
579 Groups => { 2 => 'Video' },
580 ValueConv => '$val * 1e-7',
581 PrintConv => \&ConvertTimecode,
582 },
583 VMAJ => {
584 Name => 'VegasVersionMajor',
585 Groups => { 2 => 'Video' },
586 },
587 VMIN => {
588 Name => 'VegasVersionMinor',
589 Groups => { 2 => 'Video' },
590 },
591 CMNT => {
592 Name => 'Comment',
593 Groups => { 2 => 'Video' },
594 },
595 RATE => {
596 Name => 'Rate', #? (video? units?)
597 Groups => { 2 => 'Video' },
598 },
599 STAT => {
600 Name => 'Statistics',
601 Groups => { 2 => 'Video' },
602 # ("7318 0 3.430307 1", "0 0 3500.000000 1", "7 0 3.433228 1")
603 PrintConv => [
604 '"$val frames captured"',
605 '"$val dropped"',
606 '"Data rate $val"',
607 { 0 => 'Bad', 1 => 'OK' }, # capture OK?
608 ],
609 },
610 DTIM => {
611 Name => 'DateTimeOriginal',
612 Description => 'Date/Time Original',
613 Groups => { 2 => 'Time' },
614 ValueConv => q{
615 my @v = split ' ', $val;
616 return undef unless @v == 2;
617 # get time in seconds
618 $val = 1e-7 * ($v[0] * 4294967296 + $v[1]);
619 # shift from Jan 1, 1601 to Jan 1, 1970
620 $val -= 134774 * 24 * 3600 if $val != 0;
621 return Image::ExifTool::ConvertUnixTime($val);
622 },
623 PrintConv => '$self->ConvertDateTime($val)',
624 },
625);
626
627# Sub chunks of EXIF LIST chunk
628%Image::ExifTool::RIFF::Exif = (
629 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks,
630 GROUPS => { 2 => 'Audio' },
631 NOTES => 'These tags are part of the EXIF 2.3 specification for WAV audio files.',
632 ever => 'ExifVersion',
633 erel => 'RelatedImageFile',
634 etim => { Name => 'TimeCreated', Groups => { 2 => 'Time' } },
635 ecor => { Name => 'Make', Groups => { 2 => 'Camera' } },
636 emdl => { Name => 'Model', Groups => { 2 => 'Camera' } },
637 emnt => { Name => 'MakerNotes', Binary => 1 },
638 eucm => {
639 Name => 'UserComment',
640 PrintConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val)',
641 },
642);
643
644# Sub chunks of hdrl LIST chunk
645%Image::ExifTool::RIFF::Hdrl = (
646 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks,
647 GROUPS => { 2 => 'Image' },
648 avih => {
649 Name => 'AVIHeader',
650 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AVIHeader' },
651 },
652 IDIT => {
653 Name => 'DateTimeOriginal',
654 Description => 'Date/Time Original',
655 Groups => { 2 => 'Time' },
656 ValueConv => 'Image::ExifTool::RIFF::ConvertRIFFDate($val)',
657 PrintConv => '$self->ConvertDateTime($val)',
658 },
659 ISMP => 'Timecode',
660 LIST_strl => {
661 Name => 'Stream',
662 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::Stream' },
663 },
664 LIST_odml => {
665 Name => 'OpenDML',
666 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::OpenDML' },
667 },
668);
669
670# Sub chunks of Tdat LIST chunk (ref PH)
671%Image::ExifTool::RIFF::Tdat = (
672 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks,
673 GROUPS => { 2 => 'Video' },
674 # (have seen tc_O, tc_A, rn_O and rn_A)
675);
676
677%Image::ExifTool::RIFF::AVIHeader = (
678 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
679 GROUPS => { 2 => 'Video' },
680 FORMAT => 'int32u',
681 FIRST_ENTRY => 0,
682 0 => {
683 Name => 'FrameRate',
684 # (must use RawConv because raw value used in Composite tag)
685 RawConv => '$val ? 1e6 / $val : undef',
686 PrintConv => 'int($val * 1000 + 0.5) / 1000',
687 },
688 1 => {
689 Name => 'MaxDataRate',
690 PrintConv => 'sprintf("%.4g kB/s",$val / 1024)',
691 },
692 # 2 => 'PaddingGranularity',
693 # 3 => 'Flags',
694 4 => 'FrameCount',
695 # 5 => 'InitialFrames',
696 6 => 'StreamCount',
697 # 7 => 'SuggestedBufferSize',
698 8 => 'ImageWidth',
699 9 => 'ImageHeight',
700);
701
702%Image::ExifTool::RIFF::Stream = (
703 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks,
704 GROUPS => { 2 => 'Image' },
705 strh => {
706 Name => 'StreamHeader',
707 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::StreamHeader' },
708 },
709 strn => 'StreamName',
710 strd => { #PH
711 Name => 'StreamData',
712 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::StreamData' },
713 },
714 strf => [
715 {
716 Name => 'AudioFormat',
717 Condition => '$Image::ExifTool::RIFF::streamType eq "auds"',
718 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::AudioFormat' },
719 },
720 {
721 Name => 'VideoFormat',
722 Condition => '$Image::ExifTool::RIFF::streamType eq "vids"',
723 SubDirectory => { TagTable => 'Image::ExifTool::BMP::Main' },
724 },
725 ],
726);
727
728# Open DML tags (ref http://www.morgan-multimedia.com/download/odmlff2.pdf)
729%Image::ExifTool::RIFF::OpenDML = (
730 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessChunks,
731 GROUPS => { 2 => 'Video' },
732 dmlh => {
733 Name => 'ExtendedAVIHeader',
734 SubDirectory => { TagTable => 'Image::ExifTool::RIFF::ExtAVIHdr' },
735 },
736);
737
738# Extended AVI Header tags (ref http://www.morgan-multimedia.com/download/odmlff2.pdf)
739%Image::ExifTool::RIFF::ExtAVIHdr = (
740 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
741 GROUPS => { 2 => 'Video' },
742 FORMAT => 'int32u',
743 0 => 'TotalFrameCount',
744);
745
746%Image::ExifTool::RIFF::StreamHeader = (
747 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
748 GROUPS => { 2 => 'Video' },
749 FORMAT => 'int32u',
750 FIRST_ENTRY => 0,
751 PRIORITY => 0, # so we get values from the first stream
752 0 => {
753 Name => 'StreamType',
754 Format => 'string[4]',
755 RawConv => '$Image::ExifTool::RIFF::streamType = $val',
756 PrintConv => {
757 auds => 'Audio',
758 mids => 'MIDI',
759 txts => 'Text',
760 vids => 'Video',
761 },
762 },
763 1 => [
764 {
765 Name => 'AudioCodec',
766 Condition => '$Image::ExifTool::RIFF::streamType eq "auds"',
767 Format => 'string[4]',
768 },
769 {
770 Name => 'VideoCodec',
771 Condition => '$Image::ExifTool::RIFF::streamType eq "vids"',
772 Format => 'string[4]',
773 },
774 {
775 Name => 'Codec',
776 Format => 'string[4]',
777 },
778 ],
779 # 2 => 'StreamFlags',
780 # 3 => 'StreamPriority',
781 # 3.5 => 'Language',
782 # 4 => 'InitialFrames',
783 5 => [
784 {
785 Name => 'AudioSampleRate',
786 Condition => '$Image::ExifTool::RIFF::streamType eq "auds"',
787 Format => 'rational64u',
788 ValueConv => '$val ? 1/$val : 0',
789 PrintConv => 'int($val * 100 + 0.5) / 100',
790 },
791 {
792 Name => 'VideoFrameRate',
793 Condition => '$Image::ExifTool::RIFF::streamType eq "vids"',
794 Format => 'rational64u',
795 # (must use RawConv because raw value used in Composite tag)
796 RawConv => '$val ? 1/$val : undef',
797 PrintConv => 'int($val * 1000 + 0.5) / 1000',
798 },
799 {
800 Name => 'StreamSampleRate',
801 Format => 'rational64u',
802 ValueConv => '$val ? 1/$val : 0',
803 PrintConv => 'int($val * 1000 + 0.5) / 1000',
804 },
805 ],
806 # 7 => 'Start',
807 8 => [
808 {
809 Name => 'AudioSampleCount',
810 Condition => '$Image::ExifTool::RIFF::streamType eq "auds"',
811 },
812 {
813 Name => 'VideoFrameCount',
814 Condition => '$Image::ExifTool::RIFF::streamType eq "vids"',
815 },
816 {
817 Name => 'StreamSampleCount',
818 },
819 ],
820 # 9 => 'SuggestedBufferSize',
821 10 => {
822 Name => 'Quality',
823 PrintConv => '$val eq 0xffffffff ? "Default" : $val',
824 },
825 11 => {
826 Name => 'SampleSize',
827 PrintConv => '$val ? "$val byte" . ($val==1 ? "" : "s") : "Variable"',
828 },
829 # 12 => { Name => 'Frame', Format => 'int16u[4]' },
830);
831
832%Image::ExifTool::RIFF::StreamData = ( #PH
833 PROCESS_PROC => \&Image::ExifTool::RIFF::ProcessStreamData,
834 GROUPS => { 2 => 'Video' },
835 NOTES => q{
836 This chunk is used to store proprietary information in AVI videos from some
837 cameras. The first 4 characters of the data are used as the Tag ID below.
838 },
839 AVIF => {
840 Name => 'AVIF',
841 SubDirectory => {
842 TagTable => 'Image::ExifTool::Exif::Main',
843 DirName => 'IFD0',
844 Start => 8,
845 ByteOrder => 'LittleEndian',
846 },
847 },
848 CASI => { # (used by Casio GV-10)
849 Name => 'CasioData',
850 SubDirectory => { TagTable => 'Image::ExifTool::Casio::AVI' },
851 },
852 Zora => 'VendorName', # (Samsung PL90 AVI files)
853 unknown => {
854 Name => 'UnknownData',
855 # try to interpret unknown stream data as a string
856 RawConv => '$_=$val; /^[^\0-\x1f\x7f-\xff]+$/ ? $_ : undef',
857 },
858);
859
860# RIFF composite tags
861%Image::ExifTool::RIFF::Composite = (
862 Duration => {
863 Require => {
864 0 => 'RIFF:FrameRate',
865 1 => 'RIFF:FrameCount',
866 },
867 Desire => {
868 2 => 'VideoFrameRate',
869 3 => 'VideoFrameCount',
870 },
871 # this is annoying. Apparently (although I couldn't verify this), FrameCount
872 # in the RIFF header includes multiple video tracks if they exist (ie. with the
873 # FujiFilm REAL 3D AVI's), but the video stream information isn't reliable for
874 # some cameras (ie. Olympus FE models), so use the video stream information
875 # only if the RIFF header duration is 2 to 3 times longer
876 RawConv => q {
877 my ($dur1, $dur2);
878 $dur1 = $val[1] / $val[0] if $val[0];
879 return $dur1 unless $val[2] and $val[3];
880 $dur2 = $val[3] / $val[2];
881 my $rat = $dur1 / $dur2;
882 return ($rat > 1.9 and $rat < 3.1) ? $dur2 : $dur1;
883 },
884 PrintConv => 'ConvertDuration($val)',
885 },
886 Duration2 => {
887 Name => 'Duration',
888 Require => {
889 0 => 'RIFF:AvgBytesPerSec',
890 1 => 'FileSize',
891 },
892 Desire => {
893 # check FrameCount because this calculation only applies
894 # to audio-only files (ie. WAV)
895 2 => 'FrameCount',
896 3 => 'VideoFrameCount',
897 },
898 RawConv => '($val[0] and not ($val[2] or $val[3])) ? $val[1] / $val[0] : undef',
899 PrintConv => 'ConvertDuration($val)',
900 },
901);
902
903# add our composite tags
904Image::ExifTool::AddCompositeTags('Image::ExifTool::RIFF');
905
906
907#------------------------------------------------------------------------------
908# Convert RIFF date to EXIF format
909my %monthNum = (
910 Jan=>1, Feb=>2, Mar=>3, Apr=>4, May=>5, Jun=>6,
911 Jul=>7, Aug=>8, Sep=>9, Oct=>10,Nov=>11,Dec=>12
912);
913sub ConvertRIFFDate($)
914{
915 my $val = shift;
916 my @part = split ' ', $val;
917 my $mon;
918 if (@part >= 5 and $mon = $monthNum{ucfirst(lc($part[1]))}) {
919 # the standard AVI date format (ie. "Mon Mar 10 15:04:43 2003")
920 $val = sprintf("%.4d:%.2d:%.2d %s", $part[4],
921 $mon, $part[2], $part[3]);
922 } elsif ($val =~ m{(\d{4})/\s*(\d+)/\s*(\d+)/?\s+(\d+):\s*(\d+)\s*(P?)}) {
923 # but the Casio QV-3EX writes dates like "2001/ 1/27 1:42PM",
924 # and the Casio EX-Z30 writes "2005/11/28/ 09:19"... doh!
925 $val = sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00",$1,$2,$3,$4+($6?12:0),$5);
926 }
927 return $val;
928}
929
930#------------------------------------------------------------------------------
931# Print time
932# Inputs: 0) time in seconds
933# Returns: time string
934sub ConvertTimecode($)
935{
936 my $val = shift;
937 my $hr = int($val / 3600);
938 $val -= $hr * 3600;
939 my $min = int($val / 60);
940 $val -= $min * 60;
941 return sprintf("%d:%.2d:%05.2f", $hr, $min, $val);
942}
943
944#------------------------------------------------------------------------------
945# Process stream data
946# Inputs: 0) ExifTool object ref, 1) dirInfo reference, 2) tag table ref
947# Returns: 1 on success
948sub ProcessStreamData($$$)
949{
950 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
951 my $dataPt = $$dirInfo{DataPt};
952 my $start = $$dirInfo{DirStart};
953 my $size = $$dirInfo{DirLen};
954 return 0 if $size < 4;
955 if ($exifTool->Options('Verbose')) {
956 $exifTool->VerboseDir($$dirInfo{DirName}, 0, $size);
957 }
958 my $tag = substr($$dataPt, $start, 4);
959 my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
960 unless ($tagInfo) {
961 $tagInfo = $exifTool->GetTagInfo($tagTablePtr, 'unknown');
962 return 1 unless $tagInfo;
963 }
964 my $subdir = $$tagInfo{SubDirectory};
965 if ($$tagInfo{SubDirectory}) {
966 my $offset = $$subdir{Start} || 0;
967 my $baseShift = $$dirInfo{DataPos} + $$dirInfo{DirStart} + $offset;
968 my %subdirInfo = (
969 DataPt => $dataPt,
970 DataPos => $$dirInfo{DataPos} - $baseShift,
971 Base => ($$dirInfo{Base} || 0) + $baseShift,
972 DataLen => $$dirInfo{DataLen},
973 DirStart=> $$dirInfo{DirStart} + $offset,
974 DirLen => $$dirInfo{DirLen} - $offset,
975 DirName => $$subdir{DirName},
976 Parent => $$dirInfo{DirName},
977 );
978 unless ($offset) {
979 # allow processing of 2nd directory at the same address
980 my $addr = $subdirInfo{DirStart} + $subdirInfo{DataPos} + $subdirInfo{Base};
981 delete $exifTool->{PROCESSED}->{$addr}
982 }
983 # (we could set FIRST_EXIF_POS to $subdirInfo{Base} here to make
984 # htmlDump offsets relative to EXIF base if we wanted...)
985 my $subTable = GetTagTable($$subdir{TagTable});
986 $exifTool->ProcessDirectory(\%subdirInfo, $subTable);
987 } else {
988 $exifTool->HandleTag($tagTablePtr, $tag, undef,
989 DataPt => $dataPt,
990 DataPos => $$dirInfo{DataPos},
991 Start => $start,
992 Size => $size,
993 TagInfo => $tagInfo,
994 );
995 }
996 return 1;
997}
998
999#------------------------------------------------------------------------------
1000# Process RIFF chunks
1001# Inputs: 0) ExifTool object reference, 1) directory information reference
1002# 2) tag table reference
1003# Returns: 1 on success
1004sub ProcessChunks($$$)
1005{
1006 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1007 my $dataPt = $$dirInfo{DataPt};
1008 my $start = $$dirInfo{DirStart};
1009 my $size = $$dirInfo{DirLen};
1010 my $end = $start + $size;
1011 my $base = $$dirInfo{Base};
1012
1013 if ($exifTool->Options('Verbose')) {
1014 $exifTool->VerboseDir($$dirInfo{DirName}, 0, $size);
1015 }
1016 while ($start + 8 < $end) {
1017 my $tag = substr($$dataPt, $start, 4);
1018 my $len = Get32u($dataPt, $start + 4);
1019 $start += 8;
1020 if ($start + $len > $end) {
1021 $exifTool->Warn("Bad $tag chunk");
1022 return 0;
1023 }
1024 if ($tag eq 'LIST' and $len >= 4) {
1025 $tag .= '_' . substr($$dataPt, $start, 4);
1026 $len -= 4;
1027 $start += 4;
1028 }
1029 my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
1030 my $baseShift = 0;
1031 my $val;
1032 if ($tagInfo) {
1033 if ($$tagInfo{SubDirectory}) {
1034 # adjust base if necessary (needed for Ricoh maker notes)
1035 my $newBase = $tagInfo->{SubDirectory}{Base};
1036 if (defined $newBase) {
1037 # different than your average Base eval...
1038 # here we use an absolute $start address
1039 $start += $base;
1040 #### eval Base ($start)
1041 $newBase = eval $newBase;
1042 $baseShift = $newBase - $base;
1043 $start -= $base;
1044 }
1045 } elsif (not $$tagInfo{Binary}) {
1046 $val = substr($$dataPt, $start, $len);
1047 $val =~ s/\0+$//; # remove trailing nulls from strings
1048 }
1049 }
1050 $exifTool->HandleTag($tagTablePtr, $tag, $val,
1051 DataPt => $dataPt,
1052 DataPos => $$dirInfo{DataPos} - $baseShift,
1053 Start => $start,
1054 Size => $len,
1055 Base => $base + $baseShift,
1056 );
1057 ++$len if $len & 0x01; # must account for padding if odd number of bytes
1058 $start += $len;
1059 }
1060 return 1;
1061}
1062
1063#------------------------------------------------------------------------------
1064# Extract information from a RIFF file
1065# Inputs: 0) ExifTool object reference, 1) DirInfo reference
1066# Returns: 1 on success, 0 if this wasn't a valid RIFF file
1067sub ProcessRIFF($$)
1068{
1069 my ($exifTool, $dirInfo) = @_;
1070 my $raf = $$dirInfo{RAF};
1071 my ($buff, $err);
1072 my %types = ( 'WAVE' => 'WAV', 'AVI ' => 'AVI', 'WEBP' => 'WEBP' );
1073 my $verbose = $exifTool->Options('Verbose');
1074
1075 # verify this is a valid RIFF file
1076 return 0 unless $raf->Read($buff, 12) == 12;
1077 return 0 unless $buff =~ /^RIFF....(.{4})/s;
1078 $exifTool->SetFileType($types{$1}); # set type to 'WAV', 'AVI', 'WEBP' or 'RIFF'
1079 $Image::ExifTool::RIFF::streamType = ''; # initialize stream type
1080 SetByteOrder('II');
1081 my $tagTablePtr = GetTagTable('Image::ExifTool::RIFF::Main');
1082 my $pos = 12;
1083#
1084# Read chunks in RIFF image
1085#
1086 for (;;) {
1087 my $num = $raf->Read($buff, 8);
1088 if ($num < 8) {
1089 $err = 1 if $num;
1090 last;
1091 }
1092 $pos += 8;
1093 my ($tag, $len) = unpack('a4V', $buff);
1094 # special case: construct new tag name from specific LIST type
1095 if ($tag eq 'LIST') {
1096 $raf->Read($buff, 4) == 4 or $err=1, last;
1097 $pos += 4;
1098 $tag .= "_$buff";
1099 $len -= 4; # already read 4 bytes (the LIST type)
1100 }
1101 $exifTool->VPrint(0, "RIFF '$tag' chunk ($len bytes of data):\n");
1102 # stop when we hit the audio data or AVI index or AVI movie data
1103 # --> no more because Adobe Bridge stores XMP after this!!
1104 # (so now we only do this on the FastScan option)
1105 if (($tag eq 'data' or $tag eq 'idx1' or $tag eq 'LIST_movi') and
1106 $exifTool->Options('FastScan'))
1107 {
1108 $exifTool->VPrint(0, "(end of parsing)\n");
1109 last;
1110 }
1111 # RIFF chunks are padded to an even number of bytes
1112 my $len2 = $len + ($len & 0x01);
1113 if ($$tagTablePtr{$tag} or ($verbose and $tag !~ /^(data|idx1|LIST_movi)$/)) {
1114 $raf->Read($buff, $len2) == $len2 or $err=1, last;
1115 $exifTool->HandleTag($tagTablePtr, $tag, $buff,
1116 DataPt => \$buff,
1117 DataPos => 0, # (relative to Base)
1118 Start => 0,
1119 Size => $len2,
1120 Base => $pos,
1121 );
1122 } else {
1123 $raf->Seek($len2, 1) or $err=1, last;
1124 }
1125 $pos += $len2;
1126 }
1127 $err and $exifTool->Warn('Error reading RIFF file (corrupted?)');
1128 return 1;
1129}
1130
11311; # end
1132
1133__END__
1134
1135=head1 NAME
1136
1137Image::ExifTool::RIFF - Read RIFF/WAV/AVI meta information
1138
1139=head1 SYNOPSIS
1140
1141This module is used by Image::ExifTool
1142
1143=head1 DESCRIPTION
1144
1145This module contains routines required by Image::ExifTool to extract
1146information from RIFF-based (Resource Interchange File Format) files,
1147including Windows WAV audio and AVI video files.
1148
1149=head1 AUTHOR
1150
1151Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
1152
1153This library is free software; you can redistribute it and/or modify it
1154under the same terms as Perl itself.
1155
1156=head1 REFERENCES
1157
1158=over 4
1159
1160=item L<http://www.exif.org/Exif2-2.PDF>
1161
1162=item L<http://www.vlsi.fi/datasheets/vs1011.pdf>
1163
1164=item L<http://www.music-center.com.br/spec_rif.htm>
1165
1166=item L<http://www.codeproject.com/audio/wavefiles.asp>
1167
1168=item L<http://msdn.microsoft.com/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp>
1169
1170=item L<http://wiki.multimedia.cx/index.php?title=TwoCC>
1171
1172=back
1173
1174=head1 SEE ALSO
1175
1176L<Image::ExifTool::TagNames/RIFF Tags>,
1177L<Image::ExifTool(3pm)|Image::ExifTool>
1178
1179=cut
1180
Note: See TracBrowser for help on using the repository browser.