Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 59 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
File_Ogg_Flac | |
0.00% |
0 / 59 |
|
0.00% |
0 / 6 |
182 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
20 | |||
getSecondsFromGranulePos | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getType | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
_decodeHeader | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
20 | |||
getHeader | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
_decodeCommentsHeader | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /* vim: set expandtab tabstop=4 shiftwidth=4: */ |
3 | // +----------------------------------------------------------------------------+ |
4 | // | File_Ogg PEAR Package for Accessing Ogg Bitstreams | |
5 | // | Copyright (c) 2005-2007 | |
6 | // | David Grant <david@grant.org.uk> | |
7 | // | Tim Starling <tstarling@wikimedia.org> | |
8 | // +----------------------------------------------------------------------------+ |
9 | // | This library is free software; you can redistribute it and/or | |
10 | // | modify it under the terms of the GNU Lesser General Public | |
11 | // | License as published by the Free Software Foundation; either | |
12 | // | version 2.1 of the License, or (at your option) any later version. | |
13 | // | | |
14 | // | This library is distributed in the hope that it will be useful, | |
15 | // | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | // | Lesser General Public License for more details. | |
18 | // | | |
19 | // | You should have received a copy of the GNU Lesser General Public | |
20 | // | License along with this library; if not, write to the Free Software | |
21 | // | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
22 | // +----------------------------------------------------------------------------+ |
23 | use MediaWiki\TimedMediaHandler\Handlers\OggHandler\OggException; |
24 | |
25 | /** |
26 | * @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org> |
27 | * @category File |
28 | * @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org> |
29 | * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL |
30 | * @link http://pear.php.net/package/File_Ogg |
31 | * @link http://flac.sourceforge.net/documentation.html |
32 | * @package File_Ogg |
33 | * @version CVS: $Id: Flac.php,v 1.9 2005/11/16 20:43:27 djg Exp $ |
34 | */ |
35 | class File_Ogg_Flac extends File_Ogg_Media |
36 | { |
37 | /** |
38 | * @access private |
39 | * @var string |
40 | */ |
41 | var $_version; |
42 | |
43 | /** |
44 | * @access private |
45 | * @var array |
46 | */ |
47 | var $_streamInfo; |
48 | |
49 | /** |
50 | * @access private |
51 | */ |
52 | function __construct($streamSerial, $streamData, $filePointer) |
53 | { |
54 | parent::__construct($streamSerial, $streamData, $filePointer); |
55 | $this->_decodeHeader(); |
56 | $this->_decodeCommentsHeader(); |
57 | |
58 | if ($this->_streamInfo['total_samples'] > 0) { |
59 | $this->_streamLength = $this->_streamInfo['total_samples'] |
60 | / $this->_streamInfo['sample_rate']; |
61 | } else { |
62 | // Header may have 0 for total_samples in which case we have to check. |
63 | // https://xiph.org/flac/format.html#metadata_block_streaminfo |
64 | $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos ); |
65 | $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos ); |
66 | |
67 | //make sure the offset is worth taking into account oggz_chop related hack |
68 | if( $startSec > 1) { |
69 | $this->_streamLength = $endSec - $startSec; |
70 | $this->_startOffset = $startSec; |
71 | } else { |
72 | $this->_streamLength = $endSec; |
73 | } |
74 | } |
75 | |
76 | $this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8) / $this->_streamLength : 0; |
77 | } |
78 | |
79 | function getSecondsFromGranulePos( $granulePos ){ |
80 | return (intval(substr( $granulePos, 0, 8 ), 16 ) * pow(2, 32) |
81 | + intval(substr( $granulePos, 8, 8 ), 16 )) |
82 | / $this->_streamInfo['sample_rate']; |
83 | } |
84 | |
85 | /** |
86 | * Get a short string describing the type of the stream |
87 | * @return string |
88 | */ |
89 | function getType() { |
90 | return 'FLAC'; |
91 | } |
92 | |
93 | /** |
94 | * @access private |
95 | */ |
96 | function _decodeHeader() |
97 | { |
98 | fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET); |
99 | // Check if this is the correct header. |
100 | $packet = unpack("Cdata", fread($this->_filePointer, 1)); |
101 | if ($packet['data'] != 0x7f) |
102 | throw new OggException("Stream Undecodable", OGG_ERROR_UNDECODABLE); |
103 | |
104 | // The following four characters should be "FLAC". |
105 | if (fread($this->_filePointer, 4) != 'FLAC') |
106 | throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE); |
107 | |
108 | $version = unpack("Cmajor/Cminor", fread($this->_filePointer, 2)); |
109 | $this->_version = "{$version['major']}.{$version['minor']}"; |
110 | if ($version['major'] > 1) { |
111 | throw new OggException("Cannot decode a version {$version['major']} FLAC stream", OGG_ERROR_UNDECODABLE); |
112 | } |
113 | $h = File_Ogg::_readBigEndian( $this->_filePointer, |
114 | array( |
115 | // Ogg-specific |
116 | 'num_headers' => 16, |
117 | 'flac_native_sig' => 32, |
118 | // METADATA_BLOCK_HEADER |
119 | 'is_last' => 1, |
120 | 'type' => 7, |
121 | 'length' => 24, |
122 | )); |
123 | |
124 | // METADATA_BLOCK_STREAMINFO |
125 | // The variable names are canonical, and come from the FLAC source (format.h) |
126 | $this->_streamInfo = File_Ogg::_readBigEndian( $this->_filePointer, |
127 | array( |
128 | 'min_blocksize' => 16, |
129 | 'max_blocksize' => 16, |
130 | 'min_framesize' => 24, |
131 | 'max_framesize' => 24, |
132 | 'sample_rate' => 20, |
133 | 'channels' => 3, |
134 | 'bits_per_sample' => 5, |
135 | 'total_samples' => 36, |
136 | )); |
137 | $this->_streamInfo['md5sum'] = bin2hex(fread($this->_filePointer, 16)); |
138 | } |
139 | |
140 | /** |
141 | * Get an associative array containing header information about the stream |
142 | * @access public |
143 | * @return array |
144 | */ |
145 | function getHeader() |
146 | { |
147 | return $this->_streamInfo; |
148 | } |
149 | |
150 | function _decodeCommentsHeader() |
151 | { |
152 | fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET); |
153 | $blockHeader = File_Ogg::_readBigEndian( $this->_filePointer, |
154 | array( |
155 | 'last_block' => 1, |
156 | 'block_type' => 7, |
157 | 'length' => 24 |
158 | ) |
159 | ); |
160 | if ($blockHeader['block_type'] != 4) { |
161 | throw new OggException("Stream Undecodable", OGG_ERROR_UNDECODABLE); |
162 | } |
163 | |
164 | $this->_decodeBareCommentsHeader(); |
165 | } |
166 | } |
167 | ?> |