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