PHP-FFMpeg/PHP-FFMpeg — pull request #141 by nlegoff (2014-12-19 15:43:15+00:00)
Title: Add new filters & options API

Hello,

I have just rework the filters & options API for FFMpeg commands.
I did that because before you could not apply two different filters, in previous API a filter was also an option so the following code could not work :

```php
$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');
$video
->filters()
->rotate()
->watermark();
$video
->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4')
```
The generated command will declare twice the '-vf' option so the second filter will not be applied ...

In FFMpeg Filters are different from Options see https://www.ffmpeg.org/ffmpeg-filters.html & https://ffmpeg.org/ffmpeg.html#Options

Filters can be chained and can have multiple inputs and multiple outputs. To illustrate the sorts of things that are possible, we consider the following filtergtaph.

```
[main]
input --> split ---------------------> overlay --> output
| ^
|[tmp] [flip]|
+-----> crop --> vflip -------+
```
This filtergraph splits the input stream in two streams, then sends one stream through the crop filter and the vflip filter, before merging it back with the other stream by overlaying it on top. You can use the following command to achieve this:
```
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
```

A filtergraph consists of a sequence of filterchains. A sequence of filterchains is represented by a list of ";"-separated filterchain descriptions.
A filter is represented by a string of the form: [in_link_1]...[in_link_N]filter_name=arguments[out_link_1]...[out_link_M]

To reflect this difference I have enhanced the API with some new objects.

- FilterGraph object
- FilterChain object
- Filter object

Here the new filter API for example :

Expected filter ```yadif=0:-1; movie=/path/to/image.png [watermark]; [watermark][in] overlay=main_w-overlay_w-10:main_h-overlay_h-10 [out]; split [main][tmp]; [tmp] crop=iw:ih/2:0:0:0, vflip [flip]; [main][flip] overlay=0:H/2```

```php
$g = new FilterGraph();

// filters
$interlacing = new DeInterlacingFilter();
$watermark = (new WatermarkFilter('/path/to/image.png'))->setCorner(WatermarkFilter::BOTTOM_RIGHT);
$split = new CustomFilter('split');
$crop = new CropFilter('iw', 'ih/2', '0', '0');
$flip = new CustomFilter('vflip');
$overlay = new OverlayFilter('0', 'H/2');

// filter chain
$fc = new FilterChain();
$fc->addFilter($interlacing);
$g->addFilterChain($fc);

// filter chain
$fc = new FilterChain();
$fc->addFilter($watermark);
$g->addFilterChain($fc);

// filter chain
$fc = new FilterChain();
$fc->addFilter($split);
$fc->addOutputLink(array('main', 'tmp'));
$g->addFilterChain($fc);

// filter chain
$fc = new FilterChain();
$fc->addFilter($crop);
$fc->addFilter($flip);
$fc->addInputLink('tmp');
$fc->addOutputLink('flip');
$g->addFilterChain($fc);

// filter chain
$fc = new FilterChain();
$fc->addFilter($overlay);
$fc->addInputLink(array('main', 'flip'));
$g->addFilterChain($fc);

echo $g;
//outputs: yadif=0:-1; movie=/path/to/image.png [watermark]; [watermark][in] overlay=main_w-overlay_w-10:main_h-overlay_h-10 [out]; split [main][tmp]; [tmp] crop=iw:ih/2:0:0:0, vflip [flip]; [main][flip] overlay=0:H/2
````

Now to pass filters to your command you have to declare a new filter option which take as argument a graph filter.

```php
$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');

// compose your filters
$filters = new FilterGraph();
$chain = new FilterChain();
$chain->addFilter(new WatermarkFiler());
$chain->addFilter(new DeInterlacingFilter();
$filters->addFilterChain($chain);

//compose your options
$video
->resize(new Dimension(100, 100))
->filter(filters)
->synchronize();
$video
->save(new FFMpeg\Format\Video\X264(), 'export-x264.mp4')
```

Also you can easily combine filters for example the WatermarkFilter is the composition of the 'movie' & 'overlay' filter. This way you can compose n filters in the blink of an eye.

This API allows more flexibility & more control and respect the 'libavfilter' library spirit.

Tests are missing, just wanted to have your feedback about this as it break a lot of things !