Changeset 29734 for trunk/src/wp-includes/ID3/module.audio-video.flv.php
- Timestamp:
- 09/11/2014 07:06:33 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/ID3/module.audio-video.flv.php
r23766 r29734 4 4 // available at http://getid3.sourceforge.net // 5 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 6 7 // // 7 8 // FLV module by Seth Kaufman <sethØwhirl-i-gig*com> // … … 38 39 // * version 0.6.1 (30 May 2011) // 39 40 // prevent infinite loops in expGolombUe() // 41 // // 42 // * version 0.7.0 (16 Jul 2013) // 43 // handle GETID3_FLV_VIDEO_VP6FLV_ALPHA // 44 // improved AVCSequenceParameterSetReader::readData() // 45 // by Xander Schouwerwou <schouwerwouØgmail*com> // 40 46 // // 41 47 ///////////////////////////////////////////////////////////////// … … 68 74 define('H264_PROFILE_HIGH444_PREDICTIVE', 244); 69 75 70 class getid3_flv extends getid3_handler 71 { 76 class getid3_flv extends getid3_handler { 77 78 const magic = 'FLV'; 79 72 80 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 81 … … 75 83 $info = &$this->getid3->info; 76 84 77 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);85 $this->fseek($info['avdataoffset']); 78 86 79 87 $FLVdataLength = $info['avdataend'] - $info['avdataoffset']; 80 $FLVheader = fread($this->getid3->fp,5);88 $FLVheader = $this->fread(5); 81 89 82 90 $info['fileformat'] = 'flv'; … … 85 93 $TypeFlags = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1)); 86 94 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']); 95 if ($info['flv']['header']['signature'] != self::magic) { 96 $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"'; 97 unset($info['flv'], $info['fileformat']); 92 98 return false; 93 99 } … … 96 102 $info['flv']['header']['hasVideo'] = (bool) ($TypeFlags & 0x01); 97 103 98 $FrameSizeDataLength = getid3_lib::BigEndian2Int( fread($this->getid3->fp,4));104 $FrameSizeDataLength = getid3_lib::BigEndian2Int($this->fread(4)); 99 105 $FLVheaderFrameLength = 9; 100 106 if ($FrameSizeDataLength > $FLVheaderFrameLength) { 101 fseek($this->getid3->fp,$FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR);107 $this->fseek($FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR); 102 108 } 103 109 $Duration = 0; … … 109 115 $info['flv']['framecount'] = array('total'=>0, 'audio'=>0, 'video'=>0); 110 116 $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);117 while ((($this->ftell() + 16) < $info['avdataend']) && (($tagParseCount++ <= $this->max_frames) || !$found_valid_meta_playtime)) { 118 $ThisTagHeader = $this->fread(16); 113 119 114 120 $PreviousTagLength = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 0, 4)); … … 117 123 $Timestamp = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 8, 3)); 118 124 $LastHeaderByte = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 15, 1)); 119 $NextOffset = ftell($this->getid3->fp) - 1 + $DataLength;125 $NextOffset = $this->ftell() - 1 + $DataLength; 120 126 if ($Timestamp > $Duration) { 121 127 $Duration = $Timestamp; … … 141 147 $info['flv']['video']['videoCodec'] = $LastHeaderByte & 0x07; 142 148 143 $FLVvideoHeader = fread($this->getid3->fp,11);149 $FLVvideoHeader = $this->fread(11); 144 150 145 151 if ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H264) { … … 161 167 $spsSize = getid3_lib::LittleEndian2Int(substr($FLVvideoHeader, 9, 2)); 162 168 // read the first SequenceParameterSet 163 $sps = fread($this->getid3->fp,$spsSize);169 $sps = $this->fread($spsSize); 164 170 if (strlen($sps) == $spsSize) { // make sure that whole SequenceParameterSet was red 165 171 $spsReader = new AVCSequenceParameterSetReader($sps); … … 186 192 //$info['video']['resolution_y'] = ($PictureSizeEnc & 0xFF00) >> 8; 187 193 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; 194 $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 2)) >> 7; 195 $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2)) >> 7; 192 196 $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFF; 193 197 $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFF; … … 195 199 196 200 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 $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 3)) >> 7; 202 $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 3)) >> 7; 201 203 $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFFFF; 202 204 $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFFFF; … … 234 236 235 237 } 238 239 } elseif ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_VP6FLV_ALPHA) { 240 241 /* contributed by schouwerwouØgmail*com */ 242 if (!isset($info['video']['resolution_x'])) { // only when meta data isn't set 243 $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 2)); 244 $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 7, 2)); 245 $info['video']['resolution_x'] = ($PictureSizeEnc['x'] & 0xFF) << 3; 246 $info['video']['resolution_y'] = ($PictureSizeEnc['y'] & 0xFF) << 3; 247 } 248 /* end schouwerwouØgmail*com */ 249 236 250 } 237 $info['video']['pixel_aspect_ratio'] = $info['video']['resolution_x'] / $info['video']['resolution_y']; 251 if (!empty($info['video']['resolution_x']) && !empty($info['video']['resolution_y'])) { 252 $info['video']['pixel_aspect_ratio'] = $info['video']['resolution_x'] / $info['video']['resolution_y']; 253 } 238 254 } 239 255 break; … … 243 259 if (!$found_meta) { 244 260 $found_meta = true; 245 fseek($this->getid3->fp,-1, SEEK_CUR);246 $datachunk = fread($this->getid3->fp,$DataLength);261 $this->fseek(-1, SEEK_CUR); 262 $datachunk = $this->fread($DataLength); 247 263 $AMFstream = new AMFStream($datachunk); 248 264 $reader = new AMFReader($AMFstream); … … 280 296 break; 281 297 } 282 fseek($this->getid3->fp, $NextOffset, SEEK_SET);298 $this->fseek($NextOffset); 283 299 } 284 300 … … 289 305 290 306 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']);307 $info['audio']['codec'] = self::audioFormatLookup($info['flv']['audio']['audioFormat']); 308 $info['audio']['sample_rate'] = self::audioRateLookup($info['flv']['audio']['audioRate']); 309 $info['audio']['bits_per_sample'] = self::audioBitDepthLookup($info['flv']['audio']['audioSampleSize']); 294 310 295 311 $info['audio']['channels'] = $info['flv']['audio']['audioType'] + 1; // 0=mono,1=stereo … … 298 314 } 299 315 if (!empty($info['flv']['header']['hasVideo'])) { 300 $info['video']['codec'] = $this->FLVvideoCodec($info['flv']['video']['videoCodec']);316 $info['video']['codec'] = self::videoCodecLookup($info['flv']['video']['videoCodec']); 301 317 $info['video']['dataformat'] = 'flv'; 302 318 $info['video']['lossless'] = false; … … 309 325 } 310 326 if (isset($info['flv']['meta']['onMetaData']['audiocodecid'])) { 311 $info['audio']['codec'] = $this->FLVaudioFormat($info['flv']['meta']['onMetaData']['audiocodecid']);327 $info['audio']['codec'] = self::audioFormatLookup($info['flv']['meta']['onMetaData']['audiocodecid']); 312 328 } 313 329 if (isset($info['flv']['meta']['onMetaData']['videocodecid'])) { 314 $info['video']['codec'] = $this->FLVvideoCodec($info['flv']['meta']['onMetaData']['videocodecid']);330 $info['video']['codec'] = self::videoCodecLookup($info['flv']['meta']['onMetaData']['videocodecid']); 315 331 } 316 332 return true; … … 318 334 319 335 320 public function FLVaudioFormat($id) {321 $FLVaudioFormat= array(336 public static function audioFormatLookup($id) { 337 static $lookup = array( 322 338 0 => 'Linear PCM, platform endian', 323 339 1 => 'ADPCM', … … 331 347 9 => 'reserved', 332 348 10 => 'AAC', 333 11 => false, // unknown?349 11 => 'Speex', 334 350 12 => false, // unknown? 335 351 13 => false, // unknown? … … 337 353 15 => 'Device-specific sound', 338 354 ); 339 return (isset($ FLVaudioFormat[$id]) ? $FLVaudioFormat[$id] : false);340 } 341 342 public function FLVaudioRate($id) {343 $FLVaudioRate= array(355 return (isset($lookup[$id]) ? $lookup[$id] : false); 356 } 357 358 public static function audioRateLookup($id) { 359 static $lookup = array( 344 360 0 => 5500, 345 361 1 => 11025, … … 347 363 3 => 44100, 348 364 ); 349 return (isset($ FLVaudioRate[$id]) ? $FLVaudioRate[$id] : false);350 } 351 352 public function FLVaudioBitDepth($id) {353 $FLVaudioBitDepth= array(365 return (isset($lookup[$id]) ? $lookup[$id] : false); 366 } 367 368 public static function audioBitDepthLookup($id) { 369 static $lookup = array( 354 370 0 => 8, 355 371 1 => 16, 356 372 ); 357 return (isset($ FLVaudioBitDepth[$id]) ? $FLVaudioBitDepth[$id] : false);358 } 359 360 public function FLVvideoCodec($id) {361 $FLVvideoCodec= array(373 return (isset($lookup[$id]) ? $lookup[$id] : false); 374 } 375 376 public static function videoCodecLookup($id) { 377 static $lookup = array( 362 378 GETID3_FLV_VIDEO_H263 => 'Sorenson H.263', 363 379 GETID3_FLV_VIDEO_SCREEN => 'Screen video', … … 367 383 GETID3_FLV_VIDEO_H264 => 'Sorenson H.264', 368 384 ); 369 return (isset($ FLVvideoCodec[$id]) ? $FLVvideoCodec[$id] : false);385 return (isset($lookup[$id]) ? $lookup[$id] : false); 370 386 } 371 387 } … … 375 391 public $pos; 376 392 377 public function AMFStream(&$bytes) {393 public function __construct(&$bytes) { 378 394 $this->bytes =& $bytes; 379 395 $this->pos = 0; … … 458 474 public $stream; 459 475 460 public function AMFReader(&$stream) {476 public function __construct(&$stream) { 461 477 $this->stream =& $stream; 462 478 } … … 620 636 public $height; 621 637 622 public function AVCSequenceParameterSetReader($sps) {638 public function __construct($sps) { 623 639 $this->sps = $sps; 624 640 } … … 627 643 $this->skipBits(8); 628 644 $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 } 645 $profile = $this->getBits(8); // read profile 646 if ($profile > 0) { 647 $this->skipBits(8); 648 $level_idc = $this->getBits(8); // level_idc 649 $this->expGolombUe(); // seq_parameter_set_id // sps 650 $this->expGolombUe(); // log2_max_frame_num_minus4 651 $picOrderType = $this->expGolombUe(); // pic_order_cnt_type 652 if ($picOrderType == 0) { 653 $this->expGolombUe(); // log2_max_pic_order_cnt_lsb_minus4 654 } elseif ($picOrderType == 1) { 655 $this->skipBits(1); // delta_pic_order_always_zero_flag 656 $this->expGolombSe(); // offset_for_non_ref_pic 657 $this->expGolombSe(); // offset_for_top_to_bottom_field 658 $num_ref_frames_in_pic_order_cnt_cycle = $this->expGolombUe(); // num_ref_frames_in_pic_order_cnt_cycle 659 for ($i = 0; $i < $num_ref_frames_in_pic_order_cnt_cycle; $i++) { 660 $this->expGolombSe(); // offset_for_ref_frame[ i ] 655 661 } 656 662 } 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(); 663 $this->expGolombUe(); // num_ref_frames 664 $this->skipBits(1); // gaps_in_frame_num_value_allowed_flag 665 $pic_width_in_mbs_minus1 = $this->expGolombUe(); // pic_width_in_mbs_minus1 666 $pic_height_in_map_units_minus1 = $this->expGolombUe(); // pic_height_in_map_units_minus1 667 668 $frame_mbs_only_flag = $this->getBits(1); // frame_mbs_only_flag 669 if ($frame_mbs_only_flag == 0) { 670 $this->skipBits(1); // mb_adaptive_frame_field_flag 669 671 } 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; 672 $this->skipBits(1); // direct_8x8_inference_flag 673 $frame_cropping_flag = $this->getBits(1); // frame_cropping_flag 674 675 $frame_crop_left_offset = 0; 676 $frame_crop_right_offset = 0; 677 $frame_crop_top_offset = 0; 678 $frame_crop_bottom_offset = 0; 679 680 if ($frame_cropping_flag) { 681 $frame_crop_left_offset = $this->expGolombUe(); // frame_crop_left_offset 682 $frame_crop_right_offset = $this->expGolombUe(); // frame_crop_right_offset 683 $frame_crop_top_offset = $this->expGolombUe(); // frame_crop_top_offset 684 $frame_crop_bottom_offset = $this->expGolombUe(); // frame_crop_bottom_offset 685 } 686 $this->skipBits(1); // vui_parameters_present_flag 687 // etc 688 689 $this->width = (($pic_width_in_mbs_minus1 + 1) * 16) - ($frame_crop_left_offset * 2) - ($frame_crop_right_offset * 2); 690 $this->height = ((2 - $frame_mbs_only_flag) * ($pic_height_in_map_units_minus1 + 1) * 16) - ($frame_crop_top_offset * 2) - ($frame_crop_bottom_offset * 2); 691 } 676 692 } 677 693
Note: See TracChangeset
for help on using the changeset viewer.