run:R W Run
54.21 KB
2026-03-11 16:18:51
R W Run
79.05 KB
2026-03-11 16:18:51
R W Run
1.36 KB
2026-03-11 16:18:51
R W Run
133.61 KB
2026-03-11 16:18:51
R W Run
26.5 KB
2026-03-11 16:18:51
R W Run
104.64 KB
2026-03-11 16:18:51
R W Run
164.97 KB
2026-03-11 16:18:51
R W Run
136.53 KB
2026-03-11 16:18:51
R W Run
38.46 KB
2026-03-11 16:18:51
R W Run
10.63 KB
2026-03-11 16:18:51
R W Run
19.23 KB
2026-03-11 16:18:51
R W Run
104.5 KB
2026-03-11 16:18:51
R W Run
42.74 KB
2026-03-11 16:18:51
R W Run
18.63 KB
2026-03-11 16:18:51
R W Run
14.7 KB
2026-03-11 16:18:51
R W Run
151.2 KB
2026-03-11 16:18:51
R W Run
11.75 KB
2026-03-11 16:18:51
R W Run
25.71 KB
2026-03-11 16:18:51
R W Run
error_log
📄module.audio-video.riff.php
1<?php
2
3/////////////////////////////////////////////////////////////////
4/// getID3() by James Heinrich <info@getid3.org> //
5// available at https://github.com/JamesHeinrich/getID3 //
6// or https://www.getid3.org //
7// or http://getid3.sourceforge.net //
8// see readme.txt for more details //
9/////////////////////////////////////////////////////////////////
10// //
11// module.audio-video.riff.php //
12// module for analyzing RIFF files //
13// multiple formats supported by this module: //
14// Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX //
15// dependencies: module.audio.mp3.php //
16// module.audio.ac3.php //
17// module.audio.dts.php //
18// ///
19/////////////////////////////////////////////////////////////////
20
21/**
22* @todo Parse AC-3/DTS audio inside WAVE correctly
23* @todo Rewrite RIFF parser totally
24*/
25
26if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
27 exit;
28}
29getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
30getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
31getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
32
33class getid3_riff extends getid3_handler
34{
35 protected $container = 'riff'; // default
36
37 /**
38 * @return bool
39 *
40 * @throws getid3_exception
41 */
42 public function Analyze() {
43 $info = &$this->getid3->info;
44
45 // initialize these values to an empty array, otherwise they default to NULL
46 // and you can't append array values to a NULL value
47 $info['riff'] = array('raw'=>array());
48
49 // Shortcuts
50 $thisfile_riff = &$info['riff'];
51 $thisfile_riff_raw = &$thisfile_riff['raw'];
52 $thisfile_audio = &$info['audio'];
53 $thisfile_video = &$info['video'];
54 $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
55 $thisfile_riff_audio = &$thisfile_riff['audio'];
56 $thisfile_riff_video = &$thisfile_riff['video'];
57 $thisfile_riff_WAVE = array();
58
59 $Original = array();
60 $Original['avdataoffset'] = $info['avdataoffset'];
61 $Original['avdataend'] = $info['avdataend'];
62
63 $this->fseek($info['avdataoffset']);
64 $RIFFheader = $this->fread(12);
65 $offset = $this->ftell();
66 $RIFFtype = substr($RIFFheader, 0, 4);
67 $RIFFsize = substr($RIFFheader, 4, 4);
68 $RIFFsubtype = substr($RIFFheader, 8, 4);
69
70 if ($RIFFsize == "\x00\x00\x00\x00") {
71 // https://github.com/JamesHeinrich/getID3/issues/468
72 // may occur in streaming files where the data size is unknown
73 $thisfile_riff['header_size'] = $info['avdataend'] - 8;
74 $this->warning('RIFF size field is empty, assuming the correct value is filesize-8 ('.$thisfile_riff['header_size'].')');
75 } else {
76 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
77 }
78
79 switch ($RIFFtype) {
80 case 'FORM': // AIFF, AIFC
81 //$info['fileformat'] = 'aiff';
82 $this->container = 'aiff';
83 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
84 break;
85
86 case 'RIFF': // AVI, WAV, etc
87 case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
88 case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
89 //$info['fileformat'] = 'riff';
90 $this->container = 'riff';
91 if ($RIFFsubtype == 'RMP3') {
92 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
93 $RIFFsubtype = 'WAVE';
94 }
95 if ($RIFFsubtype != 'AMV ') {
96 // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
97 // Handled separately in ParseRIFFAMV()
98 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
99 }
100 if (($info['avdataend'] - $info['filesize']) == 1) {
101 // LiteWave appears to incorrectly *not* pad actual output file
102 // to nearest WORD boundary so may appear to be short by one
103 // byte, in which case - skip warning
104 $info['avdataend'] = $info['filesize'];
105 }
106
107 $nextRIFFoffset = (int) $Original['avdataoffset'] + 8 + (int) $thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset
108 while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) {
109 try {
110 $this->fseek($nextRIFFoffset);
111 } catch (getid3_exception $e) {
112 if ($e->getCode() == 10) {
113 //$this->warning('RIFF parser: '.$e->getMessage());
114 $this->error('AVI extends beyond '.round(PHP_INT_MAX / 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
115 $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present');
116 break;
117 } else {
118 throw $e;
119 }
120 }
121 $nextRIFFheader = $this->fread(12);
122 if ($nextRIFFoffset == ($info['avdataend'] - 1)) {
123 if (substr($nextRIFFheader, 0, 1) == "\x00") {
124 // RIFF padded to WORD boundary, we're actually already at the end
125 break;
126 }
127 }
128 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4);
129 $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4));
130 $nextRIFFtype = substr($nextRIFFheader, 8, 4);
131 $chunkdata = array();
132 $chunkdata['offset'] = $nextRIFFoffset + 8;
133 $chunkdata['size'] = $nextRIFFsize;
134 $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size'];
135
136 switch ($nextRIFFheaderID) {
137 case 'RIFF':
138 $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset);
139 if (!isset($thisfile_riff[$nextRIFFtype])) {
140 $thisfile_riff[$nextRIFFtype] = array();
141 }
142 $thisfile_riff[$nextRIFFtype][] = $chunkdata;
143 break;
144
145 case 'AMV ':
146 unset($info['riff']);
147 $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] + 4, $nextRIFFoffset);
148 break;
149
150 case 'JUNK':
151 // ignore
152 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
153 break;
154
155 case 'IDVX':
156 $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size']));
157 break;
158
159 default:
160 if ($info['filesize'] == ($chunkdata['offset'] - 8 + 128)) {
161 $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12);
162 if (substr($DIVXTAG, -7) == 'DIVXTAG') {
163 // DIVXTAG is supposed to be inside an IDVX chunk in a LIST chunk, but some bad encoders just slap it on the end of a file
164 $this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway');
165 $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG);
166 break 2;
167 }
168 }
169 $this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file');
170 break 2;
171
172 }
173
174 }
175 if ($RIFFsubtype == 'WAVE') {
176 $thisfile_riff_WAVE = &$thisfile_riff['WAVE'];
177 }
178 break;
179
180 default:
181 $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead');
182 //unset($info['fileformat']);
183 return false;
184 }
185
186 $streamindex = 0;
187 switch ($RIFFsubtype) {
188
189 // http://en.wikipedia.org/wiki/Wav
190 case 'WAVE':
191 $info['fileformat'] = 'wav';
192
193 if (empty($thisfile_audio['bitrate_mode'])) {
194 $thisfile_audio['bitrate_mode'] = 'cbr';
195 }
196 if (empty($thisfile_audio_dataformat)) {
197 $thisfile_audio_dataformat = 'wav';
198 }
199
200 if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
201 $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8;
202 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size'];
203 }
204 if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
205
206 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
207 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
208 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
209 $this->error('Corrupt RIFF file: bitrate_audio == zero');
210 return false;
211 }
212 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
213 unset($thisfile_riff_audio[$streamindex]['raw']);
214 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
215
216 $thisfile_audio = (array) getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
217 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
218 $this->warning('Audio codec = '.$thisfile_audio['codec']);
219 }
220 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
221
222 if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV)
223 $info['playtime_seconds'] = (float)getid3_lib::SafeDiv(($info['avdataend'] - $info['avdataoffset']) * 8, $thisfile_audio['bitrate']);
224 }
225
226 $thisfile_audio['lossless'] = false;
227 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
228 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
229
230 case 0x0001: // PCM
231 $thisfile_audio['lossless'] = true;
232 break;
233
234 case 0x2000: // AC-3
235 $thisfile_audio_dataformat = 'ac3';
236 break;
237
238 default:
239 // do nothing
240 break;
241
242 }
243 }
244 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
245 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
246 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
247 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
248 }
249
250 if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
251
252 // shortcuts
253 $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data'];
254 $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array());
255 $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad'];
256 $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track'];
257 $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album'];
258
259 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4));
260 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2));
261 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2));
262
263 $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
264 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
265 $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
266 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
267 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
268 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
269 $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
270 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
271 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
272 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
273
274 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
275 if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) {
276 $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
277 $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
278 $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
279 }
280 if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) {
281 $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
282 $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
283 $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
284 }
285 }
286
287 if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
288 $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
289
290 // This should be a good way of calculating exact playtime,
291 // but some sample files have had incorrect number of samples,
292 // so cannot use this method
293
294 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
295 // $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
296 // }
297 }
298 if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
299 $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
300 }
301
302 if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
303 // shortcut
304 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
305
306 $thisfile_riff_WAVE_bext_0['title'] = substr($thisfile_riff_WAVE_bext_0['data'], 0, 256);
307 $thisfile_riff_WAVE_bext_0['author'] = substr($thisfile_riff_WAVE_bext_0['data'], 256, 32);
308 $thisfile_riff_WAVE_bext_0['reference'] = substr($thisfile_riff_WAVE_bext_0['data'], 288, 32);
309 foreach (array('title','author','reference') as $bext_key) {
310 // Some software (notably Logic Pro) may not blank existing data before writing a null-terminated string to the offsets
311 // assigned for text fields, resulting in a null-terminated string (or possibly just a single null) followed by garbage
312 // Keep only string as far as first null byte, discard rest of fixed-width data
313 // https://github.com/JamesHeinrich/getID3/issues/263
314 // https://github.com/JamesHeinrich/getID3/issues/430
315 $null_terminator_rows = explode("\x00", $thisfile_riff_WAVE_bext_0[$bext_key]);
316 $thisfile_riff_WAVE_bext_0[$bext_key] = $null_terminator_rows[0];
317 }
318
319 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
320 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
321 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
322 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1));
323 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
324 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
325 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
326 if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
327 $bext_timestamp = array();
328 list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
329 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
330 $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
331 } else {
332 $this->warning('RIFF.WAVE.BEXT.origin_time is invalid');
333 }
334 } else {
335 $this->warning('RIFF.WAVE.BEXT.origin_date is invalid');
336 }
337 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
338 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
339 }
340
341 if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
342 // shortcut
343 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0];
344
345 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
346 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001);
347 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
348 $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true;
349 $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004);
350 $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008);
351
352 $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
353 }
354 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
355 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
356 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001);
357 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002);
358 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004);
359 }
360
361 if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
362 // shortcut
363 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0];
364
365 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
366 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
367 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
368 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
369 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
370 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
371 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
372 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
373 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
374 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
375 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
376 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
377 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
378 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
379 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
380 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true);
381 for ($i = 0; $i < 8; $i++) {
382 $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4);
383 $thisfile_riff_WAVE_cart_0['post_time'][$i]['timer_value'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8) + 4, 4));
384 }
385 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
386 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
387 $thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772);
388
389 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
390 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
391 }
392
393 if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
394 // SoundMiner metadata
395
396 // shortcuts
397 $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0];
398 $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data'];
399 $SNDM_startoffset = 0;
400 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size'];
401
402 while ($SNDM_startoffset < $SNDM_endoffset) {
403 $SNDM_thisTagOffset = 0;
404 $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
405 $SNDM_thisTagOffset += 4;
406 $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
407 $SNDM_thisTagOffset += 4;
408 $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
409 $SNDM_thisTagOffset += 2;
410 $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
411 $SNDM_thisTagOffset += 2;
412 $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
413 $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
414
415 if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
416 $this->warning('RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
417 break;
418 } elseif ($SNDM_thisTagSize <= 0) {
419 $this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
420 break;
421 }
422 $SNDM_startoffset += $SNDM_thisTagSize;
423
424 $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
425 if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
426 $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
427 } else {
428 $this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
429 }
430 }
431
432 $tagmapping = array(
433 'tracktitle'=>'title',
434 'category' =>'genre',
435 'cdtitle' =>'album',
436 );
437 foreach ($tagmapping as $fromkey => $tokey) {
438 if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
439 $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
440 }
441 }
442 }
443
444 if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
445 // requires functions simplexml_load_string and get_object_vars
446 if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) {
447 $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
448 if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
449 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']);
450 $thisfile_riff_WAVE['iXML'][0]['master_speed'] = (int) $numerator / ($denominator ? $denominator : 1000);
451 }
452 if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
453 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']);
454 $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = (int) $numerator / ($denominator ? $denominator : 1000);
455 }
456 if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
457 $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
458 $timestamp_sample_rate = (is_array($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) ? max($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) : $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']); // XML could possibly contain more than one TIMESTAMP_SAMPLE_RATE tag, returning as array instead of integer [why? does it make sense? perhaps doesn't matter but getID3 needs to deal with it] - see https://github.com/JamesHeinrich/getID3/issues/105
459 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate;
460 $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
461 $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60);
462 $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
463 $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
464 $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
465 $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
466 unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f);
467 }
468 unset($parsedXML);
469 }
470 }
471
472 if (isset($thisfile_riff_WAVE['guan'][0]['data'])) {
473 // shortcut
474 $thisfile_riff_WAVE_guan_0 = &$thisfile_riff_WAVE['guan'][0];
475 if (!empty($thisfile_riff_WAVE_guan_0['data']) && (substr($thisfile_riff_WAVE_guan_0['data'], 0, 14) == 'GUANO|Version:')) {
476 $thisfile_riff['guano'] = array();
477 foreach (explode("\n", $thisfile_riff_WAVE_guan_0['data']) as $line) {
478 if ($line) {
479 @list($key, $value) = explode(':', $line, 2);
480 if (substr($value, 0, 3) == '[{"') {
481 if ($decoded = @json_decode($value, true)) {
482 if (count($decoded) === 1) {
483 $value = $decoded[0];
484 } else {
485 $value = $decoded;
486 }
487 }
488 }
489 $thisfile_riff['guano'] = array_merge_recursive($thisfile_riff['guano'], getid3_lib::CreateDeepArray($key, '|', $value));
490 }
491 }
492
493 // https://www.wildlifeacoustics.com/SCHEMA/GUANO.html
494 foreach ($thisfile_riff['guano'] as $key => $value) {
495 switch ($key) {
496 case 'Loc Position':
497 if (preg_match('#^([\\+\\-]?[0-9]+\\.[0-9]+) ([\\+\\-]?[0-9]+\\.[0-9]+)$#', $value, $matches)) {
498 list($dummy, $latitude, $longitude) = $matches;
499 $thisfile_riff['comments']['gps_latitude'][0] = floatval($latitude);
500 $thisfile_riff['comments']['gps_longitude'][0] = floatval($longitude);
501 $thisfile_riff['guano'][$key] = floatval($latitude).' '.floatval($longitude);
502 }
503 break;
504 case 'Loc Elevation': // Elevation/altitude above mean sea level in meters
505 $thisfile_riff['comments']['gps_altitude'][0] = floatval($value);
506 $thisfile_riff['guano'][$key] = (float) $value;
507 break;
508 case 'Filter HP': // High-pass filter frequency in kHz
509 case 'Filter LP': // Low-pass filter frequency in kHz
510 case 'Humidity': // Relative humidity as a percentage
511 case 'Length': // Recording length in seconds
512 case 'Loc Accuracy': // Estimated Position Error in meters
513 case 'Temperature Ext': // External temperature in degrees Celsius outside the recorder's housing
514 case 'Temperature Int': // Internal temperature in degrees Celsius inside the recorder's housing
515 $thisfile_riff['guano'][$key] = (float) $value;
516 break;
517 case 'Samplerate': // Recording sample rate, Hz
518 case 'TE': // Time-expansion factor. If not specified, then 1 (no time-expansion a.k.a. direct-recording) is assumed.
519 $thisfile_riff['guano'][$key] = (int) $value;
520 break;
521 }
522 }
523
524 } else {
525 $this->warning('RIFF.guan data not in expected format');
526 }
527 }
528
529 if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
530 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
531 $info['playtime_seconds'] = (float)getid3_lib::SafeDiv((($info['avdataend'] - $info['avdataoffset']) * 8), $thisfile_audio['bitrate']);
532 }
533
534 if (!empty($info['wavpack'])) {
535 $thisfile_audio_dataformat = 'wavpack';
536 $thisfile_audio['bitrate_mode'] = 'vbr';
537 $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version'];
538
539 // Reset to the way it was - RIFF parsing will have messed this up
540 $info['avdataend'] = $Original['avdataend'];
541 $thisfile_audio['bitrate'] = getid3_lib::SafeDiv(($info['avdataend'] - $info['avdataoffset']) * 8, $info['playtime_seconds']);
542
543 $this->fseek($info['avdataoffset'] - 44);
544 $RIFFdata = $this->fread(44);
545 $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8;
546 $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
547
548 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
549 $info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
550 $this->fseek($info['avdataend']);
551 $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
552 }
553
554 // move the data chunk after all other chunks (if any)
555 // so that the RIFF parser doesn't see EOF when trying
556 // to skip over the data chunk
557 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
558 $getid3_riff = new getid3_riff($this->getid3);
559 $getid3_riff->ParseRIFFdata($RIFFdata);
560 unset($getid3_riff);
561 }
562
563 if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
564 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
565 case 0x0001: // PCM
566 if (!empty($info['ac3'])) {
567 // Dolby Digital WAV files masquerade as PCM-WAV, but they're not
568 $thisfile_audio['wformattag'] = 0x2000;
569 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
570 $thisfile_audio['lossless'] = false;
571 $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
572 $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
573 }
574 if (!empty($info['dts'])) {
575 // Dolby DTS files masquerade as PCM-WAV, but they're not
576 $thisfile_audio['wformattag'] = 0x2001;
577 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
578 $thisfile_audio['lossless'] = false;
579 $thisfile_audio['bitrate'] = $info['dts']['bitrate'];
580 $thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
581 }
582 break;
583 case 0x08AE: // ClearJump LiteWave
584 $thisfile_audio['bitrate_mode'] = 'vbr';
585 $thisfile_audio_dataformat = 'litewave';
586
587 //typedef struct tagSLwFormat {
588 // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags
589 // DWORD m_dwScale; // scale factor for lossy compression
590 // DWORD m_dwBlockSize; // number of samples in encoded blocks
591 // WORD m_wQuality; // alias for the scale factor
592 // WORD m_wMarkDistance; // distance between marks in bytes
593 // WORD m_wReserved;
594 //
595 // //following paramters are ignored if CF_FILESRC is not set
596 // DWORD m_dwOrgSize; // original file size in bytes
597 // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file
598 // DWORD m_dwRiffChunkSize; // riff chunk size in the original file
599 //
600 // PCMWAVEFORMAT m_OrgWf; // original wave format
601 // }SLwFormat, *PSLwFormat;
602
603 // shortcut
604 $thisfile_riff['litewave']['raw'] = array();
605 $riff_litewave = &$thisfile_riff['litewave'];
606 $riff_litewave_raw = &$riff_litewave['raw'];
607
608 $flags = array(
609 'compression_method' => 1,
610 'compression_flags' => 1,
611 'm_dwScale' => 4,
612 'm_dwBlockSize' => 4,
613 'm_wQuality' => 2,
614 'm_wMarkDistance' => 2,
615 'm_wReserved' => 2,
616 'm_dwOrgSize' => 4,
617 'm_bFactExists' => 2,
618 'm_dwRiffChunkSize' => 4,
619 );
620 $litewave_offset = 18;
621 foreach ($flags as $flag => $length) {
622 $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
623 $litewave_offset += $length;
624 }
625
626 //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
627 $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
628
629 $riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
630 $riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
631 $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04);
632
633 $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false);
634 $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor'];
635 break;
636
637 default:
638 break;
639 }
640 }
641 if ($info['avdataend'] > $info['filesize']) {
642 switch ($thisfile_audio_dataformat) {
643 case 'wavpack': // WavPack
644 case 'lpac': // LPAC
645 case 'ofr': // OptimFROG
646 case 'ofs': // OptimFROG DualStream
647 // lossless compressed audio formats that keep original RIFF headers - skip warning
648 break;
649
650 case 'litewave':
651 if (($info['avdataend'] - $info['filesize']) == 1) {
652 // LiteWave appears to incorrectly *not* pad actual output file
653 // to nearest WORD boundary so may appear to be short by one
654 // byte, in which case - skip warning
655 } else {
656 // Short by more than one byte, throw warning
657 $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
658 $info['avdataend'] = $info['filesize'];
659 }
660 break;
661
662 default:
663 if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
664 // output file appears to be incorrectly *not* padded to nearest WORD boundary
665 // Output less severe warning
666 $this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
667 $info['avdataend'] = $info['filesize'];
668 } else {
669 // Short by more than one byte, throw warning
670 $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
671 $info['avdataend'] = $info['filesize'];
672 }
673 break;
674 }
675 }
676 if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
677 if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
678 $info['avdataend']--;
679 $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
680 }
681 }
682 if ($thisfile_audio_dataformat == 'ac3') {
683 unset($thisfile_audio['bits_per_sample']);
684 if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) {
685 $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
686 }
687 }
688 break;
689
690 // http://en.wikipedia.org/wiki/Audio_Video_Interleave
691 case 'AVI ':
692 $info['fileformat'] = 'avi';
693 $info['mime_type'] = 'video/avi';
694
695 $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
696 $thisfile_video['dataformat'] = 'avi';
697
698 $thisfile_riff_video_current = array();
699
700 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
701 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
702 if (isset($thisfile_riff['AVIX'])) {
703 $info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size'];
704 } else {
705 $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
706 }
707 if ($info['avdataend'] > $info['filesize']) {
708 $this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)');
709 $info['avdataend'] = $info['filesize'];
710 }
711 }
712
713 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
714 //$bIndexType = array(
715 // 0x00 => 'AVI_INDEX_OF_INDEXES',
716 // 0x01 => 'AVI_INDEX_OF_CHUNKS',
717 // 0x80 => 'AVI_INDEX_IS_DATA',
718 //);
719 //$bIndexSubtype = array(
720 // 0x01 => array(
721 // 0x01 => 'AVI_INDEX_2FIELD',
722 // ),
723 //);
724 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
725 $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
726
727 $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2));
728 $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1));
729 $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1));
730 $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4));
731 $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4);
732 $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
733
734 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
735 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
736
737 unset($ahsisd);
738 }
739 }
740 if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
741 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
742
743 // shortcut
744 $thisfile_riff_raw['avih'] = array();
745 $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
746
747 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
748 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
749 $this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
750 return false;
751 }
752
753 $flags = array(
754 'dwMaxBytesPerSec', // max. transfer rate
755 'dwPaddingGranularity', // pad to multiples of this size; normally 2K.
756 'dwFlags', // the ever-present flags
757 'dwTotalFrames', // # frames in file
758 'dwInitialFrames', //
759 'dwStreams', //
760 'dwSuggestedBufferSize', //
761 'dwWidth', //
762 'dwHeight', //
763 'dwScale', //
764 'dwRate', //
765 'dwStart', //
766 'dwLength', //
767 );
768 $avih_offset = 4;
769 foreach ($flags as $flag) {
770 $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
771 $avih_offset += 4;
772 }
773
774 $flags = array(
775 'hasindex' => 0x00000010,
776 'mustuseindex' => 0x00000020,
777 'interleaved' => 0x00000100,
778 'trustcktype' => 0x00000800,
779 'capturedfile' => 0x00010000,
780 'copyrighted' => 0x00020010,
781 );
782 foreach ($flags as $flag => $value) {
783 $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
784 }
785
786 // shortcut
787 $thisfile_riff_video[$streamindex] = array();
788 /** @var array $thisfile_riff_video_current */
789 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
790
791 if ($thisfile_riff_raw_avih['dwWidth'] > 0) { // @phpstan-ignore-line
792 $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
793 $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
794 }
795 if ($thisfile_riff_raw_avih['dwHeight'] > 0) { // @phpstan-ignore-line
796 $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
797 $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
798 }
799 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) { // @phpstan-ignore-line
800 $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
801 $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
802 }
803
804 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
805 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
806 }
807 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
808 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
809 $thisfile_riff_raw_strf_strhfccType_streamindex = null;
810 for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
811 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
812 $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
813 $strhfccType = substr($strhData, 0, 4);
814
815 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
816 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
817
818 if (!isset($thisfile_riff_raw['strf'][$strhfccType][$streamindex])) {
819 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = null;
820 }
821 // shortcut
822 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
823
824 switch ($strhfccType) {
825 case 'auds':
826 $thisfile_audio['bitrate_mode'] = 'cbr';
827 $thisfile_audio_dataformat = 'wav';
828 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
829 $streamindex = count($thisfile_riff_audio);
830 }
831
832 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
833 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
834
835 // shortcut
836 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
837 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
838
839 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
840 unset($thisfile_audio_streams_currentstream['bits_per_sample']);
841 }
842 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
843 unset($thisfile_audio_streams_currentstream['raw']);
844
845 // shortcut
846 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
847
848 unset($thisfile_riff_audio[$streamindex]['raw']);
849 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
850
851 $thisfile_audio['lossless'] = false;
852 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
853 case 0x0001: // PCM
854 $thisfile_audio_dataformat = 'wav';
855 $thisfile_audio['lossless'] = true;
856 break;
857
858 case 0x0050: // MPEG Layer 2 or Layer 1
859 $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2
860 break;
861
862 case 0x0055: // MPEG Layer 3
863 $thisfile_audio_dataformat = 'mp3';
864 break;
865
866 case 0x00FF: // AAC
867 $thisfile_audio_dataformat = 'aac';
868 break;
869
870 case 0x0161: // Windows Media v7 / v8 / v9
871 case 0x0162: // Windows Media Professional v9
872 case 0x0163: // Windows Media Lossess v9
873 $thisfile_audio_dataformat = 'wma';
874 break;
875
876 case 0x2000: // AC-3
877 $thisfile_audio_dataformat = 'ac3';
878 break;
879
880 case 0x2001: // DTS
881 $thisfile_audio_dataformat = 'dts';
882 break;
883
884 default:
885 $thisfile_audio_dataformat = 'wav';
886 break;
887 }
888 $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
889 $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
890 $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
891 break;
892
893
894 case 'iavs':
895 case 'vids':
896 // shortcut
897 $thisfile_riff_raw['strh'][$i] = array();
898 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i];
899
900 $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType;
901 $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
902 $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags
903 $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2));
904 $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2));
905 $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4));
906 $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4));
907 $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4));
908 $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4));
909 $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4));
910 $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
911 $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4));
912 $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4));
913 $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4));
914
915 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
916 $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
917 if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
918 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
919 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
920 }
921 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
922 $thisfile_video['pixel_aspect_ratio'] = (float) 1;
923 switch ($thisfile_riff_raw_strh_current['fccHandler']) {
924 case 'HFYU': // Huffman Lossless Codec
925 case 'IRAW': // Intel YUV Uncompressed
926 case 'YUY2': // Uncompressed YUV 4:2:2
927 $thisfile_video['lossless'] = true;
928 break;
929
930 default:
931 $thisfile_video['lossless'] = false;
932 break;
933 }
934
935 switch ($strhfccType) {
936 case 'vids':
937 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container == 'riff'));
938 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
939
940 if ($thisfile_riff_video_current['codec'] == 'DV') {
941 $thisfile_riff_video_current['dv_type'] = 2;
942 }
943 break;
944
945 case 'iavs':
946 $thisfile_riff_video_current['dv_type'] = 1;
947 break;
948 }
949 break;
950
951 default:
952 $this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"');
953 break;
954
955 }
956 }
957 }
958
959 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
960
961 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
962 if (self::fourccLookup($thisfile_video['fourcc'])) {
963 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']);
964 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
965 }
966
967 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
968 case 'HFYU': // Huffman Lossless Codec
969 case 'IRAW': // Intel YUV Uncompressed
970 case 'YUY2': // Uncompressed YUV 4:2:2
971 $thisfile_video['lossless'] = true;
972 //$thisfile_video['bits_per_sample'] = 24;
973 break;
974
975 default:
976 $thisfile_video['lossless'] = false;
977 //$thisfile_video['bits_per_sample'] = 24;
978 break;
979 }
980
981 }
982 }
983 }
984 }
985 break;
986
987
988 case 'AMV ':
989 $info['fileformat'] = 'amv';
990 $info['mime_type'] = 'video/amv';
991
992 $thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR
993 $thisfile_video['dataformat'] = 'mjpeg';
994 $thisfile_video['codec'] = 'mjpeg';
995 $thisfile_video['lossless'] = false;
996 $thisfile_video['bits_per_sample'] = 24;
997
998 $thisfile_audio['dataformat'] = 'adpcm';
999 $thisfile_audio['lossless'] = false;
1000 break;
1001
1002
1003 // http://en.wikipedia.org/wiki/CD-DA
1004 case 'CDDA':
1005 $info['fileformat'] = 'cda';
1006 unset($info['mime_type']);
1007
1008 $thisfile_audio_dataformat = 'cda';
1009
1010 $info['avdataoffset'] = 44;
1011
1012 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
1013 // shortcut
1014 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0];
1015
1016 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2));
1017 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2));
1018 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4));
1019 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4));
1020 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
1021 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
1022 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
1023
1024 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
1025 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
1026 $info['comments']['track_number'] = $thisfile_riff_CDDA_fmt_0['track_num'];
1027 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
1028
1029 // hardcoded data for CD-audio
1030 $thisfile_audio['lossless'] = true;
1031 $thisfile_audio['sample_rate'] = 44100;
1032 $thisfile_audio['channels'] = 2;
1033 $thisfile_audio['bits_per_sample'] = 16;
1034 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
1035 $thisfile_audio['bitrate_mode'] = 'cbr';
1036 }
1037 break;
1038
1039 // http://en.wikipedia.org/wiki/AIFF
1040 case 'AIFF':
1041 case 'AIFC':
1042 $info['fileformat'] = 'aiff';
1043 $info['mime_type'] = 'audio/x-aiff';
1044
1045 $thisfile_audio['bitrate_mode'] = 'cbr';
1046 $thisfile_audio_dataformat = 'aiff';
1047 $thisfile_audio['lossless'] = true;
1048
1049 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
1050 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8;
1051 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
1052 if ($info['avdataend'] > $info['filesize']) {
1053 if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) {
1054 // structures rounded to 2-byte boundary, but dumb encoders
1055 // forget to pad end of file to make this actually work
1056 } else {
1057 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
1058 }
1059 $info['avdataend'] = $info['filesize'];
1060 }
1061 }
1062
1063 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
1064
1065 // shortcut
1066 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
1067
1068 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true);
1069 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false);
1070 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true);
1071 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
1072
1073 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
1074 $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
1075 $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false);
1076 $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
1077 switch ($thisfile_riff_audio['codec_name']) {
1078 case 'NONE':
1079 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
1080 $thisfile_audio['lossless'] = true;
1081 break;
1082
1083 case '':
1084 switch ($thisfile_riff_audio['codec_fourcc']) {
1085 // http://developer.apple.com/qa/snd/snd07.html
1086 case 'sowt':
1087 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
1088 $thisfile_audio['lossless'] = true;
1089 break;
1090
1091 case 'twos':
1092 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
1093 $thisfile_audio['lossless'] = true;
1094 break;
1095
1096 default:
1097 break;
1098 }
1099 break;
1100
1101 default:
1102 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
1103 $thisfile_audio['lossless'] = false;
1104 break;
1105 }
1106 }
1107
1108 $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
1109 if ($thisfile_riff_audio['bits_per_sample'] > 0) {
1110 $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
1111 }
1112 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
1113 if ($thisfile_audio['sample_rate'] == 0) {
1114 $this->error('Corrupted AIFF file: sample_rate == zero');
1115 return false;
1116 }
1117 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
1118 }
1119
1120 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
1121 $offset = 0;
1122 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
1123 $offset += 2;
1124 for ($i = 0; $i < $CommentCount; $i++) {
1125 $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
1126 $offset += 4;
1127 $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
1128 $offset += 2;
1129 $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
1130 $offset += 2;
1131 $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
1132 $offset += $CommentLength;
1133
1134 $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']);
1135 $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment'];
1136 }
1137 }
1138
1139 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
1140 foreach ($CommentsChunkNames as $key => $value) {
1141 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
1142 // https://github.com/JamesHeinrich/getID3/issues/430
1143 $null_terminator_rows = explode("\x00", $thisfile_riff[$RIFFsubtype][$key][0]['data']);
1144 $thisfile_riff['comments'][$value][] = $null_terminator_rows[0];
1145 }
1146 }
1147/*
1148 if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
1149 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
1150 $getid3_temp = new getID3();
1151 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1152 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
1153 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
1154 if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
1155 $info['id3v2'] = $getid3_temp->info['id3v2'];
1156 }
1157 unset($getid3_temp, $getid3_id3v2);
1158 }
1159*/
1160 break;
1161
1162 // http://en.wikipedia.org/wiki/8SVX
1163 case '8SVX':
1164 $info['fileformat'] = '8svx';
1165 $info['mime_type'] = 'audio/8svx';
1166
1167 $thisfile_audio['bitrate_mode'] = 'cbr';
1168 $thisfile_audio_dataformat = '8svx';
1169 $thisfile_audio['bits_per_sample'] = 8;
1170 $thisfile_audio['channels'] = 1; // overridden below, if need be
1171 $ActualBitsPerSample = 0;
1172
1173 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
1174 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
1175 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
1176 if ($info['avdataend'] > $info['filesize']) {
1177 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
1178 }
1179 }
1180
1181 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
1182 // shortcut
1183 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0];
1184
1185 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4));
1186 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4));
1187 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4));
1188 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
1189 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
1190 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
1191 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
1192
1193 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
1194
1195 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
1196 case 0:
1197 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
1198 $thisfile_audio['lossless'] = true;
1199 $ActualBitsPerSample = 8;
1200 break;
1201
1202 case 1:
1203 $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
1204 $thisfile_audio['lossless'] = false;
1205 $ActualBitsPerSample = 4;
1206 break;
1207
1208 default:
1209 $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"');
1210 break;
1211 }
1212 }
1213
1214 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
1215 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
1216 switch ($ChannelsIndex) {
1217 case 6: // Stereo
1218 $thisfile_audio['channels'] = 2;
1219 break;
1220
1221 case 2: // Left channel only
1222 case 4: // Right channel only
1223 $thisfile_audio['channels'] = 1;
1224 break;
1225
1226 default:
1227 $this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"');
1228 break;
1229 }
1230
1231 }
1232
1233 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
1234 foreach ($CommentsChunkNames as $key => $value) {
1235 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
1236 // https://github.com/JamesHeinrich/getID3/issues/430
1237 $null_terminator_rows = explode("\x00", $thisfile_riff[$RIFFsubtype][$key][0]['data']);
1238 $thisfile_riff['comments'][$value][] = $null_terminator_rows[0];
1239 }
1240 }
1241
1242 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
1243 if (!empty($thisfile_audio['bitrate'])) {
1244 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8);
1245 }
1246 break;
1247
1248 case 'CDXA':
1249 $info['fileformat'] = 'vcd'; // Asume Video CD
1250 $info['mime_type'] = 'video/mpeg';
1251
1252 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
1253 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
1254
1255 $getid3_temp = new getID3();
1256 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1257 $getid3_mpeg = new getid3_mpeg($getid3_temp);
1258 $getid3_mpeg->Analyze();
1259 if (empty($getid3_temp->info['error'])) {
1260 $info['audio'] = $getid3_temp->info['audio'];
1261 $info['video'] = $getid3_temp->info['video'];
1262 $info['mpeg'] = $getid3_temp->info['mpeg'];
1263 $info['warning'] = $getid3_temp->info['warning'];
1264 }
1265 unset($getid3_temp, $getid3_mpeg);
1266 }
1267 break;
1268
1269 case 'WEBP':
1270 // https://developers.google.com/speed/webp/docs/riff_container
1271 // https://tools.ietf.org/html/rfc6386
1272 // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
1273 $info['fileformat'] = 'webp';
1274 $info['mime_type'] = 'image/webp';
1275
1276 if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
1277 $old_offset = $this->ftell();
1278 $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size
1279 $WEBP_VP8_header = $this->fread(10);
1280 $this->fseek($old_offset);
1281 if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
1282 $thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
1283 $thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
1284 $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
1285 $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0;
1286
1287 $thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
1288 $thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
1289 $thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
1290 $thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
1291
1292 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
1293 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
1294 } else {
1295 $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
1296 }
1297
1298 }
1299 if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
1300 $old_offset = $this->ftell();
1301 $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size
1302 $WEBP_VP8L_header = $this->fread(10);
1303 $this->fseek($old_offset);
1304 if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
1305 $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
1306 $thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1;
1307 $thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1;
1308 $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1));
1309 $thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3));
1310
1311 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
1312 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
1313 } else {
1314 $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
1315 }
1316
1317 }
1318 break;
1319
1320 default:
1321 $this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead');
1322 //unset($info['fileformat']);
1323 }
1324
1325 switch ($RIFFsubtype) {
1326 case 'WAVE':
1327 case 'AIFF':
1328 case 'AIFC':
1329 $ID3v2_key_good = 'id3 ';
1330 $ID3v2_keys_bad = array('ID3 ', 'tag ');
1331 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
1332 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
1333 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
1334 $this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"');
1335 }
1336 }
1337
1338 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
1339 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
1340
1341 $getid3_temp = new getID3();
1342 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1343 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
1344 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
1345 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
1346 $info['id3v2'] = $getid3_temp->info['id3v2'];
1347 }
1348 unset($getid3_temp, $getid3_id3v2);
1349 }
1350 break;
1351 }
1352
1353 if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
1354 $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
1355 }
1356 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
1357 self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
1358 }
1359 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
1360 self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']);
1361 }
1362
1363 if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) {
1364 $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version'];
1365 }
1366
1367 if (!isset($info['playtime_seconds'])) {
1368 $info['playtime_seconds'] = 0;
1369 }
1370 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { // @phpstan-ignore-line
1371 // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
1372 $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
1373 } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { // @phpstan-ignore-line
1374 $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
1375 }
1376
1377 if ($info['playtime_seconds'] > 0) {
1378 if ($thisfile_riff_audio !== null && $thisfile_riff_video !== null) {
1379
1380 if (!isset($info['bitrate'])) {
1381 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1382 }
1383
1384 } elseif ($thisfile_riff_audio !== null && $thisfile_riff_video === null) { // @phpstan-ignore-line
1385
1386 if (!isset($thisfile_audio['bitrate'])) {
1387 $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1388 }
1389
1390 } elseif ($thisfile_riff_audio === null && $thisfile_riff_video !== null) {
1391
1392 if (!isset($thisfile_video['bitrate'])) {
1393 $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1394 }
1395
1396 }
1397 }
1398
1399
1400 if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) {
1401
1402 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1403 $thisfile_audio['bitrate'] = 0;
1404 $thisfile_video['bitrate'] = $info['bitrate'];
1405 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
1406 $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
1407 $thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
1408 }
1409 if ($thisfile_video['bitrate'] <= 0) {
1410 unset($thisfile_video['bitrate']);
1411 }
1412 if ($thisfile_audio['bitrate'] <= 0) {
1413 unset($thisfile_audio['bitrate']);
1414 }
1415 }
1416
1417 if (isset($info['mpeg']['audio'])) {
1418 $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer'];
1419 $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
1420 $thisfile_audio['channels'] = $info['mpeg']['audio']['channels'];
1421 $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate'];
1422 $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1423 if (!empty($info['mpeg']['audio']['codec'])) {
1424 $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec'];
1425 }
1426 if (!empty($thisfile_audio['streams'])) {
1427 foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
1428 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
1429 $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
1430 $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
1431 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
1432 $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
1433 $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
1434 }
1435 }
1436 }
1437 $getid3_mp3 = new getid3_mp3($this->getid3);
1438 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
1439 unset($getid3_mp3);
1440 }
1441
1442
1443 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
1444 switch ($thisfile_audio_dataformat) {
1445 case 'ac3':
1446 // ignore bits_per_sample
1447 break;
1448
1449 default:
1450 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
1451 break;
1452 }
1453 }
1454
1455
1456 if (empty($thisfile_riff_raw)) {
1457 unset($thisfile_riff['raw']);
1458 }
1459 if (empty($thisfile_riff_audio)) {
1460 unset($thisfile_riff['audio']);
1461 }
1462 if (empty($thisfile_riff_video)) {
1463 unset($thisfile_riff['video']);
1464 }
1465
1466 return true;
1467 }
1468
1469 /**
1470 * @param int $startoffset
1471 * @param int $maxoffset
1472 *
1473 * @return array|false
1474 *
1475 * @throws Exception
1476 * @throws getid3_exception
1477 */
1478 public function ParseRIFFAMV($startoffset, $maxoffset) {
1479 // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
1480
1481 // https://code.google.com/p/amv-codec-tools/wiki/AmvDocumentation
1482 //typedef struct _amvmainheader {
1483 //FOURCC fcc; // 'amvh'
1484 //DWORD cb;
1485 //DWORD dwMicroSecPerFrame;
1486 //BYTE reserve[28];
1487 //DWORD dwWidth;
1488 //DWORD dwHeight;
1489 //DWORD dwSpeed;
1490 //DWORD reserve0;
1491 //DWORD reserve1;
1492 //BYTE bTimeSec;
1493 //BYTE bTimeMin;
1494 //WORD wTimeHour;
1495 //} AMVMAINHEADER;
1496
1497 $info = &$this->getid3->info;
1498 $RIFFchunk = false;
1499
1500 try {
1501
1502 $this->fseek($startoffset);
1503 $maxoffset = min($maxoffset, $info['avdataend']);
1504 $AMVheader = $this->fread(284);
1505 if (substr($AMVheader, 0, 8) != 'hdrlamvh') {
1506 throw new Exception('expecting "hdrlamv" at offset '.($startoffset + 0).', found "'.substr($AMVheader, 0, 8).'"');
1507 }
1508 if (substr($AMVheader, 8, 4) != "\x38\x00\x00\x00") { // "amvh" chunk size, hardcoded to 0x38 = 56 bytes
1509 throw new Exception('expecting "0x38000000" at offset '.($startoffset + 8).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 8, 4)).'"');
1510 }
1511 $RIFFchunk = array();
1512 $RIFFchunk['amvh']['us_per_frame'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 12, 4));
1513 $RIFFchunk['amvh']['reserved28'] = substr($AMVheader, 16, 28); // null? reserved?
1514 $RIFFchunk['amvh']['resolution_x'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 44, 4));
1515 $RIFFchunk['amvh']['resolution_y'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 48, 4));
1516 $RIFFchunk['amvh']['frame_rate_int'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 52, 4));
1517 $RIFFchunk['amvh']['reserved0'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 56, 4)); // 1? reserved?
1518 $RIFFchunk['amvh']['reserved1'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 60, 4)); // 0? reserved?
1519 $RIFFchunk['amvh']['runtime_sec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 64, 1));
1520 $RIFFchunk['amvh']['runtime_min'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 65, 1));
1521 $RIFFchunk['amvh']['runtime_hrs'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 66, 2));
1522
1523 $info['video']['frame_rate'] = 1000000 / $RIFFchunk['amvh']['us_per_frame'];
1524 $info['video']['resolution_x'] = $RIFFchunk['amvh']['resolution_x'];
1525 $info['video']['resolution_y'] = $RIFFchunk['amvh']['resolution_y'];
1526 $info['playtime_seconds'] = ($RIFFchunk['amvh']['runtime_hrs'] * 3600) + ($RIFFchunk['amvh']['runtime_min'] * 60) + $RIFFchunk['amvh']['runtime_sec'];
1527
1528 // the rest is all hardcoded(?) and does not appear to be useful until you get to audio info at offset 256, even then everything is probably hardcoded
1529
1530 if (substr($AMVheader, 68, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x38\x00\x00\x00") {
1531 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x38000000>" at offset '.($startoffset + 68).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 68, 20)).'"');
1532 }
1533 // followed by 56 bytes of null: substr($AMVheader, 88, 56) -> 144
1534 if (substr($AMVheader, 144, 8) != 'strf'."\x24\x00\x00\x00") {
1535 throw new Exception('expecting "strf<0x24000000>" at offset '.($startoffset + 144).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 144, 8)).'"');
1536 }
1537 // followed by 36 bytes of null: substr($AMVheader, 144, 36) -> 180
1538
1539 if (substr($AMVheader, 188, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x30\x00\x00\x00") {
1540 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x30000000>" at offset '.($startoffset + 188).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 188, 20)).'"');
1541 }
1542 // followed by 48 bytes of null: substr($AMVheader, 208, 48) -> 256
1543 if (substr($AMVheader, 256, 8) != 'strf'."\x14\x00\x00\x00") {
1544 throw new Exception('expecting "strf<0x14000000>" at offset '.($startoffset + 256).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 256, 8)).'"');
1545 }
1546 // followed by 20 bytes of a modified WAVEFORMATEX:
1547 // typedef struct {
1548 // WORD wFormatTag; //(Fixme: this is equal to PCM's 0x01 format code)
1549 // WORD nChannels; //(Fixme: this is always 1)
1550 // DWORD nSamplesPerSec; //(Fixme: for all known sample files this is equal to 22050)
1551 // DWORD nAvgBytesPerSec; //(Fixme: for all known sample files this is equal to 44100)
1552 // WORD nBlockAlign; //(Fixme: this seems to be 2 in AMV files, is this correct ?)
1553 // WORD wBitsPerSample; //(Fixme: this seems to be 16 in AMV files instead of the expected 4)
1554 // WORD cbSize; //(Fixme: this seems to be 0 in AMV files)
1555 // WORD reserved;
1556 // } WAVEFORMATEX;
1557 $RIFFchunk['strf']['wformattag'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 264, 2));
1558 $RIFFchunk['strf']['nchannels'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 266, 2));
1559 $RIFFchunk['strf']['nsamplespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 268, 4));
1560 $RIFFchunk['strf']['navgbytespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 272, 4));
1561 $RIFFchunk['strf']['nblockalign'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 276, 2));
1562 $RIFFchunk['strf']['wbitspersample'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 278, 2));
1563 $RIFFchunk['strf']['cbsize'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 280, 2));
1564 $RIFFchunk['strf']['reserved'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 282, 2));
1565
1566
1567 $info['audio']['lossless'] = false;
1568 $info['audio']['sample_rate'] = $RIFFchunk['strf']['nsamplespersec'];
1569 $info['audio']['channels'] = $RIFFchunk['strf']['nchannels'];
1570 $info['audio']['bits_per_sample'] = $RIFFchunk['strf']['wbitspersample'];
1571 $info['audio']['bitrate'] = $info['audio']['sample_rate'] * $info['audio']['channels'] * $info['audio']['bits_per_sample'];
1572 $info['audio']['bitrate_mode'] = 'cbr';
1573
1574
1575 } catch (getid3_exception $e) {
1576 if ($e->getCode() == 10) {
1577 $this->warning('RIFFAMV parser: '.$e->getMessage());
1578 } else {
1579 throw $e;
1580 }
1581 }
1582
1583 return $RIFFchunk;
1584 }
1585
1586 /**
1587 * @param int $startoffset
1588 * @param int $maxoffset
1589 *
1590 * @return array|false
1591 * @throws getid3_exception
1592 */
1593 public function ParseRIFF($startoffset, $maxoffset) {
1594 $info = &$this->getid3->info;
1595
1596 $RIFFchunk = array();
1597 $FoundAllChunksWeNeed = false;
1598 $LISTchunkParent = null;
1599 $LISTchunkMaxOffset = null;
1600 $AC3syncwordBytes = pack('n', getid3_ac3::syncword); // 0x0B77 -> "\x0B\x77"
1601
1602 try {
1603 $this->fseek($startoffset);
1604 $maxoffset = min($maxoffset, $info['avdataend']);
1605 while ($this->ftell() < $maxoffset) {
1606 $chunknamesize = $this->fread(8);
1607 //$chunkname = substr($chunknamesize, 0, 4);
1608 $chunkname = str_replace("\x00", '_', substr($chunknamesize, 0, 4)); // note: chunk names of 4 null bytes do appear to be legal (has been observed inside INFO and PRMI chunks, for example), but makes traversing array keys more difficult
1609 $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
1610 //if (strlen(trim($chunkname, "\x00")) < 4) {
1611 if (strlen($chunkname) < 4) {
1612 $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.');
1613 break;
1614 }
1615 if ($chunksize == 0) {
1616 if ($chunkname == 'JUNK') {
1617 // this is allowed
1618 } elseif ($chunkname == 'data') {
1619 // https://github.com/JamesHeinrich/getID3/issues/468
1620 // may occur in streaming files where the data size is unknown
1621 $chunksize = $info['avdataend'] - $this->ftell();
1622 $this->warning('RIFF.data size field is empty, assuming the correct value is filesize-offset ('.$chunksize.')');
1623 } else {
1624 $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.');
1625 break;
1626 }
1627 }
1628 if (($chunksize % 2) != 0) {
1629 // all structures are packed on word boundaries
1630 $chunksize++;
1631 }
1632
1633 switch ($chunkname) {
1634 case 'LIST':
1635 $listname = $this->fread(4);
1636 if (preg_match('#^(movi|rec )$#i', $listname)) {
1637 $RIFFchunk[$listname]['offset'] = $this->ftell() - 4;
1638 $RIFFchunk[$listname]['size'] = $chunksize;
1639
1640 if (!$FoundAllChunksWeNeed) {
1641 $WhereWeWere = $this->ftell();
1642 $AudioChunkHeader = $this->fread(12);
1643 $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
1644 $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
1645 $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
1646
1647 if ($AudioChunkStreamType == 'wb') {
1648 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
1649 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) {
1650 // MP3
1651 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
1652 $getid3_temp = new getID3();
1653 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1654 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
1655 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
1656 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
1657 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
1658 if (isset($getid3_temp->info['mpeg']['audio'])) {
1659 $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio'];
1660 $info['audio'] = $getid3_temp->info['audio'];
1661 $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer'];
1662 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
1663 $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
1664 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
1665 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1666 //$info['bitrate'] = $info['audio']['bitrate'];
1667 }
1668 unset($getid3_temp, $getid3_mp3);
1669 }
1670
1671 } elseif (strpos($FirstFourBytes, $AC3syncwordBytes) === 0) {
1672 // AC3
1673 $getid3_temp = new getID3();
1674 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1675 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
1676 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
1677 $getid3_ac3 = new getid3_ac3($getid3_temp);
1678 $getid3_ac3->Analyze();
1679 if (empty($getid3_temp->info['error'])) {
1680 $info['audio'] = $getid3_temp->info['audio'];
1681 $info['ac3'] = $getid3_temp->info['ac3'];
1682 if (!empty($getid3_temp->info['warning'])) {
1683 foreach ($getid3_temp->info['warning'] as $key => $value) {
1684 $this->warning($value);
1685 }
1686 }
1687 }
1688 unset($getid3_temp, $getid3_ac3);
1689 }
1690 }
1691 $FoundAllChunksWeNeed = true;
1692 $this->fseek($WhereWeWere);
1693 }
1694 $this->fseek($chunksize - 4, SEEK_CUR);
1695
1696 } else {
1697
1698 if (!isset($RIFFchunk[$listname])) {
1699 $RIFFchunk[$listname] = array();
1700 }
1701 $LISTchunkParent = $listname;
1702 $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize;
1703 if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) {
1704 $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
1705 }
1706
1707 }
1708 break;
1709
1710 default:
1711 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
1712 $this->fseek($chunksize, SEEK_CUR);
1713 break;
1714 }
1715 $thisindex = 0;
1716 if (isset($RIFFchunk[$chunkname])) {
1717 $thisindex = count($RIFFchunk[$chunkname]);
1718 }
1719 $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8;
1720 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
1721 switch ($chunkname) {
1722 case 'data':
1723 $info['avdataoffset'] = $this->ftell();
1724 $info['avdataend'] = $info['avdataoffset'] + $chunksize;
1725
1726 $testData = $this->fread(36);
1727 if ($testData === '') {
1728 break;
1729 }
1730 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) {
1731
1732 // Probably is MP3 data
1733 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
1734 $getid3_temp = new getID3();
1735 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1736 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
1737 $getid3_temp->info['avdataend'] = $info['avdataend'];
1738 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
1739 $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false);
1740 if (empty($getid3_temp->info['error'])) {
1741 $info['audio'] = $getid3_temp->info['audio'];
1742 $info['mpeg'] = $getid3_temp->info['mpeg'];
1743 }
1744 unset($getid3_temp, $getid3_mp3);
1745 }
1746
1747 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == $AC3syncwordBytes)) || substr($testData, 8, 2) == strrev($AC3syncwordBytes)) {
1748
1749 // This is probably AC-3 data
1750 $getid3_temp = new getID3();
1751 if ($isRegularAC3) {
1752 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1753 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
1754 $getid3_temp->info['avdataend'] = $info['avdataend'];
1755 }
1756 $getid3_ac3 = new getid3_ac3($getid3_temp);
1757 if ($isRegularAC3) {
1758 $getid3_ac3->Analyze();
1759 } else {
1760 // Dolby Digital WAV
1761 // AC-3 content, but not encoded in same format as normal AC-3 file
1762 // For one thing, byte order is swapped
1763 $ac3_data = '';
1764 for ($i = 0; $i < 28; $i += 2) {
1765 $ac3_data .= substr($testData, 8 + $i + 1, 1);
1766 $ac3_data .= substr($testData, 8 + $i + 0, 1);
1767 }
1768 $getid3_ac3->getid3->info['avdataoffset'] = 0;
1769 $getid3_ac3->getid3->info['avdataend'] = strlen($ac3_data);
1770 $getid3_ac3->AnalyzeString($ac3_data);
1771 }
1772
1773 if (empty($getid3_temp->info['error'])) {
1774 $info['audio'] = $getid3_temp->info['audio'];
1775 $info['ac3'] = $getid3_temp->info['ac3'];
1776 if (!empty($getid3_temp->info['warning'])) {
1777 foreach ($getid3_temp->info['warning'] as $newerror) {
1778 $this->warning('getid3_ac3() says: ['.$newerror.']');
1779 }
1780 }
1781 }
1782 unset($getid3_temp, $getid3_ac3);
1783
1784 } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) {
1785
1786 // This is probably DTS data
1787 $getid3_temp = new getID3();
1788 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
1789 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
1790 $getid3_dts = new getid3_dts($getid3_temp);
1791 $getid3_dts->Analyze();
1792 if (empty($getid3_temp->info['error'])) {
1793 $info['audio'] = $getid3_temp->info['audio'];
1794 $info['dts'] = $getid3_temp->info['dts'];
1795 $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing
1796 if (!empty($getid3_temp->info['warning'])) {
1797 foreach ($getid3_temp->info['warning'] as $newerror) {
1798 $this->warning('getid3_dts() says: ['.$newerror.']');
1799 }
1800 }
1801 }
1802
1803 unset($getid3_temp, $getid3_dts);
1804
1805 } elseif (substr($testData, 0, 4) == 'wvpk') {
1806
1807 // This is WavPack data
1808 $info['wavpack']['offset'] = $info['avdataoffset'];
1809 $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4));
1810 $this->parseWavPackHeader(substr($testData, 8, 28));
1811
1812 } else {
1813 // This is some other kind of data (quite possibly just PCM)
1814 // do nothing special, just skip it
1815 }
1816 $nextoffset = $info['avdataend'];
1817 $this->fseek($nextoffset);
1818 break;
1819
1820 case 'iXML':
1821 case 'bext':
1822 case 'cart':
1823 case 'fmt ':
1824 case 'strh':
1825 case 'strf':
1826 case 'indx':
1827 case 'MEXT':
1828 case 'DISP':
1829 case 'wamd':
1830 case 'guan':
1831 // always read data in
1832 case 'JUNK':
1833 // should be: never read data in
1834 // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
1835 if ($chunksize < 1048576) {
1836 if ($chunksize > 0) {
1837 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1838 if ($chunkname == 'JUNK') {
1839 if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
1840 // only keep text characters [chr(32)-chr(127)]
1841 $info['riff']['comments']['junk'][] = trim($matches[1]);
1842 }
1843 // but if nothing there, ignore
1844 // remove the key in either case
1845 unset($RIFFchunk[$chunkname][$thisindex]['data']);
1846 }
1847 }
1848 } else {
1849 $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data');
1850 $this->fseek($chunksize, SEEK_CUR);
1851 }
1852 break;
1853
1854 //case 'IDVX':
1855 // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
1856 // break;
1857
1858 case 'scot':
1859 // https://cmsdk.com/node-js/adding-scot-chunk-to-wav-file.html
1860 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1861 $RIFFchunk[$chunkname][$thisindex]['parsed']['alter'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 0, 1);
1862 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 1, 1);
1863 $RIFFchunk[$chunkname][$thisindex]['parsed']['artnum'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 2, 2));
1864 $RIFFchunk[$chunkname][$thisindex]['parsed']['title'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 4, 43); // "name" in other documentation
1865 $RIFFchunk[$chunkname][$thisindex]['parsed']['copy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 47, 4);
1866 $RIFFchunk[$chunkname][$thisindex]['parsed']['padd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 51, 1);
1867 $RIFFchunk[$chunkname][$thisindex]['parsed']['asclen'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 52, 5);
1868 $RIFFchunk[$chunkname][$thisindex]['parsed']['startseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 57, 2));
1869 $RIFFchunk[$chunkname][$thisindex]['parsed']['starthundredths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 59, 2));
1870 $RIFFchunk[$chunkname][$thisindex]['parsed']['endseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 61, 2));
1871 $RIFFchunk[$chunkname][$thisindex]['parsed']['endhundreths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 63, 2));
1872 $RIFFchunk[$chunkname][$thisindex]['parsed']['sdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 65, 6);
1873 $RIFFchunk[$chunkname][$thisindex]['parsed']['kdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 71, 6);
1874 $RIFFchunk[$chunkname][$thisindex]['parsed']['start_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 77, 1);
1875 $RIFFchunk[$chunkname][$thisindex]['parsed']['kill_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 78, 1);
1876 $RIFFchunk[$chunkname][$thisindex]['parsed']['digital'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 79, 1);
1877 $RIFFchunk[$chunkname][$thisindex]['parsed']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 80, 2));
1878 $RIFFchunk[$chunkname][$thisindex]['parsed']['stereo'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 82, 1);
1879 $RIFFchunk[$chunkname][$thisindex]['parsed']['compress'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 83, 1);
1880 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomstrt'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 84, 4));
1881 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 88, 2));
1882 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib2'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 90, 4));
1883 $RIFFchunk[$chunkname][$thisindex]['parsed']['future1'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 94, 12);
1884 $RIFFchunk[$chunkname][$thisindex]['parsed']['catfontcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 106, 4));
1885 $RIFFchunk[$chunkname][$thisindex]['parsed']['catcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 110, 4));
1886 $RIFFchunk[$chunkname][$thisindex]['parsed']['segeompos'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 114, 4));
1887 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_startsecs'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 118, 2));
1888 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_starthunds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 120, 2));
1889 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 122, 3);
1890 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 125, 4);
1891 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 129, 1);
1892 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 130, 3);
1893 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 133, 4);
1894 $RIFFchunk[$chunkname][$thisindex]['parsed']['postpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 137, 1);
1895 $RIFFchunk[$chunkname][$thisindex]['parsed']['hrcanplay'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 138, 21);
1896 $RIFFchunk[$chunkname][$thisindex]['parsed']['future2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 159, 108);
1897 $RIFFchunk[$chunkname][$thisindex]['parsed']['artist'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 267, 34);
1898 $RIFFchunk[$chunkname][$thisindex]['parsed']['comment'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 301, 34); // "trivia" in other documentation
1899 $RIFFchunk[$chunkname][$thisindex]['parsed']['intro'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 335, 2);
1900 $RIFFchunk[$chunkname][$thisindex]['parsed']['end'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 337, 1);
1901 $RIFFchunk[$chunkname][$thisindex]['parsed']['year'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 338, 4);
1902 $RIFFchunk[$chunkname][$thisindex]['parsed']['obsolete2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 342, 1);
1903 $RIFFchunk[$chunkname][$thisindex]['parsed']['rec_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 343, 1);
1904 $RIFFchunk[$chunkname][$thisindex]['parsed']['rdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 344, 6);
1905 $RIFFchunk[$chunkname][$thisindex]['parsed']['mpeg_bitrate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 350, 2));
1906 $RIFFchunk[$chunkname][$thisindex]['parsed']['pitch'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 352, 2));
1907 $RIFFchunk[$chunkname][$thisindex]['parsed']['playlevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 354, 2));
1908 $RIFFchunk[$chunkname][$thisindex]['parsed']['lenvalid'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 356, 1);
1909 $RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 357, 4));
1910 $RIFFchunk[$chunkname][$thisindex]['parsed']['newplaylevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 361, 2));
1911 $RIFFchunk[$chunkname][$thisindex]['parsed']['chopsize'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 363, 4));
1912 $RIFFchunk[$chunkname][$thisindex]['parsed']['vteomovr'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 367, 4));
1913 $RIFFchunk[$chunkname][$thisindex]['parsed']['desiredlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 371, 4));
1914 $RIFFchunk[$chunkname][$thisindex]['parsed']['triggers'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 375, 4));
1915 $RIFFchunk[$chunkname][$thisindex]['parsed']['fillout'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 379, 33);
1916
1917 foreach (array('title', 'artist', 'comment') as $key) {
1918 if (trim($RIFFchunk[$chunkname][$thisindex]['parsed'][$key])) {
1919 $info['riff']['comments'][$key] = array($RIFFchunk[$chunkname][$thisindex]['parsed'][$key]);
1920 }
1921 }
1922 if ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] && !empty($info['filesize']) && ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] != $info['filesize'])) {
1923 $this->warning('RIFF.WAVE.scot.filelength ('.$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'].') different from actual filesize ('.$info['filesize'].')');
1924 }
1925 break;
1926
1927 default:
1928 if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
1929 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
1930 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
1931 unset($RIFFchunk[$chunkname][$thisindex]['offset']);
1932 unset($RIFFchunk[$chunkname][$thisindex]['size']);
1933 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
1934 unset($RIFFchunk[$chunkname][$thisindex]);
1935 }
1936 if (count($RIFFchunk[$chunkname]) === 0) {
1937 unset($RIFFchunk[$chunkname]);
1938 }
1939 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1940 } elseif ($chunksize < 2048) {
1941 // only read data in if smaller than 2kB
1942 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1943 } else {
1944 $this->fseek($chunksize, SEEK_CUR);
1945 }
1946 break;
1947 }
1948 break;
1949 }
1950 }
1951
1952 } catch (getid3_exception $e) {
1953 if ($e->getCode() == 10) {
1954 $this->warning('RIFF parser: '.$e->getMessage());
1955 } else {
1956 throw $e;
1957 }
1958 }
1959
1960 return !empty($RIFFchunk) ? $RIFFchunk : false;
1961 }
1962
1963 /**
1964 * @param string $RIFFdata
1965 *
1966 * @return bool
1967 */
1968 public function ParseRIFFdata(&$RIFFdata) {
1969 $info = &$this->getid3->info;
1970 if ($RIFFdata) {
1971 $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3');
1972 $fp_temp = fopen($tempfile, 'wb');
1973 $RIFFdataLength = strlen($RIFFdata);
1974 $NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4);
1975 for ($i = 0; $i < 4; $i++) {
1976 $RIFFdata[($i + 4)] = $NewLengthString[$i];
1977 }
1978 fwrite($fp_temp, $RIFFdata);
1979 fclose($fp_temp);
1980
1981 $getid3_temp = new getID3();
1982 $getid3_temp->openfile($tempfile);
1983 $getid3_temp->info['filesize'] = $RIFFdataLength;
1984 $getid3_temp->info['filenamepath'] = $info['filenamepath'];
1985 $getid3_temp->info['tags'] = $info['tags'];
1986 $getid3_temp->info['warning'] = $info['warning'];
1987 $getid3_temp->info['error'] = $info['error'];
1988 $getid3_temp->info['comments'] = $info['comments'];
1989 $getid3_temp->info['audio'] = (isset($info['audio']) ? $info['audio'] : array());
1990 $getid3_temp->info['video'] = (isset($info['video']) ? $info['video'] : array());
1991 $getid3_riff = new getid3_riff($getid3_temp);
1992 $getid3_riff->Analyze();
1993
1994 $info['riff'] = $getid3_temp->info['riff'];
1995 $info['warning'] = $getid3_temp->info['warning'];
1996 $info['error'] = $getid3_temp->info['error'];
1997 $info['tags'] = $getid3_temp->info['tags'];
1998 $info['comments'] = $getid3_temp->info['comments'];
1999 unset($getid3_riff, $getid3_temp);
2000 unlink($tempfile);
2001 }
2002 return false;
2003 }
2004
2005 /**
2006 * @param array $RIFFinfoArray
2007 * @param array $CommentsTargetArray
2008 *
2009 * @return bool
2010 */
2011 public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
2012 $RIFFinfoKeyLookup = array(
2013 'IARL'=>'archivallocation',
2014 'IART'=>'artist',
2015 'ICDS'=>'costumedesigner',
2016 'ICMS'=>'commissionedby',
2017 'ICMT'=>'comment',
2018 'ICNT'=>'country',
2019 'ICOP'=>'copyright',
2020 'ICRD'=>'creationdate',
2021 'IDIM'=>'dimensions',
2022 'IDIT'=>'digitizationdate',
2023 'IDPI'=>'resolution',
2024 'IDST'=>'distributor',
2025 'IEDT'=>'editor',
2026 'IENG'=>'engineers',
2027 'IFRM'=>'accountofparts',
2028 'IGNR'=>'genre',
2029 'IKEY'=>'keywords',
2030 'ILGT'=>'lightness',
2031 'ILNG'=>'language',
2032 'IMED'=>'orignalmedium',
2033 'IMUS'=>'composer',
2034 'INAM'=>'title',
2035 'IPDS'=>'productiondesigner',
2036 'IPLT'=>'palette',
2037 'IPRD'=>'product',
2038 'IPRO'=>'producer',
2039 'IPRT'=>'part',
2040 'IRTD'=>'rating',
2041 'ISBJ'=>'subject',
2042 'ISFT'=>'software',
2043 'ISGN'=>'secondarygenre',
2044 'ISHP'=>'sharpness',
2045 'ISRC'=>'sourcesupplier',
2046 'ISRF'=>'digitizationsource',
2047 'ISTD'=>'productionstudio',
2048 'ISTR'=>'starring',
2049 'ITCH'=>'encoded_by',
2050 'IWEB'=>'url',
2051 'IWRI'=>'writer',
2052 '____'=>'comment',
2053 );
2054 foreach ($RIFFinfoKeyLookup as $key => $value) {
2055 if (isset($RIFFinfoArray[$key])) {
2056 foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) {
2057 if (!empty($commentdata['data']) && trim($commentdata['data']) != '') {
2058 if (isset($CommentsTargetArray[$value])) {
2059 $CommentsTargetArray[$value][] = trim($commentdata['data']);
2060 } else {
2061 $CommentsTargetArray[$value] = array(trim($commentdata['data']));
2062 }
2063 }
2064 }
2065 }
2066 }
2067 return true;
2068 }
2069
2070 /**
2071 * @param string $WaveFormatExData
2072 *
2073 * @return array
2074 */
2075 public static function parseWAVEFORMATex($WaveFormatExData) {
2076 // shortcut
2077 $WaveFormatEx = array();
2078 $WaveFormatEx['raw'] = array();
2079 $WaveFormatEx_raw = &$WaveFormatEx['raw'];
2080
2081 $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2);
2082 $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2);
2083 $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4);
2084 $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4);
2085 $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2);
2086 $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2);
2087 if (strlen($WaveFormatExData) > 16) {
2088 $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2);
2089 }
2090 $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw);
2091
2092 $WaveFormatEx['codec'] = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']);
2093 $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels'];
2094 $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec'];
2095 $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8;
2096 $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample'];
2097
2098 return $WaveFormatEx;
2099 }
2100
2101 /**
2102 * @param string $WavPackChunkData
2103 *
2104 * @return bool
2105 */
2106 public function parseWavPackHeader($WavPackChunkData) {
2107 // typedef struct {
2108 // char ckID [4];
2109 // long ckSize;
2110 // short version;
2111 // short bits; // added for version 2.00
2112 // short flags, shift; // added for version 3.00
2113 // long total_samples, crc, crc2;
2114 // char extension [4], extra_bc, extras [3];
2115 // } WavpackHeader;
2116
2117 // shortcut
2118 $info = &$this->getid3->info;
2119 $info['wavpack'] = array();
2120 $thisfile_wavpack = &$info['wavpack'];
2121
2122 $thisfile_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 0, 2));
2123 if ($thisfile_wavpack['version'] >= 2) {
2124 $thisfile_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 2, 2));
2125 }
2126 if ($thisfile_wavpack['version'] >= 3) {
2127 $thisfile_wavpack['flags_raw'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 4, 2));
2128 $thisfile_wavpack['shift'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 6, 2));
2129 $thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 8, 4));
2130 $thisfile_wavpack['crc1'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4));
2131 $thisfile_wavpack['crc2'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4));
2132 $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4);
2133 $thisfile_wavpack['extra_bc'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1));
2134 for ($i = 0; $i <= 2; $i++) {
2135 $thisfile_wavpack['extras'][] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1));
2136 }
2137
2138 // shortcut
2139 $thisfile_wavpack['flags'] = array();
2140 $thisfile_wavpack_flags = &$thisfile_wavpack['flags'];
2141
2142 $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001);
2143 $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002);
2144 $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004);
2145 $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008);
2146 $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010);
2147 $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020);
2148 $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040);
2149 $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080);
2150 $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100);
2151 $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200);
2152 $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400);
2153 $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800);
2154 $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000);
2155 $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000);
2156 $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000);
2157 $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000);
2158 $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000);
2159 $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000);
2160 $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000);
2161 $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000);
2162 }
2163
2164 return true;
2165 }
2166
2167 /**
2168 * @param string $BITMAPINFOHEADER
2169 * @param bool $littleEndian
2170 *
2171 * @return array
2172 */
2173 public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
2174
2175 $parsed = array();
2176 $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
2177 $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels
2178 $parsed['biHeight'] = substr($BITMAPINFOHEADER, 8, 4); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner
2179 $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1
2180 $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels
2181 $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
2182 $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device
2183 $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device
2184 $parsed['biClrUsed'] = substr($BITMAPINFOHEADER, 32, 4); // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
2185 $parsed['biClrImportant'] = substr($BITMAPINFOHEADER, 36, 4); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
2186 $parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed);
2187
2188 $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier
2189
2190 return $parsed;
2191 }
2192
2193 /**
2194 * @param string $DIVXTAG
2195 * @param bool $raw
2196 *
2197 * @return array
2198 */
2199 public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
2200 // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
2201 // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
2202 // 'Byte Layout: '1111111111111111
2203 // '32 for Movie - 1 '1111111111111111
2204 // '28 for Author - 6 '6666666666666666
2205 // '4 for year - 2 '6666666666662222
2206 // '3 for genre - 3 '7777777777777777
2207 // '48 for Comments - 7 '7777777777777777
2208 // '1 for Rating - 4 '7777777777777777
2209 // '5 for Future Additions - 0 '333400000DIVXTAG
2210 // '128 bytes total
2211
2212 static $DIVXTAGgenre = array(
2213 0 => 'Action',
2214 1 => 'Action/Adventure',
2215 2 => 'Adventure',
2216 3 => 'Adult',
2217 4 => 'Anime',
2218 5 => 'Cartoon',
2219 6 => 'Claymation',
2220 7 => 'Comedy',
2221 8 => 'Commercial',
2222 9 => 'Documentary',
2223 10 => 'Drama',
2224 11 => 'Home Video',
2225 12 => 'Horror',
2226 13 => 'Infomercial',
2227 14 => 'Interactive',
2228 15 => 'Mystery',
2229 16 => 'Music Video',
2230 17 => 'Other',
2231 18 => 'Religion',
2232 19 => 'Sci Fi',
2233 20 => 'Thriller',
2234 21 => 'Western',
2235 ),
2236 $DIVXTAGrating = array(
2237 0 => 'Unrated',
2238 1 => 'G',
2239 2 => 'PG',
2240 3 => 'PG-13',
2241 4 => 'R',
2242 5 => 'NC-17',
2243 );
2244
2245 $parsed = array();
2246 $parsed['title'] = trim(substr($DIVXTAG, 0, 32));
2247 $parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
2248 $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
2249 $parsed['comment'] = trim(substr($DIVXTAG, 64, 48));
2250 $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3)));
2251 $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1));
2252 //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null
2253 //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG"
2254
2255 $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ? $DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']);
2256 $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']);
2257
2258 if (!$raw) {
2259 unset($parsed['genre_id'], $parsed['rating_id']);
2260 foreach ($parsed as $key => $value) {
2261 if (empty($value)) {
2262 unset($parsed[$key]);
2263 }
2264 }
2265 }
2266
2267 foreach ($parsed as $tag => $value) {
2268 $parsed[$tag] = array($value);
2269 }
2270
2271 return $parsed;
2272 }
2273
2274 /**
2275 * @param string $tagshortname
2276 *
2277 * @return string
2278 */
2279 public static function waveSNDMtagLookup($tagshortname) {
2280 $begin = __LINE__;
2281
2282 /** This is not a comment!
2283
2284 ©kwd keywords
2285 ©BPM bpm
2286 ©trt tracktitle
2287 ©des description
2288 ©gen category
2289 ©fin featuredinstrument
2290 ©LID longid
2291 ©bex bwdescription
2292 ©pub publisher
2293 ©cdt cdtitle
2294 ©alb library
2295 ©com composer
2296
2297 */
2298
2299 return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
2300 }
2301
2302 /**
2303 * @param int $wFormatTag
2304 *
2305 * @return string
2306 */
2307 public static function wFormatTagLookup($wFormatTag) {
2308
2309 $begin = __LINE__;
2310
2311 /** This is not a comment!
2312
2313 0x0000 Microsoft Unknown Wave Format
2314 0x0001 Pulse Code Modulation (PCM)
2315 0x0002 Microsoft ADPCM
2316 0x0003 IEEE Float
2317 0x0004 Compaq Computer VSELP
2318 0x0005 IBM CVSD
2319 0x0006 Microsoft A-Law
2320 0x0007 Microsoft mu-Law
2321 0x0008 Microsoft DTS
2322 0x0010 OKI ADPCM
2323 0x0011 Intel DVI/IMA ADPCM
2324 0x0012 Videologic MediaSpace ADPCM
2325 0x0013 Sierra Semiconductor ADPCM
2326 0x0014 Antex Electronics G.723 ADPCM
2327 0x0015 DSP Solutions DigiSTD
2328 0x0016 DSP Solutions DigiFIX
2329 0x0017 Dialogic OKI ADPCM
2330 0x0018 MediaVision ADPCM
2331 0x0019 Hewlett-Packard CU
2332 0x0020 Yamaha ADPCM
2333 0x0021 Speech Compression Sonarc
2334 0x0022 DSP Group TrueSpeech
2335 0x0023 Echo Speech EchoSC1
2336 0x0024 Audiofile AF36
2337 0x0025 Audio Processing Technology APTX
2338 0x0026 AudioFile AF10
2339 0x0027 Prosody 1612
2340 0x0028 LRC
2341 0x0030 Dolby AC2
2342 0x0031 Microsoft GSM 6.10
2343 0x0032 MSNAudio
2344 0x0033 Antex Electronics ADPCME
2345 0x0034 Control Resources VQLPC
2346 0x0035 DSP Solutions DigiREAL
2347 0x0036 DSP Solutions DigiADPCM
2348 0x0037 Control Resources CR10
2349 0x0038 Natural MicroSystems VBXADPCM
2350 0x0039 Crystal Semiconductor IMA ADPCM
2351 0x003A EchoSC3
2352 0x003B Rockwell ADPCM
2353 0x003C Rockwell Digit LK
2354 0x003D Xebec
2355 0x0040 Antex Electronics G.721 ADPCM
2356 0x0041 G.728 CELP
2357 0x0042 MSG723
2358 0x0050 MPEG Layer-2 or Layer-1
2359 0x0052 RT24
2360 0x0053 PAC
2361 0x0055 MPEG Layer-3
2362 0x0059 Lucent G.723
2363 0x0060 Cirrus
2364 0x0061 ESPCM
2365 0x0062 Voxware
2366 0x0063 Canopus Atrac
2367 0x0064 G.726 ADPCM
2368 0x0065 G.722 ADPCM
2369 0x0066 DSAT
2370 0x0067 DSAT Display
2371 0x0069 Voxware Byte Aligned
2372 0x0070 Voxware AC8
2373 0x0071 Voxware AC10
2374 0x0072 Voxware AC16
2375 0x0073 Voxware AC20
2376 0x0074 Voxware MetaVoice
2377 0x0075 Voxware MetaSound
2378 0x0076 Voxware RT29HW
2379 0x0077 Voxware VR12
2380 0x0078 Voxware VR18
2381 0x0079 Voxware TQ40
2382 0x0080 Softsound
2383 0x0081 Voxware TQ60
2384 0x0082 MSRT24
2385 0x0083 G.729A
2386 0x0084 MVI MV12
2387 0x0085 DF G.726
2388 0x0086 DF GSM610
2389 0x0088 ISIAudio
2390 0x0089 Onlive
2391 0x0091 SBC24
2392 0x0092 Dolby AC3 SPDIF
2393 0x0093 MediaSonic G.723
2394 0x0094 Aculab PLC Prosody 8kbps
2395 0x0097 ZyXEL ADPCM
2396 0x0098 Philips LPCBB
2397 0x0099 Packed
2398 0x00FF AAC
2399 0x0100 Rhetorex ADPCM
2400 0x0101 IBM mu-law
2401 0x0102 IBM A-law
2402 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM)
2403 0x0111 Vivo G.723
2404 0x0112 Vivo Siren
2405 0x0123 Digital G.723
2406 0x0125 Sanyo LD ADPCM
2407 0x0130 Sipro Lab Telecom ACELP NET
2408 0x0131 Sipro Lab Telecom ACELP 4800
2409 0x0132 Sipro Lab Telecom ACELP 8V3
2410 0x0133 Sipro Lab Telecom G.729
2411 0x0134 Sipro Lab Telecom G.729A
2412 0x0135 Sipro Lab Telecom Kelvin
2413 0x0140 Windows Media Video V8
2414 0x0150 Qualcomm PureVoice
2415 0x0151 Qualcomm HalfRate
2416 0x0155 Ring Zero Systems TUB GSM
2417 0x0160 Microsoft Audio 1
2418 0x0161 Windows Media Audio V7 / V8 / V9
2419 0x0162 Windows Media Audio Professional V9
2420 0x0163 Windows Media Audio Lossless V9
2421 0x0200 Creative Labs ADPCM
2422 0x0202 Creative Labs Fastspeech8
2423 0x0203 Creative Labs Fastspeech10
2424 0x0210 UHER Informatic GmbH ADPCM
2425 0x0220 Quarterdeck
2426 0x0230 I-link Worldwide VC
2427 0x0240 Aureal RAW Sport
2428 0x0250 Interactive Products HSX
2429 0x0251 Interactive Products RPELP
2430 0x0260 Consistent Software CS2
2431 0x0270 Sony SCX
2432 0x0300 Fujitsu FM Towns Snd
2433 0x0400 BTV Digital
2434 0x0401 Intel Music Coder
2435 0x0450 QDesign Music
2436 0x0680 VME VMPCM
2437 0x0681 AT&T Labs TPC
2438 0x08AE ClearJump LiteWave
2439 0x1000 Olivetti GSM
2440 0x1001 Olivetti ADPCM
2441 0x1002 Olivetti CELP
2442 0x1003 Olivetti SBC
2443 0x1004 Olivetti OPR
2444 0x1100 Lernout & Hauspie Codec (0x1100)
2445 0x1101 Lernout & Hauspie CELP Codec (0x1101)
2446 0x1102 Lernout & Hauspie SBC Codec (0x1102)
2447 0x1103 Lernout & Hauspie SBC Codec (0x1103)
2448 0x1104 Lernout & Hauspie SBC Codec (0x1104)
2449 0x1400 Norris
2450 0x1401 AT&T ISIAudio
2451 0x1500 Soundspace Music Compression
2452 0x181C VoxWare RT24 Speech
2453 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com)
2454 0x2000 Dolby AC3
2455 0x2001 Dolby DTS
2456 0x2002 WAVE_FORMAT_14_4
2457 0x2003 WAVE_FORMAT_28_8
2458 0x2004 WAVE_FORMAT_COOK
2459 0x2005 WAVE_FORMAT_DNET
2460 0x674F Ogg Vorbis 1
2461 0x6750 Ogg Vorbis 2
2462 0x6751 Ogg Vorbis 3
2463 0x676F Ogg Vorbis 1+
2464 0x6770 Ogg Vorbis 2+
2465 0x6771 Ogg Vorbis 3+
2466 0x7A21 GSM-AMR (CBR, no SID)
2467 0x7A22 GSM-AMR (VBR, including SID)
2468 0xFFFE WAVE_FORMAT_EXTENSIBLE
2469 0xFFFF WAVE_FORMAT_DEVELOPMENT
2470
2471 */
2472
2473 return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
2474 }
2475
2476 /**
2477 * @param string $fourcc
2478 *
2479 * @return string
2480 */
2481 public static function fourccLookup($fourcc) {
2482
2483 $begin = __LINE__;
2484
2485 /** This is not a comment!
2486
2487 swot http://developer.apple.com/qa/snd/snd07.html
2488 ____ No Codec (____)
2489 _BIT BI_BITFIELDS (Raw RGB)
2490 _JPG JPEG compressed
2491 _PNG PNG compressed W3C/ISO/IEC (RFC-2083)
2492 _RAW Full Frames (Uncompressed)
2493 _RGB Raw RGB Bitmap
2494 _RL4 RLE 4bpp RGB
2495 _RL8 RLE 8bpp RGB
2496 3IV1 3ivx MPEG-4 v1
2497 3IV2 3ivx MPEG-4 v2
2498 3IVX 3ivx MPEG-4
2499 AASC Autodesk Animator
2500 ABYR Kensington ?ABYR?
2501 AEMI Array Microsystems VideoONE MPEG1-I Capture
2502 AFLC Autodesk Animator FLC
2503 AFLI Autodesk Animator FLI
2504 AMPG Array Microsystems VideoONE MPEG
2505 ANIM Intel RDX (ANIM)
2506 AP41 AngelPotion Definitive
2507 ASV1 Asus Video v1
2508 ASV2 Asus Video v2
2509 ASVX Asus Video 2.0 (audio)
2510 AUR2 AuraVision Aura 2 Codec - YUV 4:2:2
2511 AURA AuraVision Aura 1 Codec - YUV 4:1:1
2512 AVDJ Independent JPEG Group\'s codec (AVDJ)
2513 AVRN Independent JPEG Group\'s codec (AVRN)
2514 AYUV 4:4:4 YUV (AYUV)
2515 AZPR Quicktime Apple Video (AZPR)
2516 BGR Raw RGB32
2517 BLZ0 Blizzard DivX MPEG-4
2518 BTVC Conexant Composite Video
2519 BINK RAD Game Tools Bink Video
2520 BT20 Conexant Prosumer Video
2521 BTCV Conexant Composite Video Codec
2522 BW10 Data Translation Broadway MPEG Capture
2523 CC12 Intel YUV12
2524 CDVC Canopus DV
2525 CFCC Digital Processing Systems DPS Perception
2526 CGDI Microsoft Office 97 Camcorder Video
2527 CHAM Winnov Caviara Champagne
2528 CJPG Creative WebCam JPEG
2529 CLJR Cirrus Logic YUV 4:1:1
2530 CMYK Common Data Format in Printing (Colorgraph)
2531 CPLA Weitek 4:2:0 YUV Planar
2532 CRAM Microsoft Video 1 (CRAM)
2533 cvid Radius Cinepak
2534 CVID Radius Cinepak
2535 CWLT Microsoft Color WLT DIB
2536 CYUV Creative Labs YUV
2537 CYUY ATI YUV
2538 D261 H.261
2539 D263 H.263
2540 DIB Device Independent Bitmap
2541 DIV1 FFmpeg OpenDivX
2542 DIV2 Microsoft MPEG-4 v1/v2
2543 DIV3 DivX ;-) MPEG-4 v3.x Low-Motion
2544 DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion
2545 DIV5 DivX MPEG-4 v5.x
2546 DIV6 DivX ;-) (MS MPEG-4 v3.x)
2547 DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo)
2548 divx DivX MPEG-4
2549 DMB1 Matrox Rainbow Runner hardware MJPEG
2550 DMB2 Paradigm MJPEG
2551 DSVD ?DSVD?
2552 DUCK Duck TrueMotion 1.0
2553 DPS0 DPS/Leitch Reality Motion JPEG
2554 DPSC DPS/Leitch PAR Motion JPEG
2555 DV25 Matrox DVCPRO codec
2556 DV50 Matrox DVCPRO50 codec
2557 DVC IEC 61834 and SMPTE 314M (DVC/DV Video)
2558 DVCP IEC 61834 and SMPTE 314M (DVC/DV Video)
2559 DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps
2560 DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com)
2561 DVSL IEC Standard DV compressed in SD (SDL)
2562 DVAN ?DVAN?
2563 DVE2 InSoft DVE-2 Videoconferencing
2564 dvsd IEC 61834 and SMPTE 314M DVC/DV Video
2565 DVSD IEC 61834 and SMPTE 314M DVC/DV Video
2566 DVX1 Lucent DVX1000SP Video Decoder
2567 DVX2 Lucent DVX2000S Video Decoder
2568 DVX3 Lucent DVX3000S Video Decoder
2569 DX50 DivX v5
2570 DXT1 Microsoft DirectX Compressed Texture (DXT1)
2571 DXT2 Microsoft DirectX Compressed Texture (DXT2)
2572 DXT3 Microsoft DirectX Compressed Texture (DXT3)
2573 DXT4 Microsoft DirectX Compressed Texture (DXT4)
2574 DXT5 Microsoft DirectX Compressed Texture (DXT5)
2575 DXTC Microsoft DirectX Compressed Texture (DXTC)
2576 DXTn Microsoft DirectX Compressed Texture (DXTn)
2577 EM2V Etymonix MPEG-2 I-frame (www.etymonix.com)
2578 EKQ0 Elsa ?EKQ0?
2579 ELK0 Elsa ?ELK0?
2580 ESCP Eidos Escape
2581 ETV1 eTreppid Video ETV1
2582 ETV2 eTreppid Video ETV2
2583 ETVC eTreppid Video ETVC
2584 FLIC Autodesk FLI/FLC Animation
2585 FLV1 Sorenson Spark
2586 FLV4 On2 TrueMotion VP6
2587 FRWT Darim Vision Forward Motion JPEG (www.darvision.com)
2588 FRWU Darim Vision Forward Uncompressed (www.darvision.com)
2589 FLJP D-Vision Field Encoded Motion JPEG
2590 FPS1 FRAPS v1
2591 FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel
2592 FRWD SoftLab-Nsk Forward Motion JPEG
2593 FVF1 Iterated Systems Fractal Video Frame
2594 GLZW Motion LZW (gabest@freemail.hu)
2595 GPEG Motion JPEG (gabest@freemail.hu)
2596 GWLT Microsoft Greyscale WLT DIB
2597 H260 Intel ITU H.260 Videoconferencing
2598 H261 Intel ITU H.261 Videoconferencing
2599 H262 Intel ITU H.262 Videoconferencing
2600 H263 Intel ITU H.263 Videoconferencing
2601 H264 Intel ITU H.264 Videoconferencing
2602 H265 Intel ITU H.265 Videoconferencing
2603 H266 Intel ITU H.266 Videoconferencing
2604 H267 Intel ITU H.267 Videoconferencing
2605 H268 Intel ITU H.268 Videoconferencing
2606 H269 Intel ITU H.269 Videoconferencing
2607 HFYU Huffman Lossless Codec
2608 HMCR Rendition Motion Compensation Format (HMCR)
2609 HMRR Rendition Motion Compensation Format (HMRR)
2610 I263 FFmpeg I263 decoder
2611 IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane")
2612 IUYV Interlaced version of UYVY (www.leadtools.com)
2613 IY41 Interlaced version of Y41P (www.leadtools.com)
2614 IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
2615 IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
2616 IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes)
2617 i263 Intel ITU H.263 Videoconferencing (i263)
2618 I420 Intel Indeo 4
2619 IAN Intel Indeo 4 (RDX)
2620 ICLB InSoft CellB Videoconferencing
2621 IGOR Power DVD
2622 IJPG Intergraph JPEG
2623 ILVC Intel Layered Video
2624 ILVR ITU-T H.263+
2625 IPDV I-O Data Device Giga AVI DV Codec
2626 IR21 Intel Indeo 2.1
2627 IRAW Intel YUV Uncompressed
2628 IV30 Intel Indeo 3.0
2629 IV31 Intel Indeo 3.1
2630 IV32 Ligos Indeo 3.2
2631 IV33 Ligos Indeo 3.3
2632 IV34 Ligos Indeo 3.4
2633 IV35 Ligos Indeo 3.5
2634 IV36 Ligos Indeo 3.6
2635 IV37 Ligos Indeo 3.7
2636 IV38 Ligos Indeo 3.8
2637 IV39 Ligos Indeo 3.9
2638 IV40 Ligos Indeo Interactive 4.0
2639 IV41 Ligos Indeo Interactive 4.1
2640 IV42 Ligos Indeo Interactive 4.2
2641 IV43 Ligos Indeo Interactive 4.3
2642 IV44 Ligos Indeo Interactive 4.4
2643 IV45 Ligos Indeo Interactive 4.5
2644 IV46 Ligos Indeo Interactive 4.6
2645 IV47 Ligos Indeo Interactive 4.7
2646 IV48 Ligos Indeo Interactive 4.8
2647 IV49 Ligos Indeo Interactive 4.9
2648 IV50 Ligos Indeo Interactive 5.0
2649 JBYR Kensington ?JBYR?
2650 JPEG Still Image JPEG DIB
2651 JPGL Pegasus Lossless Motion JPEG
2652 KMVC Team17 Software Karl Morton\'s Video Codec
2653 LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com)
2654 LEAD LEAD Video Codec
2655 Ljpg LEAD MJPEG Codec
2656 MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de)
2657 MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com)
2658 MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com)
2659 MMES Matrox MPEG-2 I-frame
2660 MP2v Microsoft S-Mpeg 4 version 1 (MP2v)
2661 MP42 Microsoft S-Mpeg 4 version 2 (MP42)
2662 MP43 Microsoft S-Mpeg 4 version 3 (MP43)
2663 MP4S Microsoft S-Mpeg 4 version 3 (MP4S)
2664 MP4V FFmpeg MPEG-4
2665 MPG1 FFmpeg MPEG 1/2
2666 MPG2 FFmpeg MPEG 1/2
2667 MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3)
2668 MPG4 Microsoft MPEG-4
2669 MPGI Sigma Designs MPEG
2670 MPNG PNG images decoder
2671 MSS1 Microsoft Windows Screen Video
2672 MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
2673 M261 Microsoft H.261
2674 M263 Microsoft H.263
2675 M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2)
2676 m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2)
2677 MC12 ATI Motion Compensation Format (MC12)
2678 MCAM ATI Motion Compensation Format (MCAM)
2679 MJ2C Morgan Multimedia Motion JPEG2000
2680 mJPG IBM Motion JPEG w/ Huffman Tables
2681 MJPG Microsoft Motion JPEG DIB
2682 MP42 Microsoft MPEG-4 (low-motion)
2683 MP43 Microsoft MPEG-4 (fast-motion)
2684 MP4S Microsoft MPEG-4 (MP4S)
2685 mp4s Microsoft MPEG-4 (mp4s)
2686 MPEG Chromatic Research MPEG-1 Video I-Frame
2687 MPG4 Microsoft MPEG-4 Video High Speed Compressor
2688 MPGI Sigma Designs MPEG
2689 MRCA FAST Multimedia Martin Regen Codec
2690 MRLE Microsoft Run Length Encoding
2691 MSVC Microsoft Video 1
2692 MTX1 Matrox ?MTX1?
2693 MTX2 Matrox ?MTX2?
2694 MTX3 Matrox ?MTX3?
2695 MTX4 Matrox ?MTX4?
2696 MTX5 Matrox ?MTX5?
2697 MTX6 Matrox ?MTX6?
2698 MTX7 Matrox ?MTX7?
2699 MTX8 Matrox ?MTX8?
2700 MTX9 Matrox ?MTX9?
2701 MV12 Motion Pixels Codec (old)
2702 MWV1 Aware Motion Wavelets
2703 nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm)
2704 NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com)
2705 NUV1 NuppelVideo
2706 NTN1 Nogatech Video Compression 1
2707 NVS0 nVidia GeForce Texture (NVS0)
2708 NVS1 nVidia GeForce Texture (NVS1)
2709 NVS2 nVidia GeForce Texture (NVS2)
2710 NVS3 nVidia GeForce Texture (NVS3)
2711 NVS4 nVidia GeForce Texture (NVS4)
2712 NVS5 nVidia GeForce Texture (NVS5)
2713 NVT0 nVidia GeForce Texture (NVT0)
2714 NVT1 nVidia GeForce Texture (NVT1)
2715 NVT2 nVidia GeForce Texture (NVT2)
2716 NVT3 nVidia GeForce Texture (NVT3)
2717 NVT4 nVidia GeForce Texture (NVT4)
2718 NVT5 nVidia GeForce Texture (NVT5)
2719 PIXL MiroXL, Pinnacle PCTV
2720 PDVC I-O Data Device Digital Video Capture DV codec
2721 PGVV Radius Video Vision
2722 PHMO IBM Photomotion
2723 PIM1 MPEG Realtime (Pinnacle Cards)
2724 PIM2 Pegasus Imaging ?PIM2?
2725 PIMJ Pegasus Imaging Lossless JPEG
2726 PVEZ Horizons Technology PowerEZ
2727 PVMM PacketVideo Corporation MPEG-4
2728 PVW2 Pegasus Imaging Wavelet Compression
2729 Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de)
2730 Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de)
2731 QPEG Q-Team QPEG 1.0
2732 qpeq Q-Team QPEG 1.1
2733 RGB Raw BGR32
2734 RGBA Raw RGB w/ Alpha
2735 RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com)
2736 ROQV Id RoQ File Video Decoder
2737 RPZA Quicktime Apple Video (RPZA)
2738 RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/)
2739 RV10 RealVideo 1.0 (aka RealVideo 5.0)
2740 RV13 RealVideo 1.0 (RV13)
2741 RV20 RealVideo G2
2742 RV30 RealVideo 8
2743 RV40 RealVideo 9
2744 RGBT Raw RGB w/ Transparency
2745 RLE Microsoft Run Length Encoder
2746 RLE4 Run Length Encoded (4bpp, 16-color)
2747 RLE8 Run Length Encoded (8bpp, 256-color)
2748 RT21 Intel Indeo RealTime Video 2.1
2749 rv20 RealVideo G2
2750 rv30 RealVideo 8
2751 RVX Intel RDX (RVX )
2752 SMC Apple Graphics (SMC )
2753 SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2
2754 SPIG Radius Spigot
2755 SVQ3 Sorenson Video 3 (Apple Quicktime 5)
2756 s422 Tekram VideoCap C210 YUV 4:2:2
2757 SDCC Sun Communication Digital Camera Codec
2758 SFMC CrystalNet Surface Fitting Method
2759 SMSC Radius SMSC
2760 SMSD Radius SMSD
2761 smsv WorldConnect Wavelet Video
2762 SPIG Radius Spigot
2763 SPLC Splash Studios ACM Audio Codec (www.splashstudios.net)
2764 SQZ2 Microsoft VXTreme Video Codec V2
2765 STVA ST Microelectronics CMOS Imager Data (Bayer)
2766 STVB ST Microelectronics CMOS Imager Data (Nudged Bayer)
2767 STVC ST Microelectronics CMOS Imager Data (Bunched)
2768 STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format)
2769 STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data)
2770 SV10 Sorenson Video R1
2771 SVQ1 Sorenson Video
2772 T420 Toshiba YUV 4:2:0
2773 TM2A Duck TrueMotion Archiver 2.0 (www.duck.com)
2774 TVJP Pinnacle/Truevision Targa 2000 board (TVJP)
2775 TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ)
2776 TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com)
2777 TY2C Trident Decompression Driver
2778 TLMS TeraLogic Motion Intraframe Codec (TLMS)
2779 TLST TeraLogic Motion Intraframe Codec (TLST)
2780 TM20 Duck TrueMotion 2.0
2781 TM2X Duck TrueMotion 2X
2782 TMIC TeraLogic Motion Intraframe Codec (TMIC)
2783 TMOT Horizons Technology TrueMotion S
2784 tmot Horizons TrueMotion Video Compression
2785 TR20 Duck TrueMotion RealTime 2.0
2786 TSCC TechSmith Screen Capture Codec
2787 TV10 Tecomac Low-Bit Rate Codec
2788 TY2N Trident ?TY2N?
2789 U263 UB Video H.263/H.263+/H.263++ Decoder
2790 UMP4 UB Video MPEG 4 (www.ubvideo.com)
2791 UYNV Nvidia UYVY packed 4:2:2
2792 UYVP Evans & Sutherland YCbCr 4:2:2 extended precision
2793 UCOD eMajix.com ClearVideo
2794 ULTI IBM Ultimotion
2795 UYVY UYVY packed 4:2:2
2796 V261 Lucent VX2000S
2797 VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/)
2798 VIV1 FFmpeg H263+ decoder
2799 VIV2 Vivo H.263
2800 VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf)
2801 VTLP Alaris VideoGramPiX
2802 VYU9 ATI YUV (VYU9)
2803 VYUY ATI YUV (VYUY)
2804 V261 Lucent VX2000S
2805 V422 Vitec Multimedia 24-bit YUV 4:2:2 Format
2806 V655 Vitec Multimedia 16-bit YUV 4:2:2 Format
2807 VCR1 ATI Video Codec 1
2808 VCR2 ATI Video Codec 2
2809 VCR3 ATI VCR 3.0
2810 VCR4 ATI VCR 4.0
2811 VCR5 ATI VCR 5.0
2812 VCR6 ATI VCR 6.0
2813 VCR7 ATI VCR 7.0
2814 VCR8 ATI VCR 8.0
2815 VCR9 ATI VCR 9.0
2816 VDCT Vitec Multimedia Video Maker Pro DIB
2817 VDOM VDOnet VDOWave
2818 VDOW VDOnet VDOLive (H.263)
2819 VDTZ Darim Vison VideoTizer YUV
2820 VGPX Alaris VideoGramPiX
2821 VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422
2822 VIVO Vivo H.263 v2.00
2823 vivo Vivo H.263
2824 VIXL Miro/Pinnacle Video XL
2825 VLV1 VideoLogic/PURE Digital Videologic Capture
2826 VP30 On2 VP3.0
2827 VP31 On2 VP3.1
2828 VP6F On2 TrueMotion VP6
2829 VX1K Lucent VX1000S Video Codec
2830 VX2K Lucent VX2000S Video Codec
2831 VXSP Lucent VX1000SP Video Codec
2832 WBVC Winbond W9960
2833 WHAM Microsoft Video 1 (WHAM)
2834 WINX Winnov Software Compression
2835 WJPG AverMedia Winbond JPEG
2836 WMV1 Windows Media Video V7
2837 WMV2 Windows Media Video V8
2838 WMV3 Windows Media Video V9
2839 WNV1 Winnov Hardware Compression
2840 XYZP Extended PAL format XYZ palette (www.riff.org)
2841 x263 Xirlink H.263
2842 XLV0 NetXL Video Decoder
2843 XMPG Xing MPEG (I-Frame only)
2844 XVID XviD MPEG-4 (www.xvid.org)
2845 XXAN ?XXAN?
2846 YU92 Intel YUV (YU92)
2847 YUNV Nvidia Uncompressed YUV 4:2:2
2848 YUVP Extended PAL format YUV palette (www.riff.org)
2849 Y211 YUV 2:1:1 Packed
2850 Y411 YUV 4:1:1 Packed
2851 Y41B Weitek YUV 4:1:1 Planar
2852 Y41P Brooktree PC1 YUV 4:1:1 Packed
2853 Y41T Brooktree PC1 YUV 4:1:1 with transparency
2854 Y42B Weitek YUV 4:2:2 Planar
2855 Y42T Brooktree UYUV 4:2:2 with transparency
2856 Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera
2857 Y800 Simple, single Y plane for monochrome images
2858 Y8 Grayscale video
2859 YC12 Intel YUV 12 codec
2860 YUV8 Winnov Caviar YUV8
2861 YUV9 Intel YUV9
2862 YUY2 Uncompressed YUV 4:2:2
2863 YUYV Canopus YUV
2864 YV12 YVU12 Planar
2865 YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes)
2866 YVYU YVYU 4:2:2 Packed
2867 ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
2868 ZPEG Metheus Video Zipper
2869
2870 */
2871
2872 return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
2873 }
2874
2875 /**
2876 * @param string $byteword
2877 * @param bool $signed
2878 *
2879 * @return int|float|false
2880 */
2881 private function EitherEndian2Int($byteword, $signed=false) {
2882 if ($this->container == 'riff') {
2883 return getid3_lib::LittleEndian2Int($byteword, $signed);
2884 }
2885 return getid3_lib::BigEndian2Int($byteword, false, $signed);
2886 }
2887
2888}
2889
Ui Ux Design – Teachers Night Out

Get in Touch

© 2024 Teachers Night Out. All Rights Reserved.