Version 0.3

This commit is contained in:
Romain Neutron 2013-06-25 10:03:20 +02:00
commit ad3a5af623
130 changed files with 7283 additions and 2627 deletions

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Functional;
use FFMpeg\FFMpeg;
abstract class FunctionalTestCase extends \PHPUnit_Framework_TestCase
{
public function getFFMpeg()
{
return FFMpeg::create(array('timeout' => 300));
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace FFMpeg\Functional;
use FFMpeg\Format\Video\X264;
class VideoTranscodeTest extends FunctionalTestCase
{
public function testSimpleTranscodeX264()
{
$filename = __DIR__ . '/output/output-x264.mp4';
if (is_file($filename)) {
unlink(__DIR__ . '/output/output-x264.mp4');
}
$ffmpeg = $this->getFFMpeg();
$video = $ffmpeg->open(__DIR__ . '/../../files/Test.ogv');
$this->assertInstanceOf('FFMpeg\Media\Video', $video);
$lastPercentage = null;
$phpunit = $this;
$codec = new X264('libvo_aacenc');
$codec->on('progress', function ($video, $codec, $percentage) use ($phpunit, &$lastPercentage) {
if (null !== $lastPercentage) {
$phpunit->assertGreaterThanOrEqual($lastPercentage, $percentage);
}
$lastPercentage = $percentage;
$phpunit->assertGreaterThanOrEqual(0, $percentage);
$phpunit->assertLessThanOrEqual(100, $percentage);
});
$video->save($codec, $filename);
$this->assertFileExists($filename);
unlink($filename);
}
}

View file

@ -0,0 +1,83 @@
<?php
namespace FFMpeg\Tests\Coordinate;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Tests\TestCase;
use FFMpeg\Coordinate\AspectRatio;
class AspectRatioTest extends TestCase
{
/**
* @dataProvider provideDimensionsAndExpectedratio
*/
public function testFromDimensions($width, $height, $strategy, $expected, $calculatedWidth, $calculatedHeight, $modulus = 2)
{
$ratio = AspectRatio::create(new Dimension($width, $height), $strategy);
$this->assertEquals($expected, $ratio->getValue());
$this->assertEquals($calculatedHeight, $ratio->calculateHeight(240, $modulus));
$this->assertEquals($calculatedWidth, $ratio->calculateWidth(320, $modulus));
}
public function provideDimensionsAndExpectedratio()
{
return array(
//AR_5_4
array(720, 576, false, 5/4, 400, 192),
array(720, 577, false, 5/4, 400, 192),
array(720, 620, false, 720/620, 372, 206),
array(720, 576, true, 5/4, 400, 192),
//AR_ROTATED_4_5
array(576, 720, false, 4/5, 256, 300),
array(576, 720, true, 4/5, 256, 300),
//AR_4_3
array(320, 240, false, 4/3, 426, 180),
array(320, 240, true, 4/3, 426, 180),
//AR_ROTATED_3_4
array(240, 320, false, 3/4, 240, 320),
array(240, 320, true, 3/4, 240, 320),
//AR_16_9
array(1920, 1080, false, 16/9, 568, 136),
array(1920, 1080, true, 16/9, 568, 136),
array(1280, 720, false, 16/9, 568, 136),
array(1280, 720, true, 16/9, 568, 136),
array(3840, 2160, false, 16/9, 568, 136),
array(3840, 2160, true, 16/9, 568, 136),
// modulus 4
array(1920, 1080, false, 16/9, 568, 136, 4),
array(1920, 1080, true, 16/9, 568, 136, 4),
array(1280, 720, false, 16/9, 568, 136, 4),
array(1280, 720, true, 16/9, 568, 136, 4),
array(3840, 2160, false, 16/9, 568, 136, 4),
array(3840, 2160, true, 16/9, 568, 136, 4),
// modulus 16
array(1920, 1080, false, 16/9, 576, 128, 16),
array(1920, 1080, true, 16/9, 576, 128, 16),
array(1280, 720, false, 16/9, 576, 128, 16),
array(1280, 720, true, 16/9, 576, 128, 16),
array(3840, 2160, false, 16/9, 576, 128, 16),
array(3840, 2160, true, 16/9, 576, 128, 16),
//AR_ROTATED_9_16
array(1080, 1920, false, 9/16, 180, 426),
array(1080, 1920, true, 9/16, 180, 426),
array(720, 1280, false, 9/16, 180, 426),
array(720, 1280, true, 9/16, 180, 426),
array(2160, 3840, false, 9/16, 180, 426),
array(2160, 3840, true, 9/16, 180, 426),
//AR_3_2
array(360, 240, false, 3/2, 480, 160),
array(360, 240, true, 3/2, 480, 160),
//AR_ROTATED_2_3
array(240, 360, false, 2/3, 214, 360),
array(240, 360, true, 2/3, 214, 360),
//AR_5_3
//AR_ROTATED_3_5
//AR_1_1
//AR_1_DOT_85_1
//AR_ROTATED_1_DOT_85
//AR_2_DOT_39_1
//AR_ROTATED_2_DOT_39
);
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace FFMpeg\Tests\Coordinate;
use FFMpeg\Tests\TestCase;
use FFMpeg\Coordinate\Dimension;
class DimensionTest extends TestCase
{
/**
* @dataProvider provideInvalidDimensions
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testInvalidDimensions($width, $height)
{
new Dimension($width, $height);
}
public function provideInvalidDimensions()
{
return array(
array(320, 0),
array(320, -10),
array(0, 240),
array(-10, 240),
array(0, 0),
array(0, -10),
array(-10, 0),
);
}
public function testGetters()
{
$dimension = new Dimension(320, 240);
$this->assertEquals(320, $dimension->getWidth());
$this->assertEquals(240, $dimension->getHeight());
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace FFMpeg\Tests\Coordinate;
use FFMpeg\Tests\TestCase;
use FFMpeg\Coordinate\FrameRate;
class FrameRateTest extends TestCase
{
public function testGetter()
{
$fr = new FrameRate(23.997);
$this->assertEquals(23.997, $fr->getValue());
}
/**
* @dataProvider provideInvalidFrameRates
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testInvalidFrameRate($value)
{
new FrameRate($value);
}
public function provideInvalidFrameRates()
{
return array(
array(0), array(-1.5), array(-2),
);
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace FFMpeg\Tests\Coordinate;
use FFMpeg\Tests\TestCase;
use FFMpeg\Coordinate\Point;
class PointTest extends TestCase
{
public function testGetters()
{
$point = new Point(4, 25);
$this->assertEquals(4, $point->getX());
$this->assertEquals(25, $point->getY());
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace FFMpeg\Tests\Coordinate;
use FFMpeg\Tests\TestCase;
use FFMpeg\Coordinate\TimeCode;
class TimeCodeTest extends TestCase
{
/**
* @dataProvider provideTimecodes
*/
public function testFromString($timecode, $expected)
{
$tc = TimeCode::fromString($timecode);
$this->assertEquals((string) $tc, $expected);
}
public function provideTimeCodes()
{
return array(
array('1:02:04:05:20', '26:04:05.20'),
array('1:02:04:05.20', '26:04:05.20'),
array('02:04:05:20', '02:04:05.20'),
array('02:04:05.20', '02:04:05.20'),
array('00:00:05.20', '00:00:05.20'),
array('00:00:00.00', '00:00:00.00'),
);
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testFromInvalidString()
{
TimeCode::fromString('lalali lala');
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace FFMpeg\Tests\Driver;
use Alchemy\BinaryDriver\Configuration;
use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\Tests\TestCase;
use Symfony\Component\Process\ExecutableFinder;
class FFMpegDriverTest extends TestCase
{
public function setUp()
{
$executableFinder = new ExecutableFinder();
$found = false;
foreach (array('avconv', 'ffmpeg') as $name) {
if (null !== $executableFinder->find($name)) {
$found = true;
break;
}
}
if (!$found) {
$this->markTestSkipped('Neither ffmpeg or avconv found');
}
}
public function testCreate()
{
$logger = $this->getLoggerMock();
$ffmpeg = FFMpegDriver::create($logger, array());
$this->assertInstanceOf('FFMpeg\Driver\FFMpegDriver', $ffmpeg);
$this->assertEquals($logger, $ffmpeg->getProcessRunner()->getLogger());
}
public function testCreateWithConfig()
{
$conf = new Configuration();
$ffmpeg = FFMpegDriver::create($this->getLoggerMock(), $conf);
$this->assertEquals($conf, $ffmpeg->getConfiguration());
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace FFMpeg\Tests\Driver;
use Alchemy\BinaryDriver\Configuration;
use FFMpeg\Driver\FFProbeDriver;
use FFMpeg\Tests\TestCase;
use Symfony\Component\Process\ExecutableFinder;
class FFProbeDriverTest extends TestCase
{
public function setUp()
{
$executableFinder = new ExecutableFinder();
$found = false;
foreach (array('avprobe', 'ffprobe') as $name) {
if (null !== $executableFinder->find($name)) {
$found = true;
break;
}
}
if (!$found) {
$this->markTestSkipped('Neither ffprobe or avprobe found');
}
}
public function testCreate()
{
$logger = $this->getLoggerMock();
$ffprobe = FFProbeDriver::create(array(), $logger);
$this->assertInstanceOf('FFMpeg\Driver\FFProbeDriver', $ffprobe);
$this->assertEquals($logger, $ffprobe->getProcessRunner()->getLogger());
}
public function testCreateWithConfig()
{
$conf = new Configuration();
$ffprobe = FFProbeDriver::create($conf, $this->getLoggerMock());
$this->assertEquals($conf, $ffprobe->getConfiguration());
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace FFMpeg\Tests;
use FFMpeg\FFMpegServiceProvider;
use Silex\Application;
class FFMpegServiceProviderTest extends \PHPUnit_Framework_TestCase
{
public function testWithConfig()
{
$app = new Application();
$app->register(new FFMpegServiceProvider(), array(
'ffmpeg.configuration' => array(
'ffmpeg.threads' => 12,
'ffmpeg.timeout' => 10666,
'ffprobe.timeout' => 4242,
)
));
$this->assertInstanceOf('FFMpeg\FFMpeg', $app['ffmpeg']);
$this->assertSame($app['ffmpeg'], $app['ffmpeg.ffmpeg']);
$this->assertInstanceOf('FFMpeg\FFProbe', $app['ffmpeg.ffprobe']);
$this->assertEquals(12, $app['ffmpeg']->getFFMpegDriver()->getConfiguration()->get('ffmpeg.threads'));
$this->assertEquals(10666, $app['ffmpeg']->getFFMpegDriver()->getProcessBuilderFactory()->getTimeout());
$this->assertEquals(4242, $app['ffmpeg.ffprobe']->getFFProbeDriver()->getProcessBuilderFactory()->getTimeout());
}
public function testWithoutConfig()
{
$app = new Application();
$app->register(new FFMpegServiceProvider());
$this->assertInstanceOf('FFMpeg\FFMpeg', $app['ffmpeg']);
$this->assertSame($app['ffmpeg'], $app['ffmpeg.ffmpeg']);
$this->assertInstanceOf('FFMpeg\FFProbe', $app['ffmpeg.ffprobe']);
$this->assertEquals(4, $app['ffmpeg']->getFFMpegDriver()->getConfiguration()->get('ffmpeg.threads'));
$this->assertEquals(300, $app['ffmpeg']->getFFMpegDriver()->getProcessBuilderFactory()->getTimeout());
$this->assertEquals(30, $app['ffmpeg.ffprobe']->getFFProbeDriver()->getProcessBuilderFactory()->getTimeout());
}
public function testWithFFMpegBinaryConfig()
{
$app = new Application();
$app->register(new FFMpegServiceProvider(), array(
'ffmpeg.configuration' => array(
'ffmpeg.binaries' => '/path/to/ffmpeg',
)
));
$this->setExpectedException('Alchemy\BinaryDriver\Exception\ExecutableNotFoundException', 'Executable not found, proposed : /path/to/ffmpeg');
$app['ffmpeg'];
}
public function testWithFFMprobeBinaryConfig()
{
$app = new Application();
$app->register(new FFMpegServiceProvider(), array(
'ffmpeg.configuration' => array(
'ffprobe.binaries' => '/path/to/ffprobe',
)
));
$this->setExpectedException('Alchemy\BinaryDriver\Exception\ExecutableNotFoundException', 'Executable not found, proposed : /path/to/ffprobe');
$app['ffmpeg.ffprobe'];
}
}

View file

@ -0,0 +1,112 @@
<?php
namespace FFMpeg\Tests;
use FFMpeg\FFMpeg;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\FFProbe\DataMapping\Stream;
class FFMpegTest Extends TestCase
{
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testOpenInvalid()
{
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $this->getFFProbeMock());
$ffmpeg->open('/path/to/unknown/file');
}
public function testOpenAudio()
{
$streams = $this->getStreamCollectionMock();
$streams->expects($this->once())
->method('audios')
->will($this->returnValue(new StreamCollection(array(new Stream(array())))));
$streams->expects($this->once())
->method('videos')
->will($this->returnValue(array()));
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue($streams));
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$this->assertInstanceOf('FFMpeg\Media\Audio', $ffmpeg->open(__FILE__));
}
public function testOpenVideo()
{
$streams = $this->getStreamCollectionMock();
$streams->expects($this->once())
->method('videos')
->will($this->returnValue(new StreamCollection(array(new Stream(array())))));
$streams->expects($this->never())
->method('audios');
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue($streams));
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$this->assertInstanceOf('FFMpeg\Media\Video', $ffmpeg->open(__FILE__));
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testOpenUnknown()
{
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue(new StreamCollection()));
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$ffmpeg->open(__FILE__);
}
public function testCreateWithoutLoggerOrProbe()
{
$this->assertInstanceOf('FFMpeg\FFMpeg', FFMpeg::create());
}
public function testCreateWithLoggerAndProbe()
{
$logger = $this->getLoggerMock();
$ffprobe = $this->getFFProbeMock();
$ffmpeg = FFMpeg::create(array('timeout' => 42), $logger, $ffprobe);
$this->assertInstanceOf('FFMpeg\FFMpeg', $ffmpeg);
$this->assertSame($logger, $ffmpeg->getFFMpegDriver()->getProcessRunner()->getLogger());
$this->assertSame($ffprobe, $ffmpeg->getFFProbe());
$this->assertSame(42, $ffmpeg->getFFMpegDriver()->getProcessBuilderFactory()->getTimeout());
}
public function testGetSetFFProbe()
{
$ffprobe = $this->getFFProbeMock();
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$this->assertSame($ffprobe, $ffmpeg->getFFProbe());
$anotherFFProbe = $this->getFFProbeMock();
$ffmpeg->setFFProbe($anotherFFProbe);
$this->assertSame($anotherFFProbe, $ffmpeg->getFFProbe());
}
public function testGetSetDriver()
{
$driver = $this->getFFMpegDriverMock();
$ffmpeg = new FFMpeg($driver, $this->getFFProbeMock());
$this->assertSame($driver, $ffmpeg->getFFMpegDriver());
$anotherDriver = $this->getFFMpegDriverMock();
$ffmpeg->setFFMpegDriver($anotherDriver);
$this->assertSame($anotherDriver, $ffmpeg->getFFMpegDriver());
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace FFMpeg\Tests\FFProbe\DataMapping;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\DataMapping\AbstractData;
class AbstractDataTest extends TestCase
{
public function testHas()
{
$imp = new Implementation(array('key1' => 'value1', 'key2' => 'value2'));
$this->assertTrue($imp->has('key1'));
$this->assertTrue($imp->has('key2'));
$this->assertFalse($imp->has('value1'));
$this->assertFalse($imp->has('key3'));
}
public function testGet()
{
$imp = new Implementation(array('key1' => 'value1', 'key2' => 'value2'));
$this->assertEquals('value1', $imp->get('key1'));
$this->assertEquals('value2', $imp->get('key2'));
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testGetInvalid()
{
$imp = new Implementation(array('key1' => 'value1', 'key2' => 'value2'));
$imp->get('key3');
}
public function testKeys()
{
$imp = new Implementation(array('key1' => 'value1', 'key2' => 'value2'));
$this->assertEquals(array('key1', 'key2'), $imp->keys());
}
public function testAll()
{
$values = array('key1' => 'value1', 'key2' => 'value2');
$imp = new Implementation($values);
$this->assertEquals($values, $imp->all());
}
}
class Implementation extends AbstractData
{
}

View file

@ -0,0 +1,89 @@
<?php
namespace FFMpeg\Tests\FFProbe\DataMapping;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
class StreamCollectionTest extends TestCase
{
public function testAdd()
{
$stream = $this->getStreamMock();
$collection = new StreamCollection();
$this->assertEquals(array(), $collection->all());
$collection->add($stream);
$this->assertEquals(array($stream), $collection->all());
$collection->add($stream);
$this->assertEquals(array($stream, $stream), $collection->all());
}
public function testVideos()
{
$audio = $this->getStreamMock();
$audio->expects($this->once())
->method('isVideo')
->will($this->returnValue(false));
$video = $this->getStreamMock();
$video->expects($this->once())
->method('isVideo')
->will($this->returnValue(true));
$collection = new StreamCollection(array($audio, $video));
$videos = $collection->videos();
$this->assertInstanceOf('FFMpeg\FFProbe\DataMapping\StreamCollection', $videos);
$this->assertCount(1, $videos);
$this->assertEquals(array($video), $videos->all());
}
public function testAudios()
{
$audio = $this->getStreamMock();
$audio->expects($this->once())
->method('isAudio')
->will($this->returnValue(true));
$video = $this->getStreamMock();
$video->expects($this->once())
->method('isAudio')
->will($this->returnValue(false));
$collection = new StreamCollection(array($audio, $video));
$audios = $collection->audios();
$this->assertInstanceOf('FFMpeg\FFProbe\DataMapping\StreamCollection', $audios);
$this->assertCount(1, $audios);
$this->assertEquals(array($audio), $audios->all());
}
public function testCount()
{
$stream = $this->getStreamMock();
$collection = new StreamCollection(array($stream));
$this->assertCount(1, $collection);
}
public function testGetIterator()
{
$audio = $this->getStreamMock();
$video = $this->getStreamMock();
$collection = new StreamCollection(array($audio, $video));
$this->assertInstanceOf('\Iterator', $collection->getIterator());
$this->assertCount(2, $collection->getIterator());
}
public function testFirst()
{
$stream1 = $this->getStreamMock();
$stream2 = $this->getStreamMock();
$coll = new StreamCollection(array($stream1, $stream2));
$this->assertSame($stream1, $coll->first());
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace FFMpeg\Tests\FFProbe\DataMapping;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\DataMapping\Stream;
class StreamTest extends TestCase
{
/**
* @dataProvider provideAudioCases
*/
public function testIsAudio($isAudio, $properties)
{
$stream = new Stream($properties);
$this->assertTrue($isAudio === $stream->isAudio());
}
public function provideAudioCases()
{
return array(
array(true, array('codec_type' => 'audio')),
array(false, array('codec_type' => 'video')),
);
}
/**
* @dataProvider provideVideoCases
*/
public function testIsVideo($isVideo, $properties)
{
$stream = new Stream($properties);
$this->assertTrue($isVideo === $stream->isVideo());
}
public function provideVideoCases()
{
return array(
array(true, array('codec_type' => 'video')),
array(false, array('codec_type' => 'audio')),
);
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace FFMpeg\Tests\FFProbe;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\Mapper;
use FFMpeg\FFProbe;
use FFMpeg\FFProbe\DataMapping\Format;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
class MapperTest extends TestCase
{
/**
* @dataProvider provideMappings
*/
public function testMap($type, $data, $expected)
{
$mapper = new Mapper();
$this->assertEquals($expected, $mapper->map($type, $data));
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testMapInvalidArgument()
{
$mapper = new Mapper();
$mapper->map('cool type', 'data');
}
public function provideMappings()
{
$format = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_format.json'), true);
$streams = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_streams.json'), true);
return array(
array(FFProbe::TYPE_FORMAT, $format, new Format($format['format'])),
array(FFProbe::TYPE_STREAMS, $streams, new StreamCollection(array_map(function ($streamData) {
return new Stream($streamData);
}, $streams['streams']))),
);
}
}

View file

@ -0,0 +1,101 @@
<?php
namespace FFMpeg\Tests\FFProbe;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\OptionsTester;
class OptionsTesterTest extends TestCase
{
/**
* @dataProvider provideOptions
*/
public function testHasOptionWithCacheEmpty($isPresent, $data, $optionName)
{
$cache = $this->getCacheMock();
$cache->expects($this->never())
->method('fetch');
$cache->expects($this->exactly(2))
->method('contains')
->will($this->returnValue(false));
$cache->expects($this->exactly(2))
->method('save');
$ffprobe = $this->getFFProbeDriverMock();
$ffprobe->expects($this->once())
->method('command')
->with(array('-help', '-loglevel', 'quiet'))
->will($this->returnValue($data));
$tester = new OptionsTester($ffprobe, $cache);
$this->assertTrue($isPresent === $tester->has($optionName));
}
public function provideOptions()
{
$data = file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/help.raw');
return array(
array(true, $data, '-print_format'),
array(false, $data, '-another_print_format'),
);
}
/**
* @dataProvider provideOptions
*/
public function testHasOptionWithHelpCacheLoaded($isPresent, $data, $optionName)
{
$cache = $this->getCacheMock();
$cache->expects($this->once())
->method('fetch')
->will($this->returnValue($data));
$cache->expects($this->at(0))
->method('contains')
->will($this->returnValue(false));
$cache->expects($this->at(1))
->method('contains')
->will($this->returnValue(true));
$cache->expects($this->once())
->method('save');
$ffprobe = $this->getFFProbeDriverMock();
$ffprobe->expects($this->never())
->method('command');
$tester = new OptionsTester($ffprobe, $cache);
$this->assertTrue($isPresent === $tester->has($optionName));
}
/**
* @dataProvider provideOptions
*/
public function testHasOptionWithCacheFullyLoaded($isPresent, $data, $optionName)
{
$cache = $this->getCacheMock();
$cache->expects($this->once())
->method('fetch')
->with('option-' . $optionName)
->will($this->returnValue($isPresent));
$cache->expects($this->once())
->method('contains')
->with('option-' . $optionName)
->will($this->returnValue(true));
$ffprobe = $this->getFFProbeDriverMock();
$ffprobe->expects($this->never())
->method('command');
$tester = new OptionsTester($ffprobe, $cache);
$this->assertTrue($isPresent === $tester->has($optionName));
}
}

View file

@ -0,0 +1,42 @@
<?php
namespace FFMpeg\Tests\FFProbe;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\OutputParser;
use FFMpeg\FFProbe;
class OutputParserTest extends TestCase
{
/**
* @dataProvider provideTypeDataAndOutput
*/
public function testParse($type, $data, $expectedOutput)
{
$parser = new OutputParser();
$this->assertEquals($expectedOutput, $parser->parse($type, $data));
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testParseWithInvalidArgument()
{
$parser = new OutputParser();
$parser->parse('comme ca', 'data');
}
public function provideTypeDataAndOutput()
{
$expectedFormat = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_format.json'), true);
$expectedStreams = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_streams.json'), true);
$rawFormat = file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_format.raw');
$rawStreams = file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_streams.raw');
return array(
array(FFProbe::TYPE_FORMAT, $rawFormat, $expectedFormat),
array(FFProbe::TYPE_STREAMS, $rawStreams, $expectedStreams),
);
}
}

View file

@ -0,0 +1,308 @@
<?php
namespace FFMpeg\Tests;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe;
use Symfony\Component\Process\ExecutableFinder;
use Alchemy\BinaryDriver\ConfigurationInterface;
use Alchemy\BinaryDriver\Configuration;
class FFProbeTest extends TestCase
{
public function testGetSetParser()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$parser = $this->getFFProbeParserMock();
$ffprobe->setParser($parser);
$this->assertSame($parser, $ffprobe->getParser());
}
public function testGetSetFFProbeDriver()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$driver = $this->getFFProbeDriverMock();
$ffprobe->setFFProbeDriver($driver);
$this->assertSame($driver, $ffprobe->getFFProbeDriver());
}
public function testGetSetFFProbeMapper()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$ffprobe->setMapper($mapper);
$this->assertSame($mapper, $ffprobe->getMapper());
}
public function testGetSetOptionsTester()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$tester = $this->getFFProbeOptionsTesterMock();
$ffprobe->setOptionsTester($tester);
$this->assertSame($tester, $ffprobe->getOptionsTester());
}
public function testGetSetCache()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$cache = $this->getCacheMock();
$ffprobe->setCache($cache);
$this->assertSame($cache, $ffprobe->getCache());
}
public function provideDataWhitoutCache()
{
$stream = $this->getStreamMock();
$format = $this->getFormatMock();
return array(
array($stream, 'streams', array('-show_streams', '-print_format'), FFProbe::TYPE_STREAMS, array(__FILE__, '-show_streams', '-print_format', 'json'), false),
array($format, 'format', array('-show_format', '-print_format'), FFProbe::TYPE_FORMAT, array(__FILE__, '-show_format', '-print_format', 'json'), false),
array($stream, 'streams', array('-show_streams'), FFProbe::TYPE_STREAMS, array(__FILE__, '-show_streams'), true),
array($format, 'format', array('-show_format'), FFProbe::TYPE_FORMAT, array(__FILE__, '-show_format'), true),
);
}
/**
* @dataProvider provideDataWhitoutCache
*/
public function testProbeWithoutCache($output, $method, $commands, $type, $caughtCommands, $isRaw)
{
$pathfile = __FILE__;
$data = array('key' => 'value');
$rawData = 'raw data';
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$mapper->expects($this->once())
->method('map')
->with($type, $data)
->will($this->returnValue($output));
$parser = $this->getFFProbeParserMock();
if ($isRaw) {
$parser->expects($this->once())
->method('parse')
->with($type, $rawData)
->will($this->returnValue($data));
} else {
$parser->expects($this->never())
->method('parse');
}
$tester = $this->getFFProbeOptionsTesterMockWithOptions($commands);
$cache = $this->getCacheMock();
$cache->expects($this->once())
->method('contains')
->will($this->returnValue(false));
$cache->expects($this->never())
->method('fetch');
$cache->expects($this->once())
->method('save')
->with($this->anything(), $output);
$driver = $this->getFFProbeDriverMock();
$driver->expects($this->once())
->method('command')
->with($caughtCommands)
->will($this->returnValue($isRaw ? $rawData : json_encode($data)));
$ffprobe->setOptionsTester($tester)
->setCache($cache)
->setMapper($mapper)
->setFFProbeDriver($driver)
->setParser($parser);
$this->assertEquals($output, call_user_func(array($ffprobe, $method), $pathfile));
}
public function provideDataForInvalidJson()
{
$stream = $this->getStreamMock();
$format = $this->getFormatMock();
return array(
array($stream, 'streams', array('-show_streams', '-print_format'), FFProbe::TYPE_STREAMS, array(__FILE__, '-show_streams', '-print_format', 'json')),
array($format, 'format', array('-show_format', '-print_format'), FFProbe::TYPE_FORMAT, array(__FILE__, '-show_format', '-print_format', 'json')),
);
}
/**
* @dataProvider provideDataForInvalidJson
*/
public function testProbeWithWrongJson($output, $method, $commands, $type, $caughtCommands)
{
$pathfile = __FILE__;
$data = array('key' => 'value');
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$mapper->expects($this->once())
->method('map')
->with($this->isType('string'), 'good data parsed')
->will($this->returnValue($output));
$parser = $this->getFFProbeParserMock();
$parser->expects($this->once())
->method('parse')
->with($this->isType('string', json_encode($data) . 'lala'))
->will($this->returnValue('good data parsed'));
$tester = $this->getFFProbeOptionsTesterMockWithOptions($commands);
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
->method('contains')
->will($this->returnValue(false));
$cache->expects($this->never())
->method('fetch');
$driver = $this->getFFProbeDriverMock();
$driver->expects($this->exactly(2))
->method('command')
->will($this->returnValue(json_encode($data) . 'lala'));
$ffprobe->setOptionsTester($tester)
->setCache($cache)
->setMapper($mapper)
->setFFProbeDriver($driver)
->setParser($parser);
$this->assertEquals($output, call_user_func(array($ffprobe, $method), $pathfile));
}
public function provideProbingDataWithCache()
{
$stream = $this->getStreamMock();
$format = $this->getFormatMock();
return array(
array($stream, 'streams'),
array($format, 'format'),
);
}
/**
* @dataProvider provideProbingDataWithCache
*/
public function testProbeWithCache($output, $method)
{
$pathfile = __FILE__;
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$mapper->expects($this->never())
->method('map');
$tester = $this->getFFProbeOptionsTesterMock();
$cache = $this->getCacheMock();
$cache->expects($this->once())
->method('contains')
->will($this->returnValue(true));
$cache->expects($this->once())
->method('fetch')
->will($this->returnValue($output));
$cache->expects($this->never())
->method('save');
$driver = $this->getFFProbeDriverMock();
$driver->expects($this->never())
->method('command');
$ffprobe->setOptionsTester($tester)
->setCache($cache)
->setMapper($mapper)
->setFFProbeDriver($driver);
$this->assertEquals($output, call_user_func(array($ffprobe, $method), $pathfile));
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
* @dataProvider provideProbeMethod
*/
public function testProbeWithInvalidFile($method)
{
$pathfile = '/path/to/nofile';
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
call_user_func(array($ffprobe, $method), $pathfile);
}
public function provideProbeMethod()
{
return array(
array('streams'),
array('format'),
);
}
/**
* @expectedException FFMpeg\Exception\RuntimeException
* @dataProvider provideProbeMethod
*/
public function testProbeWithoutShowStreamsAvailable($method)
{
$pathfile = __FILE__;
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$ffprobe->setOptionsTester($this->getFFProbeOptionsTesterMock());
call_user_func(array($ffprobe, $method), $pathfile);
}
/**
* @dataProvider provideCreateOptions
*/
public function testCreate($logger, $conf, $cache)
{
$finder = new ExecutableFinder();
$found = false;
foreach (array('avprobe', 'ffprobe') as $name) {
if (null !== $finder->find($name)) {
$found = true;
}
}
if (!$found) {
$this->markTestSkipped("Unable to find avprobe or ffprobe on system");
}
$ffprobe = FFProbe::create();
$this->assertInstanceOf('FFMpeg\FFprobe', $ffprobe);
$ffprobe = FFProbe::create($conf, $logger, $cache);
$this->assertInstanceOf('FFMpeg\FFprobe', $ffprobe);
if (null !== $cache) {
$this->assertSame($cache, $ffprobe->getCache());
}
if (null !== $logger) {
$this->assertSame($logger, $ffprobe->getFFProbeDriver()->getProcessRunner()->getLogger());
}
if ($conf instanceof ConfigurationInterface) {
$this->assertSame($conf, $ffprobe->getFFProbeDriver()->getConfiguration());
}
}
public function provideCreateOptions()
{
return array(
array(null, array('key' => 'value'), null),
array($this->getLoggerMock(), array('key' => 'value'), null),
array(null, new Configuration(), null),
array(null, array('key' => 'value'), $this->getCacheMock()),
);
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace FFMpeg\Tests\Filters\Audio;
use FFMpeg\Filters\Audio\AudioFilters;
use FFMpeg\Tests\TestCase;
class AudioFiltersTest extends TestCase
{
public function testResample()
{
$capturedFilter = null;
$audio = $this->getAudioMock();
$audio->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Audio\AudioResamplableFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$filters = new AudioFilters($audio);
$filters->resample(8000);
$this->assertEquals(8000, $capturedFilter->getRate());
}
}

View file

@ -0,0 +1,24 @@
<?php
namespace FFMpeg\Tests\Filters\Audio;
use FFMpeg\Filters\Audio\AudioResamplableFilter;
use FFMpeg\Tests\TestCase;
class AudioResamplableFilterTest extends TestCase
{
public function testGetRate()
{
$filter = new AudioResamplableFilter(500);
$this->assertEquals(500, $filter->getRate());
}
public function testApply()
{
$audio = $this->getAudioMock();
$format = $this->getMock('FFMpeg\Format\AudioInterface');
$filter = new AudioResamplableFilter(500);
$this->assertEquals(array('-ac', 2, '-ar', 500), $filter->apply($audio, $format));
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace FFMpeg\Tests\Filters;
use FFMpeg\Filters\FiltersCollection;
class FiltersCollectionTest extends \PHPUnit_Framework_TestCase
{
public function testCount()
{
$coll = new FiltersCollection();
$this->assertCount(0, $coll);
$coll->add($this->getMock('FFMpeg\Filters\FilterInterface'));
$this->assertCount(1, $coll);
$coll->add($this->getMock('FFMpeg\Filters\FilterInterface'));
$this->assertCount(2, $coll);
}
public function testIterator()
{
$coll = new FiltersCollection();
$coll->add($this->getMock('FFMpeg\Filters\FilterInterface'));
$coll->add($this->getMock('FFMpeg\Filters\FilterInterface'));
$this->assertInstanceOf('\ArrayIterator', $coll->getIterator());
$this->assertCount(2, $coll->getIterator());
}
}

View file

@ -0,0 +1,75 @@
<?php
namespace FFMpeg\Tests\Filters\Video;
use FFMpeg\Filters\Video\ResizeFilter;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Coordinate\Dimension;
class ResizeFilterTest extends TestCase
{
/**
* @dataProvider provideDimensions
*/
public function testApply(Dimension $dimension, $mode, $width, $height, $modulus, $expected, $forceStandards = true)
{
$video = $this->getVideoMock();
$pathfile = '/path/to/file'.mt_rand();
$format = $this->getMock('FFMpeg\Format\VideoInterface');
$format->expects($this->any())
->method('getModulus')
->will($this->returnValue($modulus));
$streams = new StreamCollection(array(
new Stream(array(
'codec_type' => 'video',
'width' => $width,
'height' => $height,
))
));
$video->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$filter = new ResizeFilter($dimension, $mode, $forceStandards);
$this->assertEquals($expected, $filter->apply($video, $format));
}
public function provideDimensions()
{
return array(
array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, array('-s', '320x240')),
array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, array('-s', '320x240')),
array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, array('-s', '320x240')),
array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, array('-s', '320x240')),
array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_FIT, 320, 240, 2, array('-s', '640x480')),
array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_INSET, 320, 240, 2, array('-s', '640x480')),
array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 320, 240, 2, array('-s', '640x480')),
array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 320, 240, 2, array('-s', '640x480')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, array('-s', '640x360')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, array('-s', '640x360')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, array('-s', '640x360')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, array('-s', '640x360')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, array('-s', '640x360')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, array('-s', '640x360')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, array('-s', '640x360')),
array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, array('-s', '640x360')),
// test non standard dimension
array(new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, array('-s', '62x150'), true),
array(new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, array('-s', '40x150'), false),
array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, array('-s', '320x320')),
array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, array('-s', '320x240')),
array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, array('-s', '320x240')),
array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, array('-s', '426x320')),
);
}
}

View file

@ -0,0 +1,58 @@
<?php
namespace FFMpeg\Tests\Filters\Video;
use FFMpeg\Tests\TestCase;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\Filters\Video\SynchronizeFilter;
class SynchronizeFilterTest extends TestCase
{
/**
* @dataProvider provideStreams
*/
public function testApply($streams, $expected)
{
$video = $this->getVideoMock();
$format = $this->getMock('FFMpeg\Format\VideoInterface');
$video->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$video->expects($this->any())
->method('getPathfile')
->will($this->returnValue(__FILE__));
$filter = new SynchronizeFilter();
$this->assertEquals($expected, $filter->apply($video, $format));
}
public function provideStreams()
{
$audio = new StreamCollection(array(new Stream(array(
'index' => 0,
'codec_type' => 'audio',
))));
$synced = new StreamCollection(array(new Stream(array(
'index' => 0,
'codec_type' => 'video',
)), new Stream(array(
'index' => 1,
'codec_type' => 'audio',
))));
$video = new StreamCollection(array(new Stream(array(
'index' => 0,
'codec_type' => 'video',
'start_time' => '0.123456',
)), new Stream(array(
'index' => 1,
'codec_type' => 'audio',
))));
return array(
array($audio, array()),
array($synced, array()),
array($video, array('-itsoffset', '0.123456', '-i', __FILE__, '-map', '1:0', '-map', '0:1')),
);
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace FFMpeg\Tests\Filters\Video;
use FFMpeg\Tests\TestCase;
use FFMpeg\Filters\Video\VideoFilters;
use FFMpeg\Filters\Video\ResizeFilter;
class VideoFiltersTest extends TestCase
{
/**
* @dataProvider provideResizeOptions
*/
public function testResize($mode, $forceStandards)
{
$capturedFilter = null;
$video = $this->getVideoMock();
$filters = new VideoFilters($video);
$dimension = $this->getDimensionMock();
$video->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Video\ResizeFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$filters->resize($dimension, $mode, $forceStandards);
$this->assertSame($mode, $capturedFilter->getMode());
$this->assertSame($forceStandards, $capturedFilter->areStandardsForced());
$this->assertSame($dimension, $capturedFilter->getDimension());
}
public function provideResizeOptions()
{
return array(
array(ResizeFilter::RESIZEMODE_FIT, true),
array(ResizeFilter::RESIZEMODE_SCALE_WIDTH, true),
array(ResizeFilter::RESIZEMODE_SCALE_HEIGHT, false),
array(ResizeFilter::RESIZEMODE_INSET, false),
);
}
public function testResample()
{
$capturedFilter = null;
$video = $this->getVideoMock();
$filters = new VideoFilters($video);
$framerate = $this->getFramerateMock();
$gop = 42;
$video->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Video\VideoResampleFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$filters->resample($framerate, $gop);
$this->assertSame($framerate, $capturedFilter->getFramerate());
$this->assertSame($gop, $capturedFilter->getGOP());
}
public function testSynchronize()
{
$video = $this->getVideoMock();
$filters = new VideoFilters($video);
$video->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Video\SynchronizeFilter'));
$filters->synchronize();
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace FFMpeg\Tests\Filters\Video;
use FFMpeg\Filters\Video\VideoResampleFilter;
use FFMpeg\Tests\TestCase;
use FFMpeg\Coordinate\FrameRate;
class VideoResampleFilterTest extends TestCase
{
public function testApplyWithAFormatThatSupportsBFrames()
{
$framerate = new FrameRate(54);
$gop = 42;
$video = $this->getVideoMock();
$format = $this->getMock('FFMpeg\Format\VideoInterface');
$format->expects($this->any())
->method('supportBFrames')
->will($this->returnValue(true));
$expected = array('-r', 54, '-b_strategy', '1', '-bf', '3', '-g', 42);
$filter = new VideoResampleFilter($framerate, $gop);
$this->assertEquals($expected, $filter->apply($video, $format));
}
public function testApplyWithAFormatThatDoesNotSupportsBFrames()
{
$framerate = new FrameRate(54);
$gop = 42;
$video = $this->getVideoMock();
$format = $this->getMock('FFMpeg\Format\VideoInterface');
$format->expects($this->any())
->method('supportBFrames')
->will($this->returnValue(false));
$expected = array('-r', 54);
$filter = new VideoResampleFilter($framerate, $gop);
$this->assertEquals($expected, $filter->apply($video, $format));
}
}

View file

@ -0,0 +1,96 @@
<?php
namespace FFMpeg\Tests\Format\Audio;
use FFMpeg\Tests\TestCase;
use FFMpeg\Format\Audio\DefaultAudio;
abstract class AudioTestCase extends TestCase
{
public function testExtraParams()
{
foreach ($this->getFormat()->getExtraParams() as $param) {
$this->assertScalar($param);
}
}
public function testGetAudioCodec()
{
$this->assertScalar($this->getFormat()->getAudioCodec());
$this->assertContains($this->getFormat()->getAudioCodec(), $this->getFormat()->getAvailableAudioCodecs());
}
public function testSetAudioCodec()
{
$format = $this->getFormat();
foreach ($format->getAvailableAudioCodecs() as $codec) {
$format->setAudioCodec($codec);
$this->assertEquals($codec, $format->getAudioCodec());
}
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testSetInvalidAudioCodec()
{
$this->getFormat()->setAudioCodec('invalid-random-audio-codec');
}
public function testGetAvailableAudioCodecs()
{
$this->assertGreaterThan(0, count($this->getFormat()->getAvailableAudioCodecs()));
}
public function testGetAudioKiloBitrate()
{
$this->assertInternalType('integer', $this->getFormat()->getAudioKiloBitrate());
}
public function testSetAudioKiloBitrate()
{
$format = $this->getFormat();
$format->setAudioKiloBitrate(256);
$this->assertEquals(256, $format->getAudioKiloBitrate());
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testSetInvalidKiloBitrate()
{
$this->getFormat()->setAudioKiloBitrate(0);
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testSetNegativeKiloBitrate()
{
$this->getFormat()->setAudioKiloBitrate(-10);
}
public function testCreateProgressListener()
{
$media = $this->getMock('FFMpeg\Media\MediaTypeInterface');
$media->expects($this->any())
->method('getPathfile')
->will($this->returnValue(__FILE__));
$format = $this->getFormat();
$ffprobe = $this->getFFProbeMock();
foreach ($format->createProgressListener($media, $ffprobe, 1, 3) as $listener) {
$this->assertInstanceOf('FFMpeg\Format\ProgressListener\AudioProgressListener', $listener);
$this->assertSame($ffprobe, $listener->getFFProbe());
$this->assertSame(__FILE__, $listener->getPathfile());
$this->assertSame(1, $listener->getCurrentPass());
$this->assertSame(3, $listener->getTotalPass());
}
}
/**
* @return DefaultAudio
*/
abstract public function getFormat();
}

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Tests\Format\Audio;
use FFMpeg\Format\Audio\Flac;
class FlacTest extends AudioTestCase
{
public function getFormat()
{
return new Flac();
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Tests\Format\Audio;
use FFMpeg\Format\Audio\Mp3;
class Mp3Test extends AudioTestCase
{
public function getFormat()
{
return new Mp3();
}
}

View file

@ -0,0 +1,87 @@
<?php
namespace FFMpeg\Tests\Format\ProgressListener;
use FFMpeg\Tests\TestCase;
use FFMpeg\Format\ProgressListener\AudioProgressListener;
use FFMpeg\FFProbe\DataMapping\Format;
class AudioProgressListenerTest extends TestCase
{
/**
* @dataProvider provideData
*/
public function testHandle($size, $duration,
$data, $expectedPercent, $expectedRemaining, $expectedRate,
$data2, $expectedPercent2, $expectedRemaining2, $expectedRate2,
$currentPass, $totalPass
)
{
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('format')
->with(__FILE__)
->will($this->returnValue(new Format(array(
'size' => $size,
'duration' => $duration,
))));
$listener = new AudioProgressListener($ffprobe, __FILE__, $currentPass, $totalPass);
$phpunit = $this;
$n = 0;
$listener->on('progress', function ($percent, $remaining, $rate) use (&$n, $phpunit, $expectedPercent, $expectedRemaining, $expectedRate, $expectedPercent2, $expectedRemaining2, $expectedRate2) {
if (0 === $n) {
$phpunit->assertEquals($expectedPercent, $percent);
$phpunit->assertEquals($expectedRemaining, $remaining);
$phpunit->assertEquals($expectedRate, $rate);
} elseif (1 === $n) {
$phpunit->assertEquals($expectedPercent2, $percent);
$phpunit->assertEquals($expectedRemaining2, $remaining);
$phpunit->assertLessThan($expectedRate2 + 3, $rate);
$phpunit->assertGreaterThan($expectedRate2 - 3, $rate);
}
$n++;
});
// first one does not trigger progress event
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data2);
$this->assertEquals(2, $n);
}
public function provideData()
{
return array(
array(
2894412,
180.900750,
'size= 712kB time=00:00:45.50 bitrate= 128.1kbits/s',
25,
0,
0,
'size= 1274kB time=00:01:29.32 bitrate= 142.8kbits/s',
49,
2,
563,
1,
1
),
array(
2894412,
180.900750,
'size= 712kB time=00:00:45.50 bitrate= 128.1kbits/s',
12,
0,
0,
'size= 1274kB time=00:01:29.32 bitrate= 142.8kbits/s',
24,
2,
563,
1,
2
)
);
}
}

View file

@ -0,0 +1,87 @@
<?php
namespace FFMpeg\Tests\Format\ProgressListener;
use FFMpeg\Tests\TestCase;
use FFMpeg\Format\ProgressListener\VideoProgressListener;
use FFMpeg\FFProbe\DataMapping\Format;
class VideoProgressListenerTest extends TestCase
{
/**
* @dataProvider provideData
*/
public function testHandle($size, $duration,
$data, $expectedPercent, $expectedRemaining, $expectedRate,
$data2, $expectedPercent2, $expectedRemaining2, $expectedRate2,
$currentPass, $totalPass
)
{
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('format')
->with(__FILE__)
->will($this->returnValue(new Format(array(
'size' => $size,
'duration' => $duration,
))));
$listener = new VideoProgressListener($ffprobe, __FILE__, $currentPass, $totalPass);
$phpunit = $this;
$n = 0;
$listener->on('progress', function ($percent, $remaining, $rate) use (&$n, $phpunit, $expectedPercent, $expectedRemaining, $expectedRate, $expectedPercent2, $expectedRemaining2, $expectedRate2) {
if (0 === $n) {
$phpunit->assertEquals($expectedPercent, $percent);
$phpunit->assertEquals($expectedRemaining, $remaining);
$phpunit->assertEquals($expectedRate, $rate);
} elseif (1 === $n) {
$phpunit->assertEquals($expectedPercent2, $percent);
$phpunit->assertEquals($expectedRemaining2, $remaining);
$phpunit->assertLessThan($expectedRate2 + 10, $rate);
$phpunit->assertGreaterThan($expectedRate2 - 10, $rate);
}
$n++;
});
// first one does not trigger progress event
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data2);
$this->assertEquals(2, $n);
}
public function provideData()
{
return array(
array(
147073958,
281.147533,
'frame= 206 fps=202 q=10.0 size= 571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0',
2,
0,
0,
'frame= 854 fps=113 q=20.0 size= 4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0',
11,
32,
3868,
1,
1
),
array(
147073958,
281.147533,
'frame= 206 fps=202 q=10.0 size= 571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0',
1,
0,
0,
'frame= 854 fps=113 q=20.0 size= 4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0',
5,
32,
3868,
1,
2
)
);
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Tests\Format\Video;
use FFMpeg\Format\Video\Ogg;
class OggTest extends VideoTestCase
{
public function getFormat()
{
return new Ogg();
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace FFMpeg\Tests\Format\Video;
use FFMpeg\Tests\Format\Audio\AudioTestCase;
abstract class VideoTestCase extends AudioTestCase
{
public function testGetVideoCodec()
{
$this->assertScalar($this->getFormat()->getVideoCodec());
$this->assertContains($this->getFormat()->getVideoCodec(), $this->getFormat()->getAvailableVideoCodecs());
}
public function testSupportBFrames()
{
$this->assertInternalType('boolean', $this->getFormat()->supportBFrames());
}
public function testSetVideoCodec()
{
$format = $this->getFormat();
foreach ($format->getAvailableVideoCodecs() as $codec) {
$format->setVideoCodec($codec);
$this->assertEquals($codec, $format->getVideoCodec());
}
}
public function testGetKiloBitrate()
{
$this->assertInternalType('integer', $this->getFormat()->getKiloBitrate());
}
public function testSetKiloBitrate()
{
$format = $this->getFormat();
$format->setKiloBitrate(2560);
$this->assertEquals(2560, $format->getKiloBitrate());
}
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testSetInvalidVideoCodec()
{
$this->getFormat()->setVideoCodec('invalid-random-video-codec');
}
public function testGetAvailableVideoCodecs()
{
$this->assertGreaterThan(0, count($this->getFormat()->getAvailableVideoCodecs()));
}
public function testCreateProgressListener()
{
$media = $this->getMock('FFMpeg\Media\MediaTypeInterface');
$media->expects($this->any())
->method('getPathfile')
->will($this->returnValue(__FILE__));
$format = $this->getFormat();
$ffprobe = $this->getFFProbeMock();
foreach ($format->createProgressListener($media, $ffprobe, 1, 3) as $listener) {
$this->assertInstanceOf('FFMpeg\Format\ProgressListener\VideoProgressListener', $listener);
$this->assertSame($ffprobe, $listener->getFFProbe());
$this->assertSame(__FILE__, $listener->getPathfile());
$this->assertSame(1, $listener->getCurrentPass());
$this->assertSame(3, $listener->getTotalPass());
}
}
public function testGetPasses()
{
$this->assertInternalType('integer', $this->getFormat()->getPasses());
$this->assertGreaterThan(0, $this->getFormat()->getPasses());
}
public function testGetModulus()
{
$this->assertInternalType('integer', $this->getFormat()->getModulus());
$this->assertGreaterThan(0, $this->getFormat()->getModulus());
$this->assertEquals(0, $this->getFormat()->getModulus() % 2);
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Tests\Format\Video;
use FFMpeg\Format\Video\WMV3;
class WMV3Test extends VideoTestCase
{
public function getFormat()
{
return new WMV3();
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Tests\Format\Video;
use FFMpeg\Format\Video\WMV;
class WMVTest extends VideoTestCase
{
public function getFormat()
{
return new WMV();
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Tests\Format\Video;
use FFMpeg\Format\Video\WebM;
class WebMTest extends VideoTestCase
{
public function getFormat()
{
return new WebM();
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace FFMpeg\Tests\Format\Video;
use FFMpeg\Format\Video\X264;
class X264Test extends VideoTestCase
{
public function getFormat()
{
return new X264();
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace FFMpeg\Tests\Media;
use FFMpeg\Tests\TestCase;
abstract class AbstractMediaTestCase extends TestCase
{
abstract public function testWithInvalidFile();
}

View file

@ -0,0 +1,38 @@
<?php
namespace FFMpeg\Tests\Media;
abstract class AbstractStreamableTestCase extends AbstractMediaTestCase
{
public function testGetStreams()
{
$classname = $this->getClassName();
$ffprobe = $this->getFFProbeMock();
$format = $this->getFormatMock();
$ffprobe->expects($this->once())
->method('format')
->with(__FILE__)
->will($this->returnValue($format));
$media = new $classname(__FILE__, $this->getFFMpegDriverMock(), $ffprobe);
$this->assertSame($format, $media->getFormat());
}
public function testGetFormat()
{
$classname = $this->getClassName();
$ffprobe = $this->getFFProbeMock();
$streams = $this->getStreamCollectionMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue($streams));
$media = new $classname(__FILE__, $this->getFFMpegDriverMock(), $ffprobe);
$this->assertSame($streams, $media->getStreams());
}
abstract protected function getClassName();
}

View file

@ -0,0 +1,268 @@
<?php
namespace FFMpeg\Tests\Media;
use FFMpeg\Media\Audio;
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\AudioInterface;
class AudioTest extends AbstractStreamableTestCase
{
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testWithInvalidFile()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
new Audio('/no/file', $driver, $ffprobe);
}
public function testFiltersReturnsAudioFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$audio = new Audio(__FILE__, $driver, $ffprobe);
$this->assertInstanceOf('FFMpeg\Filters\Audio\AudioFilters', $audio->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$audio = new Audio(__FILE__, $driver, $ffprobe);
$audio->setFiltersCollection($filters);
$filter = $this->getMock('FFMpeg\Filters\Audio\AudioFilterInterface');
$filters->expects($this->once())
->method('add')
->with($filter);
$audio->addFilter($filter);
}
public function testSaveWithFailure()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMock('FFMpeg\Format\AudioInterface');
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$failure = new ExecutionFailureException('failed to encode');
$driver->expects($this->once())
->method('command')
->will($this->throwException($failure));
$audio = new Audio(__FILE__, $driver, $ffprobe);
$this->setExpectedException('FFMpeg\Exception\RuntimeException');
$audio->save($format, $outputPathfile);
}
public function testSaveAppliesFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMock('FFMpeg\Format\AudioInterface');
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$audio = new Audio(__FILE__, $driver, $ffprobe);
$filter = $this->getMock('FFMpeg\Filters\Audio\AudioFilterInterface');
$filter->expects($this->once())
->method('apply')
->with($audio, $format)
->will($this->returnValue(array('extra-filter-command')));
$capturedCommands = array();
$driver->expects($this->once())
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands) {
$capturedCommands[] = $commands;
}));
$audio->addFilter($filter);
$audio->save($format, $outputPathfile);
foreach ($capturedCommands as $commands) {
$this->assertEquals('-y', $commands[0]);
$this->assertEquals('-i', $commands[1]);
$this->assertEquals(__FILE__, $commands[2]);
$this->assertEquals('extra-filter-command', $commands[3]);
}
}
/**
* @dataProvider provideSaveData
*/
public function testSaveShouldSave($threads, $expectedCommands, $expectedListeners, $format)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->once())
->method('has')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue($threads));
if ($threads) {
$configuration->expects($this->once())
->method('get')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue(24));
} else {
$configuration->expects($this->never())
->method('get');
}
$capturedCommand = $capturedListeners = null;
$driver->expects($this->once())
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommand, &$capturedListeners) {
$capturedCommand = $commands;
$capturedListeners = $listeners;
}));
$outputPathfile = '/target/file';
$audio = new Audio(__FILE__, $driver, $ffprobe);
$audio->save($format, $outputPathfile);
$this->assertEquals($expectedCommands, $capturedCommand);
$this->assertEquals($expectedListeners, $capturedListeners);
}
public function provideSaveData()
{
$format = $this->getMock('FFMpeg\Format\AudioInterface');
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$format->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(663));
$audioFormat = $this->getMock('FFMpeg\Format\AudioInterface');
$audioFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$audioFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(664));
$audioFormat->expects($this->any())
->method('getAudioCodec')
->will($this->returnValue('patati-patata-audio'));
$formatExtra = $this->getMock('FFMpeg\Format\AudioInterface');
$formatExtra->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array('extra', 'param')));
$formatExtra->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(665));
$listeners = array($this->getMock('Alchemy\BinaryDriver\Listeners\ListenerInterface'));
$progressableFormat = $this->getMockBuilder('FFMpeg\Tests\Media\AudioProg')
->disableOriginalConstructor()->getMock();
$progressableFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$progressableFormat->expects($this->any())
->method('createProgressListener')
->will($this->returnValue($listeners));
$progressableFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(666));
return array(
array(false, array(
'-y', '-i', __FILE__,
'-b:a', '663k',
'/target/file',
), null, $format),
array(false, array(
'-y', '-i', __FILE__,
'-acodec', 'patati-patata-audio',
'-b:a', '664k',
'/target/file',
), null, $audioFormat),
array(false, array(
'-y', '-i', __FILE__,
'extra', 'param',
'-b:a', '665k',
'/target/file',
), null, $formatExtra),
array(true, array(
'-y', '-i', __FILE__,
'-threads', 24,
'-b:a', '663k',
'/target/file',
), null, $format),
array(true, array(
'-y', '-i', __FILE__,
'extra', 'param',
'-threads', 24,
'-b:a', '665k',
'/target/file',
), null, $formatExtra),
array(false, array(
'-y', '-i', __FILE__,
'-b:a', '666k',
'/target/file',
), $listeners, $progressableFormat),
array(true, array(
'-y', '-i', __FILE__,
'-threads', 24,
'-b:a', '666k',
'/target/file',
), $listeners, $progressableFormat),
);
}
public function getClassName()
{
return 'FFMpeg\Media\Audio';
}
}
abstract class AudioProg implements ProgressableInterface, AudioInterface
{
}

View file

@ -0,0 +1,98 @@
<?php
namespace FFMpeg\Tests\Media;
use FFMpeg\Media\Frame;
class FrameTest extends AbstractMediaTestCase
{
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testWithInvalidFile()
{
new Frame('/No/file', $this->getFFMpegDriverMock(), $this->getFFProbeMock(), $this->getTimeCodeMock());
}
public function testGetTimeCode()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$frame = new Frame(__FILE__, $driver, $ffprobe, $timecode);
$this->assertSame($timecode, $frame->getTimeCode());
}
public function testFiltersReturnFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$frame = new Frame(__FILE__, $driver, $ffprobe, $timecode);
$this->assertInstanceOf('FFMpeg\Filters\Frame\FrameFilters', $frame->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$filter = $this->getMock('FFMpeg\Filters\Frame\FrameFilterInterface');
$filters->expects($this->once())
->method('add')
->with($filter);
$frame = new Frame(__FILE__, $driver, $ffprobe, $timecode);
$frame->setFiltersCollection($filters);
$frame->addFilter($filter);
}
/**
* @dataProvider provideSaveAsOptions
*/
public function testSaveAs($accurate, $commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$timecode->expects($this->once())
->method('__toString')
->will($this->returnValue('timecode'));
$pathfile = '/target/destination';
array_push($commands, $pathfile);
$driver->expects($this->once())
->method('command')
->with($commands);
$frame = new Frame(__FILE__, $driver, $ffprobe, $timecode);
$this->assertSame($frame, $frame->saveAs($pathfile, $accurate));
}
public function provideSaveAsOptions()
{
return array(
array(false, array(
'-ss', 'timecode',
'-i', __FILE__,
'-vframes', '1',
'-f', 'image2')
),
array(true, array(
'-i', __FILE__,
'-vframes', '1', '-ss', 'timecode',
'-f', 'image2'
)),
);
}
}

View file

@ -0,0 +1,394 @@
<?php
namespace FFMpeg\Tests\Media;
use FFMpeg\Media\Video;
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\VideoInterface;
class VideoTest extends AbstractStreamableTestCase
{
/**
* @expectedException FFMpeg\Exception\InvalidArgumentException
*/
public function testWithInvalidFile()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
new Video('/no/file', $driver, $ffprobe);
}
public function testFiltersReturnsVideoFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$video = new Video(__FILE__, $driver, $ffprobe);
$this->assertInstanceOf('FFMpeg\Filters\Video\VideoFilters', $video->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$video = new Video(__FILE__, $driver, $ffprobe);
$video->setFiltersCollection($filters);
$filter = $this->getMock('FFMpeg\Filters\Video\VideoFilterInterface');
$filters->expects($this->once())
->method('add')
->with($filter);
$video->addFilter($filter);
}
public function testFrameShouldReturnAFrame()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$at = $this->getTimeCodeMock();
$video = new Video(__FILE__, $driver, $ffprobe);
$frame = $video->frame($at);
$this->assertInstanceOf('FFMpeg\Media\Frame', $frame);
$this->assertSame($at, $frame->getTimeCode());
$this->assertSame(__FILE__, $frame->getPathfile());
}
public function testSaveWithFailure()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMock('FFMpeg\Format\VideoInterface');
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$failure = new ExecutionFailureException('failed to encode');
$driver->expects($this->once())
->method('command')
->will($this->throwException($failure));
$video = new Video(__FILE__, $driver, $ffprobe);
$this->setExpectedException('FFMpeg\Exception\RuntimeException');
$video->save($format, $outputPathfile);
}
public function testSaveAppliesFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMock('FFMpeg\Format\VideoInterface');
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$video = new Video(__FILE__, $driver, $ffprobe);
$filter = $this->getMock('FFMpeg\Filters\Video\VideoFilterInterface');
$filter->expects($this->once())
->method('apply')
->with($video, $format)
->will($this->returnValue(array('extra-filter-command')));
$capturedCommands = array();
$driver->expects($this->exactly(2))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands) {
$capturedCommands[] = $commands;
}));
$video->addFilter($filter);
$video->save($format, $outputPathfile);
foreach ($capturedCommands as $commands) {
$this->assertEquals('-y', $commands[0]);
$this->assertEquals('-i', $commands[1]);
$this->assertEquals(__FILE__, $commands[2]);
$this->assertEquals('extra-filter-command', $commands[3]);
}
}
/**
* @dataProvider provideSaveData
*/
public function testSaveShouldSave($threads, $expectedCommands, $expectedListeners, $format)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->once())
->method('has')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue($threads));
if ($threads) {
$configuration->expects($this->once())
->method('get')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue(24));
} else {
$configuration->expects($this->never())
->method('get');
}
$capturedCommands = array();
$capturedListeners = null;
$driver->expects($this->exactly(2))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands, &$capturedListeners) {
$capturedCommands[] = $commands;
$capturedListeners = $listeners;
}));
$outputPathfile = '/target/file';
$video = new Video(__FILE__, $driver, $ffprobe);
$video->save($format, $outputPathfile);
$prefix = null;
foreach ($capturedCommands as $passKey => $pass) {
foreach ($pass as $command) {
if (0 === strpos($command, 'pass-')) {
$prefix = $command;
break;
}
}
if (null === $prefix) {
$this->fail('Unable to find pass prefix command.');
}
$found = false;
foreach ($pass as $key => $command) {
if ($command === $prefix) {
$found = true;
unset($capturedCommands[$passKey][$key]);
$capturedCommands[$passKey] = array_values($capturedCommands[$passKey]);
break;
}
}
if (!$found) {
$this->fail('Unable to find pass prefix command back.');
}
}
$this->assertEquals($expectedCommands, $capturedCommands);
$this->assertEquals($expectedListeners, $capturedListeners);
}
public function provideSaveData()
{
$format = $this->getMock('FFMpeg\Format\VideoInterface');
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$format->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(663));
$format->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$audioVideoFormat = $this->getMock('FFMpeg\Format\VideoInterface');
$audioVideoFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$audioVideoFormat->expects($this->any())
->method('getVideoCodec')
->will($this->returnValue('gloubi-boulga-video'));
$audioVideoFormat->expects($this->any())
->method('getAudioCodec')
->will($this->returnValue('patati-patata-audio'));
$audioVideoFormat->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(664));
$audioVideoFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$formatExtra = $this->getMock('FFMpeg\Format\VideoInterface');
$formatExtra->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array('extra', 'param')));
$formatExtra->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(665));
$formatExtra->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$listeners = array($this->getMock('Alchemy\BinaryDriver\Listeners\ListenerInterface'));
$progressableFormat = $this->getMockBuilder('FFMpeg\Tests\Media\Prog')
->disableOriginalConstructor()->getMock();
$progressableFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$progressableFormat->expects($this->any())
->method('createProgressListener')
->will($this->returnValue($listeners));
$progressableFormat->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(666));
$progressableFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
return array(
array(false, array(array(
'-y', '-i', __FILE__, '-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '1', '-passlogfile',
'-an', '/target/file',
), array(
'-y', '-i', __FILE__,
'-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'-ac', '2', '-ar', '44100', '/target/file',
)), null, $format),
array(false, array(array(
'-y', '-i', __FILE__,
'-vcodec', 'gloubi-boulga-video',
'-acodec', 'patati-patata-audio', '-b:v', '664k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '1', '-passlogfile',
'-an', '/target/file',
), array(
'-y', '-i', __FILE__,
'-vcodec', 'gloubi-boulga-video',
'-acodec', 'patati-patata-audio',
'-b:v', '664k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'-ac', '2', '-ar', '44100', '/target/file',
)), null, $audioVideoFormat),
array(false, array(array(
'-y', '-i', __FILE__,
'extra', 'param','-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '1', '-passlogfile',
'-an', '/target/file',
), array(
'-y', '-i', __FILE__,
'extra', 'param', '-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'-ac', '2', '-ar', '44100', '/target/file',
)), null, $formatExtra),
array(true, array(array(
'-y', '-i', __FILE__,
'-threads', 24, '-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '1', '-passlogfile',
'-an', '/target/file',
), array(
'-y', '-i', __FILE__,
'-threads', 24,
'-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'-ac', '2', '-ar', '44100', '/target/file',
)), null, $format),
array(true, array(array(
'-y', '-i', __FILE__,
'extra', 'param', '-threads', 24, '-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '1', '-passlogfile',
'-an', '/target/file',
), array(
'-y', '-i', __FILE__,
'extra', 'param', '-threads', 24, '-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'-ac', '2', '-ar', '44100', '/target/file',
)), null, $formatExtra),
array(false, array(array(
'-y', '-i', __FILE__, '-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '1', '-passlogfile',
'-an', '/target/file',
), array(
'-y', '-i', __FILE__,
'-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'-ac', '2', '-ar', '44100', '/target/file',
)), $listeners, $progressableFormat),
array(true, array(array(
'-y', '-i', __FILE__,
'-threads', 24, '-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '1', '-passlogfile',
'-an', '/target/file',
), array(
'-y', '-i', __FILE__,
'-threads', 24,
'-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'-ac', '2', '-ar', '44100', '/target/file',
)), $listeners, $progressableFormat),
);
}
public function getClassName()
{
return 'FFMpeg\Media\Video';
}
}
abstract class Prog implements ProgressableInterface, VideoInterface
{
}

View file

@ -0,0 +1,131 @@
<?php
namespace FFMpeg\Tests;
class TestCase extends \PHPUnit_Framework_TestCase
{
public function assertScalar($value)
{
$this->assertTrue(is_scalar($value));
}
public function getLoggerMock()
{
return $this->getMock('Psr\Log\LoggerInterface');
}
public function getCacheMock()
{
return $this->getMock('Doctrine\Common\Cache\Cache');
}
public function getTimeCodeMock()
{
return $this->getMockBuilder('FFMpeg\Coordinate\TimeCode')
->disableOriginalConstructor()
->getMock();
}
public function getDimensionMock()
{
return $this->getMockBuilder('FFMpeg\Coordinate\Dimension')
->disableOriginalConstructor()
->getMock();
}
public function getFramerateMock()
{
return $this->getMockBuilder('FFMpeg\Coordinate\Framerate')
->disableOriginalConstructor()
->getMock();
}
public function getFFMpegDriverMock()
{
return $this->getMockBuilder('FFMpeg\Driver\FFMpegDriver')
->disableOriginalConstructor()
->getMock();
}
public function getFFProbeDriverMock()
{
return $this->getMockBuilder('FFMpeg\Driver\FFProbeDriver')
->disableOriginalConstructor()
->getMock();
}
public function getFFProbeMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe')
->disableOriginalConstructor()
->getMock();
}
public function getStreamMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\DataMapping\Stream')
->disableOriginalConstructor()
->getMock();
}
public function getFFProbeParserMock()
{
return $this->getMock('FFMpeg\FFProbe\OutputParserInterface');
}
public function getFFProbeOptionsTesterMock()
{
return $this->getMock('FFMpeg\FFProbe\OptionsTesterInterface');
}
public function getFFProbeMapperMock()
{
return $this->getMock('FFMpeg\FFProbe\MapperInterface');
}
public function getFFProbeOptionsTesterMockWithOptions(array $options)
{
$tester = $this->getFFProbeOptionsTesterMock();
$tester->expects($this->any())
->method('has')
->will($this->returnCallback(function ($option) use ($options) {
return in_array($option, $options);
}));
return $tester;
}
public function getConfigurationMock()
{
return $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
}
public function getFormatMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\DataMapping\Format')
->disableOriginalConstructor()
->getMock();
}
public function getStreamCollectionMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\DataMapping\StreamCollection')
->disableOriginalConstructor()
->getMock();
}
protected function getAudioMock()
{
return $this->getMockBuilder('FFMpeg\Media\Audio')
->disableOriginalConstructor()
->getMock();
}
protected function getVideoMock()
{
return $this->getMockBuilder('FFMpeg\Media\Video')
->disableOriginalConstructor()
->getMock();
}
}

5
tests/bootstrap.php Normal file
View file

@ -0,0 +1,5 @@
<?php
$loader = require __DIR__.'/../vendor/autoload.php';
$loader->add('FFMpeg\Tests', __DIR__);
$loader->add('FFMpeg\Functional', __DIR__);

512
tests/fixtures/ffprobe/help.raw vendored Normal file
View file

@ -0,0 +1,512 @@
Simple multimedia streams analyzer
usage: ffprobe [OPTIONS] [INPUT_FILE]
Main options:
-L show license
-h topic show help
-? topic show help
-help topic show help
--help topic show help
-version show version
-formats show available formats
-codecs show available codecs
-decoders show available decoders
-encoders show available encoders
-bsfs show available bit stream filters
-protocols show available protocols
-filters show available filters
-pix_fmts show available pixel formats
-layouts show standard channel layouts
-sample_fmts show available audio sample formats
-loglevel loglevel set libav* logging level
-v loglevel set libav* logging level
-report generate a report
-max_alloc bytes set maximum size of a single allocated block
-cpuflags flags force specific cpu flags
-f format force format
-unit show unit of the displayed values
-prefix use SI prefixes for the displayed values
-byte_binary_prefix use binary prefixes for byte units
-sexagesimal use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units
-pretty prettify the format of displayed values, make it more human readable
-print_format format set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)
-of format alias for -print_format
-select_streams stream_specifier select the specified streams
-sections print sections structure and section information, and exit
-show_data show packets data
-show_error show probing error
-show_format show format/container info
-show_frames show frames info
-show_format_entry entry show a particular entry from the format/container info
-show_entries entry_list show a set of specified entries
-show_packets show packets info
-show_streams show streams info
-count_frames count the number of frames per stream
-count_packets count the number of packets per stream
-show_program_version show ffprobe version
-show_library_versions show library versions
-show_versions show program and library versions
-show_private_data show private data
-private same as show_private_data
-bitexact force bitexact output
-default generic catch all option
-i input_file read specified file
AVFormatContext AVOptions:
-avioflags <flags> ED....
direct ED.... reduce buffering
-probesize <int> .D.... set probing size (from 32 to INT_MAX)
-fflags <flags> ED....
ignidx .D.... ignore index
genpts .D.... generate pts
nofillin .D.... do not fill in missing values that can be exactly calculated
noparse .D.... disable AVParsers, this needs nofillin too
igndts .D.... ignore dts
discardcorrupt .D.... discard corrupted frames
sortdts .D.... try to interleave outputted packets by dts
keepside .D.... dont merge side data
nobuffer .D.... reduce the latency introduced by optional buffering
-seek2any <int> .D.... forces seeking to enable seek to any mode (from 0 to 1)
-analyzeduration <int> .D.... specify how many microseconds are analyzed to probe the input (from 0 to INT_MAX)
-cryptokey <binary> .D.... decryption key
-indexmem <int> .D.... max memory used for timestamp index (per stream) (from 0 to INT_MAX)
-rtbufsize <int> .D.... max memory used for buffering real-time frames (from 0 to INT_MAX)
-fdebug <flags> ED.... print specific debug info
ts ED....
-max_delay <int> ED.... maximum muxing or demuxing delay in microseconds (from -1 to INT_MAX)
-fpsprobesize <int> .D.... number of frames used to probe fps (from -1 to 2.14748e+09)
-f_err_detect <flags> .D.... set error detection flags (deprecated; use err_detect, save via avconv)
crccheck .D.... verify embedded CRCs
bitstream .D.... detect bitstream specification deviations
buffer .D.... detect improper bitstream length
explode .D.... abort decoding on minor error detection
careful .D.... consider things that violate the spec and have not been seen in the wild as errors
compliant .D.... consider all spec non compliancies as errors
aggressive .D.... consider things that a sane encoder shouldnt do as an error
-err_detect <flags> .D.... set error detection flags
crccheck .D.... verify embedded CRCs
bitstream .D.... detect bitstream specification deviations
buffer .D.... detect improper bitstream length
explode .D.... abort decoding on minor error detection
careful .D.... consider things that violate the spec and have not been seen in the wild as errors
compliant .D.... consider all spec non compliancies as errors
aggressive .D.... consider things that a sane encoder shouldnt do as an error
-use_wallclock_as_timestamps <int> .D.... use wallclock as timestamps (from 0 to 2.14748e+09)
-skip_initial_bytes <int> .D.... skip initial bytes (from 0 to 2.14748e+09)
-correct_ts_overflow <int> .D.... correct single timestamp overflows (from 0 to 1)
AVIOContext AVOptions:
URLContext AVOptions:
crypto AVOptions:
-key <binary> .D.... AES decryption key
-iv <binary> .D.... AES decryption initialization vector
ffrtmphttp AVOptions:
-ffrtmphttp_tls <int> .D.... Use a HTTPS tunneling connection (RTMPTS). (from 0 to 1)
file AVOptions:
http AVOptions:
-seekable <int> .D.... control seekability of connection (from -1 to 1)
-headers <string> ED.... set custom HTTP headers, can override built in default headers
-content_type <string> ED.... force a content type
-user-agent <string> .D.... override User-Agent header
-multiple_requests <int> ED.... use persistent connections (from 0 to 1)
-post_data <binary> ED.... set custom HTTP post data
-timeout <int> ED.... set timeout of socket I/O operations (from -1 to INT_MAX)
rtmp AVOptions:
-rtmp_app <string> ED.... Name of application to connect to on the RTMP server
-rtmp_buffer <int> ED.... Set buffer time in milliseconds. The default is 3000. (from 0 to INT_MAX)
-rtmp_conn <string> ED.... Append arbitrary AMF data to the Connect message
-rtmp_flashver <string> ED.... Version of the Flash plugin used to run the SWF player.
-rtmp_live <int> .D.... Specify that the media is a live stream. (from INT_MIN to INT_MAX)
any .D.... both
live .D.... live stream
recorded .D.... recorded stream
-rtmp_pageurl <string> .D.... URL of the web page in which the media was embedded. By default no value will be sent.
-rtmp_playpath <string> ED.... Stream identifier to play or to publish
-rtmp_subscribe <string> .D.... Name of live stream to subscribe to. Defaults to rtmp_playpath.
-rtmp_swfhash <binary> .D.... SHA256 hash of the decompressed SWF file (32 bytes).
-rtmp_swfsize <int> .D.... Size of the decompressed SWF file, required for SWFVerification. (from 0 to INT_MAX)
-rtmp_swfurl <string> ED.... URL of the SWF player. By default no value will be sent
-rtmp_swfverify <string> .D.... URL to player swf file, compute hash/size automatically.
-rtmp_tcurl <string> ED.... URL of the target stream. Defaults to proto://host[:port]/app.
-rtmp_listen <int> .D.... Listen for incoming rtmp connections (from INT_MIN to INT_MAX)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1 (from INT_MIN to INT_MAX)
rtmpt AVOptions:
-rtmp_app <string> ED.... Name of application to connect to on the RTMP server
-rtmp_buffer <int> ED.... Set buffer time in milliseconds. The default is 3000. (from 0 to INT_MAX)
-rtmp_conn <string> ED.... Append arbitrary AMF data to the Connect message
-rtmp_flashver <string> ED.... Version of the Flash plugin used to run the SWF player.
-rtmp_live <int> .D.... Specify that the media is a live stream. (from INT_MIN to INT_MAX)
any .D.... both
live .D.... live stream
recorded .D.... recorded stream
-rtmp_pageurl <string> .D.... URL of the web page in which the media was embedded. By default no value will be sent.
-rtmp_playpath <string> ED.... Stream identifier to play or to publish
-rtmp_subscribe <string> .D.... Name of live stream to subscribe to. Defaults to rtmp_playpath.
-rtmp_swfhash <binary> .D.... SHA256 hash of the decompressed SWF file (32 bytes).
-rtmp_swfsize <int> .D.... Size of the decompressed SWF file, required for SWFVerification. (from 0 to INT_MAX)
-rtmp_swfurl <string> ED.... URL of the SWF player. By default no value will be sent
-rtmp_swfverify <string> .D.... URL to player swf file, compute hash/size automatically.
-rtmp_tcurl <string> ED.... URL of the target stream. Defaults to proto://host[:port]/app.
-rtmp_listen <int> .D.... Listen for incoming rtmp connections (from INT_MIN to INT_MAX)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1 (from INT_MIN to INT_MAX)
srtp AVOptions:
tcp AVOptions:
-listen <int> ED.... listen on port instead of connecting (from 0 to 1)
-timeout <int> ED.... timeout of socket i/o operations (from 0 to INT_MAX)
-listen_timeout <int> ED.... connection awaiting timeout (from -1 to INT_MAX)
udp AVOptions:
-buffer_size <int> ED.... Socket buffer size in bytes (from 0 to INT_MAX)
-localport <int> ED.... Set local port to bind to (from 0 to INT_MAX)
-localaddr <string> ED.... Choose local IP address
-pkt_size <int> ED.... Set size of UDP packets (from 0 to INT_MAX)
-reuse <int> ED.... Explicitly allow or disallow reusing UDP sockets (from 0 to 1)
-connect <int> ED.... Should connect() be called on socket (from 0 to 1)
-fifo_size <int> .D.... Set the UDP receiving circular buffer size, expressed as a number of packets with size of 188 bytes (from 0 to INT_MAX)
-overrun_nonfatal <int> .D.... Survive in case of UDP receiving circular buffer overrun (from 0 to 1)
-timeout <int> .D.... In read mode: if no data arrived in more than this time interval, raise error (from 0 to INT_MAX)
Artworx Data Format demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
aqtdec AVOptions:
-subfps <rational> .D...S set the movie frame rate (from 0 to INT_MAX)
asf demuxer AVOptions:
-no_resync_search <int> .D.... Don't try to resynchronize by looking for a certain optional start code (from 0 to 1)
avi AVOptions:
-use_odml <int> .D.... use odml index (from -1 to 1)
Binary text demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
cavsvideo demuxer AVOptions:
-framerate <string> .D....
CDXL demuxer AVOptions:
-sample_rate <int> .D.... (from 1 to INT_MAX)
-framerate <string> .D....
concat demuxer AVOptions:
-safe <int> .D.... enable safe mode (from -1 to 1)
dirac demuxer AVOptions:
-framerate <string> .D....
dnxhd demuxer AVOptions:
-framerate <string> .D....
flvdec AVOptions:
-flv_metadata <int> .D.V.. Allocate streams according the onMetaData array (from 0 to 1)
g729 demuxer AVOptions:
-bit_rate <int> .D.... (from 0 to INT_MAX)
GIF demuxer AVOptions:
-min_delay <int> .D.... minimum valid delay between frames (in hundredths of second) (from 0 to 6000)
-default_delay <int> .D.... default delay between frames (in hundredths of second) (from 0 to 6000)
gsm demuxer AVOptions:
-sample_rate <int> .D.... (from 1 to 6.50753e+07)
h261 demuxer AVOptions:
-framerate <string> .D....
h263 demuxer AVOptions:
-framerate <string> .D....
h264 demuxer AVOptions:
-framerate <string> .D....
iCE Draw File demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
image2 demuxer AVOptions:
-framerate <string> .D.... set the video framerate
-loop <int> .D.... force loop over input file sequence (from 0 to 1)
-pattern_type <int> .D.... set pattern type (from 0 to INT_MAX)
glob_sequence .D.... select glob/sequence pattern type
glob .D.... select glob pattern type
sequence .D.... select sequence pattern type
-pixel_format <string> .D.... set video pixel format
-start_number <int> .D.... set first number in the sequence (from 0 to INT_MAX)
-start_number_range <int> .D.... set range for looking at the first sequence number (from 1 to INT_MAX)
-video_size <string> .D.... set video size
-frame_size <int> .D.... force frame size in bytes (from 0 to INT_MAX)
image2pipe demuxer AVOptions:
-framerate <string> .D.... set the video framerate
-loop <int> .D.... force loop over input file sequence (from 0 to 1)
-pattern_type <int> .D.... set pattern type (from 0 to INT_MAX)
glob_sequence .D.... select glob/sequence pattern type
glob .D.... select glob pattern type
sequence .D.... select sequence pattern type
-pixel_format <string> .D.... set video pixel format
-start_number <int> .D.... set first number in the sequence (from 0 to INT_MAX)
-start_number_range <int> .D.... set range for looking at the first sequence number (from 1 to INT_MAX)
-video_size <string> .D.... set video size
-frame_size <int> .D.... force frame size in bytes (from 0 to INT_MAX)
ingenient demuxer AVOptions:
-framerate <string> .D....
m4v demuxer AVOptions:
-framerate <string> .D....
mjpeg demuxer AVOptions:
-framerate <string> .D....
mov,mp4,m4a,3gp,3g2,mj2 AVOptions:
-use_absolute_path <int> .D.V.. allow using absolute path when opening alias, this is a possible security issue (from 0 to 1)
-ignore_editlist <int> .D.V.. (from 0 to 1)
mpegtsraw demuxer AVOptions:
-compute_pcr <int> .D.... Compute exact PCR for each transport stream packet. (from 0 to 1)
mpegvideo demuxer AVOptions:
-framerate <string> .D....
alaw demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
mulaw demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f64be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f64le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f32be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f32le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s32be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s32le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s24be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s24le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s16be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s16le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s8 demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u32be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u32le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u24be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u24le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u16be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u16le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u8 demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
rawvideo demuxer AVOptions:
-video_size <string> .D.... set frame size
-pixel_format <string> .D.... set pixel format
-framerate <string> .D.... set frame rate
RTP demuxer AVOptions:
-rtp_flags <flags> .D.... RTP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
RTSP demuxer AVOptions:
-initial_pause <int> .D.... Don't start playing the stream immediately (from 0 to 1)
-rtsp_transport <flags> ED.... RTSP transport protocols
udp ED.... UDP
tcp ED.... TCP
udp_multicast .D.... UDP multicast
http .D.... HTTP tunneling
-rtsp_flags <flags> .D.... RTSP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
-allowed_media_types <flags> .D.... Media types to accept from the server
video .D.... Video
audio .D.... Audio
data .D.... Data
-min_port <int> ED.... Minimum local UDP port (from 0 to 65535)
-max_port <int> ED.... Maximum local UDP port (from 0 to 65535)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen (from INT_MIN to INT_MAX)
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
sbg_demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-frame_size <int> .D.... (from 0 to INT_MAX)
-max_file_size <int> .D.... (from 0 to INT_MAX)
SDP demuxer AVOptions:
-sdp_flags <flags> .D.... SDP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
custom_io .D.... Use custom IO
-allowed_media_types <flags> .D.... Media types to accept from the server
video .D.... Video
audio .D.... Audio
data .D.... Data
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
tedcaptions_demuxer AVOptions:
-start_time <int64> .D...S set the start time (offset) of the subtitles, in ms (from I64_MIN to I64_MAX)
TTY demuxer AVOptions:
-chars_per_frame <int> .D.... (from 1 to INT_MAX)
-video_size <string> .D.... A string describing frame size, such as 640x480 or hd720.
-framerate <string> .D....
vc1 demuxer AVOptions:
-framerate <string> .D....
WAV demuxer AVOptions:
-ignore_length <int> .D.... Ignore length (from 0 to 1)
eXtended BINary text (XBIN) demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
lavfi indev AVOptions:
-graph <string> .D.... set libavfilter graph
-graph_file <string> .D.... set libavfilter graph filename
-dumpgraph <string> .D.... dump graph to stderr
AIFF muxer AVOptions:
AST muxer AVOptions:
f4v muxer AVOptions:
GIF muxer AVOptions:
hls muxer AVOptions:
image2 muxer AVOptions:
ipod muxer AVOptions:
ismv muxer AVOptions:
LATM/LOAS muxer AVOptions:
mov muxer AVOptions:
MP3 muxer AVOptions:
mp4 muxer AVOptions:
mpeg muxer AVOptions:
vcd muxer AVOptions:
dvd muxer AVOptions:
svcd muxer AVOptions:
vob muxer AVOptions:
MPEGTS muxer AVOptions:
Ogg muxer AVOptions:
psp muxer AVOptions:
RTP muxer AVOptions:
RTSP muxer AVOptions:
-initial_pause <int> .D.... Don't start playing the stream immediately (from 0 to 1)
-rtsp_transport <flags> ED.... RTSP transport protocols
udp ED.... UDP
tcp ED.... TCP
udp_multicast .D.... UDP multicast
http .D.... HTTP tunneling
-rtsp_flags <flags> .D.... RTSP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
-allowed_media_types <flags> .D.... Media types to accept from the server
video .D.... Video
audio .D.... Audio
data .D.... Data
-min_port <int> ED.... Minimum local UDP port (from 0 to 65535)
-max_port <int> ED.... Maximum local UDP port (from 0 to 65535)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen (from INT_MIN to INT_MAX)
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
segment muxer AVOptions:
stream_segment muxer AVOptions:
smooth streaming muxer AVOptions:
spdif AVOptions:
tg2 muxer AVOptions:
tgp muxer AVOptions:
WAV muxer AVOptions:
caca_outdev AVOptions:

20
tests/fixtures/ffprobe/show_format.json vendored Normal file
View file

@ -0,0 +1,20 @@
{
"format": {
"filename": "Interview5mm4500.mp4",
"nb_streams": 2,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime / MOV",
"start_time": "0.000000",
"duration": "300.011000",
"size": "173833712",
"bit_rate": "4635395",
"tags": {
"major_brand": "isom",
"minor_version": "512",
"compatible_brands": "isomiso2avc1mp41",
"creation_time": "1970-01-01 00:00:00",
"title": "5mm 4500.mp4",
"encoder": "Lavf52.108.0"
}
}
}

16
tests/fixtures/ffprobe/show_format.raw vendored Normal file
View file

@ -0,0 +1,16 @@
[FORMAT]
filename=Interview5mm4500.mp4
nb_streams=2
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
start_time=0.000000
duration=300.011000
size=173833712
bit_rate=4635395
TAG:major_brand=isom
TAG:minor_version=512
TAG:compatible_brands=isomiso2avc1mp41
TAG:creation_time=1970-01-01 00:00:00
TAG:title=5mm 4500.mp4
TAG:encoder=Lavf52.108.0
[/FORMAT]

View file

@ -0,0 +1,88 @@
{
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "High",
"codec_type": "video",
"codec_time_base": "1/100",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 960,
"height": 720,
"has_b_frames": 2,
"sample_aspect_ratio": "1:1",
"display_aspect_ratio": "4:3",
"pix_fmt": "yuv420p",
"level": 32,
"r_frame_rate": "50/1",
"avg_frame_rate": "50/1",
"time_base": "1/50000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 15000000,
"duration": "300.000000",
"bit_rate": "4499198",
"nb_frames": "15000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0
},
"tags": {
"creation_time": "1970-01-01 00:00:00",
"language": "und",
"handler_name": "VideoHandler"
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "fltp",
"sample_rate": "48000",
"channels": 2,
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 14400512,
"duration": "300.010667",
"bit_rate": "127973",
"nb_frames": "14063",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0
},
"tags": {
"creation_time": "1970-01-01 00:00:00",
"language": "und",
"handler_name": "SoundHandler"
}
}
]
}

84
tests/fixtures/ffprobe/show_streams.raw vendored Normal file
View file

@ -0,0 +1,84 @@
[STREAM]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
profile=High
codec_type=video
codec_time_base=1/100
codec_tag_string=avc1
codec_tag=0x31637661
width=960
height=720
has_b_frames=2
sample_aspect_ratio=1:1
display_aspect_ratio=4:3
pix_fmt=yuv420p
level=32
timecode=N/A
id=N/A
r_frame_rate=50/1
avg_frame_rate=50/1
time_base=1/50000
start_pts=0
start_time=0.000000
duration_ts=15000000
duration=300.000000
bit_rate=4499198
nb_frames=15000
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
TAG:creation_time=1970-01-01 00:00:00
TAG:language=und
TAG:handler_name=VideoHandler
[/STREAM]
[STREAM]
index=1
codec_name=aac
codec_long_name=AAC (Advanced Audio Coding)
profile=unknown
codec_type=audio
codec_time_base=1/48000
codec_tag_string=mp4a
codec_tag=0x6134706d
sample_fmt=fltp
sample_rate=48000
channels=2
bits_per_sample=0
id=N/A
r_frame_rate=0/0
avg_frame_rate=0/0
time_base=1/48000
start_pts=0
start_time=0.000000
duration_ts=14400512
duration=300.010667
bit_rate=127973
nb_frames=14063
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
TAG:creation_time=1970-01-01 00:00:00
TAG:language=und
TAG:handler_name=SoundHandler
[/STREAM]

View file

@ -1,103 +0,0 @@
<?php
namespace FFMpeg;
use Monolog\Logger;
use Monolog\Handler\NullHandler;
class BinaryTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Binary
*/
protected $object;
protected $logger;
public function setUp()
{
$this->logger = new Logger('tests');
$this->logger->pushHandler(new NullHandler());
}
/**
* @covers FFMpeg\Binary::__construct
* @expectedException \FFMpeg\Exception\BinaryNotFoundException
*/
public function testConstruct()
{
$binary = new BinaryTester('pretty_binary', $this->logger);
}
public function testTimeout()
{
$tester = BinaryTester::load($this->logger, 200);
$this->assertEquals(200, $tester->getTimeout());
}
public function testDefaultTimeout()
{
$tester = BinaryTester::load($this->logger);
$this->assertEquals(60, $tester->getTimeout());
}
public function testNoTimeout()
{
$tester = BinaryTester::load($this->logger, 0);
$this->assertEquals(0, $tester->getTimeout());
}
public function testSetTimeout()
{
$tester = BinaryTester::load($this->logger);
$tester->setTimeout(200);
$this->assertEquals(200, $tester->getTimeout());
}
/**
* @expectedException \FFMpeg\Exception\InvalidArgumentException
*/
public function testSetInvalidTimeout()
{
$tester = BinaryTester::load($this->logger);
$tester->setTimeout(-1);
}
/**
* @covers FFMpeg\Binary::load
*/
public function testLoad()
{
BinaryTester::load($this->logger);
}
/**
* @covers FFMpeg\Binary::load
* @expectedException \FFMpeg\Exception\BinaryNotFoundException
*/
public function testLoadWrongBinary()
{
BinaryTesterWrongBinary::load($this->logger);
}
}
class BinaryTester extends Binary
{
protected static function getBinaryName()
{
return array('php');
}
}
class BinaryTesterWrongBinary extends Binary
{
protected static function getBinaryName()
{
return array('');
}
}

View file

@ -1,83 +0,0 @@
<?php
namespace FFMpeg;
use Monolog\Logger;
use Monolog\Handler\NullHandler;
use Silex\Application;
class FFMpegServiceProviderTest extends \PHPUnit_Framework_TestCase
{
private function getApplication()
{
return new Application();
}
/**
* @covers FFMpeg\FFMpegServiceProvider::register
*/
public function testRegister()
{
$app = $this->getApplication();
$app->register(new FFMpegServiceProvider());
$this->assertInstanceOf('\\FFMpeg\\FFProbe', $app['ffmpeg.ffprobe']);
$this->assertInstanceOf('\\FFMpeg\\FFMpeg', $app['ffmpeg.ffmpeg']);
}
/**
* @expectedException FFMpeg\Exception\BinaryNotFoundException
* @covers FFMpeg\FFMpegServiceProvider::register
*/
public function testRegisterFFMpegFails()
{
$app = $this->getApplication();
$app->register(new FFMpegServiceProvider(), array('ffmpeg.ffmpeg.binary' => '/path/to/no/ffmpeg'));
$app['ffmpeg.ffmpeg'];
}
/**
* @expectedException FFMpeg\Exception\BinaryNotFoundException
* @covers FFMpeg\FFMpegServiceProvider::register
*/
public function testRegisterFFProbeFails()
{
$app = $this->getApplication();
$app->register(new FFMpegServiceProvider(), array('ffmpeg.ffprobe.binary' => '/path/to/no/ffprobe'));
$app['ffmpeg.ffprobe'];
}
/**
* @covers FFMpeg\FFMpegServiceProvider::register
*/
public function testRegisterCustomLogger()
{
$app = $this->getApplication();
$app['logger'] = $app->share(function(Application $app){
$logger = new Logger('tests');
$logger->pushHandler(new NullHandler());
return $logger;
});
$app->register(new FFMpegServiceProvider());
$this->assertInstanceOf('\\FFMpeg\\FFProbe', $app['ffmpeg.ffprobe']);
$this->assertInstanceOf('\\FFMpeg\\FFMpeg', $app['ffmpeg.ffmpeg']);
}
/**
* @covers FFMpeg\FFMpegServiceProvider::register
*/
public function testCustomThreadsFFMpeg()
{
$app = $this->getApplication();
$app->register(new FFMpegServiceProvider(), array('ffmpeg.threads'=>18));
$this->assertEquals(18, $app['ffmpeg.ffmpeg']->getThreads());
}
}

View file

@ -1,238 +0,0 @@
<?php
namespace FFMpeg;
use Monolog\Logger;
use Monolog\Handler\NullHandler;
class FFMpegTest extends \PHPUnit_Framework_TestCase
{
/**
* @var FFMpeg
*/
protected $object;
/**
* @var FFProbe
*/
protected $probe;
protected $logger;
public function setUp()
{
$this->logger = new Logger('tests');
$this->logger->pushHandler(new NullHandler());
$this->object = FFMpeg::load($this->logger);
$this->probe = FFProbe::load($this->logger);
$this->object->setProber($this->probe);
}
/**
* @covers FFMpeg\FFMpeg::open
* @expectedException \InvalidArgumentException
*/
public function testOpenInvalid()
{
$this->object->open(__DIR__ . '/invalid.files');
}
/**
* @covers FFMpeg\FFMpeg::open
*/
public function testOpen()
{
$this->object->open(__DIR__ . '/../../files/Test.ogv');
}
/**
* @covers FFMpeg\FFMpeg::extractImage
*/
public function testExtractImage()
{
$dest = __DIR__ . '/../../files/extract_Test.jpg';
$this->object->open(__DIR__ . '/../../files/Test.ogv');
$this->object->extractImage(2, $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::extractImage
*/
public function testExtractImagePng()
{
$dest = __DIR__ . '/../../files/extract_Test.png';
$this->object->open(__DIR__ . '/../../files/Test.ogv');
$this->object->extractImage(2, $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::extractImage
*/
public function testExtractImageGif()
{
$dest = __DIR__ . '/../../files/extract_Test.gif';
$this->object->open(__DIR__ . '/../../files/Test.ogv');
$this->object->extractImage(2, $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::extractImage
* @expectedException \FFMpeg\Exception\LogicException
*/
public function testExtractImageNoMovie()
{
$this->object->extractImage(2, 'Path');
}
/**
* @covers FFMpeg\FFMpeg::encode
* @expectedException \FFMpeg\Exception\LogicException
*/
public function testEncode()
{
$format = new Format\Video\WebM();
$format-> setDimensions(32, 32);
$this->object->encode($format, './invalid.file');
}
/**
* @covers FFMpeg\FFMpeg::encode
* @expectedException FFMpeg\Exception\BinaryNotFoundException
*/
public function testWrongBinary()
{
$logger = new \Monolog\Logger('test');
$logger->pushHandler(new \Monolog\Handler\NullHandler());
$ffmpeg = new FFMpeg('wrongbinary', $logger);
}
/**
* @covers FFMpeg\FFMpeg::encode
* @covers FFMpeg\FFMpeg::encodeAudio
*/
public function testEncodeMp3()
{
$dest = __DIR__ . '/../../files/encode_test.mp3';
$this->object->open(__DIR__ . '/../../files/Audio.mp3');
$this->object->encode(new Format\Audio\Mp3(), $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::encode
* @covers FFMpeg\FFMpeg::encodeAudio
*/
public function testEncodeFlac()
{
$dest = __DIR__ . '/../../files/encode_test.flac';
$this->object->open(__DIR__ . '/../../files/Audio.mp3');
$this->object->encode(new Format\Audio\Flac(), $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::encode
* @covers FFMpeg\FFMpeg::encodeVideo
*/
public function testEncodeWebm()
{
$dest = __DIR__ . '/../../files/encode_test.webm';
$format = new Format\Video\WebM();
$format-> setDimensions(32, 32);
$this->object->open(__DIR__ . '/../../files/Test.ogv');
$this->object->encode($format, $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::encode
* @covers FFMpeg\FFMpeg::encodeVideo
*/
public function testEncodeOgg()
{
$dest = __DIR__ . '/../../files/encode_test.ogv';
$format = new Format\Video\Ogg();
$format->setDimensions(32, 32);
$this->object->open(__DIR__ . '/../../files/Test.ogv');
$this->object->encode($format, $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::encode
* @covers FFMpeg\FFMpeg::encodeVideo
*/
public function testEncodeX264()
{
$dest = __DIR__ . '/../../files/encode_test.mp4';
$format = new Format\Video\X264();
$format-> setDimensions(32, 32);
$this->object->open(__DIR__ . '/../../files/Test.ogv');
$this->object->encode($format, $dest);
$this->probe->probeFormat($dest);
unlink($dest);
}
/**
* @covers FFMpeg\FFMpeg::getMultiple
*/
public function testGetMultiple()
{
$object = FFMpegTester::load($this->logger);
$this->assertEquals(336, $object->getMultipleTester(321, 16));
$this->assertEquals(322, $object->getMultipleTester(321, 2));
$this->assertEquals(324, $object->getMultipleTester(321, 4));
$this->assertEquals(328, $object->getMultipleTester(321, 8));
$this->assertEquals(320, $object->getMultipleTester(319, 16));
$this->assertEquals(320, $object->getMultipleTester(313, 16));
$this->assertEquals(320, $object->getMultipleTester(312, 16));
$this->assertEquals(336, $object->getMultipleTester(329, 16));
$this->assertEquals(16, $object->getMultipleTester(8, 16));
}
}
class FFMpegTester extends FFMpeg
{
public function getMultipleTester($value, $multiple)
{
return parent::getMultiple($value, $multiple);
}
}

View file

@ -1,77 +0,0 @@
<?php
namespace FFMpeg;
use Monolog\Logger;
use Monolog\Handler\NullHandler;
class FFProbeTest extends \PHPUnit_Framework_TestCase
{
/**
*
* @var FFProbe
*/
protected $object;
protected $logger;
public function setUp()
{
$this->logger = new Logger('tests');
$this->logger->pushHandler(new NullHandler());
$this->object = FFProbe::load($this->logger);
}
/**
* @covers FFMpeg\FFProbe::probeFormat
* @covers FFMpeg\FFProbe::probeStreams
* @covers FFMpeg\FFProbe::executeProbe
*/
public function testProbe()
{
$this->object->probeFormat(__DIR__ . '/../../files/Test.ogv');
$this->object->probeStreams(__DIR__ . '/../../files/Test.ogv');
}
/**
* @covers FFMpeg\FFProbe::probeFormat
* @covers FFMpeg\FFProbe::executeProbe
* @expectedException \RuntimeException
*/
public function testProbeInvalidFile()
{
$this->object->probeFormat(__DIR__ . '/../../files/WrongFile.mp4');
}
/**
* @covers FFMpeg\FFProbe::probeStreams
* @covers FFMpeg\FFProbe::executeProbe
* @expectedException \FFMpeg\Exception\RuntimeException
*/
public function testProbeStreamsInvalidFile()
{
$this->object->probeStreams(__DIR__ . '/../../files/WrongFile.mp4');
}
/**
* @covers FFMpeg\FFProbe::probeStreams
* @covers FFMpeg\FFProbe::executeProbe
* @expectedException \InvalidArgumentException
*/
public function testProbeStreamsInvalidPathFile()
{
$this->object->probeStreams(__DIR__ . '/../../files/unknown.file');
}
/**
* @covers FFMpeg\FFProbe::probeFormat
* @covers FFMpeg\FFProbe::executeProbe
* @expectedException \InvalidArgumentException
*/
public function testProbeFormatInvalidPathFile()
{
$this->object->probeFormat(__DIR__ . '/../../files/unknown.file');
}
}

View file

@ -1,135 +0,0 @@
<?php
namespace FFMpeg\Format\Audio;
class DefaultAudioTest extends \PHPUnit_Framework_TestCase
{
/**
* @var DefaultAudio
*/
protected $object;
protected function setUp()
{
$this->object = new DefaultAudioTester();
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::getExtraParams
*/
public function testGetExtraParams()
{
$this->assertEquals('-f format', $this->object->getExtraParams());
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::getAudioCodec
*/
public function testGetAudioCodec()
{
$this->assertEquals('audiocodec1', $this->object->getAudioCodec());
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::setAudioCodec
*/
public function testSetAudioCodec()
{
$this->object->setAudioCodec('audiocodec2');
$this->assertEquals('audiocodec2', $this->object->getAudioCodec());
$this->object->setAudioCodec('audiocodec1');
$this->assertEquals('audiocodec1', $this->object->getAudioCodec());
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::setAudioCodec
* @expectedException \InvalidArgumentException
*/
public function testSetWrongAudioCodec()
{
$this->object->setAudioCodec('audiocodec4');
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::getAudioSampleRate
*/
public function testGetAudioSampleRate()
{
$this->assertEquals(44100, $this->object->getAudioSampleRate());
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::setAudioSampleRate
*/
public function testSetAudioSampleRate()
{
$this->object->setAudioSampleRate(22050);
$this->assertEquals(22050, $this->object->getAudioSampleRate());
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::setAudioSampleRate
* @expectedException \InvalidArgumentException
* @dataProvider getWrongAudioSampleRate
*/
public function testSetWrongAudioSampleRate($samplerate)
{
$this->object->setAudioSampleRate($samplerate);
}
public function getWrongAudioSampleRate()
{
return array(array(-5), array(0));
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::getKiloBitrate
*/
public function testGetKiloBitrate()
{
$this->assertEquals(128, $this->object->getKiloBitrate());
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::setKiloBitrate
*/
public function testSetKiloBitrate()
{
$this->object->setKiloBitrate(500);
$this->assertEquals(500, $this->object->getKiloBitrate());
}
/**
* @covers FFMpeg\Format\Audio\DefaultAudio::setKiloBitrate
* @dataProvider getWrongKiloBitrate
* @expectedException \InvalidArgumentException
*/
public function testSetWrongKiloBitrate($kbrate)
{
$this->object->setKiloBitrate($kbrate);
}
public function getWrongKiloBitrate()
{
return array(array(-5), array(0));
}
}
class DefaultAudioTester extends DefaultAudio
{
protected $audioCodec = 'audiocodec1';
public function getAvailableAudioCodecs()
{
return array('audiocodec1', 'audiocodec2', 'audiocodec3');
}
public function getExtraParams()
{
return '-f format';
}
}

View file

@ -1,201 +0,0 @@
<?php
namespace FFMpeg\Format\Video;
class DefaultVideoTest extends \PHPUnit_Framework_TestCase
{
/**
* @var DefaultVideo
*/
protected $object;
protected function setUp()
{
$this->object = new DefaultVideoTester();
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setDimensions
* @covers FFMpeg\Format\Video\DefaultVideo::getWidth
* @covers FFMpeg\Format\Video\DefaultVideo::getHeight
*/
public function testSetDimensions()
{
$this->object->setDimensions(240, 640);
$this->assertEquals(240, $this->object->getWidth());
$this->assertEquals(640, $this->object->getHeight());
$this->object->setDimensions(242, 638);
$this->assertEquals(242, $this->object->getWidth());
$this->assertEquals(638, $this->object->getHeight());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setDimensions
* @dataProvider getWrongDimensions
* @expectedException \InvalidArgumentException
*/
public function testWrongDimensions($width, $height)
{
$this->object->setDimensions($width, $height);
}
/**
* Data provider for testWrongDimensions
*
* @return array
*/
public function getWrongDimensions()
{
return array(
array(0, 240),
array(240, 0),
array(-5, 240),
array(240, -5),
array(-5, -5),
array(0, 0)
);
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::getFrameRate
*/
public function testGetFrameRate()
{
$this->assertEquals(25, $this->object->getFrameRate());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setFrameRate
*/
public function testSetFrameRate()
{
$this->object->setFrameRate(12);
$this->assertEquals(12, $this->object->getFrameRate());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setFrameRate
* @dataProvider getWrongFrameRates
* @expectedException \InvalidArgumentException
*/
public function testSetWrongFrameRates($framerate)
{
$this->object->setFrameRate($framerate);
}
/**
* Data provider for testWrongFrameRates
*
* @return array
*/
public function getWrongFramerates()
{
return array(array(-5), array(0));
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::getVideoCodec
*/
public function testGetVideoCodec()
{
$this->assertEquals('videocodec2', $this->object->getVideoCodec());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setVideoCodec
*/
public function testSetVideoCodec()
{
$this->object->setVideoCodec('videocodec2');
$this->assertEquals('videocodec2', $this->object->getVideoCodec());
$this->object->setVideoCodec('videocodec1');
$this->assertEquals('videocodec1', $this->object->getVideoCodec());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setVideoCodec
* @expectedException \InvalidArgumentException
*/
public function testSetWrongVideoCodec()
{
$this->object->setVideoCodec('videocodec4');
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::getGOPsize
*/
public function testGetGOPsize()
{
$this->assertEquals(25, $this->object->getGOPsize());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setGOPsize
*/
public function testSetGOPsize()
{
$this->object->setGOPsize(100);
$this->assertEquals(100, $this->object->getGOPsize());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::setGOPsize
* @dataProvider getWrongGOPsize
* @expectedException \InvalidArgumentException
*/
public function testSetWrongGOPSize($GOP)
{
$this->object->setGOPsize($GOP);
}
public function getWrongGOPsize()
{
return array(array(-5), array(0));
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::getKiloBitrate
*/
public function testGetKiloBitrate()
{
$this->assertEquals(1000, $this->object->getKiloBitrate());
}
/**
* @covers FFMpeg\Format\Video\DefaultVideo::getExtraParams
*/
public function testGetExtraParams()
{
$this->assertTrue(is_array($this->object->getExtraParams()));
}
}
class DefaultVideoTester extends DefaultVideo
{
protected $audioCodec = 'audiocodec1';
protected $videoCodec = 'videocodec2';
public function supportBFrames()
{
return true;
}
public function getAvailableAudioCodecs()
{
return array('audiocodec1', 'audiocodec2', 'audiocodec3');
}
public function getAvailableVideoCodecs()
{
return array('videocodec1', 'videocodec2');
}
public function getExtraParams()
{
return array('-f', 'format');
}
}

View file

@ -1,35 +0,0 @@
<?php
namespace FFMpeg\Format\Video;
class OggTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Ogg
*/
protected $object;
protected function setUp()
{
$this->object = new Ogg();
$this->object->setDimensions(320, 320);
}
/**
* @covers FFMpeg\Format\Video\Ogg::getAvailableAudioCodecs
*/
public function testGetAvailableAudioCodecs()
{
$this->object->setAudioCodec('libvorbis');
}
/**
* @covers FFMpeg\Format\Video\Ogg::getAvailableVideoCodecs
*/
public function testGetAvailableVideoCodecs()
{
$this->object->setVideoCodec('libtheora');
}
}

View file

@ -1,43 +0,0 @@
<?php
namespace FFMpeg\Format\Video;
class WebMTest extends \PHPUnit_Framework_TestCase
{
/**
* @var WebM
*/
protected $object;
protected function setUp()
{
$this->object = new WebM();
$this->object->setDimensions(320, 320);
}
/**
* @covers FFMpeg\Format\Video\WebM::getAvailableAudioCodecs
*/
public function testGetAvailableAudioCodecs()
{
$this->object->setAudioCodec('libvorbis');
}
/**
* @covers FFMpeg\Format\Video\WebM::getAvailableVideoCodecs
*/
public function testGetAvailableVideoCodecs()
{
$this->object->setVideoCodec('libvpx');
}
/**
* @covers FFMpeg\Format\Video\WebM::getExtraParams
*/
public function testGetExtraParams()
{
$this->assertTrue(is_array($this->object->getExtraParams()));
}
}

View file

@ -1,35 +0,0 @@
<?php
namespace FFMpeg\Format\Video;
class X264Test extends \PHPUnit_Framework_TestCase
{
/**
* @var X264
*/
protected $object;
protected function setUp()
{
$this->object = new X264();
$this->object->setDimensions(320, 320);
}
/**
* @covers FFMpeg\Format\Video\X264::getAvailableAudioCodecs
*/
public function testGetAvailableAudioCodecs()
{
$this->object->setAudioCodec('libmp3lame');
}
/**
* @covers FFMpeg\Format\Video\X264::getAvailableVideoCodecs
*/
public function testGetAvailableVideoCodecs()
{
$this->object->setVideoCodec('libx264');
}
}

View file

@ -1,93 +0,0 @@
<?php
use FFMpeg\Helper\AudioProgressHelper;
use FFMpeg\FFProbe;
use FFMpeg\FFMpeg;
use FFMpeg\Format\Audio\Mp3;
use FFMpeg\Helper\VideoProgressHelper;
use Monolog\Logger;
use Monolog\Handler\NullHandler;
class ProgressTest extends \PHPUnit_Framework_TestCase
{
/**
* @var FFMpeg
*/
protected $object;
/**
* @var FFProbe
*/
protected $probe;
protected $logger;
public function setUp()
{
$this->logger = new Logger('tests');
$this->logger->pushHandler(new NullHandler());
$this->object = FFMpeg::load($this->logger);
$this->probe = FFProbe::load($this->logger);
$this->object->setProber($this->probe);
}
/**
* @covers FFMpeg\Helper\ProgressHelper::parseProgress
* @covers FFMpeg\Helper\ProgressHelper::convertDuration
* @covers FFMpeg\Helper\ProgressHelper::getProgressInfo
* @covers FFMpeg\Helper\AudioProgressHelper::getPattern
*/
public function testProgressHelper()
{
$progressInfo = array();
$audioProgress = new AudioProgressHelper(function($percent, $remaining, $rate) use ($progressInfo ) {
$progressInfo[] = $percent;
});
$dest = __DIR__ . '/../../../files/encode_test.mp3';
$this->object->open(__DIR__ . '/../../../files/Audio.mp3');
$this->object->attachHelper($audioProgress);
$this->object->encode(new Mp3(), $dest);
$this->assertGreaterThanOrEqual(3, $progressInfo);
}
/**
* @covers FFMpeg\Helper\AudioProgressHelper::getPattern
*/
public function testAudioProgressHelper()
{
$audioProgress = new AudioProgressHelper(function($percent, $remaining, $rate) { });
$audioProgress->setDuration(500);
$line = "size= 712kB time=00:00:45.50 bitrate= 128.1kbits/s";
$audioProgress->parseProgress($line);
sleep(1);
$line = "size= 4712kB time=00:01:45.50 bitrate= 128.1kbits/s";
$progress = $audioProgress->parseProgress($line);
$this->assertEquals('21.0', $progress['percent']);
}
/**
* @covers FFMpeg\Helper\VideoProgressHelper::getPattern
*/
public function testVideoProgress()
{
$videoProgress = new VideoProgressHelper(function($percent, $remaining, $rate) {});
$videoProgress->setDuration(500);
$line = "frame= 206 fps=202 q=10.0 size= 571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0";
$videoProgress->parseProgress($line);
sleep(1);
$line = "frame= 854 fps=113 q=20.0 size= 4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0";
$progress = $videoProgress->parseProgress($line);
$this->assertEquals('6.0', $progress['percent']);
}
}