source: spip-zone/_core_/plugins/medias/lib/getid3/module.audio-video.real.php @ 113161

Last change on this file since 113161 was 113161, checked in by spip.franck@…, 5 months ago

Mise à jour de la lib getid en 1.9.16, nous étions en 1.9.14
https://github.com/JamesHeinrich/getID3/blob/master/changelog.txt

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