Mercurial > judyates
view e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.aac_adts.php @ 20:1038db2374ec judyates
change address
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 08 Sep 2013 00:47:09 -0400 |
parents | 3f6b44aa6b35 |
children |
line wrap: on
line source
1 <?php2 // +----------------------------------------------------------------------+3 // | PHP version 5 |4 // +----------------------------------------------------------------------+5 // | Copyright (c) 2002-2006 James Heinrich, Allan Hansen |6 // +----------------------------------------------------------------------+7 // | This source file is subject to version 2 of the GPL license, |8 // | that is bundled with this package in the file license.txt and is |9 // | available through the world-wide-web at the following url: |10 // | http://www.gnu.org/copyleft/gpl.html |11 // +----------------------------------------------------------------------+12 // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org |13 // +----------------------------------------------------------------------+14 // | Authors: James Heinrich <infoØgetid3*org> |15 // | Allan Hansen <ahØartemis*dk> |16 // +----------------------------------------------------------------------+17 // | module.audio.aac_adts.php |18 // | Module for analyzing AAC files with ADTS header. |19 // | dependencies: NONE |20 // +----------------------------------------------------------------------+21 //22 // $Id: module.audio.aac_adts.php,v 1.4 2006/11/02 10:48:01 ah Exp $26 class getid3_aac_adts extends getid3_handler27 {29 public $option_max_frames_to_scan = 1000000;30 public $option_return_extended_info = false;33 private $decbin_cache;34 private $bitrate_cache;38 public function __construct(getID3 $getid3) {40 parent::__construct($getid3);42 // Populate bindec_cache43 for ($i = 0; $i < 256; $i++) {44 $this->decbin_cache[chr($i)] = str_pad(decbin($i), 8, '0', STR_PAD_LEFT);45 }47 // Init cache48 $this->bitrate_cache = array ();50 // Fast scanning?51 if (!$getid3->option_accurate_results) {52 $this->option_max_frames_to_scan = 200;53 $getid3->warning('option_accurate_results set to false - bitrate and playing time are not accurate.');54 }55 }59 public function Analyze() {61 $getid3 = $this->getid3;63 // based loosely on code from AACfile by Jurgen Faul <jfaulØgmx.de>64 // http://jfaul.de/atl or http://j-faul.virtualave.net/atl/atl.html67 // http://faac.sourceforge.net/wiki/index.php?page=ADTS69 // * ADTS Fixed Header: these don't change from frame to frame70 // syncword 12 always: '111111111111'71 // ID 1 0: MPEG-4, 1: MPEG-272 // layer 2 always: '00'73 // protection_absent 174 // profile 275 // sampling_frequency_index 476 // private_bit 177 // channel_configuration 378 // original/copy 179 // home 180 // emphasis 2 only if ID == 0 (ie MPEG-4)82 // * ADTS Variable Header: these can change from frame to frame83 // copyright_identification_bit 184 // copyright_identification_start 185 // aac_frame_length 13 length of the frame including header (in bytes)86 // adts_buffer_fullness 11 0x7FF indicates VBR87 // no_raw_data_blocks_in_frame 289 // * ADTS Error check90 // crc_check 16 only if protection_absent == 092 $getid3->info['aac']['header'] = array () ;93 $info_aac = &$getid3->info['aac'];94 $info_aac_header = & $info_aac['header'];96 $byte_offset = $frame_number = 0;98 while (true) {100 // Breaks out when end-of-file encountered, or invalid data found,101 // or MaxFramesToScan frames have been scanned103 fseek($getid3->fp, $byte_offset, SEEK_SET);105 // First get substring106 $sub_string = fread($getid3->fp, 10);107 $sub_string_length = strlen($sub_string);108 if ($sub_string_length != 10) {109 throw new getid3_exception('Failed to read 10 bytes at offset '.(ftell($getid3->fp) - $sub_string_length).' (only read '.$sub_string_length.' bytes)');110 }112 // Initialise $aac_header_bitstream113 $aac_header_bitstream = '';115 // Loop thru substring chars116 for ($i = 0; $i < 10; $i++) {117 $aac_header_bitstream .= $this->decbin_cache[$sub_string[$i]];118 }120 $sync_test = bindec(substr($aac_header_bitstream, 0, 12));121 $bit_offset = 12;123 if ($sync_test != 0x0FFF) {124 throw new getid3_exception('Synch pattern (0x0FFF) not found at offset '.(ftell($getid3->fp) - 10).' (found 0x0'.strtoupper(dechex($sync_test)).' instead)');125 }127 // Only gather info once - this takes time to do 1000 times!128 if ($frame_number > 0) {130 // MPEG-4: 20, // MPEG-2: 18131 $bit_offset += $aac_header_bitstream[$bit_offset] ? 18 : 20;132 }134 // Gather info for first frame only - this takes time to do 1000 times!135 else {137 $info_aac['header_type'] = 'ADTS';138 $info_aac_header['synch'] = $sync_test;139 $getid3->info['fileformat'] = 'aac';140 $getid3->info['audio']['dataformat'] = 'aac';142 $info_aac_header['mpeg_version'] = $aac_header_bitstream{$bit_offset++} == '0' ? 4 : 2;143 $info_aac_header['layer'] = bindec(substr($aac_header_bitstream, $bit_offset, 2));144 $bit_offset += 2;146 if ($info_aac_header['layer'] != 0) {147 throw new getid3_exception('Layer error - expected 0x00, found 0x'.dechex($info_aac_header['layer']).' instead');148 }150 $info_aac_header['crc_present'] = $aac_header_bitstream{$bit_offset++} == '0' ? true : false;152 $info_aac_header['profile_id'] = bindec(substr($aac_header_bitstream, $bit_offset, 2));153 $bit_offset += 2;155 $info_aac_header['profile_text'] = getid3_aac_adts::AACprofileLookup($info_aac_header['profile_id'], $info_aac_header['mpeg_version']);157 $info_aac_header['sample_frequency_index'] = bindec(substr($aac_header_bitstream, $bit_offset, 4));158 $bit_offset += 4;160 $info_aac_header['sample_frequency'] = getid3_aac_adts::AACsampleRateLookup($info_aac_header['sample_frequency_index']);162 $getid3->info['audio']['sample_rate'] = $info_aac_header['sample_frequency'];164 $info_aac_header['private'] = $aac_header_bitstream{$bit_offset++} == 1;166 $info_aac_header['channel_configuration'] = $getid3->info['audio']['channels'] = bindec(substr($aac_header_bitstream, $bit_offset, 3));167 $bit_offset += 3;169 $info_aac_header['original'] = $aac_header_bitstream{$bit_offset++} == 1;170 $info_aac_header['home'] = $aac_header_bitstream{$bit_offset++} == 1;172 if ($info_aac_header['mpeg_version'] == 4) {173 $info_aac_header['emphasis'] = bindec(substr($aac_header_bitstream, $bit_offset, 2));174 $bit_offset += 2;175 }177 if ($this->option_return_extended_info) {179 $info_aac[$frame_number]['copyright_id_bit'] = $aac_header_bitstream{$bit_offset++} == 1;180 $info_aac[$frame_number]['copyright_id_start'] = $aac_header_bitstream{$bit_offset++} == 1;182 } else {183 $bit_offset += 2;184 }185 }187 $frame_length = bindec(substr($aac_header_bitstream, $bit_offset, 13));189 if (!isset($this->bitrate_cache[$frame_length])) {190 $this->bitrate_cache[$frame_length] = ($info_aac_header['sample_frequency'] / 1024) * $frame_length * 8;191 }192 @$info_aac['bitrate_distribution'][$this->bitrate_cache[$frame_length]]++;194 $info_aac[$frame_number]['aac_frame_length'] = $frame_length;195 $bit_offset += 13;197 $info_aac[$frame_number]['adts_buffer_fullness'] = bindec(substr($aac_header_bitstream, $bit_offset, 11));198 $bit_offset += 11;200 $getid3->info['audio']['bitrate_mode'] = ($info_aac[$frame_number]['adts_buffer_fullness'] == 0x07FF) ? 'vbr' : 'cbr';202 $info_aac[$frame_number]['num_raw_data_blocks'] = bindec(substr($aac_header_bitstream, $bit_offset, 2));203 $bit_offset += 2;205 if ($info_aac_header['crc_present']) {206 $bit_offset += 16;207 }209 if (!$this->option_return_extended_info) {210 unset($info_aac[$frame_number]);211 }213 $byte_offset += $frame_length;214 if ((++$frame_number < $this->option_max_frames_to_scan) && (($byte_offset + 10) < $getid3->info['avdataend'])) {216 // keep scanning218 } else {220 $info_aac['frames'] = $frame_number;221 $getid3->info['playtime_seconds'] = ($getid3->info['avdataend'] / $byte_offset) * (($frame_number * 1024) / $info_aac_header['sample_frequency']); // (1 / % of file scanned) * (samples / (samples/sec)) = seconds222 $getid3->info['audio']['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds'];223 ksort($info_aac['bitrate_distribution']);225 $getid3->info['audio']['encoder_options'] = $info_aac['header_type'].' '.$info_aac_header['profile_text'];227 return true;228 }229 }230 }234 public static function AACsampleRateLookup($samplerate_id) {236 static $lookup = array (237 0 => 96000,238 1 => 88200,239 2 => 64000,240 3 => 48000,241 4 => 44100,242 5 => 32000,243 6 => 24000,244 7 => 22050,245 8 => 16000,246 9 => 12000,247 10 => 11025,248 11 => 8000,249 12 => 0,250 13 => 0,251 14 => 0,252 15 => 0253 );254 return (isset($lookup[$samplerate_id]) ? $lookup[$samplerate_id] : 'invalid');255 }259 public static function AACprofileLookup($profile_id, $mpeg_version) {261 static $lookup = array (262 2 => array (263 0 => 'Main profile',264 1 => 'Low Complexity profile (LC)',265 2 => 'Scalable Sample Rate profile (SSR)',266 3 => '(reserved)'267 ),268 4 => array (269 0 => 'AAC_MAIN',270 1 => 'AAC_LC',271 2 => 'AAC_SSR',272 3 => 'AAC_LTP'273 )274 );275 return (isset($lookup[$mpeg_version][$profile_id]) ? $lookup[$mpeg_version][$profile_id] : 'invalid');276 }279 }282 ?>