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 
30 class 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 }
GetId3() by James Heinrich info@getid3.org //.
Definition: BaseHandler.php:25
Add rich text string
The name of the decorator.
ParseOldRAheader($OldRAheaderData, &$ParsedArray)
Definition: Real.php:395
static RIFFfourccLookup($fourcc)
Definition: Riff.php:2101
fseek($bytes, $whence=SEEK_SET)
$info
Definition: example_052.php:80
GetId3() by James Heinrich info@getid3.org //.
Definition: Real.php:30
Create styles array
The data for the language used.
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
Definition: Helper.php:374
RealAudioCodecFourCClookup($fourcc, $bitrate)
array $RealAudioCodecFourCClookup
Definition: Real.php:516