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