Mercurial > judyates
comparison e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.aac_adts.php @ 3:3f6b44aa6b35 judyates
[svn r4] added ability to buy stuff, from a Prints page, but it doesn't work well with the css, and it also has not been fitted into the perl make system.
author | rlm |
---|---|
date | Mon, 22 Feb 2010 08:02:39 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:670229c4eb4b | 3:3f6b44aa6b35 |
---|---|
1 <?php | |
2 // +----------------------------------------------------------------------+ | |
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 $ | |
23 | |
24 | |
25 | |
26 class getid3_aac_adts extends getid3_handler | |
27 { | |
28 | |
29 public $option_max_frames_to_scan = 1000000; | |
30 public $option_return_extended_info = false; | |
31 | |
32 | |
33 private $decbin_cache; | |
34 private $bitrate_cache; | |
35 | |
36 | |
37 | |
38 public function __construct(getID3 $getid3) { | |
39 | |
40 parent::__construct($getid3); | |
41 | |
42 // Populate bindec_cache | |
43 for ($i = 0; $i < 256; $i++) { | |
44 $this->decbin_cache[chr($i)] = str_pad(decbin($i), 8, '0', STR_PAD_LEFT); | |
45 } | |
46 | |
47 // Init cache | |
48 $this->bitrate_cache = array (); | |
49 | |
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 } | |
56 | |
57 | |
58 | |
59 public function Analyze() { | |
60 | |
61 $getid3 = $this->getid3; | |
62 | |
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.html | |
65 | |
66 | |
67 // http://faac.sourceforge.net/wiki/index.php?page=ADTS | |
68 | |
69 // * ADTS Fixed Header: these don't change from frame to frame | |
70 // syncword 12 always: '111111111111' | |
71 // ID 1 0: MPEG-4, 1: MPEG-2 | |
72 // layer 2 always: '00' | |
73 // protection_absent 1 | |
74 // profile 2 | |
75 // sampling_frequency_index 4 | |
76 // private_bit 1 | |
77 // channel_configuration 3 | |
78 // original/copy 1 | |
79 // home 1 | |
80 // emphasis 2 only if ID == 0 (ie MPEG-4) | |
81 | |
82 // * ADTS Variable Header: these can change from frame to frame | |
83 // copyright_identification_bit 1 | |
84 // copyright_identification_start 1 | |
85 // aac_frame_length 13 length of the frame including header (in bytes) | |
86 // adts_buffer_fullness 11 0x7FF indicates VBR | |
87 // no_raw_data_blocks_in_frame 2 | |
88 | |
89 // * ADTS Error check | |
90 // crc_check 16 only if protection_absent == 0 | |
91 | |
92 $getid3->info['aac']['header'] = array () ; | |
93 $info_aac = &$getid3->info['aac']; | |
94 $info_aac_header = & $info_aac['header']; | |
95 | |
96 $byte_offset = $frame_number = 0; | |
97 | |
98 while (true) { | |
99 | |
100 // Breaks out when end-of-file encountered, or invalid data found, | |
101 // or MaxFramesToScan frames have been scanned | |
102 | |
103 fseek($getid3->fp, $byte_offset, SEEK_SET); | |
104 | |
105 // First get substring | |
106 $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 } | |
111 | |
112 // Initialise $aac_header_bitstream | |
113 $aac_header_bitstream = ''; | |
114 | |
115 // Loop thru substring chars | |
116 for ($i = 0; $i < 10; $i++) { | |
117 $aac_header_bitstream .= $this->decbin_cache[$sub_string[$i]]; | |
118 } | |
119 | |
120 $sync_test = bindec(substr($aac_header_bitstream, 0, 12)); | |
121 $bit_offset = 12; | |
122 | |
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 } | |
126 | |
127 // Only gather info once - this takes time to do 1000 times! | |
128 if ($frame_number > 0) { | |
129 | |
130 // MPEG-4: 20, // MPEG-2: 18 | |
131 $bit_offset += $aac_header_bitstream[$bit_offset] ? 18 : 20; | |
132 } | |
133 | |
134 // Gather info for first frame only - this takes time to do 1000 times! | |
135 else { | |
136 | |
137 $info_aac['header_type'] = 'ADTS'; | |
138 $info_aac_header['synch'] = $sync_test; | |
139 $getid3->info['fileformat'] = 'aac'; | |
140 $getid3->info['audio']['dataformat'] = 'aac'; | |
141 | |
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; | |
145 | |
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 } | |
149 | |
150 $info_aac_header['crc_present'] = $aac_header_bitstream{$bit_offset++} == '0' ? true : false; | |
151 | |
152 $info_aac_header['profile_id'] = bindec(substr($aac_header_bitstream, $bit_offset, 2)); | |
153 $bit_offset += 2; | |
154 | |
155 $info_aac_header['profile_text'] = getid3_aac_adts::AACprofileLookup($info_aac_header['profile_id'], $info_aac_header['mpeg_version']); | |
156 | |
157 $info_aac_header['sample_frequency_index'] = bindec(substr($aac_header_bitstream, $bit_offset, 4)); | |
158 $bit_offset += 4; | |
159 | |
160 $info_aac_header['sample_frequency'] = getid3_aac_adts::AACsampleRateLookup($info_aac_header['sample_frequency_index']); | |
161 | |
162 $getid3->info['audio']['sample_rate'] = $info_aac_header['sample_frequency']; | |
163 | |
164 $info_aac_header['private'] = $aac_header_bitstream{$bit_offset++} == 1; | |
165 | |
166 $info_aac_header['channel_configuration'] = $getid3->info['audio']['channels'] = bindec(substr($aac_header_bitstream, $bit_offset, 3)); | |
167 $bit_offset += 3; | |
168 | |
169 $info_aac_header['original'] = $aac_header_bitstream{$bit_offset++} == 1; | |
170 $info_aac_header['home'] = $aac_header_bitstream{$bit_offset++} == 1; | |
171 | |
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 } | |
176 | |
177 if ($this->option_return_extended_info) { | |
178 | |
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; | |
181 | |
182 } else { | |
183 $bit_offset += 2; | |
184 } | |
185 } | |
186 | |
187 $frame_length = bindec(substr($aac_header_bitstream, $bit_offset, 13)); | |
188 | |
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]]++; | |
193 | |
194 $info_aac[$frame_number]['aac_frame_length'] = $frame_length; | |
195 $bit_offset += 13; | |
196 | |
197 $info_aac[$frame_number]['adts_buffer_fullness'] = bindec(substr($aac_header_bitstream, $bit_offset, 11)); | |
198 $bit_offset += 11; | |
199 | |
200 $getid3->info['audio']['bitrate_mode'] = ($info_aac[$frame_number]['adts_buffer_fullness'] == 0x07FF) ? 'vbr' : 'cbr'; | |
201 | |
202 $info_aac[$frame_number]['num_raw_data_blocks'] = bindec(substr($aac_header_bitstream, $bit_offset, 2)); | |
203 $bit_offset += 2; | |
204 | |
205 if ($info_aac_header['crc_present']) { | |
206 $bit_offset += 16; | |
207 } | |
208 | |
209 if (!$this->option_return_extended_info) { | |
210 unset($info_aac[$frame_number]); | |
211 } | |
212 | |
213 $byte_offset += $frame_length; | |
214 if ((++$frame_number < $this->option_max_frames_to_scan) && (($byte_offset + 10) < $getid3->info['avdataend'])) { | |
215 | |
216 // keep scanning | |
217 | |
218 } else { | |
219 | |
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)) = seconds | |
222 $getid3->info['audio']['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds']; | |
223 ksort($info_aac['bitrate_distribution']); | |
224 | |
225 $getid3->info['audio']['encoder_options'] = $info_aac['header_type'].' '.$info_aac_header['profile_text']; | |
226 | |
227 return true; | |
228 } | |
229 } | |
230 } | |
231 | |
232 | |
233 | |
234 public static function AACsampleRateLookup($samplerate_id) { | |
235 | |
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 => 0 | |
253 ); | |
254 return (isset($lookup[$samplerate_id]) ? $lookup[$samplerate_id] : 'invalid'); | |
255 } | |
256 | |
257 | |
258 | |
259 public static function AACprofileLookup($profile_id, $mpeg_version) { | |
260 | |
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 } | |
277 | |
278 | |
279 } | |
280 | |
281 | |
282 ?> |