Example #1
0
 /**
  * @param  type    $BlockData
  *
  * @return bool
  */
 private function parseVORBIS_COMMENT($BlockData)
 {
     $info =& $this->getid3->info;
     $getid3_ogg = new Ogg($this->getid3);
     if ($this->isDependencyFor('matroska')) {
         $getid3_ogg->data_string_flag = true;
         $getid3_ogg->data_string = $this->data_string;
     }
     $getid3_ogg->ParseVorbisComments();
     if (isset($info['ogg'])) {
         unset($info['ogg']['comments_raw']);
         $info['flac']['VORBIS_COMMENT'] = $info['ogg'];
         unset($info['ogg']);
     }
     unset($getid3_ogg);
     return true;
 }
Example #2
0
 /**
  * @return bool
  */
 public function analyze()
 {
     $info =& $this->getid3->info;
     // parse container
     try {
         $this->parseEBML($info);
     } catch (DefaultException $e) {
         $info['error'][] = 'EBML parser: ' . $e->getMessage();
     }
     // calculate playtime
     if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) {
         foreach ($info['matroska']['info'] as $key => $infoarray) {
             if (isset($infoarray['Duration'])) {
                 // TimecodeScale is how many nanoseconds each Duration unit is
                 $info['playtime_seconds'] = $infoarray['Duration'] * ((isset($infoarray['TimecodeScale']) ? $infoarray['TimecodeScale'] : 1000000) / 1000000000);
                 break;
             }
         }
     }
     // extract tags
     if (isset($info['matroska']['tags']) && is_array($info['matroska']['tags'])) {
         foreach ($info['matroska']['tags'] as $key => $infoarray) {
             $this->ExtractCommentsSimpleTag($infoarray);
         }
     }
     // process tracks
     if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) {
         foreach ($info['matroska']['tracks']['tracks'] as $key => $trackarray) {
             $track_info = array();
             $track_info['dataformat'] = self::MatroskaCodecIDtoCommonName($trackarray['CodecID']);
             $track_info['default'] = isset($trackarray['FlagDefault']) ? $trackarray['FlagDefault'] : true;
             if (isset($trackarray['Name'])) {
                 $track_info['name'] = $trackarray['Name'];
             }
             switch ($trackarray['TrackType']) {
                 case 1:
                     // Video
                     $track_info['resolution_x'] = $trackarray['PixelWidth'];
                     $track_info['resolution_y'] = $trackarray['PixelHeight'];
                     if (isset($trackarray['DisplayWidth'])) {
                         $track_info['display_x'] = $trackarray['DisplayWidth'];
                     }
                     if (isset($trackarray['DisplayHeight'])) {
                         $track_info['display_y'] = $trackarray['DisplayHeight'];
                     }
                     if (isset($trackarray['DefaultDuration'])) {
                         $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3);
                     }
                     if (isset($trackarray['CodecName'])) {
                         $track_info['codec'] = $trackarray['CodecName'];
                     }
                     switch ($trackarray['CodecID']) {
                         case 'V_MS/VFW/FOURCC':
                             if (!class_exists('GetId3\\Module\\AudioVideo\\Riff')) {
                                 $this->getid3->warning('Unable to parse codec private data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "' . str_replace('_', DIRECTORY_SEPARATOR, 'GetId3\\Module\\AudioVideo\\Riff') . '.php"');
                                 break;
                             }
                             $parsed = Riff::ParseBITMAPINFOHEADER($trackarray['CodecPrivate']);
                             $track_info['codec'] = Riff::RIFFfourccLookup($parsed['fourcc']);
                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
                             break;
                             /*case 'V_MPEG4/ISO/AVC':
                               $h264['profile']    = GetId3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 1, 1));
                               $h264['level']      = GetId3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 3, 1));
                               $rn                 = GetId3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 4, 1));
                               $h264['NALUlength'] = ($rn & 3) + 1;
                               $rn                 = GetId3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 5, 1));
                               $nsps               = ($rn & 31);
                               $offset             = 6;
                               for ($i = 0; $i < $nsps; $i ++) {
                                   $length        = GetId3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2));
                                   $h264['SPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length);
                                   $offset       += 2 + $length;
                               }
                               $npps               = GetId3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 1));
                               $offset            += 1;
                               for ($i = 0; $i < $npps; $i ++) {
                                   $length        = GetId3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2));
                                   $h264['PPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length);
                                   $offset       += 2 + $length;
                               }
                               $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $h264;
                               break;*/
                     }
                     $info['video']['streams'][] = $track_info;
                     break;
                 case 2:
                     // Audio
                     $track_info['sample_rate'] = isset($trackarray['SamplingFrequency']) ? $trackarray['SamplingFrequency'] : 8000.0;
                     $track_info['channels'] = isset($trackarray['Channels']) ? $trackarray['Channels'] : 1;
                     $track_info['language'] = isset($trackarray['Language']) ? $trackarray['Language'] : 'eng';
                     if (isset($trackarray['BitDepth'])) {
                         $track_info['bits_per_sample'] = $trackarray['BitDepth'];
                     }
                     if (isset($trackarray['CodecName'])) {
                         $track_info['codec'] = $trackarray['CodecName'];
                     }
                     switch ($trackarray['CodecID']) {
                         case 'A_PCM/INT/LIT':
                         case 'A_PCM/INT/BIG':
                             $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth'];
                             break;
                         case 'A_AC3':
                         case 'A_DTS':
                         case 'A_MPEG/L3':
                         case 'A_MPEG/L2':
                         case 'A_FLAC':
                             $class = 'Helpers\\GetId3\\Module\\Audio\\' . ucfirst($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']);
                             if (!class_exists($class)) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.' . $track_info['dataformat'] . '.php"');
                                 break;
                             }
                             if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because $info[matroska][track_data_offsets][' . $trackarray['TrackNumber'] . '] not set');
                                 break;
                             }
                             // create temp instance
                             $getid3_temp = new GetId3Core();
                             if ($track_info['dataformat'] != 'flac') {
                                 $getid3_temp->openfile($this->getid3->filename);
                             }
                             $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                             if ($track_info['dataformat'][0] == 'm' || $track_info['dataformat'] == 'flac') {
                                 $getid3_temp->info['avdataend'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'] + $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['length'];
                             }
                             // analyze
                             $header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
                             $getid3_audio = new $class($getid3_temp, __CLASS__);
                             if ($track_info['dataformat'] == 'flac') {
                                 $getid3_audio->AnalyzeString($trackarray['CodecPrivate']);
                             } else {
                                 $getid3_audio->analyze();
                             }
                             if (!empty($getid3_temp->info[$header_data_key])) {
                                 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
                                 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                     foreach ($getid3_temp->info['audio'] as $key => $value) {
                                         $track_info[$key] = $value;
                                     }
                                 }
                             } else {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because ' . $class . '::Analyze() failed at offset ' . $getid3_temp->info['avdataoffset']);
                             }
                             // copy errors and warnings
                             if (!empty($getid3_temp->info['error'])) {
                                 foreach ($getid3_temp->info['error'] as $newerror) {
                                     $this->getid3->warning($class . '() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['warning'])) {
                                 foreach ($getid3_temp->info['warning'] as $newerror) {
                                     if ($track_info['dataformat'] == 'mp3' && preg_match('/^Probable truncated file: expecting \\d+ bytes of audio data, only found \\d+ \\(short by \\d+ bytes\\)$/', $newerror)) {
                                         // LAME/Xing header is probably set, but audio data is chunked into Matroska file and near-impossible to verify if audio stream is complete, so ignore useless warning
                                         continue;
                                     }
                                     $this->getid3->warning($class . '() says: [' . $newerror . ']');
                                 }
                             }
                             unset($getid3_temp, $getid3_audio);
                             break;
                         case 'A_AAC':
                         case 'A_AAC/MPEG2/LC':
                         case 'A_AAC/MPEG4/LC':
                         case 'A_AAC/MPEG4/LC/SBR':
                             $this->getid3->warning($trackarray['CodecID'] . ' audio data contains no header, audio/video bitrates can\'t be calculated');
                             break;
                         case 'A_VORBIS':
                             if (!isset($trackarray['CodecPrivate'])) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because CodecPrivate data not set');
                                 break;
                             }
                             $vorbis_offset = strpos($trackarray['CodecPrivate'], 'vorbis', 1);
                             if ($vorbis_offset === false) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because CodecPrivate data does not contain "vorbis" keyword');
                                 break;
                             }
                             $vorbis_offset -= 1;
                             if (!class_exists('Helpers\\GetId3\\Module\\Audio\\Ogg')) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "Helpers\\GetId3\\Module\\Audio\\Ogg.php"');
                                 break;
                             }
                             // create temp instance
                             $getid3_temp = new GetId3Core();
                             // analyze
                             $getid3_ogg = new Ogg($getid3_temp);
                             $oggpageinfo['page_seqno'] = 0;
                             $getid3_ogg->ParseVorbisPageHeader($trackarray['CodecPrivate'], $vorbis_offset, $oggpageinfo);
                             if (!empty($getid3_temp->info['ogg'])) {
                                 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
                                 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                     foreach ($getid3_temp->info['audio'] as $key => $value) {
                                         $track_info[$key] = $value;
                                     }
                                 }
                             }
                             // copy errors and warnings
                             if (!empty($getid3_temp->info['error'])) {
                                 foreach ($getid3_temp->info['error'] as $newerror) {
                                     $this->getid3->warning('getid3_ogg() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['warning'])) {
                                 foreach ($getid3_temp->info['warning'] as $newerror) {
                                     $this->getid3->warning('getid3_ogg() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['ogg']['bitrate_nominal'])) {
                                 $track_info['bitrate'] = $getid3_temp->info['ogg']['bitrate_nominal'];
                             }
                             unset($getid3_temp, $getid3_ogg, $oggpageinfo, $vorbis_offset);
                             break;
                         case 'A_MS/ACM':
                             if (!class_exists('GetId3\\Module\\AudioVideo\\Riff')) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "' . str_replace('_', DIRECTORY_SEPARATOR, 'GetId3\\Module\\AudioVideo\\Riff') . '.php"');
                                 break;
                             }
                             $parsed = Riff::RIFFparseWAVEFORMATex($trackarray['CodecPrivate']);
                             foreach ($parsed as $key => $value) {
                                 if ($key != 'raw') {
                                     $track_info[$key] = $value;
                                 }
                             }
                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
                             break;
                         default:
                             $this->getid3->warning('Unhandled audio type "' . (isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '') . '"');
                     }
                     $info['audio']['streams'][] = $track_info;
                     break;
             }
         }
         if (!empty($info['video']['streams'])) {
             $info['video'] = self::getDefaultStreamInfo($info['video']['streams']);
         }
         if (!empty($info['audio']['streams'])) {
             $info['audio'] = self::getDefaultStreamInfo($info['audio']['streams']);
         }
     }
     // determine mime type
     if (!empty($info['video']['streams'])) {
         $info['mime_type'] = $info['matroska']['doctype'] == 'webm' ? 'video/webm' : 'video/x-matroska';
     } elseif (!empty($info['audio']['streams'])) {
         $info['mime_type'] = $info['matroska']['doctype'] == 'webm' ? 'audio/webm' : 'audio/x-matroska';
     } elseif (isset($info['mime_type'])) {
         unset($info['mime_type']);
     }
     return true;
 }