source: branches/MootoolsFileManager-Update/plugins/MootoolsFileManager/mootools-filemanager/Assets/Connector/Assets/getid3/module.audio-video.flv.php @ 1300

Last change on this file since 1300 was 1300, checked in by gogo, 9 years ago

Update the MootoolsFileManager? to the latest cpojer with some modifications.
Add a demo for the MFM examples/mootools-file-manager.php
Change the default config for ImageManager? and ExtendedFileManager? for added security.

File size: 22.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//  FLV module by Seth Kaufman <seth@whirl-i-gig.com>          //
8//                                                             //
9//  * version 0.1 (26 June 2005)                               //
10//                                                             //
11//  minor modifications by James Heinrich <info@getid3.org>    //
12//  * version 0.1.1 (15 July 2005)                             //
13//                                                             //
14//  Support for On2 VP6 codec and meta information             //
15//    by Steve Webster <steve.webster@featurecreep.com>        //
16//  * version 0.2 (22 February 2006)                           //
17//                                                             //
18//  Modified to not read entire file into memory               //
19//    by James Heinrich <info@getid3.org>                      //
20//  * version 0.3 (15 June 2006)                               //
21//                                                             //
22//  Bugfixes for incorrectly parsed FLV dimensions             //
23//    and incorrect parsing of onMetaTag                       //
24//    by Evgeny Moysevich <moysevich@gmail.com>                //
25//  * version 0.4 (07 December 2007)                           //
26//                                                             //
27//  Fixed parsing of audio tags and added additional codec     //
28//    details. The duration is now read from onMetaTag (if     //
29//    exists), rather than parsing whole file                  //
30//    by Nigel Barnes <ngbarnes@hotmail.com>                   //
31//  * version 0.5 (21 May 2009)                                //
32//                                                             //
33//  Better parsing of files with h264 video                    //
34//    by Evgeny Moysevich <moysevichØgmail*com>                //
35//  * version 0.6 (24 May 2009)                                //
36//                                                             //
37/////////////////////////////////////////////////////////////////
38//                                                             //
39// module.audio-video.flv.php                                  //
40// module for analyzing Shockwave Flash Video files            //
41// dependencies: NONE                                          //
42//                                                            ///
43/////////////////////////////////////////////////////////////////
44
45define('GETID3_FLV_TAG_AUDIO',          8);
46define('GETID3_FLV_TAG_VIDEO',          9);
47define('GETID3_FLV_TAG_META',          18);
48
49define('GETID3_FLV_VIDEO_H263',         2);
50define('GETID3_FLV_VIDEO_SCREEN',       3);
51define('GETID3_FLV_VIDEO_VP6FLV',       4);
52define('GETID3_FLV_VIDEO_VP6FLV_ALPHA', 5);
53define('GETID3_FLV_VIDEO_SCREENV2',     6);
54define('GETID3_FLV_VIDEO_H264',         7);
55
56define('H264_AVC_SEQUENCE_HEADER',          0);
57define('H264_PROFILE_BASELINE',            66);
58define('H264_PROFILE_MAIN',                77);
59define('H264_PROFILE_EXTENDED',            88);
60define('H264_PROFILE_HIGH',               100);
61define('H264_PROFILE_HIGH10',             110);
62define('H264_PROFILE_HIGH422',            122);
63define('H264_PROFILE_HIGH444',            144);
64define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
65
66class getid3_flv
67{
68
69        function getid3_flv(&$fd, &$ThisFileInfo, $ReturnAllTagData=false) {
70//$start_time = microtime(true);
71                fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
72
73                $FLVdataLength = $ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'];
74                $FLVheader = fread($fd, 5);
75
76                $ThisFileInfo['fileformat'] = 'flv';
77                $ThisFileInfo['flv']['header']['signature'] =                           substr($FLVheader, 0, 3);
78                $ThisFileInfo['flv']['header']['version']   = getid3_lib::BigEndian2Int(substr($FLVheader, 3, 1));
79                $TypeFlags                                  = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1));
80
81                if ($ThisFileInfo['flv']['header']['signature'] != 'FLV') {
82                        $ThisFileInfo['error'][] = 'Expecting "FLV" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$ThisFileInfo['flv']['header']['signature'].'"';
83                        unset($ThisFileInfo['flv']);
84                        unset($ThisFileInfo['fileformat']);
85                        return false;
86                }
87
88                $ThisFileInfo['flv']['header']['hasAudio'] = (bool) ($TypeFlags & 0x04);
89                $ThisFileInfo['flv']['header']['hasVideo'] = (bool) ($TypeFlags & 0x01);
90
91                $FrameSizeDataLength = getid3_lib::BigEndian2Int(fread($fd, 4));
92                $FLVheaderFrameLength = 9;
93                if ($FrameSizeDataLength > $FLVheaderFrameLength) {
94                        fseek($fd, $FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR);
95                }
96//echo __LINE__.'='.number_format(microtime(true) - $start_time, 3).'<br>';
97
98                $Duration = 0;
99                $found_video = false;
100                $found_audio = false;
101                $found_meta  = false;
102                $tagParsed = 0;
103                while (((ftell($fd) + 16) < $ThisFileInfo['avdataend']) && ($tagParsed <= 20 || !$found_meta))  {
104                        $ThisTagHeader = fread($fd, 16);
105
106                        $PreviousTagLength = getid3_lib::BigEndian2Int(substr($ThisTagHeader,  0, 4));
107                        $TagType           = getid3_lib::BigEndian2Int(substr($ThisTagHeader,  4, 1));
108                        $DataLength        = getid3_lib::BigEndian2Int(substr($ThisTagHeader,  5, 3));
109                        $Timestamp         = getid3_lib::BigEndian2Int(substr($ThisTagHeader,  8, 3));
110                        $LastHeaderByte    = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 15, 1));
111                        $NextOffset = ftell($fd) - 1 + $DataLength;
112                        if ($Timestamp > $Duration) {
113                                $Duration = $Timestamp;
114                        }
115
116//echo __LINE__.'['.ftell($fd).']=('.$TagType.')='.number_format(microtime(true) - $start_time, 3).'<br>';
117
118                        switch ($TagType) {
119                                case GETID3_FLV_TAG_AUDIO:
120                                        if (!$found_audio) {
121                                                $found_audio = true;
122                                                $ThisFileInfo['flv']['audio']['audioFormat']     = ($LastHeaderByte >> 4) & 0x0F;
123                                                $ThisFileInfo['flv']['audio']['audioRate']       = ($LastHeaderByte >> 2) & 0x03;
124                                                $ThisFileInfo['flv']['audio']['audioSampleSize'] = ($LastHeaderByte >> 1) & 0x01;
125                                                $ThisFileInfo['flv']['audio']['audioType']       =  $LastHeaderByte       & 0x01;
126                                        }
127                                        break;
128
129                                case GETID3_FLV_TAG_VIDEO:
130                                        if (!$found_video) {
131                                                $found_video = true;
132                                                $ThisFileInfo['flv']['video']['videoCodec'] = $LastHeaderByte & 0x07;
133
134                                                $FLVvideoHeader = fread($fd, 11);
135
136                                                if ($ThisFileInfo['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H264) {
137                                                        // this code block contributed by: moysevichØgmail*com
138
139                                                        $AVCPacketType = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 0, 1));
140                                                        if ($AVCPacketType == H264_AVC_SEQUENCE_HEADER) {
141                                                                //      read AVCDecoderConfigurationRecord
142                                                                $configurationVersion       = getid3_lib::BigEndian2Int(substr($FLVvideoHeader,  4, 1));
143                                                                $AVCProfileIndication       = getid3_lib::BigEndian2Int(substr($FLVvideoHeader,  5, 1));
144                                                                $profile_compatibility      = getid3_lib::BigEndian2Int(substr($FLVvideoHeader,  6, 1));
145                                                                $lengthSizeMinusOne         = getid3_lib::BigEndian2Int(substr($FLVvideoHeader,  7, 1));
146                                                                $numOfSequenceParameterSets = getid3_lib::BigEndian2Int(substr($FLVvideoHeader,  8, 1));
147
148                                                                if (($numOfSequenceParameterSets & 0x1F) != 0) {
149                                                                        //      there is at least one SequenceParameterSet
150                                                                        //      read size of the first SequenceParameterSet
151                                                                        //$spsSize = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 9, 2));
152                                                                        $spsSize = getid3_lib::LittleEndian2Int(substr($FLVvideoHeader, 9, 2));
153                                                                        //      read the first SequenceParameterSet
154                                                                        $sps = fread($fd, $spsSize);
155                                                                        if (strlen($sps) == $spsSize) { //      make sure that whole SequenceParameterSet was red
156                                                                                $spsReader = new AVCSequenceParameterSetReader($sps);
157                                                                                $spsReader->readData();
158                                                                                $ThisFileInfo['video']['resolution_x'] = $spsReader->getWidth();
159                                                                                $ThisFileInfo['video']['resolution_y'] = $spsReader->getHeight();
160                                                                        }
161                                                                }
162                                                        }
163                                                        // end: moysevichØgmail*com
164
165                                                } elseif ($ThisFileInfo['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H263) {
166
167                                                        $PictureSizeType = (getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 3, 2))) >> 7;
168                                                        $PictureSizeType = $PictureSizeType & 0x0007;
169                                                        $ThisFileInfo['flv']['header']['videoSizeType'] = $PictureSizeType;
170                                                        switch ($PictureSizeType) {
171                                                                case 0:
172                                                                        //$PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2));
173                                                                        //$PictureSizeEnc <<= 1;
174                                                                        //$ThisFileInfo['video']['resolution_x'] = ($PictureSizeEnc & 0xFF00) >> 8;
175                                                                        //$PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 2));
176                                                                        //$PictureSizeEnc <<= 1;
177                                                                        //$ThisFileInfo['video']['resolution_y'] = ($PictureSizeEnc & 0xFF00) >> 8;
178
179                                                                        $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 2));
180                                                                        $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2));
181                                                                        $PictureSizeEnc['x'] >>= 7;
182                                                                        $PictureSizeEnc['y'] >>= 7;
183                                                                        $ThisFileInfo['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFF;
184                                                                        $ThisFileInfo['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFF;
185                                                                        break;
186
187                                                                case 1:
188                                                                        $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 3));
189                                                                        $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 3));
190                                                                        $PictureSizeEnc['x'] >>= 7;
191                                                                        $PictureSizeEnc['y'] >>= 7;
192                                                                        $ThisFileInfo['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFFFF;
193                                                                        $ThisFileInfo['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFFFF;
194                                                                        break;
195
196                                                                case 2:
197                                                                        $ThisFileInfo['video']['resolution_x'] = 352;
198                                                                        $ThisFileInfo['video']['resolution_y'] = 288;
199                                                                        break;
200
201                                                                case 3:
202                                                                        $ThisFileInfo['video']['resolution_x'] = 176;
203                                                                        $ThisFileInfo['video']['resolution_y'] = 144;
204                                                                        break;
205
206                                                                case 4:
207                                                                        $ThisFileInfo['video']['resolution_x'] = 128;
208                                                                        $ThisFileInfo['video']['resolution_y'] = 96;
209                                                                        break;
210
211                                                                case 5:
212                                                                        $ThisFileInfo['video']['resolution_x'] = 320;
213                                                                        $ThisFileInfo['video']['resolution_y'] = 240;
214                                                                        break;
215
216                                                                case 6:
217                                                                        $ThisFileInfo['video']['resolution_x'] = 160;
218                                                                        $ThisFileInfo['video']['resolution_y'] = 120;
219                                                                        break;
220
221                                                                default:
222                                                                        $ThisFileInfo['video']['resolution_x'] = 0;
223                                                                        $ThisFileInfo['video']['resolution_y'] = 0;
224                                                                        break;
225
226                                                        }
227                                                }
228                                                $ThisFileInfo['video']['pixel_aspect_ratio'] = $ThisFileInfo['video']['resolution_x'] / $ThisFileInfo['video']['resolution_y'];
229                                        }
230                                        break;
231
232                                // Meta tag
233                                case GETID3_FLV_TAG_META:
234                                        if (!$found_meta) {
235                                                $found_meta = true;
236                                                fseek($fd, -1, SEEK_CUR);
237                                                $datachunk = fread($fd, $DataLength);
238                                                $AMFstream = new AMFStream($datachunk);
239                                                $reader = new AMFReader($AMFstream);
240                                                $eventName = $reader->readData();
241                                                $ThisFileInfo['flv']['meta'][$eventName] = $reader->readData();
242                                                unset($reader);
243
244                                                $copykeys = array('framerate'=>'frame_rate', 'width'=>'resolution_x', 'height'=>'resolution_y', 'audiodatarate'=>'bitrate', 'videodatarate'=>'bitrate');
245                                                foreach ($copykeys as $sourcekey => $destkey) {
246                                                        if (isset($ThisFileInfo['flv']['meta']['onMetaData'][$sourcekey])) {
247                                                                switch ($sourcekey) {
248                                                                        case 'width':
249                                                                        case 'height':
250                                                                                $ThisFileInfo['video'][$destkey] = intval(round($ThisFileInfo['flv']['meta']['onMetaData'][$sourcekey]));
251                                                                                break;
252                                                                        case 'audiodatarate':
253                                                                                $ThisFileInfo['audio'][$destkey] = $ThisFileInfo['flv']['meta']['onMetaData'][$sourcekey];
254                                                                                break;
255                                                                        case 'videodatarate':
256                                                                        case 'frame_rate':
257                                                                        default:
258                                                                                $ThisFileInfo['video'][$destkey] = $ThisFileInfo['flv']['meta']['onMetaData'][$sourcekey];
259                                                                                break;
260                                                                }
261                                                        }
262                                                }
263                                        }
264                                        break;
265
266                                default:
267                                        // noop
268                                        break;
269                        }
270
271                        fseek($fd, $NextOffset, SEEK_SET);
272
273                        // Increase parsed tag count: break out of loop if more than 20 tags parsed
274                        $tagParsed++;
275                }
276
277                $ThisFileInfo['playtime_seconds'] = $Duration / 1000;
278                if ($ThisFileInfo['playtime_seconds'] > 0) {
279                        $ThisFileInfo['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
280                }
281
282                if ($ThisFileInfo['flv']['header']['hasAudio']) {
283                        $ThisFileInfo['audio']['codec']           =   $this->FLVaudioFormat($ThisFileInfo['flv']['audio']['audioFormat']);
284                        $ThisFileInfo['audio']['sample_rate']     =     $this->FLVaudioRate($ThisFileInfo['flv']['audio']['audioRate']);
285                        $ThisFileInfo['audio']['bits_per_sample'] = $this->FLVaudioBitDepth($ThisFileInfo['flv']['audio']['audioSampleSize']);
286
287                        $ThisFileInfo['audio']['channels']   =  $ThisFileInfo['flv']['audio']['audioType'] + 1; // 0=mono,1=stereo
288                        $ThisFileInfo['audio']['lossless']   = ($ThisFileInfo['flv']['audio']['audioFormat'] ? false : true); // 0=uncompressed
289                        $ThisFileInfo['audio']['dataformat'] = 'flv';
290                }
291                if (!empty($ThisFileInfo['flv']['header']['hasVideo'])) {
292                        $ThisFileInfo['video']['codec']      = $this->FLVvideoCodec($ThisFileInfo['flv']['video']['videoCodec']);
293                        $ThisFileInfo['video']['dataformat'] = 'flv';
294                        $ThisFileInfo['video']['lossless']   = false;
295                }
296
297                // Set information from meta
298                if (isset($ThisFileInfo['flv']['meta']['onMetaData']['duration'])) {
299                        $ThisFileInfo['playtime_seconds'] = $ThisFileInfo['flv']['meta']['onMetaData']['duration'];
300                        $ThisFileInfo['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
301                }
302                if (isset($ThisFileInfo['flv']['meta']['onMetaData']['audiocodecid'])) {
303                        $ThisFileInfo['audio']['codec'] = $this->FLVaudioFormat($ThisFileInfo['flv']['meta']['onMetaData']['audiocodecid']);
304                }
305                if (isset($ThisFileInfo['flv']['meta']['onMetaData']['videocodecid'])) {
306                        $ThisFileInfo['video']['codec'] = $this->FLVvideoCodec($ThisFileInfo['flv']['meta']['onMetaData']['videocodecid']);
307                }
308                return true;
309        }
310
311
312        function FLVaudioFormat($id) {
313                $FLVaudioFormat = array(
314                        0  => 'Linear PCM, platform endian',
315                        1  => 'ADPCM',
316                        2  => 'mp3',
317                        3  => 'Linear PCM, little endian',
318                        4  => 'Nellymoser 16kHz mono',
319                        5  => 'Nellymoser 8kHz mono',
320                        6  => 'Nellymoser',
321                        7  => 'G.711A-law logarithmic PCM',
322                        8  => 'G.711 mu-law logarithmic PCM',
323                        9  => 'reserved',
324                        10 => 'AAC',
325                        11 => false, // unknown?
326                        12 => false, // unknown?
327                        13 => false, // unknown?
328                        14 => 'mp3 8kHz',
329                        15 => 'Device-specific sound',
330                );
331                return (isset($FLVaudioFormat[$id]) ? $FLVaudioFormat[$id] : false);
332        }
333
334        function FLVaudioRate($id) {
335                $FLVaudioRate = array(
336                        0 =>  5500,
337                        1 => 11025,
338                        2 => 22050,
339                        3 => 44100,
340                );
341                return (isset($FLVaudioRate[$id]) ? $FLVaudioRate[$id] : false);
342        }
343
344        function FLVaudioBitDepth($id) {
345                $FLVaudioBitDepth = array(
346                        0 =>  8,
347                        1 => 16,
348                );
349                return (isset($FLVaudioBitDepth[$id]) ? $FLVaudioBitDepth[$id] : false);
350        }
351
352        function FLVvideoCodec($id) {
353                $FLVvideoCodec = array(
354                        GETID3_FLV_VIDEO_H263         => 'Sorenson H.263',
355                        GETID3_FLV_VIDEO_SCREEN       => 'Screen video',
356                        GETID3_FLV_VIDEO_VP6FLV       => 'On2 VP6',
357                        GETID3_FLV_VIDEO_VP6FLV_ALPHA => 'On2 VP6 with alpha channel',
358                        GETID3_FLV_VIDEO_SCREENV2     => 'Screen video v2',
359                        GETID3_FLV_VIDEO_H264         => 'Sorenson H.264',
360                );
361                return (isset($FLVvideoCodec[$id]) ? $FLVvideoCodec[$id] : false);
362        }
363}
364
365class AMFStream {
366        var $bytes;
367        var $pos;
368
369        function AMFStream(&$bytes) {
370                $this->bytes =& $bytes;
371                $this->pos = 0;
372        }
373
374        function readByte() {
375                return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1));
376        }
377
378        function readInt() {
379                return ($this->readByte() << 8) + $this->readByte();
380        }
381
382        function readLong() {
383                return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
384        }
385
386        function readDouble() {
387                return getid3_lib::BigEndian2Float($this->read(8));
388        }
389
390        function readUTF() {
391                $length = $this->readInt();
392                return $this->read($length);
393        }
394
395        function readLongUTF() {
396                $length = $this->readLong();
397                return $this->read($length);
398        }
399
400        function read($length) {
401                $val = substr($this->bytes, $this->pos, $length);
402                $this->pos += $length;
403                return $val;
404        }
405
406        function peekByte() {
407                $pos = $this->pos;
408                $val = $this->readByte();
409                $this->pos = $pos;
410                return $val;
411        }
412
413        function peekInt() {
414                $pos = $this->pos;
415                $val = $this->readInt();
416                $this->pos = $pos;
417                return $val;
418        }
419
420        function peekLong() {
421                $pos = $this->pos;
422                $val = $this->readLong();
423                $this->pos = $pos;
424                return $val;
425        }
426
427        function peekDouble() {
428                $pos = $this->pos;
429                $val = $this->readDouble();
430                $this->pos = $pos;
431                return $val;
432        }
433
434        function peekUTF() {
435                $pos = $this->pos;
436                $val = $this->readUTF();
437                $this->pos = $pos;
438                return $val;
439        }
440
441        function peekLongUTF() {
442                $pos = $this->pos;
443                $val = $this->readLongUTF();
444                $this->pos = $pos;
445                return $val;
446        }
447}
448
449class AMFReader {
450        var $stream;
451
452        function AMFReader(&$stream) {
453                $this->stream =& $stream;
454        }
455
456        function readData() {
457                $value = null;
458
459                $type = $this->stream->readByte();
460                switch ($type) {
461
462                        // Double
463                        case 0:
464                                $value = $this->readDouble();
465                        break;
466
467                        // Boolean
468                        case 1:
469                                $value = $this->readBoolean();
470                                break;
471
472                        // String
473                        case 2:
474                                $value = $this->readString();
475                                break;
476
477                        // Object
478                        case 3:
479                                $value = $this->readObject();
480                                break;
481
482                        // null
483                        case 6:
484                                return null;
485                                break;
486
487                        // Mixed array
488                        case 8:
489                                $value = $this->readMixedArray();
490                                break;
491
492                        // Array
493                        case 10:
494                                $value = $this->readArray();
495                                break;
496
497                        // Date
498                        case 11:
499                                $value = $this->readDate();
500                                break;
501
502                        // Long string
503                        case 13:
504                                $value = $this->readLongString();
505                                break;
506
507                        // XML (handled as string)
508                        case 15:
509                                $value = $this->readXML();
510                                break;
511
512                        // Typed object (handled as object)
513                        case 16:
514                                $value = $this->readTypedObject();
515                                break;
516
517                        // Long string
518                        default:
519                                $value = '(unknown or unsupported data type)';
520                        break;
521                }
522
523                return $value;
524        }
525
526        function readDouble() {
527                return $this->stream->readDouble();
528        }
529
530        function readBoolean() {
531                return $this->stream->readByte() == 1;
532        }
533
534        function readString() {
535                return $this->stream->readUTF();
536        }
537
538        function readObject() {
539                // Get highest numerical index - ignored
540//              $highestIndex = $this->stream->readLong();
541
542                $data = array();
543
544                while ($key = $this->stream->readUTF()) {
545                        $data[$key] = $this->readData();
546                }
547                // Mixed array record ends with empty string (0x00 0x00) and 0x09
548                if (($key == '') && ($this->stream->peekByte() == 0x09)) {
549                        // Consume byte
550                        $this->stream->readByte();
551                }
552                return $data;
553        }
554
555        function readMixedArray() {
556                // Get highest numerical index - ignored
557                $highestIndex = $this->stream->readLong();
558
559                $data = array();
560
561                while ($key = $this->stream->readUTF()) {
562                        if (is_numeric($key)) {
563                                $key = (float) $key;
564                        }
565                        $data[$key] = $this->readData();
566                }
567                // Mixed array record ends with empty string (0x00 0x00) and 0x09
568                if (($key == '') && ($this->stream->peekByte() == 0x09)) {
569                        // Consume byte
570                        $this->stream->readByte();
571                }
572
573                return $data;
574        }
575
576        function readArray() {
577                $length = $this->stream->readLong();
578                $data = array();
579
580                for ($i = 0; $i < $length; $i++) {
581                        $data[] = $this->readData();
582                }
583                return $data;
584        }
585
586        function readDate() {
587                $timestamp = $this->stream->readDouble();
588                $timezone = $this->stream->readInt();
589                return $timestamp;
590        }
591
592        function readLongString() {
593                return $this->stream->readLongUTF();
594        }
595
596        function readXML() {
597                return $this->stream->readLongUTF();
598        }
599
600        function readTypedObject() {
601                $className = $this->stream->readUTF();
602                return $this->readObject();
603        }
604}
605
606class AVCSequenceParameterSetReader {
607        var $sps;
608        var $start = 0;
609        var $currentBytes = 0;
610        var $currentBits = 0;
611        var $width;
612        var $height;
613
614        function AVCSequenceParameterSetReader($sps) {
615                $this->sps = $sps;
616        }
617
618        function readData() {
619                $this->skipBits(8);
620                $this->skipBits(8);
621                $profile = $this->getBits(8);   //      read profile
622                $this->skipBits(16);
623                $this->expGolombUe();   //      read sps id
624                if (in_array($profile, array(H264_PROFILE_HIGH, H264_PROFILE_HIGH10, H264_PROFILE_HIGH422, H264_PROFILE_HIGH444, H264_PROFILE_HIGH444_PREDICTIVE))) {
625                        if ($this->expGolombUe() == 3) {
626                                $this->skipBits(1);
627                        }
628                        $this->expGolombUe();
629                        $this->expGolombUe();
630                        $this->skipBits(1);
631                        if ($this->getBit()) {
632                                for ($i = 0; $i < 8; $i++) {
633                                        if ($this->getBit()) {
634                                                $size = $i < 6 ? 16 : 64;
635                                                $lastScale = 8;
636                                                $nextScale = 8;
637                                                for ($j = 0; $j < $size; $j++) {
638                                                        if ($nextScale != 0) {
639                                                                $deltaScale = $this->expGolombUe();
640                                                                $nextScale = ($lastScale + $deltaScale + 256) % 256;
641                                                        }
642                                                        if ($nextScale != 0) {
643                                                                $lastScale = $nextScale;
644                                                        }
645                                                }
646                                        }
647                                }
648                        }
649                }
650                $this->expGolombUe();
651                $pocType = $this->expGolombUe();
652                if ($pocType == 0) {
653                        $this->expGolombUe();
654                } elseif ($pocType == 1) {
655                        $this->skipBits(1);
656                        $this->expGolombSe();
657                        $this->expGolombSe();
658                        $pocCycleLength = $this->expGolombUe();
659                        for ($i = 0; $i < $pocCycleLength; $i++) {
660                                $this->expGolombSe();
661                        }
662                }
663                $this->expGolombUe();
664                $this->skipBits(1);
665                $this->width = ($this->expGolombUe() + 1) * 16;
666                $heightMap = $this->expGolombUe() + 1;
667                $this->height = (2 - $this->getBit()) * $heightMap * 16;
668        }
669
670        function skipBits($bits) {
671                $newBits = $this->currentBits + $bits;
672                $this->currentBytes += (int)floor($newBits / 8);
673                $this->currentBits = $newBits % 8;
674        }
675
676        function getBit() {
677                $result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01;
678                $this->skipBits(1);
679                return $result;
680        }
681
682        function getBits($bits) {
683                $result = 0;
684                for ($i = 0; $i < $bits; $i++) {
685                        $result = ($result << 1) + $this->getBit();
686                }
687                return $result;
688        }
689
690        function expGolombUe() {
691                $significantBits = 0;
692                $bit = $this->getBit();
693                while ($bit == 0) {
694                        $significantBits++;
695                        $bit = $this->getBit();
696                }
697                return (1 << $significantBits) + $this->getBits($significantBits) - 1;
698        }
699
700        function expGolombSe() {
701                $result = $this->expGolombUe();
702                if (($result & 0x01) == 0) {
703                        return -($result >> 1);
704                } else {
705                        return ($result + 1) >> 1;
706                }
707        }
708
709        function getWidth() {
710                return $this->width;
711        }
712
713        function getHeight() {
714                return $this->height;
715        }
716}
717
718?>
Note: See TracBrowser for help on using the repository browser.