File indexing completed on 2024-12-22 05:33:11
0001 <?php 0002 ///////////////////////////////////////////////////////////////// 0003 /// getID3() by James Heinrich <info@getid3.org> // 0004 // available at http://getid3.sourceforge.net // 0005 // or http://www.getid3.org // 0006 // also https://github.com/JamesHeinrich/getID3 // 0007 ///////////////////////////////////////////////////////////////// 0008 // See readme.txt for more details // 0009 ///////////////////////////////////////////////////////////////// 0010 // // 0011 // module.audio-video.real.php // 0012 // module for analyzing Real Audio/Video files // 0013 // dependencies: module.audio-video.riff.php // 0014 // /// 0015 ///////////////////////////////////////////////////////////////// 0016 0017 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); 0018 0019 class getid3_real extends getid3_handler 0020 { 0021 0022 public function Analyze() { 0023 $info = &$this->getid3->info; 0024 0025 $info['fileformat'] = 'real'; 0026 $info['bitrate'] = 0; 0027 $info['playtime_seconds'] = 0; 0028 0029 $this->fseek($info['avdataoffset']); 0030 $ChunkCounter = 0; 0031 while ($this->ftell() < $info['avdataend']) { 0032 $ChunkData = $this->fread(8); 0033 $ChunkName = substr($ChunkData, 0, 4); 0034 $ChunkSize = getid3_lib::BigEndian2Int(substr($ChunkData, 4, 4)); 0035 0036 if ($ChunkName == '.ra'."\xFD") { 0037 $ChunkData .= $this->fread($ChunkSize - 8); 0038 if ($this->ParseOldRAheader(substr($ChunkData, 0, 128), $info['real']['old_ra_header'])) { 0039 $info['audio']['dataformat'] = 'real'; 0040 $info['audio']['lossless'] = false; 0041 $info['audio']['sample_rate'] = $info['real']['old_ra_header']['sample_rate']; 0042 $info['audio']['bits_per_sample'] = $info['real']['old_ra_header']['bits_per_sample']; 0043 $info['audio']['channels'] = $info['real']['old_ra_header']['channels']; 0044 0045 $info['playtime_seconds'] = 60 * ($info['real']['old_ra_header']['audio_bytes'] / $info['real']['old_ra_header']['bytes_per_minute']); 0046 $info['audio']['bitrate'] = 8 * ($info['real']['old_ra_header']['audio_bytes'] / $info['playtime_seconds']); 0047 $info['audio']['codec'] = $this->RealAudioCodecFourCClookup($info['real']['old_ra_header']['fourcc'], $info['audio']['bitrate']); 0048 0049 foreach ($info['real']['old_ra_header']['comments'] as $key => $valuearray) { 0050 if (strlen(trim($valuearray[0])) > 0) { 0051 $info['real']['comments'][$key][] = trim($valuearray[0]); 0052 } 0053 } 0054 return true; 0055 } 0056 $info['error'][] = 'There was a problem parsing this RealAudio file. Please submit it for analysis to info@getid3.org'; 0057 unset($info['bitrate']); 0058 unset($info['playtime_seconds']); 0059 return false; 0060 } 0061 0062 // shortcut 0063 $info['real']['chunks'][$ChunkCounter] = array(); 0064 $thisfile_real_chunks_currentchunk = &$info['real']['chunks'][$ChunkCounter]; 0065 0066 $thisfile_real_chunks_currentchunk['name'] = $ChunkName; 0067 $thisfile_real_chunks_currentchunk['offset'] = $this->ftell() - 8; 0068 $thisfile_real_chunks_currentchunk['length'] = $ChunkSize; 0069 if (($thisfile_real_chunks_currentchunk['offset'] + $thisfile_real_chunks_currentchunk['length']) > $info['avdataend']) { 0070 $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'; 0071 return false; 0072 } 0073 0074 if ($ChunkSize > ($this->getid3->fread_buffer_size() + 8)) { 0075 0076 $ChunkData .= $this->fread($this->getid3->fread_buffer_size() - 8); 0077 $this->fseek($thisfile_real_chunks_currentchunk['offset'] + $ChunkSize); 0078 0079 } elseif(($ChunkSize - 8) > 0) { 0080 0081 $ChunkData .= $this->fread($ChunkSize - 8); 0082 0083 } 0084 $offset = 8; 0085 0086 switch ($ChunkName) { 0087 0088 case '.RMF': // RealMedia File Header 0089 $thisfile_real_chunks_currentchunk['object_version'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0090 $offset += 2; 0091 switch ($thisfile_real_chunks_currentchunk['object_version']) { 0092 0093 case 0: 0094 $thisfile_real_chunks_currentchunk['file_version'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0095 $offset += 4; 0096 $thisfile_real_chunks_currentchunk['headers_count'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0097 $offset += 4; 0098 break; 0099 0100 default: 0101 //$info['warning'][] = 'Expected .RMF-object_version to be "0", actual value is "'.$thisfile_real_chunks_currentchunk['object_version'].'" (should not be a problem)'; 0102 break; 0103 0104 } 0105 break; 0106 0107 0108 case 'PROP': // Properties Header 0109 $thisfile_real_chunks_currentchunk['object_version'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0110 $offset += 2; 0111 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) { 0112 $thisfile_real_chunks_currentchunk['max_bit_rate'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0113 $offset += 4; 0114 $thisfile_real_chunks_currentchunk['avg_bit_rate'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0115 $offset += 4; 0116 $thisfile_real_chunks_currentchunk['max_packet_size'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0117 $offset += 4; 0118 $thisfile_real_chunks_currentchunk['avg_packet_size'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0119 $offset += 4; 0120 $thisfile_real_chunks_currentchunk['num_packets'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0121 $offset += 4; 0122 $thisfile_real_chunks_currentchunk['duration'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0123 $offset += 4; 0124 $thisfile_real_chunks_currentchunk['preroll'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0125 $offset += 4; 0126 $thisfile_real_chunks_currentchunk['index_offset'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0127 $offset += 4; 0128 $thisfile_real_chunks_currentchunk['data_offset'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0129 $offset += 4; 0130 $thisfile_real_chunks_currentchunk['num_streams'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0131 $offset += 2; 0132 $thisfile_real_chunks_currentchunk['flags_raw'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0133 $offset += 2; 0134 $info['playtime_seconds'] = $thisfile_real_chunks_currentchunk['duration'] / 1000; 0135 if ($thisfile_real_chunks_currentchunk['duration'] > 0) { 0136 $info['bitrate'] += $thisfile_real_chunks_currentchunk['avg_bit_rate']; 0137 } 0138 $thisfile_real_chunks_currentchunk['flags']['save_enabled'] = (bool) ($thisfile_real_chunks_currentchunk['flags_raw'] & 0x0001); 0139 $thisfile_real_chunks_currentchunk['flags']['perfect_play'] = (bool) ($thisfile_real_chunks_currentchunk['flags_raw'] & 0x0002); 0140 $thisfile_real_chunks_currentchunk['flags']['live_broadcast'] = (bool) ($thisfile_real_chunks_currentchunk['flags_raw'] & 0x0004); 0141 } 0142 break; 0143 0144 case 'MDPR': // Media Properties Header 0145 $thisfile_real_chunks_currentchunk['object_version'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0146 $offset += 2; 0147 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) { 0148 $thisfile_real_chunks_currentchunk['stream_number'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0149 $offset += 2; 0150 $thisfile_real_chunks_currentchunk['max_bit_rate'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0151 $offset += 4; 0152 $thisfile_real_chunks_currentchunk['avg_bit_rate'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0153 $offset += 4; 0154 $thisfile_real_chunks_currentchunk['max_packet_size'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0155 $offset += 4; 0156 $thisfile_real_chunks_currentchunk['avg_packet_size'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0157 $offset += 4; 0158 $thisfile_real_chunks_currentchunk['start_time'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0159 $offset += 4; 0160 $thisfile_real_chunks_currentchunk['preroll'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0161 $offset += 4; 0162 $thisfile_real_chunks_currentchunk['duration'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0163 $offset += 4; 0164 $thisfile_real_chunks_currentchunk['stream_name_size'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 1)); 0165 $offset += 1; 0166 $thisfile_real_chunks_currentchunk['stream_name'] = substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['stream_name_size']); 0167 $offset += $thisfile_real_chunks_currentchunk['stream_name_size']; 0168 $thisfile_real_chunks_currentchunk['mime_type_size'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 1)); 0169 $offset += 1; 0170 $thisfile_real_chunks_currentchunk['mime_type'] = substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['mime_type_size']); 0171 $offset += $thisfile_real_chunks_currentchunk['mime_type_size']; 0172 $thisfile_real_chunks_currentchunk['type_specific_len'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0173 $offset += 4; 0174 $thisfile_real_chunks_currentchunk['type_specific_data'] = substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['type_specific_len']); 0175 $offset += $thisfile_real_chunks_currentchunk['type_specific_len']; 0176 0177 // shortcut 0178 $thisfile_real_chunks_currentchunk_typespecificdata = &$thisfile_real_chunks_currentchunk['type_specific_data']; 0179 0180 switch ($thisfile_real_chunks_currentchunk['mime_type']) { 0181 case 'video/x-pn-realvideo': 0182 case 'video/x-pn-multirate-realvideo': 0183 // http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html 0184 0185 // shortcut 0186 $thisfile_real_chunks_currentchunk['video_info'] = array(); 0187 $thisfile_real_chunks_currentchunk_videoinfo = &$thisfile_real_chunks_currentchunk['video_info']; 0188 0189 $thisfile_real_chunks_currentchunk_videoinfo['dwSize'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 0, 4)); 0190 $thisfile_real_chunks_currentchunk_videoinfo['fourcc1'] = substr($thisfile_real_chunks_currentchunk_typespecificdata, 4, 4); 0191 $thisfile_real_chunks_currentchunk_videoinfo['fourcc2'] = substr($thisfile_real_chunks_currentchunk_typespecificdata, 8, 4); 0192 $thisfile_real_chunks_currentchunk_videoinfo['width'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 12, 2)); 0193 $thisfile_real_chunks_currentchunk_videoinfo['height'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 14, 2)); 0194 $thisfile_real_chunks_currentchunk_videoinfo['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 16, 2)); 0195 //$thisfile_real_chunks_currentchunk_videoinfo['unknown1'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 18, 2)); 0196 //$thisfile_real_chunks_currentchunk_videoinfo['unknown2'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 20, 2)); 0197 $thisfile_real_chunks_currentchunk_videoinfo['frames_per_second'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 22, 2)); 0198 //$thisfile_real_chunks_currentchunk_videoinfo['unknown3'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 24, 2)); 0199 //$thisfile_real_chunks_currentchunk_videoinfo['unknown4'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 26, 2)); 0200 //$thisfile_real_chunks_currentchunk_videoinfo['unknown5'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 28, 2)); 0201 //$thisfile_real_chunks_currentchunk_videoinfo['unknown6'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 30, 2)); 0202 //$thisfile_real_chunks_currentchunk_videoinfo['unknown7'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 32, 2)); 0203 //$thisfile_real_chunks_currentchunk_videoinfo['unknown8'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 34, 2)); 0204 //$thisfile_real_chunks_currentchunk_videoinfo['unknown9'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 36, 2)); 0205 0206 $thisfile_real_chunks_currentchunk_videoinfo['codec'] = getid3_riff::fourccLookup($thisfile_real_chunks_currentchunk_videoinfo['fourcc2']); 0207 0208 $info['video']['resolution_x'] = $thisfile_real_chunks_currentchunk_videoinfo['width']; 0209 $info['video']['resolution_y'] = $thisfile_real_chunks_currentchunk_videoinfo['height']; 0210 $info['video']['frame_rate'] = (float) $thisfile_real_chunks_currentchunk_videoinfo['frames_per_second']; 0211 $info['video']['codec'] = $thisfile_real_chunks_currentchunk_videoinfo['codec']; 0212 $info['video']['bits_per_sample'] = $thisfile_real_chunks_currentchunk_videoinfo['bits_per_sample']; 0213 break; 0214 0215 case 'audio/x-pn-realaudio': 0216 case 'audio/x-pn-multirate-realaudio': 0217 $this->ParseOldRAheader($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk['parsed_audio_data']); 0218 0219 $info['audio']['sample_rate'] = $thisfile_real_chunks_currentchunk['parsed_audio_data']['sample_rate']; 0220 $info['audio']['bits_per_sample'] = $thisfile_real_chunks_currentchunk['parsed_audio_data']['bits_per_sample']; 0221 $info['audio']['channels'] = $thisfile_real_chunks_currentchunk['parsed_audio_data']['channels']; 0222 if (!empty($info['audio']['dataformat'])) { 0223 foreach ($info['audio'] as $key => $value) { 0224 if ($key != 'streams') { 0225 $info['audio']['streams'][$thisfile_real_chunks_currentchunk['stream_number']][$key] = $value; 0226 } 0227 } 0228 } 0229 break; 0230 0231 case 'logical-fileinfo': 0232 // shortcut 0233 $thisfile_real_chunks_currentchunk['logical_fileinfo'] = array(); 0234 $thisfile_real_chunks_currentchunk_logicalfileinfo = &$thisfile_real_chunks_currentchunk['logical_fileinfo']; 0235 0236 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset = 0; 0237 $thisfile_real_chunks_currentchunk_logicalfileinfo['logical_fileinfo_length'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4)); 0238 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4; 0239 0240 //$thisfile_real_chunks_currentchunk_logicalfileinfo['unknown1'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4)); 0241 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4; 0242 0243 $thisfile_real_chunks_currentchunk_logicalfileinfo['num_tags'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4)); 0244 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4; 0245 0246 //$thisfile_real_chunks_currentchunk_logicalfileinfo['unknown2'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4)); 0247 $thisfile_real_chunks_currentchunk_logicalfileinfo_offset += 4; 0248 0249 //$thisfile_real_chunks_currentchunk_logicalfileinfo['d'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 1)); 0250 0251 //$thisfile_real_chunks_currentchunk_logicalfileinfo['one_type'] = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 4)); 0252 //$thisfile_real_chunks_currentchunk_logicalfileinfo_thislength = getid3_lib::BigEndian2Int(substr($thisfile_real_chunks_currentchunk_typespecificdata, 4 + $thisfile_real_chunks_currentchunk_logicalfileinfo_offset, 2)); 0253 //$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); 0254 //$thisfile_real_chunks_currentchunk_logicalfileinfo_offset += (6 + $thisfile_real_chunks_currentchunk_logicalfileinfo_thislength); 0255 0256 break; 0257 0258 } 0259 0260 0261 if (empty($info['playtime_seconds'])) { 0262 $info['playtime_seconds'] = max($info['playtime_seconds'], ($thisfile_real_chunks_currentchunk['duration'] + $thisfile_real_chunks_currentchunk['start_time']) / 1000); 0263 } 0264 if ($thisfile_real_chunks_currentchunk['duration'] > 0) { 0265 switch ($thisfile_real_chunks_currentchunk['mime_type']) { 0266 case 'audio/x-pn-realaudio': 0267 case 'audio/x-pn-multirate-realaudio': 0268 $info['audio']['bitrate'] = (isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : 0) + $thisfile_real_chunks_currentchunk['avg_bit_rate']; 0269 $info['audio']['codec'] = $this->RealAudioCodecFourCClookup($thisfile_real_chunks_currentchunk['parsed_audio_data']['fourcc'], $info['audio']['bitrate']); 0270 $info['audio']['dataformat'] = 'real'; 0271 $info['audio']['lossless'] = false; 0272 break; 0273 0274 case 'video/x-pn-realvideo': 0275 case 'video/x-pn-multirate-realvideo': 0276 $info['video']['bitrate'] = (isset($info['video']['bitrate']) ? $info['video']['bitrate'] : 0) + $thisfile_real_chunks_currentchunk['avg_bit_rate']; 0277 $info['video']['bitrate_mode'] = 'cbr'; 0278 $info['video']['dataformat'] = 'real'; 0279 $info['video']['lossless'] = false; 0280 $info['video']['pixel_aspect_ratio'] = (float) 1; 0281 break; 0282 0283 case 'audio/x-ralf-mpeg4-generic': 0284 $info['audio']['bitrate'] = (isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : 0) + $thisfile_real_chunks_currentchunk['avg_bit_rate']; 0285 $info['audio']['codec'] = 'RealAudio Lossless'; 0286 $info['audio']['dataformat'] = 'real'; 0287 $info['audio']['lossless'] = true; 0288 break; 0289 } 0290 $info['bitrate'] = (isset($info['video']['bitrate']) ? $info['video']['bitrate'] : 0) + (isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : 0); 0291 } 0292 } 0293 break; 0294 0295 case 'CONT': // Content Description Header (text comments) 0296 $thisfile_real_chunks_currentchunk['object_version'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0297 $offset += 2; 0298 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) { 0299 $thisfile_real_chunks_currentchunk['title_len'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0300 $offset += 2; 0301 $thisfile_real_chunks_currentchunk['title'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['title_len']); 0302 $offset += $thisfile_real_chunks_currentchunk['title_len']; 0303 0304 $thisfile_real_chunks_currentchunk['artist_len'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0305 $offset += 2; 0306 $thisfile_real_chunks_currentchunk['artist'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['artist_len']); 0307 $offset += $thisfile_real_chunks_currentchunk['artist_len']; 0308 0309 $thisfile_real_chunks_currentchunk['copyright_len'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0310 $offset += 2; 0311 $thisfile_real_chunks_currentchunk['copyright'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['copyright_len']); 0312 $offset += $thisfile_real_chunks_currentchunk['copyright_len']; 0313 0314 $thisfile_real_chunks_currentchunk['comment_len'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0315 $offset += 2; 0316 $thisfile_real_chunks_currentchunk['comment'] = (string) substr($ChunkData, $offset, $thisfile_real_chunks_currentchunk['comment_len']); 0317 $offset += $thisfile_real_chunks_currentchunk['comment_len']; 0318 0319 0320 $commentkeystocopy = array('title'=>'title', 'artist'=>'artist', 'copyright'=>'copyright', 'comment'=>'comment'); 0321 foreach ($commentkeystocopy as $key => $val) { 0322 if ($thisfile_real_chunks_currentchunk[$key]) { 0323 $info['real']['comments'][$val][] = trim($thisfile_real_chunks_currentchunk[$key]); 0324 } 0325 } 0326 0327 } 0328 break; 0329 0330 0331 case 'DATA': // Data Chunk Header 0332 // do nothing 0333 break; 0334 0335 case 'INDX': // Index Section Header 0336 $thisfile_real_chunks_currentchunk['object_version'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0337 $offset += 2; 0338 if ($thisfile_real_chunks_currentchunk['object_version'] == 0) { 0339 $thisfile_real_chunks_currentchunk['num_indices'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0340 $offset += 4; 0341 $thisfile_real_chunks_currentchunk['stream_number'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 2)); 0342 $offset += 2; 0343 $thisfile_real_chunks_currentchunk['next_index_header'] = getid3_lib::BigEndian2Int(substr($ChunkData, $offset, 4)); 0344 $offset += 4; 0345 0346 if ($thisfile_real_chunks_currentchunk['next_index_header'] == 0) { 0347 // last index chunk found, ignore rest of file 0348 break 2; 0349 } else { 0350 // non-last index chunk, seek to next index chunk (skipping actual index data) 0351 $this->fseek($thisfile_real_chunks_currentchunk['next_index_header']); 0352 } 0353 } 0354 break; 0355 0356 default: 0357 $info['warning'][] = 'Unhandled RealMedia chunk "'.$ChunkName.'" at offset '.$thisfile_real_chunks_currentchunk['offset']; 0358 break; 0359 } 0360 $ChunkCounter++; 0361 } 0362 0363 if (!empty($info['audio']['streams'])) { 0364 $info['audio']['bitrate'] = 0; 0365 foreach ($info['audio']['streams'] as $key => $valuearray) { 0366 $info['audio']['bitrate'] += $valuearray['bitrate']; 0367 } 0368 } 0369 0370 return true; 0371 } 0372 0373 0374 public function ParseOldRAheader($OldRAheaderData, &$ParsedArray) { 0375 // http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html 0376 0377 $ParsedArray = array(); 0378 $ParsedArray['magic'] = substr($OldRAheaderData, 0, 4); 0379 if ($ParsedArray['magic'] != '.ra'."\xFD") { 0380 return false; 0381 } 0382 $ParsedArray['version1'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 4, 2)); 0383 0384 if ($ParsedArray['version1'] < 3) { 0385 0386 return false; 0387 0388 } elseif ($ParsedArray['version1'] == 3) { 0389 0390 $ParsedArray['fourcc1'] = '.ra3'; 0391 $ParsedArray['bits_per_sample'] = 16; // hard-coded for old versions? 0392 $ParsedArray['sample_rate'] = 8000; // hard-coded for old versions? 0393 0394 $ParsedArray['header_size'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 6, 2)); 0395 $ParsedArray['channels'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 8, 2)); // always 1 (?) 0396 //$ParsedArray['unknown1'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 10, 2)); 0397 //$ParsedArray['unknown2'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 12, 2)); 0398 //$ParsedArray['unknown3'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 14, 2)); 0399 $ParsedArray['bytes_per_minute'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 16, 2)); 0400 $ParsedArray['audio_bytes'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 18, 4)); 0401 $ParsedArray['comments_raw'] = substr($OldRAheaderData, 22, $ParsedArray['header_size'] - 22 + 1); // not including null terminator 0402 0403 $commentoffset = 0; 0404 $commentlength = getid3_lib::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1)); 0405 $ParsedArray['comments']['title'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength); 0406 $commentoffset += $commentlength; 0407 0408 $commentlength = getid3_lib::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1)); 0409 $ParsedArray['comments']['artist'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength); 0410 $commentoffset += $commentlength; 0411 0412 $commentlength = getid3_lib::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1)); 0413 $ParsedArray['comments']['copyright'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength); 0414 $commentoffset += $commentlength; 0415 0416 $commentoffset++; // final null terminator (?) 0417 $commentoffset++; // fourcc length (?) should be 4 0418 $ParsedArray['fourcc'] = substr($OldRAheaderData, 23 + $commentoffset, 4); 0419 0420 } elseif ($ParsedArray['version1'] <= 5) { 0421 0422 //$ParsedArray['unknown1'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 6, 2)); 0423 $ParsedArray['fourcc1'] = substr($OldRAheaderData, 8, 4); 0424 $ParsedArray['file_size'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 12, 4)); 0425 $ParsedArray['version2'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 16, 2)); 0426 $ParsedArray['header_size'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 18, 4)); 0427 $ParsedArray['codec_flavor_id'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 22, 2)); 0428 $ParsedArray['coded_frame_size'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 24, 4)); 0429 $ParsedArray['audio_bytes'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 28, 4)); 0430 $ParsedArray['bytes_per_minute'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 32, 4)); 0431 //$ParsedArray['unknown5'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 36, 4)); 0432 $ParsedArray['sub_packet_h'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 40, 2)); 0433 $ParsedArray['frame_size'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 42, 2)); 0434 $ParsedArray['sub_packet_size'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 44, 2)); 0435 //$ParsedArray['unknown6'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 46, 2)); 0436 0437 switch ($ParsedArray['version1']) { 0438 0439 case 4: 0440 $ParsedArray['sample_rate'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 48, 2)); 0441 //$ParsedArray['unknown8'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 50, 2)); 0442 $ParsedArray['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 52, 2)); 0443 $ParsedArray['channels'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 54, 2)); 0444 $ParsedArray['length_fourcc2'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 56, 1)); 0445 $ParsedArray['fourcc2'] = substr($OldRAheaderData, 57, 4); 0446 $ParsedArray['length_fourcc3'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 61, 1)); 0447 $ParsedArray['fourcc3'] = substr($OldRAheaderData, 62, 4); 0448 //$ParsedArray['unknown9'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 66, 1)); 0449 //$ParsedArray['unknown10'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 67, 2)); 0450 $ParsedArray['comments_raw'] = substr($OldRAheaderData, 69, $ParsedArray['header_size'] - 69 + 16); 0451 0452 $commentoffset = 0; 0453 $commentlength = getid3_lib::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1)); 0454 $ParsedArray['comments']['title'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength); 0455 $commentoffset += $commentlength; 0456 0457 $commentlength = getid3_lib::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1)); 0458 $ParsedArray['comments']['artist'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength); 0459 $commentoffset += $commentlength; 0460 0461 $commentlength = getid3_lib::BigEndian2Int(substr($ParsedArray['comments_raw'], $commentoffset++, 1)); 0462 $ParsedArray['comments']['copyright'][] = substr($ParsedArray['comments_raw'], $commentoffset, $commentlength); 0463 $commentoffset += $commentlength; 0464 break; 0465 0466 case 5: 0467 $ParsedArray['sample_rate'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 48, 4)); 0468 $ParsedArray['sample_rate2'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 52, 4)); 0469 $ParsedArray['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 56, 4)); 0470 $ParsedArray['channels'] = getid3_lib::BigEndian2Int(substr($OldRAheaderData, 60, 2)); 0471 $ParsedArray['genr'] = substr($OldRAheaderData, 62, 4); 0472 $ParsedArray['fourcc3'] = substr($OldRAheaderData, 66, 4); 0473 $ParsedArray['comments'] = array(); 0474 break; 0475 } 0476 $ParsedArray['fourcc'] = $ParsedArray['fourcc3']; 0477 0478 } 0479 foreach ($ParsedArray['comments'] as $key => $value) { 0480 if ($ParsedArray['comments'][$key][0] === false) { 0481 $ParsedArray['comments'][$key][0] = ''; 0482 } 0483 } 0484 0485 return true; 0486 } 0487 0488 public function RealAudioCodecFourCClookup($fourcc, $bitrate) { 0489 static $RealAudioCodecFourCClookup = array(); 0490 if (empty($RealAudioCodecFourCClookup)) { 0491 // http://www.its.msstate.edu/net/real/reports/config/tags.stats 0492 // http://www.freelists.org/archives/matroska-devel/06-2003/fullthread18.html 0493 0494 $RealAudioCodecFourCClookup['14_4'][8000] = 'RealAudio v2 (14.4kbps)'; 0495 $RealAudioCodecFourCClookup['14.4'][8000] = 'RealAudio v2 (14.4kbps)'; 0496 $RealAudioCodecFourCClookup['lpcJ'][8000] = 'RealAudio v2 (14.4kbps)'; 0497 $RealAudioCodecFourCClookup['28_8'][15200] = 'RealAudio v2 (28.8kbps)'; 0498 $RealAudioCodecFourCClookup['28.8'][15200] = 'RealAudio v2 (28.8kbps)'; 0499 $RealAudioCodecFourCClookup['sipr'][4933] = 'RealAudio v4 (5kbps Voice)'; 0500 $RealAudioCodecFourCClookup['sipr'][6444] = 'RealAudio v4 (6.5kbps Voice)'; 0501 $RealAudioCodecFourCClookup['sipr'][8444] = 'RealAudio v4 (8.5kbps Voice)'; 0502 $RealAudioCodecFourCClookup['sipr'][16000] = 'RealAudio v4 (16kbps Wideband)'; 0503 $RealAudioCodecFourCClookup['dnet'][8000] = 'RealAudio v3 (8kbps Music)'; 0504 $RealAudioCodecFourCClookup['dnet'][16000] = 'RealAudio v3 (16kbps Music Low Response)'; 0505 $RealAudioCodecFourCClookup['dnet'][15963] = 'RealAudio v3 (16kbps Music Mid/High Response)'; 0506 $RealAudioCodecFourCClookup['dnet'][20000] = 'RealAudio v3 (20kbps Music Stereo)'; 0507 $RealAudioCodecFourCClookup['dnet'][32000] = 'RealAudio v3 (32kbps Music Mono)'; 0508 $RealAudioCodecFourCClookup['dnet'][31951] = 'RealAudio v3 (32kbps Music Stereo)'; 0509 $RealAudioCodecFourCClookup['dnet'][39965] = 'RealAudio v3 (40kbps Music Mono)'; 0510 $RealAudioCodecFourCClookup['dnet'][40000] = 'RealAudio v3 (40kbps Music Stereo)'; 0511 $RealAudioCodecFourCClookup['dnet'][79947] = 'RealAudio v3 (80kbps Music Mono)'; 0512 $RealAudioCodecFourCClookup['dnet'][80000] = 'RealAudio v3 (80kbps Music Stereo)'; 0513 0514 $RealAudioCodecFourCClookup['dnet'][0] = 'RealAudio v3'; 0515 $RealAudioCodecFourCClookup['sipr'][0] = 'RealAudio v4'; 0516 $RealAudioCodecFourCClookup['cook'][0] = 'RealAudio G2'; 0517 $RealAudioCodecFourCClookup['atrc'][0] = 'RealAudio 8'; 0518 } 0519 $roundbitrate = intval(round($bitrate)); 0520 if (isset($RealAudioCodecFourCClookup[$fourcc][$roundbitrate])) { 0521 return $RealAudioCodecFourCClookup[$fourcc][$roundbitrate]; 0522 } elseif (isset($RealAudioCodecFourCClookup[$fourcc][0])) { 0523 return $RealAudioCodecFourCClookup[$fourcc][0]; 0524 } 0525 return $fourcc; 0526 } 0527 0528 }