2019-02-08 11:19:40 +01:00
|
|
|
|
using FFMpegCore.Enums;
|
2019-02-09 15:20:04 +01:00
|
|
|
|
using FFMpegCore.FFMPEG.Argument;
|
2019-02-08 11:19:40 +01:00
|
|
|
|
using FFMpegCore.FFMPEG.Enums;
|
2020-04-28 21:40:33 +02:00
|
|
|
|
using FFMpegCore.FFMPEG.Exceptions;
|
2020-04-27 18:24:26 +02:00
|
|
|
|
using FFMpegCore.FFMPEG.Pipes;
|
2019-03-03 00:33:00 +01:00
|
|
|
|
using FFMpegCore.Test.Resources;
|
2019-02-08 11:19:40 +01:00
|
|
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
2020-01-29 15:33:15 +01:00
|
|
|
|
using System;
|
2019-02-08 11:19:40 +01:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing.Imaging;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
2020-05-08 11:07:51 +02:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using FFMpegCore.FFMPEG;
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2019-03-03 00:33:00 +01:00
|
|
|
|
namespace FFMpegCore.Test
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
|
|
|
|
[TestClass]
|
|
|
|
|
public class VideoTest : BaseTest
|
|
|
|
|
{
|
|
|
|
|
public bool Convert(VideoType type, bool multithreaded = false, VideoSize size = VideoSize.Original)
|
|
|
|
|
{
|
|
|
|
|
var output = Input.OutputLocation(type);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var input = FFProbe.Analyse(Input.FullName);
|
|
|
|
|
FFMpeg.Convert(input, output, type, size: size, multithreaded: multithreaded);
|
|
|
|
|
var outputVideo = FFProbe.Analyse(output);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
|
|
|
|
Assert.AreEqual(outputVideo.Duration.TotalSeconds, input.Duration.TotalSeconds, 0.1);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
if (size == VideoSize.Original)
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
2019-03-27 23:51:41 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, (int)size);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
2020-05-08 11:07:51 +02:00
|
|
|
|
return File.Exists(output) &&
|
2019-02-08 11:19:40 +01:00
|
|
|
|
outputVideo.Duration == input.Duration &&
|
|
|
|
|
(
|
|
|
|
|
(
|
|
|
|
|
size == VideoSize.Original &&
|
2020-05-08 11:07:51 +02:00
|
|
|
|
outputVideo.PrimaryVideoStream.Width == input.PrimaryVideoStream.Width &&
|
|
|
|
|
outputVideo.PrimaryVideoStream.Height == input.PrimaryVideoStream.Height
|
2019-02-08 11:19:40 +01:00
|
|
|
|
) ||
|
|
|
|
|
(
|
|
|
|
|
size != VideoSize.Original &&
|
2020-05-08 11:07:51 +02:00
|
|
|
|
outputVideo.PrimaryVideoStream.Width != input.PrimaryVideoStream.Width &&
|
|
|
|
|
outputVideo.PrimaryVideoStream.Height != input.PrimaryVideoStream.Height &&
|
|
|
|
|
outputVideo.PrimaryVideoStream.Height == (int)size
|
2019-02-08 11:19:40 +01:00
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-28 21:40:33 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
private void ConvertFromStreamPipe(VideoType type, params IArgument[] inputArguments)
|
2020-04-27 20:22:05 +02:00
|
|
|
|
{
|
|
|
|
|
var output = Input.OutputLocation(type);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var input = FFProbe.Analyse(VideoLibrary.LocalVideoWebm.FullName);
|
|
|
|
|
using (var inputStream = System.IO.File.OpenRead(input.Path))
|
2020-04-27 20:22:05 +02:00
|
|
|
|
{
|
2020-04-28 17:50:29 +02:00
|
|
|
|
var pipeSource = new StreamPipeDataWriter(inputStream);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var arguments = FFMpegArguments.FromPipe(pipeSource);
|
|
|
|
|
foreach (var arg in inputArguments)
|
|
|
|
|
arguments.WithArgument(arg);
|
|
|
|
|
var processor = arguments.OutputToFile(output);
|
2020-04-27 20:22:05 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var scaling = arguments.Find<ScaleArgument>();
|
2020-04-27 20:22:05 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var success = processor.ProcessSynchronously();
|
2020-04-27 20:22:05 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var outputVideo = FFProbe.Analyse(output);
|
|
|
|
|
|
|
|
|
|
Assert.IsTrue(success);
|
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
|
|
|
|
Assert.IsTrue(Math.Abs((outputVideo.Duration - input.Duration).TotalMilliseconds) < 1000.0 / input.PrimaryVideoStream.FrameRate);
|
2020-04-27 20:22:05 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling?.Size == null)
|
2020-04-27 20:22:05 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
2020-04-27 20:22:05 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling.Size.Value.Width != -1)
|
2020-04-27 20:22:05 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width);
|
2020-04-27 20:22:05 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling.Size.Value.Height != -1)
|
2020-04-27 20:22:05 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height);
|
2020-04-27 20:22:05 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
2020-04-27 20:22:05 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2020-04-27 20:22:05 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
private void ConvertToStreamPipe(params IArgument[] inputArguments)
|
2020-04-28 21:40:33 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
using var ms = new MemoryStream();
|
|
|
|
|
var arguments = FFMpegArguments.FromInputFiles(VideoLibrary.LocalVideo);
|
|
|
|
|
foreach (var arg in inputArguments)
|
|
|
|
|
arguments.WithArgument(arg);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var streamPipeDataReader = new StreamPipeDataReader(ms);
|
|
|
|
|
var processor = arguments.OutputToPipe(streamPipeDataReader);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var scaling = arguments.Find<ScaleArgument>();
|
2020-04-28 21:40:33 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
processor.ProcessSynchronously();
|
2020-04-28 21:40:33 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ms.Position = 0;
|
|
|
|
|
var outputVideo = FFProbe.Analyse(ms);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var input = FFProbe.Analyse(VideoLibrary.LocalVideo.FullName);
|
2020-05-08 13:01:59 +02:00
|
|
|
|
// Assert.IsTrue(Math.Abs((outputVideo.Duration - input.Duration).TotalMilliseconds) < 1000.0 / input.PrimaryVideoStream.FrameRate);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling?.Size == null)
|
|
|
|
|
{
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (scaling.Size.Value.Width != -1)
|
2020-04-28 21:40:33 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling.Size.Value.Height != -1)
|
|
|
|
|
{
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
}
|
2020-05-08 11:07:51 +02:00
|
|
|
|
|
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
public void Convert(VideoType type, params IArgument[] inputArguments)
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
|
|
|
|
var output = Input.OutputLocation(type);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var input = FFProbe.Analyse(Input.FullName);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var arguments = FFMpegArguments.FromInputFiles(VideoLibrary.LocalVideo.FullName);
|
|
|
|
|
foreach (var arg in inputArguments)
|
|
|
|
|
arguments.WithArgument(arg);
|
2019-02-08 17:17:05 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var processor = arguments.OutputToFile(output);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var scaling = arguments.Find<ScaleArgument>();
|
|
|
|
|
processor.ProcessSynchronously();
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var outputVideo = FFProbe.Analyse(output);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
|
|
|
|
Assert.AreEqual(outputVideo.Duration.TotalSeconds, input.Duration.TotalSeconds, 0.1);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling?.Size == null)
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
2019-03-27 23:51:41 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling.Size.Value.Width != -1)
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling.Size.Value.Height != -1)
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
public void ConvertFromPipe(VideoType type, params IArgument[] inputArguments)
|
2020-04-27 18:24:26 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertFromPipe(type, PixelFormat.Format24bppRgb, inputArguments);
|
|
|
|
|
ConvertFromPipe(type, PixelFormat.Format32bppArgb, inputArguments);
|
|
|
|
|
ConvertFromPipe(type, PixelFormat.Format48bppRgb, inputArguments);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
public void ConvertFromPipe(VideoType type, PixelFormat fmt, params IArgument[] inputArguments)
|
2020-04-27 18:24:26 +02:00
|
|
|
|
{
|
|
|
|
|
var output = Input.OutputLocation(type);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-04-28 17:50:29 +02:00
|
|
|
|
var videoFramesSource = new RawVideoPipeDataWriter(BitmapSource.CreateBitmaps(128, fmt, 256, 256));
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var arguments = FFMpegArguments.FromPipe(videoFramesSource);
|
|
|
|
|
foreach (var arg in inputArguments)
|
|
|
|
|
arguments.WithArgument(arg);
|
|
|
|
|
var processor = arguments.OutputToFile(output);
|
|
|
|
|
|
|
|
|
|
var scaling = arguments.Find<ScaleArgument>();
|
|
|
|
|
processor.ProcessSynchronously();
|
2020-04-27 18:24:26 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var outputVideo = FFProbe.Analyse(output);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
2020-04-27 18:24:26 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling?.Size == null)
|
2020-04-27 18:24:26 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, videoFramesSource.Width);
|
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, videoFramesSource.Height);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling.Size.Value.Width != -1)
|
2020-04-27 18:24:26 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (scaling.Size.Value.Height != -1)
|
2020-04-27 18:24:26 +02:00
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, videoFramesSource.Width);
|
|
|
|
|
Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, videoFramesSource.Height);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-08 11:19:40 +01:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Mp4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Args()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Convert(VideoType.Mp4, new VideoCodecArgument(VideoCodec.LibX264));
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-27 18:24:26 +02:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Args_Pipe()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertFromPipe(VideoType.Mp4, new VideoCodecArgument(VideoCodec.LibX264));
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-27 20:22:05 +02:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Args_StreamPipe()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertFromStreamPipe(VideoType.Mp4, new VideoCodecArgument(VideoCodec.LibX264));
|
2020-04-27 20:22:05 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 21:40:33 +02:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Args_StreamOutputPipe_Async_Failure()
|
|
|
|
|
{
|
|
|
|
|
Assert.ThrowsException<FFMpegException>(() =>
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
using var ms = new MemoryStream();
|
|
|
|
|
var pipeSource = new StreamPipeDataReader(ms);
|
|
|
|
|
FFMpegArguments
|
|
|
|
|
.FromInputFiles(VideoLibrary.LocalVideo)
|
2020-05-08 13:01:59 +02:00
|
|
|
|
.ForceFormat("mkv")
|
2020-05-08 11:07:51 +02:00
|
|
|
|
.OutputToPipe(pipeSource)
|
|
|
|
|
.ProcessAsynchronously()
|
|
|
|
|
.WaitForResult();
|
2020-05-08 13:01:59 +02:00
|
|
|
|
FFProbe.Analyse(ms);
|
2020-04-28 21:40:33 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Args_StreamOutputPipe_Failure()
|
|
|
|
|
{
|
|
|
|
|
Assert.ThrowsException<FFMpegException>(() =>
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertToStreamPipe(new ForceFormatArgument("mkv"));
|
2020-04-28 21:40:33 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Args_StreamOutputPipe_Async()
|
|
|
|
|
{
|
2020-05-02 12:02:22 +02:00
|
|
|
|
using (var ms = new MemoryStream())
|
2020-04-28 21:40:33 +02:00
|
|
|
|
{
|
2020-05-02 12:02:22 +02:00
|
|
|
|
var pipeSource = new StreamPipeDataReader(ms);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
FFMpegArguments
|
|
|
|
|
.FromInputFiles(VideoLibrary.LocalVideo)
|
|
|
|
|
.WithVideoCodec(VideoCodec.LibX264)
|
|
|
|
|
.ForceFormat("matroska")
|
|
|
|
|
.OutputToPipe(pipeSource)
|
|
|
|
|
.ProcessAsynchronously()
|
|
|
|
|
.WaitForResult();
|
2020-05-02 12:02:22 +02:00
|
|
|
|
}
|
2020-04-28 21:40:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Args_StreamOutputPipe()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertToStreamPipe(new VideoCodecArgument(VideoCodec.LibX264), new ForceFormatArgument("matroska"));
|
2020-04-28 21:40:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-08 11:19:40 +01:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToTS()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Ts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToTS_Args()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Convert(VideoType.Ts,
|
2020-02-27 21:12:48 +01:00
|
|
|
|
new CopyArgument(),
|
|
|
|
|
new BitStreamFilterArgument(Channel.Video, Filter.H264_Mp4ToAnnexB),
|
2020-05-08 11:07:51 +02:00
|
|
|
|
new ForceFormatArgument(VideoCodec.MpegTs));
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-27 18:24:26 +02:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToTS_Args_Pipe()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertFromPipe(VideoType.Ts, new ForceFormatArgument(VideoCodec.MpegTs));
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToOGV_Resize()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Ogv, true, VideoSize.Ed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToOGV_Resize_Args()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Convert(VideoType.Ogv, new ScaleArgument(VideoSize.Ed), new VideoCodecArgument(VideoCodec.LibTheora));
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-27 18:24:26 +02:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToOGV_Resize_Args_Pipe()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertFromPipe(VideoType.Ogv, new ScaleArgument(VideoSize.Ed), new VideoCodecArgument(VideoCodec.LibTheora));
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-08 11:19:40 +01:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Resize()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Mp4, true, VideoSize.Ed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Resize_Args()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Convert(VideoType.Mp4, new ScaleArgument(VideoSize.Ld), new VideoCodecArgument(VideoCodec.LibX264));
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-27 18:24:26 +02:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_Resize_Args_Pipe()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
ConvertFromPipe(VideoType.Mp4, new ScaleArgument(VideoSize.Ld), new VideoCodecArgument(VideoCodec.LibX264));
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-08 11:19:40 +01:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToOGV()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Ogv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToMP4_MultiThread()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Mp4, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToTS_MultiThread()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Ts, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_ToOGV_MultiThread()
|
|
|
|
|
{
|
|
|
|
|
Convert(VideoType.Ogv, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_Snapshot()
|
|
|
|
|
{
|
|
|
|
|
var output = Input.OutputLocation(ImageType.Png);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var input = FFProbe.Analyse(Input.FullName);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
using var bitmap = FFMpeg.Snapshot(input, output);
|
|
|
|
|
Assert.AreEqual(input.PrimaryVideoStream.Width, bitmap.Width);
|
|
|
|
|
Assert.AreEqual(input.PrimaryVideoStream.Height, bitmap.Height);
|
2020-02-27 21:12:48 +01:00
|
|
|
|
Assert.AreEqual(bitmap.RawFormat, ImageFormat.Png);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-27 23:51:41 +01:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_Snapshot_PersistSnapshot()
|
|
|
|
|
{
|
|
|
|
|
var output = Input.OutputLocation(ImageType.Png);
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var input = FFProbe.Analyse(Input.FullName);
|
2019-03-27 23:51:41 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
using var bitmap = FFMpeg.Snapshot(input, output, persistSnapshotOnFileSystem: true);
|
|
|
|
|
Assert.AreEqual(input.PrimaryVideoStream.Width, bitmap.Width);
|
|
|
|
|
Assert.AreEqual(input.PrimaryVideoStream.Height, bitmap.Height);
|
2020-02-27 21:12:48 +01:00
|
|
|
|
Assert.AreEqual(bitmap.RawFormat, ImageFormat.Png);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
2019-03-27 23:51:41 +01:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2019-03-27 23:51:41 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-08 11:19:40 +01:00
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_Join()
|
|
|
|
|
{
|
|
|
|
|
var output = Input.OutputLocation(VideoType.Mp4);
|
|
|
|
|
var newInput = Input.OutputLocation(VideoType.Mp4, "duplicate");
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var input = FFProbe.Analyse(Input.FullName);
|
|
|
|
|
File.Copy(input.Path, newInput);
|
|
|
|
|
var input2 = FFProbe.Analyse(newInput);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var success = FFMpeg.Join(output, input, input2);
|
|
|
|
|
Assert.IsTrue(success);
|
|
|
|
|
|
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
2020-02-27 21:12:48 +01:00
|
|
|
|
var expectedDuration = input.Duration * 2;
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var result = FFProbe.Analyse(output);
|
2020-02-13 17:36:49 +01:00
|
|
|
|
Assert.AreEqual(expectedDuration.Days, result.Duration.Days);
|
|
|
|
|
Assert.AreEqual(expectedDuration.Hours, result.Duration.Hours);
|
|
|
|
|
Assert.AreEqual(expectedDuration.Minutes, result.Duration.Minutes);
|
|
|
|
|
Assert.AreEqual(expectedDuration.Seconds, result.Duration.Seconds);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(input.PrimaryVideoStream.Height, result.PrimaryVideoStream.Height);
|
|
|
|
|
Assert.AreEqual(input.PrimaryVideoStream.Width, result.PrimaryVideoStream.Width);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(newInput))
|
|
|
|
|
File.Delete(newInput);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_Join_Image_Sequence()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var imageSet = new List<ImageInfo>();
|
|
|
|
|
Directory.EnumerateFiles(VideoLibrary.ImageDirectory.FullName)
|
|
|
|
|
.Where(file => file.ToLower().EndsWith(".png"))
|
|
|
|
|
.ToList()
|
|
|
|
|
.ForEach(file =>
|
|
|
|
|
{
|
2020-02-27 21:12:48 +01:00
|
|
|
|
for (var i = 0; i < 15; i++)
|
2019-02-08 11:19:40 +01:00
|
|
|
|
{
|
|
|
|
|
imageSet.Add(new ImageInfo(file));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var success = FFMpeg.JoinImageSequence(VideoLibrary.ImageJoinOutput.FullName, images: imageSet.ToArray());
|
|
|
|
|
var result = FFProbe.Analyse(VideoLibrary.ImageJoinOutput.FullName);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
|
|
|
|
|
VideoLibrary.ImageJoinOutput.Refresh();
|
|
|
|
|
|
|
|
|
|
Assert.IsTrue(VideoLibrary.ImageJoinOutput.Exists);
|
|
|
|
|
Assert.AreEqual(3, result.Duration.Seconds);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreEqual(imageSet.First().Width, result.PrimaryVideoStream.Width);
|
|
|
|
|
Assert.AreEqual(imageSet.First().Height, result.PrimaryVideoStream.Height);
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
VideoLibrary.ImageJoinOutput.Refresh();
|
|
|
|
|
if (VideoLibrary.ImageJoinOutput.Exists)
|
|
|
|
|
{
|
|
|
|
|
VideoLibrary.ImageJoinOutput.Delete();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-01 11:56:50 +02:00
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_With_Only_Audio_Should_Extract_Metadata()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var video = FFProbe.Analyse(VideoLibrary.LocalVideoAudioOnly.FullName);
|
|
|
|
|
Assert.AreEqual(null, video.PrimaryVideoStream);
|
|
|
|
|
Assert.AreEqual("aac", video.PrimaryAudioStream.CodecName);
|
2020-02-18 17:17:59 +01:00
|
|
|
|
Assert.AreEqual(79.5, video.Duration.TotalSeconds, 0.5);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
// Assert.AreEqual(1.25, video.Size);
|
2019-04-01 11:56:50 +02:00
|
|
|
|
}
|
2020-04-27 18:24:26 +02:00
|
|
|
|
|
2020-01-29 15:33:15 +01:00
|
|
|
|
[TestMethod]
|
2020-04-27 18:24:26 +02:00
|
|
|
|
public void Video_Duration()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var video = FFProbe.Analyse(VideoLibrary.LocalVideo.FullName);
|
2020-01-29 15:33:15 +01:00
|
|
|
|
var output = Input.OutputLocation(VideoType.Mp4);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
|
2020-04-27 18:24:26 +02:00
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
FFMpegArguments
|
|
|
|
|
.FromInputFiles(VideoLibrary.LocalVideo)
|
|
|
|
|
.WithDuration(TimeSpan.FromSeconds(video.Duration.TotalSeconds - 5))
|
|
|
|
|
.OutputToFile(output)
|
|
|
|
|
.ProcessSynchronously();
|
2020-01-29 15:33:15 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
|
|
|
|
var outputVideo = FFProbe.Analyse(output);
|
2020-02-13 17:36:49 +01:00
|
|
|
|
|
|
|
|
|
Assert.AreEqual(video.Duration.Days, outputVideo.Duration.Days);
|
|
|
|
|
Assert.AreEqual(video.Duration.Hours, outputVideo.Duration.Hours);
|
|
|
|
|
Assert.AreEqual(video.Duration.Minutes, outputVideo.Duration.Minutes);
|
|
|
|
|
Assert.AreEqual(video.Duration.Seconds - 5, outputVideo.Duration.Seconds);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2020-01-29 15:33:15 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-27 18:24:26 +02:00
|
|
|
|
|
2020-03-02 22:50:04 +01:00
|
|
|
|
[TestMethod]
|
2020-04-27 18:24:26 +02:00
|
|
|
|
public void Video_UpdatesProgress()
|
|
|
|
|
{
|
2020-03-02 22:50:04 +01:00
|
|
|
|
var output = Input.OutputLocation(VideoType.Mp4);
|
|
|
|
|
|
|
|
|
|
var percentageDone = 0.0;
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var timeDone = TimeSpan.Zero;
|
|
|
|
|
void OnPercentageProgess(double percentage) => percentageDone = percentage;
|
|
|
|
|
void OnTimeProgess(TimeSpan time) => timeDone = time;
|
2020-03-02 22:50:04 +01:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var analysis = FFProbe.Analyse(VideoLibrary.LocalVideo.FullName);
|
|
|
|
|
|
2020-03-02 22:50:04 +01:00
|
|
|
|
|
2020-04-27 18:24:26 +02:00
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
var success = FFMpegArguments
|
|
|
|
|
.FromInputFiles(VideoLibrary.LocalVideo)
|
|
|
|
|
.WithDuration(TimeSpan.FromSeconds(8))
|
|
|
|
|
.OutputToFile(output)
|
|
|
|
|
.NotifyOnProgress(OnPercentageProgess, analysis.Duration)
|
|
|
|
|
.NotifyOnProgress(OnTimeProgess)
|
|
|
|
|
.ProcessSynchronously();
|
2020-04-27 18:24:26 +02:00
|
|
|
|
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.IsTrue(success);
|
|
|
|
|
Assert.IsTrue(File.Exists(output));
|
2020-03-02 22:50:04 +01:00
|
|
|
|
Assert.AreNotEqual(0.0, percentageDone);
|
2020-05-08 11:07:51 +02:00
|
|
|
|
Assert.AreNotEqual(TimeSpan.Zero, timeDone);
|
2020-04-27 18:24:26 +02:00
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
if (File.Exists(output))
|
|
|
|
|
File.Delete(output);
|
2020-03-02 22:50:04 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-28 21:54:39 +02:00
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
public void Video_TranscodeInMemory()
|
|
|
|
|
{
|
2020-05-08 11:07:51 +02:00
|
|
|
|
using var resStream = new MemoryStream();
|
|
|
|
|
var reader = new StreamPipeDataReader(resStream);
|
|
|
|
|
var writer = new RawVideoPipeDataWriter(BitmapSource.CreateBitmaps(128, PixelFormat.Format24bppRgb, 128, 128));
|
|
|
|
|
|
|
|
|
|
FFMpegArguments
|
|
|
|
|
.FromPipe(writer)
|
|
|
|
|
.WithVideoCodec("vp9")
|
|
|
|
|
.ForceFormat("webm")
|
|
|
|
|
.OutputToPipe(reader)
|
|
|
|
|
.ProcessSynchronously();
|
|
|
|
|
|
|
|
|
|
resStream.Position = 0;
|
|
|
|
|
var vi = FFProbe.Analyse(resStream);
|
|
|
|
|
Assert.AreEqual(vi.PrimaryVideoStream.Width, 128);
|
|
|
|
|
Assert.AreEqual(vi.PrimaryVideoStream.Height, 128);
|
2020-04-28 21:54:39 +02:00
|
|
|
|
}
|
2019-02-08 11:19:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|