source: extensions/charlies_content/getid3/getid3/module.audio-video.real.php @ 3544

Last change on this file since 3544 was 3544, checked in by vdigital, 15 years ago

Change: getid3 upgraded to -> 1.7.9

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 32.1 KB
Line 
1<?php
2/////////////////////////////////////////////////////////////////
3/// getID3() by James Heinrich <info@getid3.org>               //
4//  available at http://getid3.sourceforge.net                 //
5//            or http://www.getid3.org                         //
6/////////////////////////////////////////////////////////////////
7// See readme.txt for more details                             //
8/////////////////////////////////////////////////////////////////
9//                                                             //
10// module.audio-video.real.php                                 //
11// module for analyzing Real Audio/Video files                 //
12// dependencies: module.audio-video.riff.php                   //
13//                                                            ///
14/////////////////////////////////////////////////////////////////
15
16getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
17
18class getid3_real
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                        } elseif(($ChunkSize - 8) > 0) {
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?>
Note: See TracBrowser for help on using the repository browser.