ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
Real.php
Go to the documentation of this file.
1<?php
2
4
7
10// available at http://getid3.sourceforge.net //
11// or http://www.getid3.org //
13// See readme.txt for more details //
15// //
16// module.audio-video.real.php //
17// module for analyzing Real Audio/Video files //
18// dependencies: module.audio-video.riff.php //
19// ///
21
30class Real extends BaseHandler
31{
32
37 public function analyze()
38 {
39 $info = &$this->getid3->info;
40
41 $info['fileformat'] = 'real';
42 $info['bitrate'] = 0;
43 $info['playtime_seconds'] = 0;
44
45 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
46 $ChunkCounter = 0;
47 while (ftell($this->getid3->fp) < $info['avdataend']) {
48 $ChunkData = fread($this->getid3->fp, 8);
49 $ChunkName = substr($ChunkData, 0, 4);
50 $ChunkSize = Helper::BigEndian2Int(substr($ChunkData, 4, 4));
51
52 if ($ChunkName == '.ra'."\xFD") {
53 $ChunkData .= fread($this->getid3->fp, $ChunkSize - 8);
54 if ($this->ParseOldRAheader(substr($ChunkData, 0, 128), $info['real']['old_ra_header'])) {
55 $info['audio']['dataformat'] = 'real';
56 $info['audio']['lossless'] = false;
57 $info['audio']['sample_rate'] = $info['real']['old_ra_header']['sample_rate'];
58 $info['audio']['bits_per_sample'] = $info['real']['old_ra_header']['bits_per_sample'];
59 $info['audio']['channels'] = $info['real']['old_ra_header']['channels'];
60
61 $info['playtime_seconds'] = 60 * ($info['real']['old_ra_header']['audio_bytes'] / $info['real']['old_ra_header']['bytes_per_minute']);
62 $info['audio']['bitrate'] = 8 * ($info['real']['old_ra_header']['audio_bytes'] / $info['playtime_seconds']);
63 $info['audio']['codec'] = $this->RealAudioCodecFourCClookup($info['real']['old_ra_header']['fourcc'], $info['audio']['bitrate']);
64
65 foreach ($info['real']['old_ra_header']['comments'] as $key => $valuearray) {
66 if (strlen(trim($valuearray[0])) > 0) {
67 $info['real']['comments'][$key][] = trim($valuearray[0]);
68 }
69 }
70
71 return true;
72 }
73 $info['error'][] = 'There was a problem parsing this RealAudio file. Please submit it for analysis to info@getid3.org';
74 unset($info['bitrate']);
75 unset($info['playtime_seconds']);
76
77 return false;
78 }
79
80 // shortcut
81 $info['real']['chunks'][$ChunkCounter] = array();
82 $thisfile_real_chunks_currentchunk = &$info['real']['chunks'][$ChunkCounter];
83
84 $thisfile_real_chunks_currentchunk['name'] = $ChunkName;
85 $thisfile_real_chunks_currentchunk['offset'] = ftell($this->getid3->fp) - 8;
86 $thisfile_real_chunks_currentchunk['length'] = $ChunkSize;
87 if (($thisfile_real_chunks_currentchunk['offset'] + $thisfile_real_chunks_currentchunk['length']) > $info['avdataend']) {
88 $info['warning'][] = 'Chunk "'.$thisfile_real_chunks_currentchunk['name'].'" at offset '.$thisfile_real_chunks_currentchunk['offset'].' claims to be '.$thisfile_real_chunks_currentchunk['length'].' bytes long, which is beyond end of file';
89
90 return false;
91 }
92
93 if ($ChunkSize > ($this->getid3->fread_buffer_size() + 8)) {
94
95 $ChunkData .= fread($this->getid3->fp, $this->getid3->fread_buffer_size() - 8);
96 fseek($this->getid3->fp, $thisfile_real_chunks_currentchunk['offset'] + $ChunkSize, SEEK_SET);
97
98 } elseif (($ChunkSize - 8) > 0) {
99
100 $ChunkData .= fread($this->getid3->fp, $ChunkSize - 8);
101
102 }
103 $offset = 8;
104
105 switch ($ChunkName) {
106
107 case '.RMF': // RealMedia File Header
108 $thisfile_real_chunks_currentchunk['object_version'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
109 $offset += 2;
110 switch ($thisfile_real_chunks_currentchunk['object_version']) {
111
112 case 0:
113 $thisfile_real_chunks_currentchunk['file_version'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
114 $offset += 4;
115 $thisfile_real_chunks_currentchunk['headers_count'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
116 $offset += 4;
117 break;
118
119 default:
120 //$info['warning'][] = 'Expected .RMF-object_version to be "0", actual value is "'.$thisfile_real_chunks_currentchunk['object_version'].'" (should not be a problem)';
121 break;
122
123 }
124 break;
125
126 case 'PROP': // Properties Header
127 $thisfile_real_chunks_currentchunk['object_version'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
128 $offset += 2;
129 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) {
130 $thisfile_real_chunks_currentchunk['max_bit_rate'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
131 $offset += 4;
132 $thisfile_real_chunks_currentchunk['avg_bit_rate'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
133 $offset += 4;
134 $thisfile_real_chunks_currentchunk['max_packet_size'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
135 $offset += 4;
136 $thisfile_real_chunks_currentchunk['avg_packet_size'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
137 $offset += 4;
138 $thisfile_real_chunks_currentchunk['num_packets'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
139 $offset += 4;
140 $thisfile_real_chunks_currentchunk['duration'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
141 $offset += 4;
142 $thisfile_real_chunks_currentchunk['preroll'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
143 $offset += 4;
144 $thisfile_real_chunks_currentchunk['index_offset'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
145 $offset += 4;
146 $thisfile_real_chunks_currentchunk['data_offset'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
147 $offset += 4;
148 $thisfile_real_chunks_currentchunk['num_streams'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
149 $offset += 2;
150 $thisfile_real_chunks_currentchunk['flags_raw'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
151 $offset += 2;
152 $info['playtime_seconds'] = $thisfile_real_chunks_currentchunk['duration'] / 1000;
153 if ($thisfile_real_chunks_currentchunk['duration'] > 0) {
154 $info['bitrate'] += $thisfile_real_chunks_currentchunk['avg_bit_rate'];
155 }
156 $thisfile_real_chunks_currentchunk['flags']['save_enabled'] = (bool) ($thisfile_real_chunks_currentchunk['flags_raw'] & 0x0001);
157 $thisfile_real_chunks_currentchunk['flags']['perfect_play'] = (bool) ($thisfile_real_chunks_currentchunk['flags_raw'] & 0x0002);
158 $thisfile_real_chunks_currentchunk['flags']['live_broadcast'] = (bool) ($thisfile_real_chunks_currentchunk['flags_raw'] & 0x0004);
159 }
160 break;
161
162 case 'MDPR': // Media Properties Header
163 $thisfile_real_chunks_currentchunk['object_version'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
164 $offset += 2;
165 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) {
166 $thisfile_real_chunks_currentchunk['stream_number'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
167 $offset += 2;
168 $thisfile_real_chunks_currentchunk['max_bit_rate'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
169 $offset += 4;
170 $thisfile_real_chunks_currentchunk['avg_bit_rate'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
171 $offset += 4;
172 $thisfile_real_chunks_currentchunk['max_packet_size'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
173 $offset += 4;
174 $thisfile_real_chunks_currentchunk['avg_packet_size'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
175 $offset += 4;
176 $thisfile_real_chunks_currentchunk['start_time'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
177 $offset += 4;
178 $thisfile_real_chunks_currentchunk['preroll'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
179 $offset += 4;
180 $thisfile_real_chunks_currentchunk['duration'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
181 $offset += 4;
182 $thisfile_real_chunks_currentchunk['stream_name_size'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 1));
183 $offset += 1;
184 $thisfile_real_chunks_currentchunk['stream_name'] = substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['stream_name_size']);
185 $offset += $thisfile_real_chunks_currentchunk['stream_name_size'];
186 $thisfile_real_chunks_currentchunk['mime_type_size'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 1));
187 $offset += 1;
188 $thisfile_real_chunks_currentchunk['mime_type'] = substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['mime_type_size']);
189 $offset += $thisfile_real_chunks_currentchunk['mime_type_size'];
190 $thisfile_real_chunks_currentchunk['type_specific_len'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
191 $offset += 4;
192 $thisfile_real_chunks_currentchunk['type_specific_data'] = substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['type_specific_len']);
193 $offset += $thisfile_real_chunks_currentchunk['type_specific_len'];
194
195 // shortcut
196 $thisfile_real_chunks_currentchunk_typespecificdata = &$thisfile_real_chunks_currentchunk['type_specific_data'];
197
198 switch ($thisfile_real_chunks_currentchunk['mime_type']) {
199 case 'video/x-pn-realvideo':
200 case 'video/x-pn-multirate-realvideo':
201 // http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html
202
203 // shortcut
204 $thisfile_real_chunks_currentchunk['video_info'] = array();
205 $thisfile_real_chunks_currentchunk_videoinfo = &$thisfile_real_chunks_currentchunk['video_info'];
206
207 $thisfile_real_chunks_currentchunk_videoinfo['dwSize'] = Helper::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 0, 4));
208 $thisfile_real_chunks_currentchunk_videoinfo['fourcc1'] = substr($thisfile_real_chunks_currentchunk_typespecificdata, 4, 4);
209 $thisfile_real_chunks_currentchunk_videoinfo['fourcc2'] = substr($thisfile_real_chunks_currentchunk_typespecificdata, 8, 4);
210 $thisfile_real_chunks_currentchunk_videoinfo['width'] = Helper::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 12, 2));
211 $thisfile_real_chunks_currentchunk_videoinfo['height'] = Helper::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 14, 2));
212 $thisfile_real_chunks_currentchunk_videoinfo['bits_per_sample'] = Helper::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 16, 2));
213 //$thisfile_real_chunks_currentchunk_videoinfo['unknown1'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 18, 2));
214 //$thisfile_real_chunks_currentchunk_videoinfo['unknown2'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 20, 2));
215 $thisfile_real_chunks_currentchunk_videoinfo['frames_per_second'] = Helper::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 22, 2));
216 //$thisfile_real_chunks_currentchunk_videoinfo['unknown3'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 24, 2));
217 //$thisfile_real_chunks_currentchunk_videoinfo['unknown4'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 26, 2));
218 //$thisfile_real_chunks_currentchunk_videoinfo['unknown5'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 28, 2));
219 //$thisfile_real_chunks_currentchunk_videoinfo['unknown6'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 30, 2));
220 //$thisfile_real_chunks_currentchunk_videoinfo['unknown7'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 32, 2));
221 //$thisfile_real_chunks_currentchunk_videoinfo['unknown8'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 34, 2));
222 //$thisfile_real_chunks_currentchunk_videoinfo['unknown9'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 36, 2));
223
224 $thisfile_real_chunks_currentchunk_videoinfo['codec'] = Riff::RIFFfourccLookup($thisfile_real_chunks_currentchunk_videoinfo['fourcc2']);
225
226 $info['video']['resolution_x'] = $thisfile_real_chunks_currentchunk_videoinfo['width'];
227 $info['video']['resolution_y'] = $thisfile_real_chunks_currentchunk_videoinfo['height'];
228 $info['video']['frame_rate'] = (float) $thisfile_real_chunks_currentchunk_videoinfo['frames_per_second'];
229 $info['video']['codec'] = $thisfile_real_chunks_currentchunk_videoinfo['codec'];
230 $info['video']['bits_per_sample'] = $thisfile_real_chunks_currentchunk_videoinfo['bits_per_sample'];
231 break;
232
233 case 'audio/x-pn-realaudio':
234 case 'audio/x-pn-multirate-realaudio':
235 $this->ParseOldRAheader($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk['parsed_audio_data']);
236
237 $info['audio']['sample_rate'] = $thisfile_real_chunks_currentchunk['parsed_audio_data']['sample_rate'];
238 $info['audio']['bits_per_sample'] = $thisfile_real_chunks_currentchunk['parsed_audio_data']['bits_per_sample'];
239 $info['audio']['channels'] = $thisfile_real_chunks_currentchunk['parsed_audio_data']['channels'];
240 if (!empty($info['audio']['dataformat'])) {
241 foreach ($info['audio'] as $key => $value) {
242 if ($key != 'streams') {
243 $info['audio']['streams'][$thisfile_real_chunks_currentchunk['stream_number']][$key] = $value;
244 }
245 }
246 }
247 break;
248
249 case 'logical-fileinfo':
250 // shortcut
251 $thisfile_real_chunks_currentchunk['logical_fileinfo'] = array();
252 $thisfile_real_chunks_currentchunk_logicalfileinfo = &$thisfile_real_chunks_currentchunk['logical_fileinfo'];
253
254 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset = 0;
255 $thisfile_real_chunks_currentchunk_logicalfileinfo['logical_fileinfo_length'] = Helper::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4));
256 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4;
257
258 //$thisfile_real_chunks_currentchunk_logicalfileinfo['unknown1'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4));
259 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4;
260
261 $thisfile_real_chunks_currentchunk_logicalfileinfo['num_tags'] = Helper::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4));
262 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4;
263
264 //$thisfile_real_chunks_currentchunk_logicalfileinfo['unknown2'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4));
265 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4;
266
267 //$thisfile_real_chunks_currentchunk_logicalfileinfo['d'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 1));
268
269 //$thisfile_real_chunks_currentchunk_logicalfileinfo['one_type'] = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4));
270 //$thisfile_real_chunks_currentchunk_logicalfileinfo_thislength = GetId3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 4 + $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 2));
271 //$thisfile_real_chunks_currentchunk_logicalfileinfo['one'] = substr($thisfile_real_chunks_currentchunk_typespecificdata, 6 + $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, $thisfile_real_chunks_currentchunk_logicalfileinfo_thislength);
272 //$thisfile_real_chunks_currentchunk_logicalfileinfo_offset += (6 + $thisfile_real_chunks_currentchunk_logicalfileinfo_thislength);
273
274 break;
275
276 }
277
278 if (empty($info['playtime_seconds'])) {
279 $info['playtime_seconds'] = max($info['playtime_seconds'], ($thisfile_real_chunks_currentchunk['duration'] + $thisfile_real_chunks_currentchunk['start_time']) / 1000);
280 }
281 if ($thisfile_real_chunks_currentchunk['duration'] > 0) {
282 switch ($thisfile_real_chunks_currentchunk['mime_type']) {
283 case 'audio/x-pn-realaudio':
284 case 'audio/x-pn-multirate-realaudio':
285 $info['audio']['bitrate'] = (isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : 0) + $thisfile_real_chunks_currentchunk['avg_bit_rate'];
286 $info['audio']['codec'] = $this->RealAudioCodecFourCClookup($thisfile_real_chunks_currentchunk['parsed_audio_data']['fourcc'], $info['audio']['bitrate']);
287 $info['audio']['dataformat'] = 'real';
288 $info['audio']['lossless'] = false;
289 break;
290
291 case 'video/x-pn-realvideo':
292 case 'video/x-pn-multirate-realvideo':
293 $info['video']['bitrate'] = (isset($info['video']['bitrate']) ? $info['video']['bitrate'] : 0) + $thisfile_real_chunks_currentchunk['avg_bit_rate'];
294 $info['video']['bitrate_mode'] = 'cbr';
295 $info['video']['dataformat'] = 'real';
296 $info['video']['lossless'] = false;
297 $info['video']['pixel_aspect_ratio'] = (float) 1;
298 break;
299
300 case 'audio/x-ralf-mpeg4-generic':
301 $info['audio']['bitrate'] = (isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : 0) + $thisfile_real_chunks_currentchunk['avg_bit_rate'];
302 $info['audio']['codec'] = 'RealAudio Lossless';
303 $info['audio']['dataformat'] = 'real';
304 $info['audio']['lossless'] = true;
305 break;
306 }
307 $info['bitrate'] = (isset($info['video']['bitrate']) ? $info['video']['bitrate'] : 0) + (isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : 0);
308 }
309 }
310 break;
311
312 case 'CONT': // Content Description Header (text comments)
313 $thisfile_real_chunks_currentchunk['object_version'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
314 $offset += 2;
315 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) {
316 $thisfile_real_chunks_currentchunk['title_len'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
317 $offset += 2;
318 $thisfile_real_chunks_currentchunk['title'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['title_len']);
319 $offset += $thisfile_real_chunks_currentchunk['title_len'];
320
321 $thisfile_real_chunks_currentchunk['artist_len'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
322 $offset += 2;
323 $thisfile_real_chunks_currentchunk['artist'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['artist_len']);
324 $offset += $thisfile_real_chunks_currentchunk['artist_len'];
325
326 $thisfile_real_chunks_currentchunk['copyright_len'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
327 $offset += 2;
328 $thisfile_real_chunks_currentchunk['copyright'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['copyright_len']);
329 $offset += $thisfile_real_chunks_currentchunk['copyright_len'];
330
331 $thisfile_real_chunks_currentchunk['comment_len'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
332 $offset += 2;
333 $thisfile_real_chunks_currentchunk['comment'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['comment_len']);
334 $offset += $thisfile_real_chunks_currentchunk['comment_len'];
335
336 $commentkeystocopy = array('title'=>'title', 'artist'=>'artist', 'copyright'=>'copyright', 'comment'=>'comment');
337 foreach ($commentkeystocopy as $key => $val) {
338 if ($thisfile_real_chunks_currentchunk[$key]) {
339 $info['real']['comments'][$val][] = trim($thisfile_real_chunks_currentchunk[$key]);
340 }
341 }
342
343 }
344 break;
345
346 case 'DATA': // Data Chunk Header
347 // do nothing
348 break;
349
350 case 'INDX': // Index Section Header
351 $thisfile_real_chunks_currentchunk['object_version'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
352 $offset += 2;
353 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) {
354 $thisfile_real_chunks_currentchunk['num_indices'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
355 $offset += 4;
356 $thisfile_real_chunks_currentchunk['stream_number'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 2));
357 $offset += 2;
358 $thisfile_real_chunks_currentchunk['next_index_header'] = Helper::BigEndian2Int(substr($ChunkData, $offset, 4));
359 $offset += 4;
360
361 if ($thisfile_real_chunks_currentchunk['next_index_header'] == 0) {
362 // last index chunk found, ignore rest of file
363 break 2;
364 } else {
365 // non-last index chunk, seek to next index chunk (skipping actual index data)
366 fseek($this->getid3->fp, $thisfile_real_chunks_currentchunk['next_index_header'], SEEK_SET);
367 }
368 }
369 break;
370
371 default:
372 $info['warning'][] = 'Unhandled RealMedia chunk "'.$ChunkName.'" at offset '.$thisfile_real_chunks_currentchunk['offset'];
373 break;
374 }
375 $ChunkCounter++;
376 }
377
378 if (!empty($info['audio']['streams'])) {
379 $info['audio']['bitrate'] = 0;
380 foreach ($info['audio']['streams'] as $key => $valuearray) {
381 $info['audio']['bitrate'] += $valuearray['bitrate'];
382 }
383 }
384
385 return true;
386 }
387
395 public function ParseOldRAheader($OldRAheaderData, &$ParsedArray)
396 {
397 $ParsedArray = array();
398 $ParsedArray['magic'] = substr($OldRAheaderData, 0, 4);
399 if ($ParsedArray['magic'] != '.ra'."\xFD") {
400 return false;
401 }
402 $ParsedArray['version1'] = Helper::BigEndian2Int(substr($OldRAheaderData, 4, 2));
403
404 if ($ParsedArray['version1'] < 3) {
405 return false;
406
407 } elseif ($ParsedArray['version1'] == 3) {
408
409 $ParsedArray['fourcc1'] = '.ra3';
410 $ParsedArray['bits_per_sample'] = 16; // hard-coded for old versions?
411 $ParsedArray['sample_rate'] = 8000; // hard-coded for old versions?
412
413 $ParsedArray['header_size'] = Helper::BigEndian2Int(substr($OldRAheaderData, 6, 2));
414 $ParsedArray['channels'] = Helper::BigEndian2Int(substr($OldRAheaderData, 8, 2)); // always 1 (?)
415 //$ParsedArray['unknown1'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 10, 2));
416 //$ParsedArray['unknown2'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 12, 2));
417 //$ParsedArray['unknown3'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 14, 2));
418 $ParsedArray['bytes_per_minute'] = Helper::BigEndian2Int(substr($OldRAheaderData, 16, 2));
419 $ParsedArray['audio_bytes'] = Helper::BigEndian2Int(substr($OldRAheaderData, 18, 4));
420 $ParsedArray['comments_raw'] = substr($OldRAheaderData, 22, $ParsedArray['header_size'] - 22 + 1); // not including null terminator
421
422 $commentoffset = 0;
423 $commentlength = Helper::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1));
424 $ParsedArray['comments']['title'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength);
425 $commentoffset += $commentlength;
426
427 $commentlength = Helper::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1));
428 $ParsedArray['comments']['artist'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength);
429 $commentoffset += $commentlength;
430
431 $commentlength = Helper::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1));
432 $ParsedArray['comments']['copyright'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength);
433 $commentoffset += $commentlength;
434
435 $commentoffset++; // final null terminator (?)
436 $commentoffset++; // fourcc length (?) should be 4
437 $ParsedArray['fourcc'] = substr($OldRAheaderData, 23 + $commentoffset, 4);
438
439 } elseif ($ParsedArray['version1'] <= 5) {
440
441 //$ParsedArray['unknown1'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 6, 2));
442 $ParsedArray['fourcc1'] = substr($OldRAheaderData, 8, 4);
443 $ParsedArray['file_size'] = Helper::BigEndian2Int(substr($OldRAheaderData, 12, 4));
444 $ParsedArray['version2'] = Helper::BigEndian2Int(substr($OldRAheaderData, 16, 2));
445 $ParsedArray['header_size'] = Helper::BigEndian2Int(substr($OldRAheaderData, 18, 4));
446 $ParsedArray['codec_flavor_id'] = Helper::BigEndian2Int(substr($OldRAheaderData, 22, 2));
447 $ParsedArray['coded_frame_size'] = Helper::BigEndian2Int(substr($OldRAheaderData, 24, 4));
448 $ParsedArray['audio_bytes'] = Helper::BigEndian2Int(substr($OldRAheaderData, 28, 4));
449 $ParsedArray['bytes_per_minute'] = Helper::BigEndian2Int(substr($OldRAheaderData, 32, 4));
450 //$ParsedArray['unknown5'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 36, 4));
451 $ParsedArray['sub_packet_h'] = Helper::BigEndian2Int(substr($OldRAheaderData, 40, 2));
452 $ParsedArray['frame_size'] = Helper::BigEndian2Int(substr($OldRAheaderData, 42, 2));
453 $ParsedArray['sub_packet_size'] = Helper::BigEndian2Int(substr($OldRAheaderData, 44, 2));
454 //$ParsedArray['unknown6'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 46, 2));
455
456 switch ($ParsedArray['version1']) {
457
458 case 4:
459 $ParsedArray['sample_rate'] = Helper::BigEndian2Int(substr($OldRAheaderData, 48, 2));
460 //$ParsedArray['unknown8'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 50, 2));
461 $ParsedArray['bits_per_sample'] = Helper::BigEndian2Int(substr($OldRAheaderData, 52, 2));
462 $ParsedArray['channels'] = Helper::BigEndian2Int(substr($OldRAheaderData, 54, 2));
463 $ParsedArray['length_fourcc2'] = Helper::BigEndian2Int(substr($OldRAheaderData, 56, 1));
464 $ParsedArray['fourcc2'] = substr($OldRAheaderData, 57, 4);
465 $ParsedArray['length_fourcc3'] = Helper::BigEndian2Int(substr($OldRAheaderData, 61, 1));
466 $ParsedArray['fourcc3'] = substr($OldRAheaderData, 62, 4);
467 //$ParsedArray['unknown9'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 66, 1));
468 //$ParsedArray['unknown10'] = GetId3_lib::BigEndian2Int(substr($OldRAheaderData, 67, 2));
469 $ParsedArray['comments_raw'] = substr($OldRAheaderData, 69, $ParsedArray['header_size'] - 69 + 16);
470
471 $commentoffset = 0;
472 $commentlength = Helper::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1));
473 $ParsedArray['comments']['title'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength);
474 $commentoffset += $commentlength;
475
476 $commentlength = Helper::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1));
477 $ParsedArray['comments']['artist'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength);
478 $commentoffset += $commentlength;
479
480 $commentlength = Helper::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1));
481 $ParsedArray['comments']['copyright'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength);
482 $commentoffset += $commentlength;
483 break;
484
485 case 5:
486 $ParsedArray['sample_rate'] = Helper::BigEndian2Int(substr($OldRAheaderData, 48, 4));
487 $ParsedArray['sample_rate2'] = Helper::BigEndian2Int(substr($OldRAheaderData, 52, 4));
488 $ParsedArray['bits_per_sample'] = Helper::BigEndian2Int(substr($OldRAheaderData, 56, 4));
489 $ParsedArray['channels'] = Helper::BigEndian2Int(substr($OldRAheaderData, 60, 2));
490 $ParsedArray['genr'] = substr($OldRAheaderData, 62, 4);
491 $ParsedArray['fourcc3'] = substr($OldRAheaderData, 66, 4);
492 $ParsedArray['comments'] = array();
493 break;
494 }
495 $ParsedArray['fourcc'] = $ParsedArray['fourcc3'];
496
497 }
498 foreach ($ParsedArray['comments'] as $key => $value) {
499 if ($ParsedArray['comments'][$key][0] === false) {
500 $ParsedArray['comments'][$key][0] = '';
501 }
502 }
503
504 return true;
505 }
506
516 public function RealAudioCodecFourCClookup($fourcc, $bitrate)
517 {
518 static $RealAudioCodecFourCClookup = array();
519 if (empty($RealAudioCodecFourCClookup)) {
520
521 $RealAudioCodecFourCClookup['14_4'][8000] = 'RealAudio v2 (14.4kbps)';
522 $RealAudioCodecFourCClookup['14.4'][8000] = 'RealAudio v2 (14.4kbps)';
523 $RealAudioCodecFourCClookup['lpcJ'][8000] = 'RealAudio v2 (14.4kbps)';
524 $RealAudioCodecFourCClookup['28_8'][15200] = 'RealAudio v2 (28.8kbps)';
525 $RealAudioCodecFourCClookup['28.8'][15200] = 'RealAudio v2 (28.8kbps)';
526 $RealAudioCodecFourCClookup['sipr'][4933] = 'RealAudio v4 (5kbps Voice)';
527 $RealAudioCodecFourCClookup['sipr'][6444] = 'RealAudio v4 (6.5kbps Voice)';
528 $RealAudioCodecFourCClookup['sipr'][8444] = 'RealAudio v4 (8.5kbps Voice)';
529 $RealAudioCodecFourCClookup['sipr'][16000] = 'RealAudio v4 (16kbps Wideband)';
530 $RealAudioCodecFourCClookup['dnet'][8000] = 'RealAudio v3 (8kbps Music)';
531 $RealAudioCodecFourCClookup['dnet'][16000] = 'RealAudio v3 (16kbps Music Low Response)';
532 $RealAudioCodecFourCClookup['dnet'][15963] = 'RealAudio v3 (16kbps Music Mid/High Response)';
533 $RealAudioCodecFourCClookup['dnet'][20000] = 'RealAudio v3 (20kbps Music Stereo)';
534 $RealAudioCodecFourCClookup['dnet'][32000] = 'RealAudio v3 (32kbps Music Mono)';
535 $RealAudioCodecFourCClookup['dnet'][31951] = 'RealAudio v3 (32kbps Music Stereo)';
536 $RealAudioCodecFourCClookup['dnet'][39965] = 'RealAudio v3 (40kbps Music Mono)';
537 $RealAudioCodecFourCClookup['dnet'][40000] = 'RealAudio v3 (40kbps Music Stereo)';
538 $RealAudioCodecFourCClookup['dnet'][79947] = 'RealAudio v3 (80kbps Music Mono)';
539 $RealAudioCodecFourCClookup['dnet'][80000] = 'RealAudio v3 (80kbps Music Stereo)';
540
541 $RealAudioCodecFourCClookup['dnet'][0] = 'RealAudio v3';
542 $RealAudioCodecFourCClookup['sipr'][0] = 'RealAudio v4';
543 $RealAudioCodecFourCClookup['cook'][0] = 'RealAudio G2';
544 $RealAudioCodecFourCClookup['atrc'][0] = 'RealAudio 8';
545 }
546 $roundbitrate = intval(round($bitrate));
547 if (isset($RealAudioCodecFourCClookup[$fourcc][$roundbitrate])) {
548 return $RealAudioCodecFourCClookup[$fourcc][$roundbitrate];
549 } elseif (isset($RealAudioCodecFourCClookup[$fourcc][0])) {
550 return $RealAudioCodecFourCClookup[$fourcc][0];
551 }
552
553 return $fourcc;
554 }
555
556}
An exception for terminatinating execution or to throw for unit testing.
GetId3() by James Heinrich info@getid3.org //.
Definition: BaseHandler.php:26
fseek($bytes, $whence=SEEK_SET)
GetId3() by James Heinrich info@getid3.org //.
Definition: Helper.php:27
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
Definition: Helper.php:374
GetId3() by James Heinrich info@getid3.org //.
Definition: Real.php:31
RealAudioCodecFourCClookup($fourcc, $bitrate)
@staticvar array $RealAudioCodecFourCClookup
Definition: Real.php:516
ParseOldRAheader($OldRAheaderData, &$ParsedArray)
Definition: Real.php:395
static RIFFfourccLookup($fourcc)
Definition: Riff.php:2101
$info
Definition: example_052.php:80