24 |
24 |
25 $info['fileformat'] = 'ogg'; |
25 $info['fileformat'] = 'ogg'; |
26 |
26 |
27 // Warn about illegal tags - only vorbiscomments are allowed |
27 // Warn about illegal tags - only vorbiscomments are allowed |
28 if (isset($info['id3v2'])) { |
28 if (isset($info['id3v2'])) { |
29 $info['warning'][] = 'Illegal ID3v2 tag present.'; |
29 $this->warning('Illegal ID3v2 tag present.'); |
30 } |
30 } |
31 if (isset($info['id3v1'])) { |
31 if (isset($info['id3v1'])) { |
32 $info['warning'][] = 'Illegal ID3v1 tag present.'; |
32 $this->warning('Illegal ID3v1 tag present.'); |
33 } |
33 } |
34 if (isset($info['ape'])) { |
34 if (isset($info['ape'])) { |
35 $info['warning'][] = 'Illegal APE tag present.'; |
35 $this->warning('Illegal APE tag present.'); |
36 } |
36 } |
37 |
37 |
38 |
38 |
39 // Page 1 - Stream Header |
39 // Page 1 - Stream Header |
40 |
40 |
42 |
42 |
43 $oggpageinfo = $this->ParseOggPageHeader(); |
43 $oggpageinfo = $this->ParseOggPageHeader(); |
44 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; |
44 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; |
45 |
45 |
46 if ($this->ftell() >= $this->getid3->fread_buffer_size()) { |
46 if ($this->ftell() >= $this->getid3->fread_buffer_size()) { |
47 $info['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?)'; |
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']); |
48 unset($info['fileformat']); |
49 unset($info['ogg']); |
49 unset($info['ogg']); |
50 return false; |
50 return false; |
51 } |
51 } |
52 |
52 |
60 $info['audio']['lossless'] = true; |
60 $info['audio']['lossless'] = true; |
61 |
61 |
62 } elseif (substr($filedata, 1, 6) == 'vorbis') { |
62 } elseif (substr($filedata, 1, 6) == 'vorbis') { |
63 |
63 |
64 $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo); |
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 } |
65 |
71 |
66 } elseif (substr($filedata, 0, 8) == 'Speex ') { |
72 } elseif (substr($filedata, 0, 8) == 'Speex ') { |
67 |
73 |
68 // http://www.speex.org/manual/node10.html |
74 // http://www.speex.org/manual/node10.html |
69 |
75 |
171 $info['video']['frame_rate'] = (float) $info['ogg']['pageheader']['theora']['frame_rate_numerator'] / $info['ogg']['pageheader']['theora']['frame_rate_denominator']; |
177 $info['video']['frame_rate'] = (float) $info['ogg']['pageheader']['theora']['frame_rate_numerator'] / $info['ogg']['pageheader']['theora']['frame_rate_denominator']; |
172 } |
178 } |
173 if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) { |
179 if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) { |
174 $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator']; |
180 $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator']; |
175 } |
181 } |
176 $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable'; |
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'); |
177 |
183 |
178 |
184 |
179 } elseif (substr($filedata, 0, 8) == "fishead\x00") { |
185 } elseif (substr($filedata, 0, 8) == "fishead\x00") { |
180 |
186 |
181 // Ogg Skeleton version 3.0 Format Specification |
187 // Ogg Skeleton version 3.0 Format Specification |
232 $filedataoffset += 3; |
238 $filedataoffset += 3; |
233 |
239 |
234 } elseif (substr($filedata, 1, 6) == 'theora') { |
240 } elseif (substr($filedata, 1, 6) == 'theora') { |
235 |
241 |
236 $info['video']['dataformat'] = 'theora1'; |
242 $info['video']['dataformat'] = 'theora1'; |
237 $info['error'][] = 'Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']'; |
243 $this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']'); |
238 //break; |
244 //break; |
239 |
245 |
240 } elseif (substr($filedata, 1, 6) == 'vorbis') { |
246 } elseif (substr($filedata, 1, 6) == 'vorbis') { |
241 |
247 |
242 $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo); |
248 $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo); |
243 |
249 |
244 } else { |
250 } else { |
245 $info['error'][] = 'unexpected'; |
251 $this->error('unexpected'); |
246 //break; |
252 //break; |
247 } |
253 } |
248 //} while ($oggpageinfo['page_seqno'] == 0); |
254 //} while ($oggpageinfo['page_seqno'] == 0); |
249 } while (($oggpageinfo['page_seqno'] == 0) && (substr($filedata, 0, 8) != "fisbone\x00")); |
255 } while (($oggpageinfo['page_seqno'] == 0) && (substr($filedata, 0, 8) != "fisbone\x00")); |
250 |
256 |
251 $this->fseek($oggpageinfo['page_start_offset']); |
257 $this->fseek($oggpageinfo['page_start_offset']); |
252 |
258 |
253 $info['error'][] = 'Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']'; |
259 $this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']'); |
254 //return false; |
260 //return false; |
255 |
261 |
256 } else { |
262 } else { |
257 |
263 |
258 $info['error'][] = 'Expecting either "Speex " or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"'; |
264 $this->error('Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"'); |
259 unset($info['ogg']); |
265 unset($info['ogg']); |
260 unset($info['mime_type']); |
266 unset($info['mime_type']); |
261 return false; |
267 return false; |
262 |
268 |
263 } |
269 } |
276 break; |
282 break; |
277 |
283 |
278 case 'flac': |
284 case 'flac': |
279 $flac = new getid3_flac($this->getid3); |
285 $flac = new getid3_flac($this->getid3); |
280 if (!$flac->parseMETAdata()) { |
286 if (!$flac->parseMETAdata()) { |
281 $info['error'][] = 'Failed to parse FLAC headers'; |
287 $this->error('Failed to parse FLAC headers'); |
282 return false; |
288 return false; |
283 } |
289 } |
284 unset($flac); |
290 unset($flac); |
285 break; |
291 break; |
286 |
292 |
287 case 'speex': |
293 case 'speex': |
288 $this->fseek($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR); |
294 $this->fseek($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR); |
289 $this->ParseVorbisComments(); |
295 $this->ParseVorbisComments(); |
290 break; |
296 break; |
291 } |
297 |
292 |
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 } |
293 |
310 |
294 // Last Page - Number of Samples |
311 // Last Page - Number of Samples |
295 if (!getid3_lib::intValueSupported($info['avdataend'])) { |
312 if (!getid3_lib::intValueSupported($info['avdataend'])) { |
296 |
313 |
297 $info['warning'][] = 'Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)'; |
314 $this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)'); |
298 |
315 |
299 } else { |
316 } else { |
300 |
317 |
301 $this->fseek(max($info['avdataend'] - $this->getid3->fread_buffer_size(), 0)); |
318 $this->fseek(max($info['avdataend'] - $this->getid3->fread_buffer_size(), 0)); |
302 $LastChunkOfOgg = strrev($this->fread($this->getid3->fread_buffer_size())); |
319 $LastChunkOfOgg = strrev($this->fread($this->getid3->fread_buffer_size())); |
304 $this->fseek($info['avdataend'] - ($LastOggSpostion + strlen('SggO'))); |
321 $this->fseek($info['avdataend'] - ($LastOggSpostion + strlen('SggO'))); |
305 $info['avdataend'] = $this->ftell(); |
322 $info['avdataend'] = $this->ftell(); |
306 $info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader(); |
323 $info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader(); |
307 $info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position']; |
324 $info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position']; |
308 if ($info['ogg']['samples'] == 0) { |
325 if ($info['ogg']['samples'] == 0) { |
309 $info['error'][] = 'Corrupt Ogg file: eos.number of samples == zero'; |
326 $this->error('Corrupt Ogg file: eos.number of samples == zero'); |
310 return false; |
327 return false; |
311 } |
328 } |
312 if (!empty($info['audio']['sample_rate'])) { |
329 if (!empty($info['audio']['sample_rate'])) { |
313 $info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']); |
330 $info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']); |
314 } |
331 } |
323 } elseif (!empty($info['ogg']['bitrate_min']) && !empty($info['ogg']['bitrate_max'])) { |
340 } elseif (!empty($info['ogg']['bitrate_min']) && !empty($info['ogg']['bitrate_max'])) { |
324 $info['audio']['bitrate'] = ($info['ogg']['bitrate_min'] + $info['ogg']['bitrate_max']) / 2; |
341 $info['audio']['bitrate'] = ($info['ogg']['bitrate_min'] + $info['ogg']['bitrate_max']) / 2; |
325 } |
342 } |
326 if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) { |
343 if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) { |
327 if ($info['audio']['bitrate'] == 0) { |
344 if ($info['audio']['bitrate'] == 0) { |
328 $info['error'][] = 'Corrupt Ogg file: bitrate_audio == zero'; |
345 $this->error('Corrupt Ogg file: bitrate_audio == zero'); |
329 return false; |
346 return false; |
330 } |
347 } |
331 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']); |
348 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']); |
332 } |
349 } |
333 |
350 |
376 $filedataoffset += 1; |
393 $filedataoffset += 1; |
377 $info['audio']['channels'] = $info['ogg']['numberofchannels']; |
394 $info['audio']['channels'] = $info['ogg']['numberofchannels']; |
378 $info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); |
395 $info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); |
379 $filedataoffset += 4; |
396 $filedataoffset += 4; |
380 if ($info['ogg']['samplerate'] == 0) { |
397 if ($info['ogg']['samplerate'] == 0) { |
381 $info['error'][] = 'Corrupt Ogg file: sample rate == zero'; |
398 $this->error('Corrupt Ogg file: sample rate == zero'); |
382 return false; |
399 return false; |
383 } |
400 } |
384 $info['audio']['sample_rate'] = $info['ogg']['samplerate']; |
401 $info['audio']['sample_rate'] = $info['ogg']['samplerate']; |
385 $info['ogg']['samples'] = 0; // filled in later |
402 $info['ogg']['samples'] = 0; // filled in later |
386 $info['ogg']['bitrate_average'] = 0; // filled in later |
403 $info['ogg']['bitrate_average'] = 0; // filled in later |
406 unset($info['ogg']['bitrate_min']); |
423 unset($info['ogg']['bitrate_min']); |
407 $info['audio']['bitrate_mode'] = 'abr'; |
424 $info['audio']['bitrate_mode'] = 'abr'; |
408 } |
425 } |
409 return true; |
426 return true; |
410 } |
427 } |
|
428 |
|
429 // http://tools.ietf.org/html/draft-ietf-codec-oggopus-03 |
|
430 public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) { |
|
431 $info = &$this->getid3->info; |
|
432 $info['audio']['dataformat'] = 'opus'; |
|
433 $info['mime_type'] = 'audio/ogg; codecs=opus'; |
|
434 |
|
435 /** @todo find a usable way to detect abr (vbr that is padded to be abr) */ |
|
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 } |
|
478 |
411 |
479 |
412 public function ParseOggPageHeader() { |
480 public function ParseOggPageHeader() { |
413 // http://xiph.org/ogg/vorbis/doc/framing.html |
481 // http://xiph.org/ogg/vorbis/doc/framing.html |
414 $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file |
482 $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file |
415 |
483 |
469 $VorbisCommentPage = 1; |
537 $VorbisCommentPage = 1; |
470 |
538 |
471 switch ($info['audio']['dataformat']) { |
539 switch ($info['audio']['dataformat']) { |
472 case 'vorbis': |
540 case 'vorbis': |
473 case 'speex': |
541 case 'speex': |
|
542 case 'opus': |
474 $CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block |
543 $CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block |
475 $this->fseek($CommentStartOffset); |
544 $this->fseek($CommentStartOffset); |
476 $commentdataoffset = 27 + $info['ogg']['pageheader'][$VorbisCommentPage]['page_segments']; |
545 $commentdataoffset = 27 + $info['ogg']['pageheader'][$VorbisCommentPage]['page_segments']; |
477 $commentdata = $this->fread(self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset); |
546 $commentdata = $this->fread(self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset); |
478 |
547 |
479 if ($info['audio']['dataformat'] == 'vorbis') { |
548 if ($info['audio']['dataformat'] == 'vorbis') { |
480 $commentdataoffset += (strlen('vorbis') + 1); |
549 $commentdataoffset += (strlen('vorbis') + 1); |
481 } |
550 } |
|
551 else if ($info['audio']['dataformat'] == 'opus') { |
|
552 $commentdataoffset += strlen('OpusTags'); |
|
553 } |
|
554 |
482 break; |
555 break; |
483 |
556 |
484 case 'flac': |
557 case 'flac': |
485 $CommentStartOffset = $info['flac']['VORBIS_COMMENT']['raw']['offset'] + 4; |
558 $CommentStartOffset = $info['flac']['VORBIS_COMMENT']['raw']['offset'] + 4; |
486 $this->fseek($CommentStartOffset); |
559 $this->fseek($CommentStartOffset); |
487 $commentdata = $this->fread($info['flac']['VORBIS_COMMENT']['raw']['block_length']); |
560 $commentdata = $this->fread($info['flac']['VORBIS_COMMENT']['raw']['block_length']); |
488 break; |
561 break; |
489 |
562 |
490 default: |
563 default: |
491 return false; |
564 return false; |
|
565 break; |
492 } |
566 } |
493 |
567 |
494 $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4)); |
568 $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4)); |
495 $commentdataoffset += 4; |
569 $commentdataoffset += 4; |
496 |
570 |
503 |
577 |
504 $basicfields = array('TITLE', 'ARTIST', 'ALBUM', 'TRACKNUMBER', 'GENRE', 'DATE', 'DESCRIPTION', 'COMMENT'); |
578 $basicfields = array('TITLE', 'ARTIST', 'ALBUM', 'TRACKNUMBER', 'GENRE', 'DATE', 'DESCRIPTION', 'COMMENT'); |
505 $ThisFileInfo_ogg_comments_raw = &$info['ogg']['comments_raw']; |
579 $ThisFileInfo_ogg_comments_raw = &$info['ogg']['comments_raw']; |
506 for ($i = 0; $i < $CommentsCount; $i++) { |
580 for ($i = 0; $i < $CommentsCount; $i++) { |
507 |
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 |
508 $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset; |
588 $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset; |
509 |
589 |
510 if ($this->ftell() < ($ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + 4)) { |
590 if ($this->ftell() < ($ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + 4)) { |
511 if ($oggpageinfo = $this->ParseOggPageHeader()) { |
591 if ($oggpageinfo = $this->ParseOggPageHeader()) { |
512 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; |
592 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; |
537 $info['avdataoffset'] = $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + $ThisFileInfo_ogg_comments_raw[$i]['size'] + 4; |
617 $info['avdataoffset'] = $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + $ThisFileInfo_ogg_comments_raw[$i]['size'] + 4; |
538 |
618 |
539 $commentdataoffset += 4; |
619 $commentdataoffset += 4; |
540 while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) { |
620 while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) { |
541 if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) { |
621 if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) { |
542 $info['warning'][] = 'Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments'; |
622 $this->warning('Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments'); |
543 break 2; |
623 break 2; |
544 } |
624 } |
545 |
625 |
546 $VorbisCommentPage++; |
626 $VorbisCommentPage++; |
547 |
627 |
561 // Finally, stick the unused data back on the end |
641 // Finally, stick the unused data back on the end |
562 $commentdata .= $AsYetUnusedData; |
642 $commentdata .= $AsYetUnusedData; |
563 |
643 |
564 //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); |
644 //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); |
565 if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { |
645 if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { |
566 $info['warning'][] = 'undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell(); |
646 $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); |
567 break; |
647 break; |
568 } |
648 } |
569 $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); |
649 $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); |
570 if ($readlength <= 0) { |
650 if ($readlength <= 0) { |
571 $info['warning'][] = 'invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell(); |
651 $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); |
572 break; |
652 break; |
573 } |
653 } |
574 $commentdata .= $this->fread($readlength); |
654 $commentdata .= $this->fread($readlength); |
575 |
655 |
576 //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset']; |
656 //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset']; |
580 $commentdataoffset += $ThisFileInfo_ogg_comments_raw[$i]['size']; |
660 $commentdataoffset += $ThisFileInfo_ogg_comments_raw[$i]['size']; |
581 |
661 |
582 if (!$commentstring) { |
662 if (!$commentstring) { |
583 |
663 |
584 // no comment? |
664 // no comment? |
585 $info['warning'][] = 'Blank Ogg comment ['.$i.']'; |
665 $this->warning('Blank Ogg comment ['.$i.']'); |
586 |
666 |
587 } elseif (strstr($commentstring, '=')) { |
667 } elseif (strstr($commentstring, '=')) { |
588 |
668 |
589 $commentexploded = explode('=', $commentstring, 2); |
669 $commentexploded = explode('=', $commentstring, 2); |
590 $ThisFileInfo_ogg_comments_raw[$i]['key'] = strtoupper($commentexploded[0]); |
670 $ThisFileInfo_ogg_comments_raw[$i]['key'] = strtoupper($commentexploded[0]); |
613 } |
693 } |
614 |
694 |
615 $ogg = new self($this->getid3); |
695 $ogg = new self($this->getid3); |
616 $ogg->setStringMode($data); |
696 $ogg->setStringMode($data); |
617 $info['ogg']['comments']['picture'][] = array( |
697 $info['ogg']['comments']['picture'][] = array( |
618 'image_mime' => $imageinfo['mime'], |
698 'image_mime' => $imageinfo['mime'], |
619 'data' => $ogg->saveAttachment('coverart', 0, strlen($data), $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']), |
620 ); |
704 ); |
621 unset($ogg); |
705 unset($ogg); |
622 |
706 |
623 } else { |
707 } else { |
624 |
708 |