~ubuntu-branches/ubuntu/karmic/ampache/karmic

« back to all changes in this revision

Viewing changes to modules/getid3/module.audio-video.flv.php

  • Committer: Bazaar Package Importer
  • Author(s): Charlie Smotherman
  • Date: 2008-05-15 18:44:23 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080515184423-n47i81yk2s99iuci
Tags: 3.4-2
Included some upstream gather album art fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 $
 
41
 
 
42
 
 
43
 
 
44
class getid3_flv extends getid3_handler
 
45
{
 
46
    
 
47
    const TAG_AUDIO    =  8;
 
48
    const TAG_VIDEO    =  9;
 
49
    const TAG_META     = 18;
 
50
 
 
51
    const VIDEO_H263   = 2;
 
52
    const VIDEO_SCREEN = 3;
 
53
    const VIDEO_VP6    = 4;
 
54
 
 
55
    
 
56
        public function Analyze()
 
57
        {
 
58
            $info = &$this->getid3->info;
 
59
            
 
60
            $info['flv'] = array ();
 
61
            $info_flv = &$info['flv'];
 
62
            
 
63
                fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
 
64
 
 
65
                $flv_data_length = $info['avdataend'] - $info['avdataoffset'];
 
66
                $flv_header = fread($this->getid3->fp, 5);
 
67
 
 
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));
 
72
 
 
73
                $info_flv['header']['hasAudio'] = (bool) ($type_flags & 0x04);
 
74
                $info_flv['header']['hasVideo'] = (bool) ($type_flags & 0x01);
 
75
 
 
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
                }
 
81
 
 
82
                $duration = 0;
 
83
                while ((ftell($this->getid3->fp) + 1) < $info['avdataend']) {
 
84
                        
 
85
                        $this_tag_header = fread($this->getid3->fp, 16);
 
86
 
 
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;
 
93
 
 
94
                        switch ($tag_type) {
 
95
                                
 
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;
 
104
 
 
105
 
 
106
                                case getid3_flv::TAG_VIDEO:
 
107
                                        if (!isset($info_flv['video']['videoCodec'])) {
 
108
                                                $info_flv['video']['videoCodec'] = $last_header_byte & 0x07;
 
109
 
 
110
                                                $flv_video_header = fread($this->getid3->fp, 11);
 
111
 
 
112
                                                if ($info_flv['video']['videoCodec'] != getid3_flv::VIDEO_VP6) {
 
113
 
 
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;
 
117
                                                        
 
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;
 
127
 
 
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;
 
132
 
 
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;
 
137
 
 
138
                                                                case 2:
 
139
                                                                        $info['video']['resolution_x'] = 352;
 
140
                                                                        $info['video']['resolution_y'] = 288;
 
141
                                                                        break;
 
142
 
 
143
                                                                case 3:
 
144
                                                                        $info['video']['resolution_x'] = 176;
 
145
                                                                        $info['video']['resolution_y'] = 144;
 
146
                                                                        break;
 
147
 
 
148
                                                                case 4:
 
149
                                                                        $info['video']['resolution_x'] = 128;
 
150
                                                                        $info['video']['resolution_y'] = 96;
 
151
                                                                        break;
 
152
 
 
153
                                                                case 5:
 
154
                                                                        $info['video']['resolution_x'] = 320;
 
155
                                                                        $info['video']['resolution_y'] = 240;
 
156
                                                                        break;
 
157
 
 
158
                                                                case 6:
 
159
                                                                        $info['video']['resolution_x'] = 160;
 
160
                                                                        $info['video']['resolution_y'] = 120;
 
161
                                                                        break;
 
162
 
 
163
                                                                default:
 
164
                                                                        $info['video']['resolution_x'] = 0;
 
165
                                                                        $info['video']['resolution_y'] = 0;
 
166
                                                                        break;
 
167
                                                        }
 
168
                                                }
 
169
                                        }
 
170
                                        break;
 
171
 
 
172
 
 
173
                                // Meta tag
 
174
                                case getid3_flv::TAG_META:
 
175
 
 
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);
 
181
 
 
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;
 
186
 
 
187
                                default:
 
188
                                        // noop
 
189
                                        break;
 
190
                        }
 
191
 
 
192
                        if ($timestamp > $duration) {
 
193
                                $duration = $timestamp;
 
194
                        }
 
195
 
 
196
                        fseek($this->getid3->fp, $next_offset, SEEK_SET);
 
197
                }
 
198
 
 
199
                if ($info['playtime_seconds'] = $duration / 1000) {
 
200
                    $info['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'];
 
201
                }
 
202
 
 
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']);
 
207
 
 
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
                }
 
217
 
 
218
                return true;
 
219
        }
 
220
 
 
221
 
 
222
        public static function FLVaudioFormat($id) {
 
223
            
 
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
        }
 
233
 
 
234
 
 
235
        public static function FLVaudioRate($id) {
 
236
            
 
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
        }
 
245
 
 
246
 
 
247
        public static function FLVaudioBitDepth($id) {
 
248
            
 
249
                static $lookup = array(
 
250
                        0 =>  8,
 
251
                        1 => 16,
 
252
                );
 
253
                return (@$lookup[$id] ? @$lookup[$id] : false);
 
254
        }
 
255
 
 
256
 
 
257
        public static function FLVvideoCodec($id) {
 
258
            
 
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
}
 
267
 
 
268
 
 
269
 
 
270
class AMFStream 
 
271
{
 
272
        public $bytes;
 
273
        public $pos;
 
274
 
 
275
 
 
276
        public function AMFStream($bytes) {
 
277
            
 
278
                $this->bytes = $bytes;
 
279
                $this->pos = 0;
 
280
        }
 
281
 
 
282
 
 
283
        public function readByte() {
 
284
            
 
285
                return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1));
 
286
        }
 
287
 
 
288
 
 
289
        public function readInt() {
 
290
            
 
291
                return ($this->readByte() << 8) + $this->readByte();
 
292
        }
 
293
 
 
294
 
 
295
        public function readLong() {
 
296
            
 
297
                return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
 
298
        }
 
299
 
 
300
 
 
301
        public function readDouble() {
 
302
            
 
303
                return getid3_lib::BigEndian2Float($this->read(8));
 
304
        }
 
305
 
 
306
 
 
307
        public function readUTF() {
 
308
            
 
309
                $length = $this->readInt();
 
310
                return $this->read($length);
 
311
        }
 
312
 
 
313
 
 
314
        public function readLongUTF() {
 
315
            
 
316
                $length = $this->readLong();
 
317
                return $this->read($length);
 
318
        }
 
319
 
 
320
 
 
321
        public function read($length) {
 
322
 
 
323
                $val = substr($this->bytes, $this->pos, $length);
 
324
                $this->pos += $length;
 
325
                return $val;
 
326
        }
 
327
 
 
328
        
 
329
        public function peekByte() {
 
330
            
 
331
                $pos = $this->pos;
 
332
                $val = $this->readByte();
 
333
                $this->pos = $pos;
 
334
                return $val;
 
335
        }
 
336
 
 
337
 
 
338
        public function peekInt() {
 
339
 
 
340
                $pos = $this->pos;
 
341
                $val = $this->readInt();
 
342
                $this->pos = $pos;
 
343
                return $val;
 
344
        }
 
345
 
 
346
 
 
347
        public function peekLong() {
 
348
            
 
349
                $pos = $this->pos;
 
350
                $val = $this->readLong();
 
351
                $this->pos = $pos;
 
352
                return $val;
 
353
        }
 
354
 
 
355
 
 
356
        public function peekDouble() {  
 
357
            
 
358
                $pos = $this->pos;
 
359
                $val = $this->readDouble();
 
360
                $this->pos = $pos;
 
361
                return $val;
 
362
        }
 
363
 
 
364
 
 
365
        public function peekUTF() {
 
366
            
 
367
                $pos = $this->pos;
 
368
                $val = $this->readUTF();
 
369
                $this->pos = $pos;
 
370
                return $val;
 
371
        }
 
372
 
 
373
 
 
374
        public function peekLongUTF() {
 
375
            
 
376
                $pos = $this->pos;
 
377
                $val = $this->readLongUTF();
 
378
                $this->pos = $pos;
 
379
                return $val;
 
380
        }
 
381
}
 
382
 
 
383
 
 
384
 
 
385
class AMFReader 
 
386
{
 
387
        public $stream;
 
388
 
 
389
        public function __construct($stream) {
 
390
            
 
391
                $this->stream = $stream;
 
392
        }
 
393
 
 
394
 
 
395
        public function readData() {
 
396
            
 
397
                $value = null;
 
398
 
 
399
                $type = $this->stream->readByte();
 
400
 
 
401
                switch($type) {
 
402
                        // Double
 
403
                        case 0:
 
404
                                $value = $this->readDouble();
 
405
                        break;
 
406
 
 
407
                        // Boolean
 
408
                        case 1:
 
409
                                $value = $this->readBoolean();
 
410
                                break;
 
411
 
 
412
                        // String
 
413
                        case 2:
 
414
                                $value = $this->readString();
 
415
                                break;
 
416
 
 
417
                        // Object
 
418
                        case 3:
 
419
                                $value = $this->readObject();
 
420
                                break;
 
421
 
 
422
                        // null
 
423
                        case 6:
 
424
                                return null;
 
425
                                break;
 
426
 
 
427
                        // Mixed array
 
428
                        case 8:
 
429
                                $value = $this->readMixedArray();
 
430
                                break;
 
431
 
 
432
                        // Array
 
433
                        case 10:
 
434
                                $value = $this->readArray();
 
435
                                break;
 
436
 
 
437
                        // Date
 
438
                        case 11:
 
439
                                $value = $this->readDate();
 
440
                                break;
 
441
 
 
442
                        // Long string
 
443
                        case 13:
 
444
                                $value = $this->readLongString();
 
445
                                break;
 
446
 
 
447
                        // XML (handled as string)
 
448
                        case 15:
 
449
                                $value = $this->readXML();
 
450
                                break;
 
451
 
 
452
                        // Typed object (handled as object)
 
453
                        case 16:
 
454
                                $value = $this->readTypedObject();
 
455
                                break;
 
456
 
 
457
                        // Long string
 
458
                        default:
 
459
                                $value = '(unknown or unsupported data type)';
 
460
                        break;
 
461
                }
 
462
 
 
463
                return $value;
 
464
        }
 
465
 
 
466
 
 
467
        public function readDouble() {    
 
468
            
 
469
                return $this->stream->readDouble();
 
470
        }
 
471
 
 
472
 
 
473
        public function readBoolean() {
 
474
            
 
475
                return $this->stream->readByte() == 1;
 
476
        }
 
477
           
 
478
           
 
479
        public function readString() {
 
480
            
 
481
                return $this->stream->readUTF();
 
482
        }
 
483
 
 
484
 
 
485
        public function readObject() {
 
486
            
 
487
                // Get highest numerical index - ignored
 
488
                $highestIndex = $this->stream->readLong();
 
489
 
 
490
                $data = array();
 
491
 
 
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
                        }
 
499
 
 
500
                        $data[$key] = $this->readData();
 
501
                }
 
502
 
 
503
                return $data;
 
504
        }
 
505
 
 
506
 
 
507
        public function readMixedArray() {
 
508
            
 
509
                // Get highest numerical index - ignored
 
510
                $highestIndex = $this->stream->readLong();
 
511
 
 
512
                $data = array();
 
513
 
 
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
                        }
 
521
 
 
522
                        if (is_numeric($key)) {
 
523
                                $key = (float) $key;
 
524
                        }
 
525
 
 
526
                        $data[$key] = $this->readData();
 
527
                }
 
528
 
 
529
                return $data;
 
530
        }
 
531
 
 
532
 
 
533
        public function readArray() {
 
534
            
 
535
                $length = $this->stream->readLong();
 
536
 
 
537
                $data = array();
 
538
 
 
539
                for ($i = 0; $i < count($length); $i++) {
 
540
                        $data[] = $this->readData();
 
541
                }
 
542
 
 
543
                return $data;
 
544
        }
 
545
 
 
546
 
 
547
        public function readDate() {
 
548
            
 
549
                $timestamp = $this->stream->readDouble();
 
550
                $timezone = $this->stream->readInt();
 
551
                return $timestamp;
 
552
        }
 
553
 
 
554
 
 
555
        public function readLongString() {
 
556
            
 
557
                return $this->stream->readLongUTF();
 
558
        }
 
559
 
 
560
 
 
561
        public function readXML() {
 
562
            
 
563
                return $this->stream->readLongUTF();
 
564
        }
 
565
 
 
566
 
 
567
        public function readTypedObject() {  
 
568
            
 
569
                $className = $this->stream->readUTF();
 
570
                return $this->readObject();
 
571
        }
 
572
}
 
573
 
 
574
?>
 
 
b'\\ No newline at end of file'