ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
getid3_ogg Class Reference
+ Inheritance diagram for getid3_ogg:
+ Collaboration diagram for getid3_ogg:

Public Member Functions

 Analyze ()
 
 ParseVorbisPageHeader (&$filedata, &$filedataoffset, &$oggpageinfo)
 
 ParseOpusPageHeader (&$filedata, &$filedataoffset, &$oggpageinfo)
 
 ParseOggPageHeader ()
 
 ParseVorbisComments ()
 
- Public Member Functions inherited from getid3_handler
 __construct (getID3 $getid3, $call_module=null)
 
 Analyze ()
 
 AnalyzeString ($string)
 
 setStringMode ($string)
 
 saveAttachment ($name, $offset, $length, $image_mime=null)
 

Static Public Member Functions

static SpeexBandModeLookup ($mode)
 
static OggPageSegmentLength ($OggInfoArray, $SegmentNumber=1)
 
static get_quality_from_nominal_bitrate ($nominal_bitrate)
 
static TheoraColorSpace ($colorspace_id)
 
static TheoraPixelFormat ($pixelformat_id)
 

Additional Inherited Members

- Protected Member Functions inherited from getid3_handler
 ftell ()
 
 fread ($bytes)
 
 fseek ($bytes, $whence=SEEK_SET)
 
 feof ()
 
 isDependencyFor ($module)
 
 error ($text)
 
 warning ($text)
 
 notice ($text)
 
- Protected Attributes inherited from getid3_handler
 $getid3
 
 $data_string_flag = false
 
 $data_string = ''
 
 $data_string_position = 0
 
 $data_string_length = 0
 

Detailed Description

Definition at line 19 of file module.audio.ogg.php.

Member Function Documentation

◆ Analyze()

getid3_ogg::Analyze ( )

Reimplemented from getid3_handler.

Definition at line 22 of file module.audio.ogg.php.

22 {
23 $info = &$this->getid3->info;
24
25 $info['fileformat'] = 'ogg';
26
27 // Warn about illegal tags - only vorbiscomments are allowed
28 if (isset($info['id3v2'])) {
29 $this->warning('Illegal ID3v2 tag present.');
30 }
31 if (isset($info['id3v1'])) {
32 $this->warning('Illegal ID3v1 tag present.');
33 }
34 if (isset($info['ape'])) {
35 $this->warning('Illegal APE tag present.');
36 }
37
38
39 // Page 1 - Stream Header
40
41 $this->fseek($info['avdataoffset']);
42
43 $oggpageinfo = $this->ParseOggPageHeader();
44 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
45
46 if ($this->ftell() >= $this->getid3->fread_buffer_size()) {
47 $this->error('Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)');
48 unset($info['fileformat']);
49 unset($info['ogg']);
50 return false;
51 }
52
53 $filedata = $this->fread($oggpageinfo['page_length']);
54 $filedataoffset = 0;
55
56 if (substr($filedata, 0, 4) == 'fLaC') {
57
58 $info['audio']['dataformat'] = 'flac';
59 $info['audio']['bitrate_mode'] = 'vbr';
60 $info['audio']['lossless'] = true;
61
62 } elseif (substr($filedata, 1, 6) == 'vorbis') {
63
64 $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
65
66 } elseif (substr($filedata, 0, 8) == 'OpusHead') {
67
68 if( $this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) == false ) {
69 return false;
70 }
71
72 } elseif (substr($filedata, 0, 8) == 'Speex ') {
73
74 // http://www.speex.org/manual/node10.html
75
76 $info['audio']['dataformat'] = 'speex';
77 $info['mime_type'] = 'audio/speex';
78 $info['audio']['bitrate_mode'] = 'abr';
79 $info['audio']['lossless'] = false;
80
81 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'Speex '
82 $filedataoffset += 8;
83 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version'] = substr($filedata, $filedataoffset, 20);
84 $filedataoffset += 20;
85 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version_id'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
86 $filedataoffset += 4;
87 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['header_size'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
88 $filedataoffset += 4;
89 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
90 $filedataoffset += 4;
91 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
92 $filedataoffset += 4;
93 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode_bitstream_version'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
94 $filedataoffset += 4;
95 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
96 $filedataoffset += 4;
97 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['bitrate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
98 $filedataoffset += 4;
99 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['framesize'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
100 $filedataoffset += 4;
101 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
102 $filedataoffset += 4;
103 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['frames_per_packet'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
104 $filedataoffset += 4;
105 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['extra_headers'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
106 $filedataoffset += 4;
107 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved1'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
108 $filedataoffset += 4;
109 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved2'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
110 $filedataoffset += 4;
111
112 $info['speex']['speex_version'] = trim($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']);
113 $info['speex']['sample_rate'] = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'];
114 $info['speex']['channels'] = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'];
115 $info['speex']['vbr'] = (bool) $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'];
116 $info['speex']['band_type'] = $this->SpeexBandModeLookup($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']);
117
118 $info['audio']['sample_rate'] = $info['speex']['sample_rate'];
119 $info['audio']['channels'] = $info['speex']['channels'];
120 if ($info['speex']['vbr']) {
121 $info['audio']['bitrate_mode'] = 'vbr';
122 }
123
124 } elseif (substr($filedata, 0, 7) == "\x80".'theora') {
125
126 // http://www.theora.org/doc/Theora.pdf (section 6.2)
127
128 $info['ogg']['pageheader']['theora']['theora_magic'] = substr($filedata, $filedataoffset, 7); // hard-coded to "\x80.'theora'
129 $filedataoffset += 7;
130 $info['ogg']['pageheader']['theora']['version_major'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
131 $filedataoffset += 1;
132 $info['ogg']['pageheader']['theora']['version_minor'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
133 $filedataoffset += 1;
134 $info['ogg']['pageheader']['theora']['version_revision'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
135 $filedataoffset += 1;
136 $info['ogg']['pageheader']['theora']['frame_width_macroblocks'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2));
137 $filedataoffset += 2;
138 $info['ogg']['pageheader']['theora']['frame_height_macroblocks'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2));
139 $filedataoffset += 2;
140 $info['ogg']['pageheader']['theora']['resolution_x'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
141 $filedataoffset += 3;
142 $info['ogg']['pageheader']['theora']['resolution_y'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
143 $filedataoffset += 3;
144 $info['ogg']['pageheader']['theora']['picture_offset_x'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
145 $filedataoffset += 1;
146 $info['ogg']['pageheader']['theora']['picture_offset_y'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
147 $filedataoffset += 1;
148 $info['ogg']['pageheader']['theora']['frame_rate_numerator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 4));
149 $filedataoffset += 4;
150 $info['ogg']['pageheader']['theora']['frame_rate_denominator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 4));
151 $filedataoffset += 4;
152 $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
153 $filedataoffset += 3;
154 $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
155 $filedataoffset += 3;
156 $info['ogg']['pageheader']['theora']['color_space_id'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1));
157 $filedataoffset += 1;
158 $info['ogg']['pageheader']['theora']['nominal_bitrate'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3));
159 $filedataoffset += 3;
160 $info['ogg']['pageheader']['theora']['flags'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2));
161 $filedataoffset += 2;
162
163 $info['ogg']['pageheader']['theora']['quality'] = ($info['ogg']['pageheader']['theora']['flags'] & 0xFC00) >> 10;
164 $info['ogg']['pageheader']['theora']['kfg_shift'] = ($info['ogg']['pageheader']['theora']['flags'] & 0x03E0) >> 5;
165 $info['ogg']['pageheader']['theora']['pixel_format_id'] = ($info['ogg']['pageheader']['theora']['flags'] & 0x0018) >> 3;
166 $info['ogg']['pageheader']['theora']['reserved'] = ($info['ogg']['pageheader']['theora']['flags'] & 0x0007) >> 0; // should be 0
167 $info['ogg']['pageheader']['theora']['color_space'] = self::TheoraColorSpace($info['ogg']['pageheader']['theora']['color_space_id']);
168 $info['ogg']['pageheader']['theora']['pixel_format'] = self::TheoraPixelFormat($info['ogg']['pageheader']['theora']['pixel_format_id']);
169
170 $info['video']['dataformat'] = 'theora';
171 $info['mime_type'] = 'video/ogg';
172 //$info['audio']['bitrate_mode'] = 'abr';
173 //$info['audio']['lossless'] = false;
174 $info['video']['resolution_x'] = $info['ogg']['pageheader']['theora']['resolution_x'];
175 $info['video']['resolution_y'] = $info['ogg']['pageheader']['theora']['resolution_y'];
176 if ($info['ogg']['pageheader']['theora']['frame_rate_denominator'] > 0) {
177 $info['video']['frame_rate'] = (float) $info['ogg']['pageheader']['theora']['frame_rate_numerator'] / $info['ogg']['pageheader']['theora']['frame_rate_denominator'];
178 }
179 if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
180 $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
181 }
182$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');
183
184
185 } elseif (substr($filedata, 0, 8) == "fishead\x00") {
186
187 // Ogg Skeleton version 3.0 Format Specification
188 // http://xiph.org/ogg/doc/skeleton.html
189 $filedataoffset += 8;
190 $info['ogg']['skeleton']['fishead']['raw']['version_major'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
191 $filedataoffset += 2;
192 $info['ogg']['skeleton']['fishead']['raw']['version_minor'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
193 $filedataoffset += 2;
194 $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
195 $filedataoffset += 8;
196 $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
197 $filedataoffset += 8;
198 $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
199 $filedataoffset += 8;
200 $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
201 $filedataoffset += 8;
202 $info['ogg']['skeleton']['fishead']['raw']['utc'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 20));
203 $filedataoffset += 20;
204
205 $info['ogg']['skeleton']['fishead']['version'] = $info['ogg']['skeleton']['fishead']['raw']['version_major'].'.'.$info['ogg']['skeleton']['fishead']['raw']['version_minor'];
206 $info['ogg']['skeleton']['fishead']['presentationtime'] = $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'];
207 $info['ogg']['skeleton']['fishead']['basetime'] = $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator'];
208 $info['ogg']['skeleton']['fishead']['utc'] = $info['ogg']['skeleton']['fishead']['raw']['utc'];
209
210
211 $counter = 0;
212 do {
213 $oggpageinfo = $this->ParseOggPageHeader();
214 $info['ogg']['pageheader'][$oggpageinfo['page_seqno'].'.'.$counter++] = $oggpageinfo;
215 $filedata = $this->fread($oggpageinfo['page_length']);
216 $this->fseek($oggpageinfo['page_end_offset']);
217
218 if (substr($filedata, 0, 8) == "fisbone\x00") {
219
220 $filedataoffset = 8;
221 $info['ogg']['skeleton']['fisbone']['raw']['message_header_offset'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
222 $filedataoffset += 4;
223 $info['ogg']['skeleton']['fisbone']['raw']['serial_number'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
224 $filedataoffset += 4;
225 $info['ogg']['skeleton']['fisbone']['raw']['number_header_packets'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
226 $filedataoffset += 4;
227 $info['ogg']['skeleton']['fisbone']['raw']['granulerate_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
228 $filedataoffset += 8;
229 $info['ogg']['skeleton']['fisbone']['raw']['granulerate_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
230 $filedataoffset += 8;
231 $info['ogg']['skeleton']['fisbone']['raw']['basegranule'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
232 $filedataoffset += 8;
233 $info['ogg']['skeleton']['fisbone']['raw']['preroll'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
234 $filedataoffset += 4;
235 $info['ogg']['skeleton']['fisbone']['raw']['granuleshift'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
236 $filedataoffset += 1;
237 $info['ogg']['skeleton']['fisbone']['raw']['padding'] = substr($filedata, $filedataoffset, 3);
238 $filedataoffset += 3;
239
240 } elseif (substr($filedata, 1, 6) == 'theora') {
241
242 $info['video']['dataformat'] = 'theora1';
243 $this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']');
244 //break;
245
246 } elseif (substr($filedata, 1, 6) == 'vorbis') {
247
248 $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
249
250 } else {
251 $this->error('unexpected');
252 //break;
253 }
254 //} while ($oggpageinfo['page_seqno'] == 0);
255 } while (($oggpageinfo['page_seqno'] == 0) && (substr($filedata, 0, 8) != "fisbone\x00"));
256
257 $this->fseek($oggpageinfo['page_start_offset']);
258
259 $this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
260 //return false;
261
262 } else {
263
264 $this->error('Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"');
265 unset($info['ogg']);
266 unset($info['mime_type']);
267 return false;
268
269 }
270
271 // Page 2 - Comment Header
272 $oggpageinfo = $this->ParseOggPageHeader();
273 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
274
275 switch ($info['audio']['dataformat']) {
276 case 'vorbis':
277 $filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
278 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, 0, 1));
279 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 1, 6); // hard-coded to 'vorbis'
280
281 $this->ParseVorbisComments();
282 break;
283
284 case 'flac':
285 $flac = new getid3_flac($this->getid3);
286 if (!$flac->parseMETAdata()) {
287 $this->error('Failed to parse FLAC headers');
288 return false;
289 }
290 unset($flac);
291 break;
292
293 case 'speex':
294 $this->fseek($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR);
295 $this->ParseVorbisComments();
296 break;
297
298 case 'opus':
299 $filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
300 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags'
301 if(substr($filedata, 0, 8) != 'OpusTags') {
302 $this->error('Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"');
303 return false;
304 }
305
306 $this->ParseVorbisComments();
307 break;
308
309 }
310
311 // Last Page - Number of Samples
312 if (!getid3_lib::intValueSupported($info['avdataend'])) {
313
314 $this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)');
315
316 } else {
317
318 $this->fseek(max($info['avdataend'] - $this->getid3->fread_buffer_size(), 0));
319 $LastChunkOfOgg = strrev($this->fread($this->getid3->fread_buffer_size()));
320 if ($LastOggSpostion = strpos($LastChunkOfOgg, 'SggO')) {
321 $this->fseek($info['avdataend'] - ($LastOggSpostion + strlen('SggO')));
322 $info['avdataend'] = $this->ftell();
323 $info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
324 $info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position'];
325 if ($info['ogg']['samples'] == 0) {
326 $this->error('Corrupt Ogg file: eos.number of samples == zero');
327 return false;
328 }
329 if (!empty($info['audio']['sample_rate'])) {
330 $info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']);
331 }
332 }
333
334 }
335
336 if (!empty($info['ogg']['bitrate_average'])) {
337 $info['audio']['bitrate'] = $info['ogg']['bitrate_average'];
338 } elseif (!empty($info['ogg']['bitrate_nominal'])) {
339 $info['audio']['bitrate'] = $info['ogg']['bitrate_nominal'];
340 } elseif (!empty($info['ogg']['bitrate_min']) && !empty($info['ogg']['bitrate_max'])) {
341 $info['audio']['bitrate'] = ($info['ogg']['bitrate_min'] + $info['ogg']['bitrate_max']) / 2;
342 }
343 if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) {
344 if ($info['audio']['bitrate'] == 0) {
345 $this->error('Corrupt Ogg file: bitrate_audio == zero');
346 return false;
347 }
348 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
349 }
350
351 if (isset($info['ogg']['vendor'])) {
352 $info['audio']['encoder'] = preg_replace('/^Encoded with /', '', $info['ogg']['vendor']);
353
354 // Vorbis only
355 if ($info['audio']['dataformat'] == 'vorbis') {
356
357 // Vorbis 1.0 starts with Xiph.Org
358 if (preg_match('/^Xiph.Org/', $info['audio']['encoder'])) {
359
360 if ($info['audio']['bitrate_mode'] == 'abr') {
361
362 // Set -b 128 on abr files
363 $info['audio']['encoder_options'] = '-b '.round($info['ogg']['bitrate_nominal'] / 1000);
364
365 } elseif (($info['audio']['bitrate_mode'] == 'vbr') && ($info['audio']['channels'] == 2) && ($info['audio']['sample_rate'] >= 44100) && ($info['audio']['sample_rate'] <= 48000)) {
366 // Set -q N on vbr files
367 $info['audio']['encoder_options'] = '-q '.$this->get_quality_from_nominal_bitrate($info['ogg']['bitrate_nominal']);
368
369 }
370 }
371
372 if (empty($info['audio']['encoder_options']) && !empty($info['ogg']['bitrate_nominal'])) {
373 $info['audio']['encoder_options'] = 'Nominal bitrate: '.intval(round($info['ogg']['bitrate_nominal'] / 1000)).'kbps';
374 }
375 }
376 }
377
378 return true;
379 }
@tutorial http://flac.sourceforge.net/format.html
fseek($bytes, $whence=SEEK_SET)
Definition: getid3.php:1711
fread($bytes)
Definition: getid3.php:1683
warning($text)
Definition: getid3.php:1758
error($text)
Definition: getid3.php:1752
static LittleEndian2Int($byteword, $signed=false)
Definition: getid3.lib.php:292
static intValueSupported($num)
Definition: getid3.lib.php:80
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
Definition: getid3.lib.php:263
static TheoraPixelFormat($pixelformat_id)
ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo)
static SpeexBandModeLookup($mode)
ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo)
static TheoraColorSpace($colorspace_id)
$counter
$info
Definition: index.php:5

References $counter, $info, getid3_lib\BigEndian2Int(), getid3_handler\error(), getid3_handler\fread(), getid3_handler\fseek(), getid3_handler\ftell(), getid3_lib\intValueSupported(), getid3_lib\LittleEndian2Int(), ParseOggPageHeader(), ParseOpusPageHeader(), ParseVorbisComments(), ParseVorbisPageHeader(), SpeexBandModeLookup(), TheoraColorSpace(), TheoraPixelFormat(), and getid3_handler\warning().

+ Here is the call graph for this function:

◆ get_quality_from_nominal_bitrate()

static getid3_ogg::get_quality_from_nominal_bitrate (   $nominal_bitrate)
static

Definition at line 793 of file module.audio.ogg.php.

793 {
794
795 // decrease precision
796 $nominal_bitrate = $nominal_bitrate / 1000;
797
798 if ($nominal_bitrate < 128) {
799 // q-1 to q4
800 $qval = ($nominal_bitrate - 64) / 16;
801 } elseif ($nominal_bitrate < 256) {
802 // q4 to q8
803 $qval = $nominal_bitrate / 32;
804 } elseif ($nominal_bitrate < 320) {
805 // q8 to q9
806 $qval = ($nominal_bitrate + 256) / 64;
807 } else {
808 // q9 to q10
809 $qval = ($nominal_bitrate + 1300) / 180;
810 }
811 //return $qval; // 5.031324
812 //return intval($qval); // 5
813 return round($qval, 1); // 5 or 4.9
814 }

◆ OggPageSegmentLength()

static getid3_ogg::OggPageSegmentLength (   $OggInfoArray,
  $SegmentNumber = 1 
)
static

Definition at line 779 of file module.audio.ogg.php.

779 {
780 for ($i = 0; $i < $SegmentNumber; $i++) {
781 $segmentlength = 0;
782 foreach ($OggInfoArray['segment_table'] as $key => $value) {
783 $segmentlength += $value;
784 if ($value < 255) {
785 break;
786 }
787 }
788 }
789 return $segmentlength;
790 }
$key
Definition: croninfo.php:18
$i
Definition: disco.tpl.php:19

References $i, and $key.

Referenced by ParseVorbisComments().

+ Here is the caller graph for this function:

◆ ParseOggPageHeader()

getid3_ogg::ParseOggPageHeader ( )

Definition at line 480 of file module.audio.ogg.php.

480 {
481 // http://xiph.org/ogg/vorbis/doc/framing.html
482 $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
483
484 $filedata = $this->fread($this->getid3->fread_buffer_size());
485 $filedataoffset = 0;
486 while ((substr($filedata, $filedataoffset++, 4) != 'OggS')) {
487 if (($this->ftell() - $oggheader['page_start_offset']) >= $this->getid3->fread_buffer_size()) {
488 // should be found before here
489 return false;
490 }
491 if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
492 if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === false)) {
493 // get some more data, unless eof, in which case fail
494 return false;
495 }
496 }
497 }
498 $filedataoffset += strlen('OggS') - 1; // page, delimited by 'OggS'
499
500 $oggheader['stream_structver'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
501 $filedataoffset += 1;
502 $oggheader['flags_raw'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
503 $filedataoffset += 1;
504 $oggheader['flags']['fresh'] = (bool) ($oggheader['flags_raw'] & 0x01); // fresh packet
505 $oggheader['flags']['bos'] = (bool) ($oggheader['flags_raw'] & 0x02); // first page of logical bitstream (bos)
506 $oggheader['flags']['eos'] = (bool) ($oggheader['flags_raw'] & 0x04); // last page of logical bitstream (eos)
507
508 $oggheader['pcm_abs_position'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8));
509 $filedataoffset += 8;
510 $oggheader['stream_serialno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
511 $filedataoffset += 4;
512 $oggheader['page_seqno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
513 $filedataoffset += 4;
514 $oggheader['page_checksum'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
515 $filedataoffset += 4;
516 $oggheader['page_segments'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
517 $filedataoffset += 1;
518 $oggheader['page_length'] = 0;
519 for ($i = 0; $i < $oggheader['page_segments']; $i++) {
520 $oggheader['segment_table'][$i] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
521 $filedataoffset += 1;
522 $oggheader['page_length'] += $oggheader['segment_table'][$i];
523 }
524 $oggheader['header_end_offset'] = $oggheader['page_start_offset'] + $filedataoffset;
525 $oggheader['page_end_offset'] = $oggheader['header_end_offset'] + $oggheader['page_length'];
526 $this->fseek($oggheader['header_end_offset']);
527
528 return $oggheader;
529 }

References $i, getid3_handler\feof(), getid3_handler\fread(), getid3_handler\fseek(), getid3_handler\ftell(), and getid3_lib\LittleEndian2Int().

Referenced by Analyze(), and ParseVorbisComments().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ParseOpusPageHeader()

getid3_ogg::ParseOpusPageHeader ( $filedata,
$filedataoffset,
$oggpageinfo 
)
Todo:
find a usable way to detect abr (vbr that is padded to be abr)

Definition at line 430 of file module.audio.ogg.php.

430 {
431 $info = &$this->getid3->info;
432 $info['audio']['dataformat'] = 'opus';
433 $info['mime_type'] = 'audio/ogg; codecs=opus';
434
436 $info['audio']['bitrate_mode'] = 'vbr';
437
438 $info['audio']['lossless'] = false;
439
440 $info['ogg']['pageheader']['opus']['opus_magic'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'OpusHead'
441 $filedataoffset += 8;
442 $info['ogg']['pageheader']['opus']['version'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
443 $filedataoffset += 1;
444
445 if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) {
446 $this->error('Unknown opus version number (only accepting 1-15)');
447 return false;
448 }
449
450 $info['ogg']['pageheader']['opus']['out_channel_count'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
451 $filedataoffset += 1;
452
453 if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
454 $this->error('Invalid channel count in opus header (must not be zero)');
455 return false;
456 }
457
458 $info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
459 $filedataoffset += 2;
460
461 $info['ogg']['pageheader']['opus']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
462 $filedataoffset += 4;
463
464 //$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
465 //$filedataoffset += 2;
466
467 //$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
468 //$filedataoffset += 1;
469
470 $info['opus']['opus_version'] = $info['ogg']['pageheader']['opus']['version'];
471 $info['opus']['sample_rate'] = $info['ogg']['pageheader']['opus']['sample_rate'];
472 $info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count'];
473
474 $info['audio']['channels'] = $info['opus']['out_channel_count'];
475 $info['audio']['sample_rate'] = $info['opus']['sample_rate'];
476 return true;
477 }

References $info, getid3_handler\error(), and getid3_lib\LittleEndian2Int().

Referenced by Analyze().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ParseVorbisComments()

getid3_ogg::ParseVorbisComments ( )
Todo:
use 'coverartmime' where available

Definition at line 532 of file module.audio.ogg.php.

532 {
533 $info = &$this->getid3->info;
534
535 $OriginalOffset = $this->ftell();
536 $commentdataoffset = 0;
537 $VorbisCommentPage = 1;
538
539 switch ($info['audio']['dataformat']) {
540 case 'vorbis':
541 case 'speex':
542 case 'opus':
543 $CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block
544 $this->fseek($CommentStartOffset);
545 $commentdataoffset = 27 + $info['ogg']['pageheader'][$VorbisCommentPage]['page_segments'];
546 $commentdata = $this->fread(self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset);
547
548 if ($info['audio']['dataformat'] == 'vorbis') {
549 $commentdataoffset += (strlen('vorbis') + 1);
550 }
551 else if ($info['audio']['dataformat'] == 'opus') {
552 $commentdataoffset += strlen('OpusTags');
553 }
554
555 break;
556
557 case 'flac':
558 $CommentStartOffset = $info['flac']['VORBIS_COMMENT']['raw']['offset'] + 4;
559 $this->fseek($CommentStartOffset);
560 $commentdata = $this->fread($info['flac']['VORBIS_COMMENT']['raw']['block_length']);
561 break;
562
563 default:
564 return false;
565 break;
566 }
567
568 $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
569 $commentdataoffset += 4;
570
571 $info['ogg']['vendor'] = substr($commentdata, $commentdataoffset, $VendorSize);
572 $commentdataoffset += $VendorSize;
573
574 $CommentsCount = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
575 $commentdataoffset += 4;
576 $info['avdataoffset'] = $CommentStartOffset + $commentdataoffset;
577
578 $basicfields = array('TITLE', 'ARTIST', 'ALBUM', 'TRACKNUMBER', 'GENRE', 'DATE', 'DESCRIPTION', 'COMMENT');
579 $ThisFileInfo_ogg_comments_raw = &$info['ogg']['comments_raw'];
580 for ($i = 0; $i < $CommentsCount; $i++) {
581
582 if ($i >= 10000) {
583 // https://github.com/owncloud/music/issues/212#issuecomment-43082336
584 $this->warning('Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments');
585 break;
586 }
587
588 $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset;
589
590 if ($this->ftell() < ($ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + 4)) {
591 if ($oggpageinfo = $this->ParseOggPageHeader()) {
592 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
593
594 $VorbisCommentPage++;
595
596 // First, save what we haven't read yet
597 $AsYetUnusedData = substr($commentdata, $commentdataoffset);
598
599 // Then take that data off the end
600 $commentdata = substr($commentdata, 0, $commentdataoffset);
601
602 // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
603 $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
604 $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
605
606 // Finally, stick the unused data back on the end
607 $commentdata .= $AsYetUnusedData;
608
609 //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
610 $commentdata .= $this->fread($this->OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1));
611 }
612
613 }
614 $ThisFileInfo_ogg_comments_raw[$i]['size'] = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
615
616 // replace avdataoffset with position just after the last vorbiscomment
617 $info['avdataoffset'] = $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + $ThisFileInfo_ogg_comments_raw[$i]['size'] + 4;
618
619 $commentdataoffset += 4;
620 while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) {
621 if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) {
622 $this->warning('Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments');
623 break 2;
624 }
625
626 $VorbisCommentPage++;
627
628 $oggpageinfo = $this->ParseOggPageHeader();
629 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
630
631 // First, save what we haven't read yet
632 $AsYetUnusedData = substr($commentdata, $commentdataoffset);
633
634 // Then take that data off the end
635 $commentdata = substr($commentdata, 0, $commentdataoffset);
636
637 // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct
638 $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
639 $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']);
640
641 // Finally, stick the unused data back on the end
642 $commentdata .= $AsYetUnusedData;
643
644 //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
645 if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
646 $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
647 break;
648 }
649 $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1);
650 if ($readlength <= 0) {
651 $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
652 break;
653 }
654 $commentdata .= $this->fread($readlength);
655
656 //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset'];
657 }
658 $ThisFileInfo_ogg_comments_raw[$i]['offset'] = $commentdataoffset;
659 $commentstring = substr($commentdata, $commentdataoffset, $ThisFileInfo_ogg_comments_raw[$i]['size']);
660 $commentdataoffset += $ThisFileInfo_ogg_comments_raw[$i]['size'];
661
662 if (!$commentstring) {
663
664 // no comment?
665 $this->warning('Blank Ogg comment ['.$i.']');
666
667 } elseif (strstr($commentstring, '=')) {
668
669 $commentexploded = explode('=', $commentstring, 2);
670 $ThisFileInfo_ogg_comments_raw[$i]['key'] = strtoupper($commentexploded[0]);
671 $ThisFileInfo_ogg_comments_raw[$i]['value'] = (isset($commentexploded[1]) ? $commentexploded[1] : '');
672
673 if ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'METADATA_BLOCK_PICTURE') {
674
675 // http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
676 // The unencoded format is that of the FLAC picture block. The fields are stored in big endian order as in FLAC, picture data is stored according to the relevant standard.
677 // http://flac.sourceforge.net/format.html#metadata_block_picture
678 $flac = new getid3_flac($this->getid3);
679 $flac->setStringMode(base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']));
680 $flac->parsePICTURE();
681 $info['ogg']['comments']['picture'][] = $flac->getid3->info['flac']['PICTURE'][0];
682 unset($flac);
683
684 } elseif ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'COVERART') {
685
686 $data = base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']);
687 $this->notice('Found deprecated COVERART tag, it should be replaced in honor of METADATA_BLOCK_PICTURE structure');
690 if ($imageinfo === false || !isset($imageinfo['mime'])) {
691 $this->warning('COVERART vorbiscomment tag contains invalid image');
692 continue;
693 }
694
695 $ogg = new self($this->getid3);
696 $ogg->setStringMode($data);
697 $info['ogg']['comments']['picture'][] = array(
698 'image_mime' => $imageinfo['mime'],
699 'datalength' => strlen($data),
700 'picturetype' => 'cover art',
701 'image_height' => $imageinfo['height'],
702 'image_width' => $imageinfo['width'],
703 'data' => $ogg->saveAttachment('coverart', 0, strlen($data), $imageinfo['mime']),
704 );
705 unset($ogg);
706
707 } else {
708
709 $info['ogg']['comments'][strtolower($ThisFileInfo_ogg_comments_raw[$i]['key'])][] = $ThisFileInfo_ogg_comments_raw[$i]['value'];
710
711 }
712
713 } else {
714
715 $this->warning('[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring);
716
717 }
718 unset($ThisFileInfo_ogg_comments_raw[$i]);
719 }
720 unset($ThisFileInfo_ogg_comments_raw);
721
722
723 // Replay Gain Adjustment
724 // http://privatewww.essex.ac.uk/~djmrob/replaygain/
725 if (isset($info['ogg']['comments']) && is_array($info['ogg']['comments'])) {
726 foreach ($info['ogg']['comments'] as $index => $commentvalue) {
727 switch ($index) {
728 case 'rg_audiophile':
729 case 'replaygain_album_gain':
730 $info['replay_gain']['album']['adjustment'] = (double) $commentvalue[0];
731 unset($info['ogg']['comments'][$index]);
732 break;
733
734 case 'rg_radio':
735 case 'replaygain_track_gain':
736 $info['replay_gain']['track']['adjustment'] = (double) $commentvalue[0];
737 unset($info['ogg']['comments'][$index]);
738 break;
739
740 case 'replaygain_album_peak':
741 $info['replay_gain']['album']['peak'] = (double) $commentvalue[0];
742 unset($info['ogg']['comments'][$index]);
743 break;
744
745 case 'rg_peak':
746 case 'replaygain_track_peak':
747 $info['replay_gain']['track']['peak'] = (double) $commentvalue[0];
748 unset($info['ogg']['comments'][$index]);
749 break;
750
751 case 'replaygain_reference_loudness':
752 $info['replay_gain']['reference_volume'] = (double) $commentvalue[0];
753 unset($info['ogg']['comments'][$index]);
754 break;
755
756 default:
757 // do nothing
758 break;
759 }
760 }
761 }
762
763 $this->fseek($OriginalOffset);
764
765 return true;
766 }
notice($text)
Definition: getid3.php:1762
static GetDataImageSize($imgData, &$imageinfo=array())
static OggPageSegmentLength($OggInfoArray, $SegmentNumber=1)
$index
Definition: metadata.php:60

References $data, getid3_handler\$getid3, $i, $index, $info, getid3_handler\fread(), getid3_handler\fseek(), getid3_handler\ftell(), getid3_lib\GetDataImageSize(), getid3_lib\LittleEndian2Int(), getid3_handler\notice(), OggPageSegmentLength(), ParseOggPageHeader(), and getid3_handler\warning().

Referenced by Analyze().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ParseVorbisPageHeader()

getid3_ogg::ParseVorbisPageHeader ( $filedata,
$filedataoffset,
$oggpageinfo 
)

Definition at line 381 of file module.audio.ogg.php.

381 {
382 $info = &$this->getid3->info;
383 $info['audio']['dataformat'] = 'vorbis';
384 $info['audio']['lossless'] = false;
385
386 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
387 $filedataoffset += 1;
388 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, $filedataoffset, 6); // hard-coded to 'vorbis'
389 $filedataoffset += 6;
390 $info['ogg']['bitstreamversion'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
391 $filedataoffset += 4;
392 $info['ogg']['numberofchannels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
393 $filedataoffset += 1;
394 $info['audio']['channels'] = $info['ogg']['numberofchannels'];
395 $info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
396 $filedataoffset += 4;
397 if ($info['ogg']['samplerate'] == 0) {
398 $this->error('Corrupt Ogg file: sample rate == zero');
399 return false;
400 }
401 $info['audio']['sample_rate'] = $info['ogg']['samplerate'];
402 $info['ogg']['samples'] = 0; // filled in later
403 $info['ogg']['bitrate_average'] = 0; // filled in later
404 $info['ogg']['bitrate_max'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
405 $filedataoffset += 4;
406 $info['ogg']['bitrate_nominal'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
407 $filedataoffset += 4;
408 $info['ogg']['bitrate_min'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
409 $filedataoffset += 4;
410 $info['ogg']['blocksize_small'] = pow(2, getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0x0F);
411 $info['ogg']['blocksize_large'] = pow(2, (getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0xF0) >> 4);
412 $info['ogg']['stop_bit'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); // must be 1, marks end of packet
413
414 $info['audio']['bitrate_mode'] = 'vbr'; // overridden if actually abr
415 if ($info['ogg']['bitrate_max'] == 0xFFFFFFFF) {
416 unset($info['ogg']['bitrate_max']);
417 $info['audio']['bitrate_mode'] = 'abr';
418 }
419 if ($info['ogg']['bitrate_nominal'] == 0xFFFFFFFF) {
420 unset($info['ogg']['bitrate_nominal']);
421 }
422 if ($info['ogg']['bitrate_min'] == 0xFFFFFFFF) {
423 unset($info['ogg']['bitrate_min']);
424 $info['audio']['bitrate_mode'] = 'abr';
425 }
426 return true;
427 }

References $info, getid3_handler\error(), and getid3_lib\LittleEndian2Int().

Referenced by Analyze().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SpeexBandModeLookup()

static getid3_ogg::SpeexBandModeLookup (   $mode)
static

Definition at line 768 of file module.audio.ogg.php.

768 {
769 static $SpeexBandModeLookup = array();
770 if (empty($SpeexBandModeLookup)) {
771 $SpeexBandModeLookup[0] = 'narrow';
772 $SpeexBandModeLookup[1] = 'wide';
773 $SpeexBandModeLookup[2] = 'ultra-wide';
774 }
775 return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
776 }

Referenced by Analyze().

+ Here is the caller graph for this function:

◆ TheoraColorSpace()

static getid3_ogg::TheoraColorSpace (   $colorspace_id)
static

Definition at line 816 of file module.audio.ogg.php.

816 {
817 // http://www.theora.org/doc/Theora.pdf (table 6.3)
818 static $TheoraColorSpaceLookup = array();
819 if (empty($TheoraColorSpaceLookup)) {
820 $TheoraColorSpaceLookup[0] = 'Undefined';
821 $TheoraColorSpaceLookup[1] = 'Rec. 470M';
822 $TheoraColorSpaceLookup[2] = 'Rec. 470BG';
823 $TheoraColorSpaceLookup[3] = 'Reserved';
824 }
825 return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
826 }

Referenced by Analyze().

+ Here is the caller graph for this function:

◆ TheoraPixelFormat()

static getid3_ogg::TheoraPixelFormat (   $pixelformat_id)
static

Definition at line 828 of file module.audio.ogg.php.

828 {
829 // http://www.theora.org/doc/Theora.pdf (table 6.4)
830 static $TheoraPixelFormatLookup = array();
831 if (empty($TheoraPixelFormatLookup)) {
832 $TheoraPixelFormatLookup[0] = '4:2:0';
833 $TheoraPixelFormatLookup[1] = 'Reserved';
834 $TheoraPixelFormatLookup[2] = '4:2:2';
835 $TheoraPixelFormatLookup[3] = '4:4:4';
836 }
837 return (isset($TheoraPixelFormatLookup[$pixelformat_id]) ? $TheoraPixelFormatLookup[$pixelformat_id] : null);
838 }

Referenced by Analyze().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following file: