* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace FFMpeg\FFProbe\DataMapping; use FFMpeg\Exception\LogicException; use FFMpeg\Exception\RuntimeException; use FFMpeg\Coordinate\Dimension; class Stream extends AbstractData { /** * Returns true if the stream is an audio stream. * * @return Boolean */ public function isAudio() { return $this->has('codec_type') ? 'audio' === $this->get('codec_type') : false; } /** * Returns true if the stream is a video stream. * * @return Boolean */ public function isVideo() { return $this->has('codec_type') ? 'video' === $this->get('codec_type') : false; } /** * Returns the dimension of the video stream. * * @return Dimension * * @throws LogicException In case the stream is not a video stream. * @throws RuntimeException In case the dimensions can not be extracted. */ public function getDimensions() { if (!$this->isVideo()) { throw new LogicException('Dimensions can only be retrieved from video streams.'); } $width = $height = $sampleRatio = $displayRatio = null; if ($this->has('width')) { $width = $this->get('width'); } if ($this->has('height')) { $height = $this->get('height'); } if (null !== $ratio = $this->extractRatio($this, 'sample_aspect_ratio')) { $sampleRatio = $ratio; } if (null !== $ratio = $this->extractRatio($this, 'display_aspect_ratio')) { $displayRatio = $ratio; } if (null === $height || null === $width) { throw new RuntimeException('Unable to extract dimensions.'); } if (null !== $displayRatio && null !== $sampleRatio) { if ($sampleRatio[0] !== 1 && $sampleRatio[1] !== 1) { $width = round($width / $sampleRatio[0] * $sampleRatio[1] * $displayRatio[0] / $displayRatio[1]); } } return new Dimension($width, $height); } /** * Extracts a ratio from a string in a \d+:\d+ format given a key name. * * @param Stream $stream The stream where to look for the ratio. * @param string $name the name of the key. * @return null|array An array containing the width and the height, null if not found. */ private function extractRatio(Stream $stream, $name) { if ($stream->has($name)) { $ratio = $stream->get($name); if (preg_match('/\d+:\d+/', $ratio)) { $data = array_filter(explode(':', $ratio), function ($int) { return $int > 0; }); if (2 === count($data)) { return array_map(function ($int) { return (int) $int; }, $data); } } } return null; } }