view e2gallerypro/e2upload/Backend/Assets/getid3/module.audio-video.flv.php @ 11:ed6ee381b8fd judyates

[svn r12] compressed photos and assembled them into a working web gallery
author rlm
date Mon, 12 Apr 2010 02:31:43 -0400
parents 3f6b44aa6b35
children
line wrap: on
line source
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.archive.gzip.php |
18 // | module for analyzing GZIP files |
19 // | dependencies: NONE |
20 // +----------------------------------------------------------------------+
21 // | FLV module by Seth Kaufman <sethØwhirl-i.gig*com> |
22 // | |
23 // | * version 0.1 (26 June 2005) |
24 // | |
25 // | minor modifications by James Heinrich <infoØgetid3*org> |
26 // | * version 0.1.1 (15 July 2005) |
27 // | |
28 // | Support for On2 VP6 codec and meta information by |
29 // | Steve Webster <steve.websterØfeaturecreep*com> |
30 // | * version 0.2 (22 February 2006) |
31 // | |
32 // | Modified to not read entire file into memory |
33 // | by James Heinrich <infoØgetid3*org> |
34 // | * version 0.3 (15 June 2006) |
35 // | |
36 // | Modifications by Allan Hansen <ahØartemis*dk> |
37 // | Adapted module for PHP5 and getID3 2.0.0. |
38 // +----------------------------------------------------------------------+
39 //
40 // $Id: module.audio-video.flv.php,v 1.7 2006/11/10 11:20:12 ah Exp $
44 class getid3_flv extends getid3_handler
45 {
47 const TAG_AUDIO = 8;
48 const TAG_VIDEO = 9;
49 const TAG_META = 18;
51 const VIDEO_H263 = 2;
52 const VIDEO_SCREEN = 3;
53 const VIDEO_VP6 = 4;
56 public function Analyze()
57 {
58 $info = &$this->getid3->info;
60 $info['flv'] = array ();
61 $info_flv = &$info['flv'];
63 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
65 $flv_data_length = $info['avdataend'] - $info['avdataoffset'];
66 $flv_header = fread($this->getid3->fp, 5);
68 $info['fileformat'] = 'flv';
69 $info_flv['header']['signature'] = substr($flv_header, 0, 3);
70 $info_flv['header']['version'] = getid3_lib::BigEndian2Int(substr($flv_header, 3, 1));
71 $type_flags = getid3_lib::BigEndian2Int(substr($flv_header, 4, 1));
73 $info_flv['header']['hasAudio'] = (bool) ($type_flags & 0x04);
74 $info_flv['header']['hasVideo'] = (bool) ($type_flags & 0x01);
76 $frame_size_data_length = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 4));
77 $flv_header_frame_length = 9;
78 if ($frame_size_data_length > $flv_header_frame_length) {
79 fseek($this->getid3->fp, $frame_size_data_length - $flv_header_frame_length, SEEK_CUR);
80 }
82 $duration = 0;
83 while ((ftell($this->getid3->fp) + 1) < $info['avdataend']) {
85 $this_tag_header = fread($this->getid3->fp, 16);
87 $previous_tag_length = getid3_lib::BigEndian2Int(substr($this_tag_header, 0, 4));
88 $tag_type = getid3_lib::BigEndian2Int(substr($this_tag_header, 4, 1));
89 $data_length = getid3_lib::BigEndian2Int(substr($this_tag_header, 5, 3));
90 $timestamp = getid3_lib::BigEndian2Int(substr($this_tag_header, 8, 3));
91 $last_header_byte = getid3_lib::BigEndian2Int(substr($this_tag_header, 15, 1));
92 $next_offset = ftell($this->getid3->fp) - 1 + $data_length;
94 switch ($tag_type) {
96 case getid3_flv::TAG_AUDIO:
97 if (!isset($info_flv['audio']['audioFormat'])) {
98 $info_flv['audio']['audioFormat'] = $last_header_byte & 0x07;
99 $info_flv['audio']['audioRate'] = ($last_header_byte & 0x30) / 0x10;
100 $info_flv['audio']['audioSampleSize'] = ($last_header_byte & 0x40) / 0x40;
101 $info_flv['audio']['audioType'] = ($last_header_byte & 0x80) / 0x80;
102 }
103 break;
106 case getid3_flv::TAG_VIDEO:
107 if (!isset($info_flv['video']['videoCodec'])) {
108 $info_flv['video']['videoCodec'] = $last_header_byte & 0x07;
110 $flv_video_header = fread($this->getid3->fp, 11);
112 if ($info_flv['video']['videoCodec'] != getid3_flv::VIDEO_VP6) {
114 $picture_size_type = (getid3_lib::BigEndian2Int(substr($flv_video_header, 3, 2))) >> 7;
115 $picture_size_type = $picture_size_type & 0x0007;
116 $info_flv['header']['videoSizeType'] = $picture_size_type;
118 switch ($picture_size_type) {
119 case 0:
120 $picture_size_enc = getid3_lib::BigEndian2Int(substr($flv_video_header, 5, 2));
121 $picture_size_enc <<= 1;
122 $info['video']['resolution_x'] = ($picture_size_enc & 0xFF00) >> 8;
123 $picture_size_enc = getid3_lib::BigEndian2Int(substr($flv_video_header, 6, 2));
124 $picture_size_enc <<= 1;
125 $info['video']['resolution_y'] = ($picture_size_enc & 0xFF00) >> 8;
126 break;
128 case 1:
129 $picture_size_enc = getid3_lib::BigEndian2Int(substr($flv_video_header, 5, 4));
130 $picture_size_enc <<= 1;
131 $info['video']['resolution_x'] = ($picture_size_enc & 0xFFFF0000) >> 16;
133 $picture_size_enc = getid3_lib::BigEndian2Int(substr($flv_video_header, 7, 4));
134 $picture_size_enc <<= 1;
135 $info['video']['resolution_y'] = ($picture_size_enc & 0xFFFF0000) >> 16;
136 break;
138 case 2:
139 $info['video']['resolution_x'] = 352;
140 $info['video']['resolution_y'] = 288;
141 break;
143 case 3:
144 $info['video']['resolution_x'] = 176;
145 $info['video']['resolution_y'] = 144;
146 break;
148 case 4:
149 $info['video']['resolution_x'] = 128;
150 $info['video']['resolution_y'] = 96;
151 break;
153 case 5:
154 $info['video']['resolution_x'] = 320;
155 $info['video']['resolution_y'] = 240;
156 break;
158 case 6:
159 $info['video']['resolution_x'] = 160;
160 $info['video']['resolution_y'] = 120;
161 break;
163 default:
164 $info['video']['resolution_x'] = 0;
165 $info['video']['resolution_y'] = 0;
166 break;
167 }
168 }
169 }
170 break;
173 // Meta tag
174 case getid3_flv::TAG_META:
176 fseek($this->getid3->fp, -1, SEEK_CUR);
177 $reader = new AMFReader(new AMFStream(fread($this->getid3->fp, $data_length)));
178 $event_name = $reader->readData();
179 $info['meta'][$event_name] = $reader->readData();
180 unset($reader);
182 $info['video']['frame_rate'] = @$info['meta']['onMetaData']['framerate'];
183 $info['video']['resolution_x'] = @$info['meta']['onMetaData']['width'];
184 $info['video']['resolution_y'] = @$info['meta']['onMetaData']['height'];
185 break;
187 default:
188 // noop
189 break;
190 }
192 if ($timestamp > $duration) {
193 $duration = $timestamp;
194 }
196 fseek($this->getid3->fp, $next_offset, SEEK_SET);
197 }
199 if ($info['playtime_seconds'] = $duration / 1000) {
200 $info['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'];
201 }
203 if ($info_flv['header']['hasAudio']) {
204 $info['audio']['codec'] = $this->FLVaudioFormat($info_flv['audio']['audioFormat']);
205 $info['audio']['sample_rate'] = $this->FLVaudioRate($info_flv['audio']['audioRate']);
206 $info['audio']['bits_per_sample'] = $this->FLVaudioBitDepth($info_flv['audio']['audioSampleSize']);
208 $info['audio']['channels'] = $info_flv['audio']['audioType'] + 1; // 0=mono,1=stereo
209 $info['audio']['lossless'] = ($info_flv['audio']['audioFormat'] ? false : true); // 0=uncompressed
210 $info['audio']['dataformat'] = 'flv';
211 }
212 if (@$info_flv['header']['hasVideo']) {
213 $info['video']['codec'] = $this->FLVvideoCodec($info_flv['video']['videoCodec']);
214 $info['video']['dataformat'] = 'flv';
215 $info['video']['lossless'] = false;
216 }
218 return true;
219 }
222 public static function FLVaudioFormat($id) {
224 static $lookup = array(
225 0 => 'uncompressed',
226 1 => 'ADPCM',
227 2 => 'mp3',
228 5 => 'Nellymoser 8kHz mono',
229 6 => 'Nellymoser',
230 );
231 return (@$lookup[$id] ? @$lookup[$id] : false);
232 }
235 public static function FLVaudioRate($id) {
237 static $lookup = array(
238 0 => 5500,
239 1 => 11025,
240 2 => 22050,
241 3 => 44100,
242 );
243 return (@$lookup[$id] ? @$lookup[$id] : false);
244 }
247 public static function FLVaudioBitDepth($id) {
249 static $lookup = array(
250 0 => 8,
251 1 => 16,
252 );
253 return (@$lookup[$id] ? @$lookup[$id] : false);
254 }
257 public static function FLVvideoCodec($id) {
259 static $lookup = array(
260 getid3_flv::VIDEO_H263 => 'Sorenson H.263',
261 getid3_flv::VIDEO_SCREEN => 'Screen video',
262 getid3_flv::VIDEO_VP6 => 'On2 VP6',
263 );
264 return (@$lookup[$id] ? @$lookup[$id] : false);
265 }
266 }
270 class AMFStream
271 {
272 public $bytes;
273 public $pos;
276 public function AMFStream($bytes) {
278 $this->bytes = $bytes;
279 $this->pos = 0;
280 }
283 public function readByte() {
285 return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1));
286 }
289 public function readInt() {
291 return ($this->readByte() << 8) + $this->readByte();
292 }
295 public function readLong() {
297 return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
298 }
301 public function readDouble() {
303 return getid3_lib::BigEndian2Float($this->read(8));
304 }
307 public function readUTF() {
309 $length = $this->readInt();
310 return $this->read($length);
311 }
314 public function readLongUTF() {
316 $length = $this->readLong();
317 return $this->read($length);
318 }
321 public function read($length) {
323 $val = substr($this->bytes, $this->pos, $length);
324 $this->pos += $length;
325 return $val;
326 }
329 public function peekByte() {
331 $pos = $this->pos;
332 $val = $this->readByte();
333 $this->pos = $pos;
334 return $val;
335 }
338 public function peekInt() {
340 $pos = $this->pos;
341 $val = $this->readInt();
342 $this->pos = $pos;
343 return $val;
344 }
347 public function peekLong() {
349 $pos = $this->pos;
350 $val = $this->readLong();
351 $this->pos = $pos;
352 return $val;
353 }
356 public function peekDouble() {
358 $pos = $this->pos;
359 $val = $this->readDouble();
360 $this->pos = $pos;
361 return $val;
362 }
365 public function peekUTF() {
367 $pos = $this->pos;
368 $val = $this->readUTF();
369 $this->pos = $pos;
370 return $val;
371 }
374 public function peekLongUTF() {
376 $pos = $this->pos;
377 $val = $this->readLongUTF();
378 $this->pos = $pos;
379 return $val;
380 }
381 }
385 class AMFReader
386 {
387 public $stream;
389 public function __construct($stream) {
391 $this->stream = $stream;
392 }
395 public function readData() {
397 $value = null;
399 $type = $this->stream->readByte();
401 switch($type) {
402 // Double
403 case 0:
404 $value = $this->readDouble();
405 break;
407 // Boolean
408 case 1:
409 $value = $this->readBoolean();
410 break;
412 // String
413 case 2:
414 $value = $this->readString();
415 break;
417 // Object
418 case 3:
419 $value = $this->readObject();
420 break;
422 // null
423 case 6:
424 return null;
425 break;
427 // Mixed array
428 case 8:
429 $value = $this->readMixedArray();
430 break;
432 // Array
433 case 10:
434 $value = $this->readArray();
435 break;
437 // Date
438 case 11:
439 $value = $this->readDate();
440 break;
442 // Long string
443 case 13:
444 $value = $this->readLongString();
445 break;
447 // XML (handled as string)
448 case 15:
449 $value = $this->readXML();
450 break;
452 // Typed object (handled as object)
453 case 16:
454 $value = $this->readTypedObject();
455 break;
457 // Long string
458 default:
459 $value = '(unknown or unsupported data type)';
460 break;
461 }
463 return $value;
464 }
467 public function readDouble() {
469 return $this->stream->readDouble();
470 }
473 public function readBoolean() {
475 return $this->stream->readByte() == 1;
476 }
479 public function readString() {
481 return $this->stream->readUTF();
482 }
485 public function readObject() {
487 // Get highest numerical index - ignored
488 $highestIndex = $this->stream->readLong();
490 $data = array();
492 while ($key = $this->stream->readUTF()) {
493 // Mixed array record ends with empty string (0x00 0x00) and 0x09
494 if (($key == '') && ($this->stream->peekByte() == 0x09)) {
495 // Consume byte
496 $this->stream->readByte();
497 break;
498 }
500 $data[$key] = $this->readData();
501 }
503 return $data;
504 }
507 public function readMixedArray() {
509 // Get highest numerical index - ignored
510 $highestIndex = $this->stream->readLong();
512 $data = array();
514 while ($key = $this->stream->readUTF()) {
515 // Mixed array record ends with empty string (0x00 0x00) and 0x09
516 if (($key == '') && ($this->stream->peekByte() == 0x09)) {
517 // Consume byte
518 $this->stream->readByte();
519 break;
520 }
522 if (is_numeric($key)) {
523 $key = (float) $key;
524 }
526 $data[$key] = $this->readData();
527 }
529 return $data;
530 }
533 public function readArray() {
535 $length = $this->stream->readLong();
537 $data = array();
539 for ($i = 0; $i < count($length); $i++) {
540 $data[] = $this->readData();
541 }
543 return $data;
544 }
547 public function readDate() {
549 $timestamp = $this->stream->readDouble();
550 $timezone = $this->stream->readInt();
551 return $timestamp;
552 }
555 public function readLongString() {
557 return $this->stream->readLongUTF();
558 }
561 public function readXML() {
563 return $this->stream->readLongUTF();
564 }
567 public function readTypedObject() {
569 $className = $this->stream->readUTF();
570 return $this->readObject();
571 }
572 }
574 ?>