diff --git a/CHANGELOG.md b/CHANGELOG.md index 26d9950..9d3e74e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ CHANGELOG --------- -* 0.4.2 (xx-xx-xx) +* 0.4.3 (11-xx-2013) + + * Fix using rotate and resize filters at the same time (#78) + +* 0.4.2 (11-29-2013) * Add Rotate filter. * Remove time_start metadata when using synchronize filter diff --git a/src/FFMpeg/FFProbe/DataMapping/AbstractData.php b/src/FFMpeg/FFProbe/DataMapping/AbstractData.php index d35e2b6..63134b2 100644 --- a/src/FFMpeg/FFProbe/DataMapping/AbstractData.php +++ b/src/FFMpeg/FFProbe/DataMapping/AbstractData.php @@ -50,6 +50,21 @@ abstract class AbstractData implements \Countable return $this->properties[$property]; } + /** + * Sets the property value given its name. + * + * @param string $property + * @param mixed $value + * + * @return AbstractData + */ + public function set($property, $value) + { + $this->properties[$property] = $value; + + return $this; + } + /** * Returns all property names. * diff --git a/src/FFMpeg/Filters/Video/RotateFilter.php b/src/FFMpeg/Filters/Video/RotateFilter.php index 95da3ad..5902a54 100644 --- a/src/FFMpeg/Filters/Video/RotateFilter.php +++ b/src/FFMpeg/Filters/Video/RotateFilter.php @@ -55,6 +55,16 @@ class RotateFilter implements VideoFilterInterface */ public function apply(Video $video, VideoInterface $format) { + if (in_array($this->angle, array(self::ROTATE_90, self::ROTATE_270), true)) { + foreach ($video->getStreams()->videos() as $stream) { + if ($stream->has('width') && $stream->has('height')) { + $width = $stream->get('width'); + $stream->set('width', $stream->get('height')); + $stream->set('height', $width); + } + } + } + return array('-vf', $this->angle, '-metadata:s:v:0', 'rotate=0'); } diff --git a/src/FFMpeg/Filters/Video/VideoFilters.php b/src/FFMpeg/Filters/Video/VideoFilters.php index a9faacb..30b4b2a 100644 --- a/src/FFMpeg/Filters/Video/VideoFilters.php +++ b/src/FFMpeg/Filters/Video/VideoFilters.php @@ -96,9 +96,9 @@ class VideoFilters extends AudioFilters return $this; } - public function rotate($angle, $priority = 0) + public function rotate($angle) { - $this->media->addFilter(new RotateFilter($angle, $priority)); + $this->media->addFilter(new RotateFilter($angle, 30)); return $this; } diff --git a/src/FFMpeg/Media/AbstractStreamableMedia.php b/src/FFMpeg/Media/AbstractStreamableMedia.php index 5458015..e09bba0 100644 --- a/src/FFMpeg/Media/AbstractStreamableMedia.php +++ b/src/FFMpeg/Media/AbstractStreamableMedia.php @@ -16,12 +16,18 @@ use FFMpeg\FFProbe\DataMapping\StreamCollection; abstract class AbstractStreamableMedia extends AbstractMediaType { + private $streams; + /** * @return StreamCollection */ public function getStreams() { - return $this->ffprobe->streams($this->pathfile); + if (null === $this->streams) { + $this->streams = $this->ffprobe->streams($this->pathfile); + } + + return $this->streams; } /** diff --git a/tests/FFMpeg/Functional/VideoTranscodeTest.php b/tests/FFMpeg/Functional/VideoTranscodeTest.php index 38e230e..bcc714c 100644 --- a/tests/FFMpeg/Functional/VideoTranscodeTest.php +++ b/tests/FFMpeg/Functional/VideoTranscodeTest.php @@ -2,6 +2,9 @@ namespace FFMpeg\Functional; +use FFMpeg\Coordinate\Dimension; +use FFMpeg\Filters\Video\ResizeFilter; +use FFMpeg\Filters\Video\RotateFilter; use FFMpeg\Format\Video\X264; use FFMpeg\Media\Video; @@ -54,4 +57,32 @@ class VideoTranscodeTest extends FunctionalTestCase $this->setExpectedException('FFMpeg\Exception\RuntimeException'); $video->save(new X264('libvo_aacenc'), __DIR__ . '/output/output-x264.mp4'); } + + public function testTranscodePortraitVideo() + { + $filename = __DIR__ . '/output/output-x264.mp4'; + if (is_file($filename)) { + unlink(__DIR__ . '/output/output-x264.mp4'); + } + + $ffmpeg = $this->getFFMpeg(); + $video = $ffmpeg->open(__DIR__ . '/../../files/portrait.MOV'); + + $video->filters() + ->resize(new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET) + ->rotate(RotateFilter::ROTATE_90); + $video->save(new X264('libvo_aacenc'), $filename); + + $dimension = $ffmpeg->getFFProbe() + ->streams($filename) + ->videos() + ->first() + ->getDimensions(); + + $this->assertLessThan(1, $dimension->getRatio(false)->getValue()); + $this->assertEquals(240, $dimension->getHeight()); + + $this->assertFileExists($filename); + unlink($filename); + } } diff --git a/tests/FFMpeg/Tests/Filters/Video/RotateFilterTest.php b/tests/FFMpeg/Tests/Filters/Video/RotateFilterTest.php index 103b313..95c676f 100644 --- a/tests/FFMpeg/Tests/Filters/Video/RotateFilterTest.php +++ b/tests/FFMpeg/Tests/Filters/Video/RotateFilterTest.php @@ -2,18 +2,63 @@ namespace FFMpeg\Tests\Filters\Video; +use FFMpeg\FFProbe\DataMapping\Stream; +use FFMpeg\FFProbe\DataMapping\StreamCollection; use FFMpeg\Filters\Video\RotateFilter; use FFMpeg\Tests\TestCase; class RotateFilterTest extends TestCase { - public function testApply() + /** + * @dataProvider provide90degresTranspositions + */ + public function testApplyWithSizeTransformation($value) { + $stream = new Stream(array('width' => 320, 'height' => 240, 'codec_type' => 'video')); + $streams = new StreamCollection(array($stream)); + $video = $this->getVideoMock(); + $video->expects($this->once()) + ->method('getStreams') + ->will($this->returnValue($streams)); + $format = $this->getMock('FFMpeg\Format\VideoInterface'); - $filter = new RotateFilter(RotateFilter::ROTATE_90); - $this->assertEquals(array('-vf', RotateFilter::ROTATE_90, '-metadata:s:v:0', 'rotate=0'), $filter->apply($video, $format)); + $filter = new RotateFilter($value); + $this->assertEquals(array('-vf', $value, '-metadata:s:v:0', 'rotate=0'), $filter->apply($video, $format)); + + $this->assertEquals(240, $stream->get('width')); + $this->assertEquals(320, $stream->get('height')); + } + + public function provide90degresTranspositions() + { + return array( + array(RotateFilter::ROTATE_90), + array(RotateFilter::ROTATE_270), + ); + } + + /** + * @dataProvider provideDegresWithoutTranspositions + */ + public function testApplyWithoutSizeTransformation($value) + { + $video = $this->getVideoMock(); + $video->expects($this->never()) + ->method('getStreams'); + + $format = $this->getMock('FFMpeg\Format\VideoInterface'); + + $filter = new RotateFilter($value); + $this->assertEquals(array('-vf', $value, '-metadata:s:v:0', 'rotate=0'), $filter->apply($video, $format)); + } + + public function provideDegresWithoutTranspositions() + { + return array( + array(RotateFilter::ROTATE_180), + ); } /** diff --git a/tests/files/portrait.MOV b/tests/files/portrait.MOV new file mode 100644 index 0000000..4d31edc Binary files /dev/null and b/tests/files/portrait.MOV differ