<?php
+
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
-// available at http://getid3.sourceforge.net //
-// or http://www.getid3.org //
-// also https://github.com/JamesHeinrich/getID3 //
-/////////////////////////////////////////////////////////////////
-// See readme.txt for more details //
+// available at https://github.com/JamesHeinrich/getID3 //
+// or https://www.getid3.org //
+// or http://getid3.sourceforge.net //
+// see readme.txt for more details //
/////////////////////////////////////////////////////////////////
// //
// module.audio-video.riff.php //
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
-class getid3_riff extends getid3_handler {
-
+class getid3_riff extends getid3_handler
+{
protected $container = 'riff'; // default
+ /**
+ * @return bool
+ *
+ * @throws getid3_exception
+ */
public function Analyze() {
$info = &$this->getid3->info;
$thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
$thisfile_riff_audio = &$thisfile_riff['audio'];
$thisfile_riff_video = &$thisfile_riff['video'];
+ $thisfile_riff_WAVE = array();
$Original['avdataoffset'] = $info['avdataoffset'];
$Original['avdataend'] = $info['avdataend'];
}
$thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
$thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
+ $thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772);
$thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
'tracktitle'=>'title',
'category' =>'genre',
'cdtitle' =>'album',
- 'tracktitle'=>'title',
);
foreach ($tagmapping as $fromkey => $tokey) {
if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
$thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
$thisfile_video['dataformat'] = 'avi';
+ $thisfile_riff_video_current = array();
+
if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
if (isset($thisfile_riff['AVIX'])) {
// shortcut
$thisfile_riff_video[$streamindex] = array();
+ /** @var array $thisfile_riff_video_current */
$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
}
}
- if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
+ if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
if (self::fourccLookup($thisfile_video['fourcc'])) {
$thisfile_audio_dataformat = '8svx';
$thisfile_audio['bits_per_sample'] = 8;
$thisfile_audio['channels'] = 1; // overridden below, if need be
+ $ActualBitsPerSample = 0;
if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
break;
default:
- $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"');
+ $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"');
break;
}
}
case 'WEBP':
// https://developers.google.com/speed/webp/docs/riff_container
+ // https://tools.ietf.org/html/rfc6386
+ // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
$info['fileformat'] = 'webp';
$info['mime_type'] = 'image/webp';
-$this->error('WebP image parsing not supported in this version of getID3()');
+ if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
+ $old_offset = $this->ftell();
+ $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size
+ $WEBP_VP8_header = $this->fread(10);
+ $this->fseek($old_offset);
+ if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
+ $thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
+ $thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
+ $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
+ $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0;
+
+ $thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
+ $thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
+ $thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
+ $thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
+
+ $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
+ $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
+ } else {
+ $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
+ }
+
+ }
+ if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
+ $old_offset = $this->ftell();
+ $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size
+ $WEBP_VP8L_header = $this->fread(10);
+ $this->fseek($old_offset);
+ if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
+ $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
+ $thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1;
+ $thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1;
+ $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1));
+ $thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3));
+
+ $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
+ $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
+ } else {
+ $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
+ }
+
+ }
break;
default:
return true;
}
+ /**
+ * @param int $startoffset
+ * @param int $maxoffset
+ *
+ * @return array|false
+ *
+ * @throws Exception
+ * @throws getid3_exception
+ */
public function ParseRIFFAMV($startoffset, $maxoffset) {
// AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
return $RIFFchunk;
}
-
+ /**
+ * @param int $startoffset
+ * @param int $maxoffset
+ *
+ * @return array|false
+ * @throws getid3_exception
+ */
public function ParseRIFF($startoffset, $maxoffset) {
$info = &$this->getid3->info;
// break;
default:
- if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
+ if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
unset($RIFFchunk[$chunkname][$thisindex]['offset']);
return $RIFFchunk;
}
+ /**
+ * @param string $RIFFdata
+ *
+ * @return bool
+ */
public function ParseRIFFdata(&$RIFFdata) {
$info = &$this->getid3->info;
if ($RIFFdata) {
return false;
}
+ /**
+ * @param array $RIFFinfoArray
+ * @param array $CommentsTargetArray
+ *
+ * @return bool
+ */
public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
$RIFFinfoKeyLookup = array(
'IARL'=>'archivallocation',
return true;
}
+ /**
+ * @param string $WaveFormatExData
+ *
+ * @return array
+ */
public static function parseWAVEFORMATex($WaveFormatExData) {
// shortcut
+ $WaveFormatEx = array();
$WaveFormatEx['raw'] = array();
$WaveFormatEx_raw = &$WaveFormatEx['raw'];
return $WaveFormatEx;
}
+ /**
+ * @param string $WavPackChunkData
+ *
+ * @return bool
+ */
public function parseWavPackHeader($WavPackChunkData) {
// typedef struct {
// char ckID [4];
return true;
}
+ /**
+ * @param string $BITMAPINFOHEADER
+ * @param bool $littleEndian
+ *
+ * @return array
+ */
public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
$parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
return $parsed;
}
+ /**
+ * @param string $DIVXTAG
+ * @param bool $raw
+ *
+ * @return array
+ */
public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
// structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
// source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
5 => 'NC-17',
);
+ $parsed = array();
$parsed['title'] = trim(substr($DIVXTAG, 0, 32));
$parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
$parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
if (!$raw) {
unset($parsed['genre_id'], $parsed['rating_id']);
foreach ($parsed as $key => $value) {
- if (!$value === '') {
- unset($parsed['key']);
+ if (empty($value)) {
+ unset($parsed[$key]);
}
}
}
return $parsed;
}
+ /**
+ * @param string $tagshortname
+ *
+ * @return string
+ */
public static function waveSNDMtagLookup($tagshortname) {
$begin = __LINE__;
return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
}
+ /**
+ * @param int $wFormatTag
+ *
+ * @return string
+ */
public static function wFormatTagLookup($wFormatTag) {
$begin = __LINE__;
return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
}
+ /**
+ * @param string $fourcc
+ *
+ * @return string
+ */
public static function fourccLookup($fourcc) {
$begin = __LINE__;
return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
}
+ /**
+ * @param string $byteword
+ * @param bool $signed
+ *
+ * @return int|float|false
+ */
private function EitherEndian2Int($byteword, $signed=false) {
if ($this->container == 'riff') {
return getid3_lib::LittleEndian2Int($byteword, $signed);
return getid3_lib::BigEndian2Int($byteword, false, $signed);
}
-}
\ No newline at end of file
+}