[ Index ] |
WordPress Cross Reference |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 25 01:41:18 2014 | WordPress honlapkészítés: online1.hu |