[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-includes/ID3/ -> module.audio-video.flv.php (source)

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


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu