ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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
16getid3_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?>
fseek($bytes, $whence=SEEK_SET)
Definition: getid3.php:1697
fread($bytes)
Definition: getid3.php:1685
IncludeDependency($filename, $sourcefile, $DieOnFailure=false)
BigEndian2Int($byteword, $synchsafe=false, $signed=false)
Definition: getid3.lib.php:234
getid3_real(&$fd, &$ThisFileInfo)
ParseOldRAheader($OldRAheaderData, &$ParsedArray)
RealAudioCodecFourCClookup($fourcc, $bitrate)
const GETID3_FREAD_BUFFER_SIZE
Definition: getid3.php:14