diff --git a/src/FFMpeg/Filters/Audio/AudioResamplableFilter.php b/src/FFMpeg/Filters/Audio/AudioResamplableFilter.php index 2a25d57..5a6bfba 100644 --- a/src/FFMpeg/Filters/Audio/AudioResamplableFilter.php +++ b/src/FFMpeg/Filters/Audio/AudioResamplableFilter.php @@ -18,10 +18,21 @@ class AudioResamplableFilter implements AudioFilterInterface { /** @var string */ private $rate; + /** @var integer */ + private $priority; - public function __construct($rate) + public function __construct($rate, $priority = 0) { $this->rate = $rate; + $this->priority = $priority; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; } /** diff --git a/src/FFMpeg/Filters/Audio/SimpleFilter.php b/src/FFMpeg/Filters/Audio/SimpleFilter.php new file mode 100644 index 0000000..69a9e73 --- /dev/null +++ b/src/FFMpeg/Filters/Audio/SimpleFilter.php @@ -0,0 +1,34 @@ +params = $params; + $this->priority = $priority; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; + } + + /** + * {@inheritdoc} + */ + public function apply(Audio $audio, AudioInterface $format) + { + return $this->params; + } +} diff --git a/src/FFMpeg/Filters/FilterInterface.php b/src/FFMpeg/Filters/FilterInterface.php index 4939fb5..cb41d51 100644 --- a/src/FFMpeg/Filters/FilterInterface.php +++ b/src/FFMpeg/Filters/FilterInterface.php @@ -13,4 +13,10 @@ namespace FFMpeg\Filters; interface FilterInterface { + /** + * Returns the priority of the filter. + * + * @return integer + */ + public function getPriority(); } diff --git a/src/FFMpeg/Filters/FiltersCollection.php b/src/FFMpeg/Filters/FiltersCollection.php index 43a856b..d44a880 100644 --- a/src/FFMpeg/Filters/FiltersCollection.php +++ b/src/FFMpeg/Filters/FiltersCollection.php @@ -13,6 +13,7 @@ namespace FFMpeg\Filters; class FiltersCollection implements \Countable, \IteratorAggregate { + private $sorted; private $filters = array(); /** @@ -22,7 +23,8 @@ class FiltersCollection implements \Countable, \IteratorAggregate */ public function add(FilterInterface $filter) { - $this->filters[] = $filter; + $this->filters[$filter->getPriority()][] = $filter; + $this->sorted = null; return $this; } @@ -32,7 +34,11 @@ class FiltersCollection implements \Countable, \IteratorAggregate */ public function count() { - return count($this->filters); + if (0 === count($this->filters)) { + return 0; + } + + return count(call_user_func_array('array_merge', $this->filters)); } /** @@ -40,6 +46,11 @@ class FiltersCollection implements \Countable, \IteratorAggregate */ public function getIterator() { - return new \ArrayIterator($this->filters); + if (null === $this->sorted) { + krsort($this->filters); + $this->sorted = call_user_func_array('array_merge', $this->filters); + } + + return new \ArrayIterator($this->sorted); } } diff --git a/src/FFMpeg/Filters/Video/ResizeFilter.php b/src/FFMpeg/Filters/Video/ResizeFilter.php index c183d57..e483b0c 100644 --- a/src/FFMpeg/Filters/Video/ResizeFilter.php +++ b/src/FFMpeg/Filters/Video/ResizeFilter.php @@ -28,12 +28,23 @@ class ResizeFilter implements VideoFilterInterface private $mode; /** @var Boolean */ private $forceStandards; + /** @var integer */ + private $priority; - public function __construct(Dimension $dimension, $mode = self::RESIZEMODE_FIT, $forceStandards = true) + public function __construct(Dimension $dimension, $mode = self::RESIZEMODE_FIT, $forceStandards = true, $priority = 0) { $this->dimension = $dimension; $this->mode = $mode; $this->forceStandards = $forceStandards; + $this->priority = $priority; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; } /** diff --git a/src/FFMpeg/Filters/Video/SynchronizeFilter.php b/src/FFMpeg/Filters/Video/SynchronizeFilter.php index 748a191..2863d87 100644 --- a/src/FFMpeg/Filters/Video/SynchronizeFilter.php +++ b/src/FFMpeg/Filters/Video/SynchronizeFilter.php @@ -19,6 +19,21 @@ use FFMpeg\Media\Video; */ class SynchronizeFilter implements VideoFilterInterface { + private $priority; + + public function __construct($priority = 12) + { + $this->priority = $priority; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; + } + /** * {@inheritdoc} */ diff --git a/src/FFMpeg/Filters/Video/VideoResampleFilter.php b/src/FFMpeg/Filters/Video/VideoResampleFilter.php index b27e9dd..a2213e4 100644 --- a/src/FFMpeg/Filters/Video/VideoResampleFilter.php +++ b/src/FFMpeg/Filters/Video/VideoResampleFilter.php @@ -19,11 +19,21 @@ class VideoResampleFilter implements VideoFilterInterface { private $rate; private $gop; + private $priority; - public function __construct(FrameRate $rate, $gop) + public function __construct(FrameRate $rate, $gop, $priority = 0) { $this->rate = $rate; $this->gop = $gop; + $this->priority = $priority; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; } /** diff --git a/src/FFMpeg/Media/Audio.php b/src/FFMpeg/Media/Audio.php index 961c6b0..756ad21 100644 --- a/src/FFMpeg/Media/Audio.php +++ b/src/FFMpeg/Media/Audio.php @@ -14,6 +14,7 @@ namespace FFMpeg\Media; use Alchemy\BinaryDriver\Exception\ExecutionFailureException; use FFMpeg\Filters\Audio\AudioFilters; use FFMpeg\Format\FormatInterface; +use FFMpeg\Filters\Audio\SimpleFilter; use FFMpeg\Exception\RuntimeException; use FFMpeg\Exception\InvalidArgumentException; use FFMpeg\Filters\Audio\AudioFilterInterface; @@ -66,22 +67,21 @@ class Audio extends AbstractStreamableMedia $listeners = $format->createProgressListener($this, $this->ffprobe, 1, 1); } - $commands = array_merge(array('-y', '-i', $this->pathfile), $format->getExtraParams()); + $commands = array('-y', '-i', $this->pathfile); + + $this->addFilter(new SimpleFilter($format->getExtraParams(), 10)); + + if ($this->driver->getConfiguration()->has('ffmpeg.threads')) { + $this->addFilter(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads')))); + } + if (null !== $format->getAudioCodec()) { + $this->addFilter(new SimpleFilter(array('-acodec', $format->getAudioCodec()))); + } foreach ($this->filters as $filter) { $commands = array_merge($commands, $filter->apply($this, $format)); } - if ($this->driver->getConfiguration()->has('ffmpeg.threads')) { - $commands[] = '-threads'; - $commands[] = $this->driver->getConfiguration()->get('ffmpeg.threads'); - } - - if (null !== $format->getAudioCodec()) { - $commands[] = '-acodec'; - $commands[] = $format->getAudioCodec(); - } - $commands[] = '-b:a'; $commands[] = $format->getAudioKiloBitrate() . 'k'; $commands[] = $outputPathfile; diff --git a/src/FFMpeg/Media/Video.php b/src/FFMpeg/Media/Video.php index f98d0f2..f9c3884 100644 --- a/src/FFMpeg/Media/Video.php +++ b/src/FFMpeg/Media/Video.php @@ -13,6 +13,7 @@ namespace FFMpeg\Media; use Alchemy\BinaryDriver\Exception\ExecutionFailureException; use FFMpeg\Coordinate\TimeCode; +use FFMpeg\Filters\Audio\SimpleFilter; use FFMpeg\Exception\RuntimeException; use FFMpeg\Filters\Video\VideoFilters; use FFMpeg\Filters\FilterInterface; @@ -56,26 +57,24 @@ class Video extends Audio */ public function save(FormatInterface $format, $outputPathfile) { - $commands = array_merge(array('-y', '-i', $this->pathfile), $format->getExtraParams()); + $commands = array('-y', '-i', $this->pathfile); + + $this->addFilter(new SimpleFilter($format->getExtraParams(), 10)); + + if ($this->driver->getConfiguration()->has('ffmpeg.threads')) { + $this->addFilter(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads')))); + } + if (null !== $format->getVideoCodec()) { + $this->addFilter(new SimpleFilter(array('-vcodec', $format->getVideoCodec()))); + } + if (null !== $format->getAudioCodec()) { + $this->addFilter(new SimpleFilter(array('-acodec', $format->getAudioCodec()))); + } foreach ($this->filters as $filter) { $commands = array_merge($commands, $filter->apply($this, $format)); } - if ($this->driver->getConfiguration()->has('ffmpeg.threads')) { - $commands[] = '-threads'; - $commands[] = $this->driver->getConfiguration()->get('ffmpeg.threads'); - } - - if (null !== $format->getVideoCodec()) { - $commands[] = '-vcodec'; - $commands[] = $format->getVideoCodec(); - } - if (null !== $format->getAudioCodec()) { - $commands[] = '-acodec'; - $commands[] = $format->getAudioCodec(); - } - $commands[] = '-b:v'; $commands[] = $format->getKiloBitrate() . 'k'; $commands[] = '-refs'; diff --git a/tests/FFMpeg/Tests/Filters/FiltersCollectionTest.php b/tests/FFMpeg/Tests/Filters/FiltersCollectionTest.php index 6ac820e..52a1395 100644 --- a/tests/FFMpeg/Tests/Filters/FiltersCollectionTest.php +++ b/tests/FFMpeg/Tests/Filters/FiltersCollectionTest.php @@ -3,8 +3,10 @@ namespace FFMpeg\Tests\Filters; use FFMpeg\Filters\FiltersCollection; +use FFMpeg\Filters\Audio\SimpleFilter; +use FFMpeg\Tests\TestCase; -class FiltersCollectionTest extends \PHPUnit_Framework_TestCase +class FiltersCollectionTest extends TestCase { public function testCount() { @@ -27,4 +29,28 @@ class FiltersCollectionTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('\ArrayIterator', $coll->getIterator()); $this->assertCount(2, $coll->getIterator()); } + + public function testIteratorSort() + { + $coll = new FiltersCollection(); + $coll->add(new SimpleFilter(array('a'))); + $coll->add(new SimpleFilter(array('1'), 12)); + $coll->add(new SimpleFilter(array('b'))); + $coll->add(new SimpleFilter(array('2'), 12)); + $coll->add(new SimpleFilter(array('c'))); + $coll->add(new SimpleFilter(array('3'), 10)); + $coll->add(new SimpleFilter(array('d'))); + $coll->add(new SimpleFilter(array('4'), -2)); + $coll->add(new SimpleFilter(array('e'))); + + $data = array(); + $video = $this->getVideoMock(); + $format = $this->getMock('FFMpeg\Format\AudioInterface'); + + foreach ($coll as $filter) { + $data = array_merge($data, $filter->apply($video, $format)); + } + + $this->assertEquals(array('1', '2', '3', 'a', 'b', 'c', 'd', 'e', '4'), $data); + } }