From b0f46bc289c93b077339241e3c410e259bead8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=91=D0=B0=D0=B3?= =?UTF-8?q?=D1=80=D1=8F=D0=BD=D1=86=D0=B5=D0=B2?= Date: Mon, 27 Apr 2020 21:22:05 +0300 Subject: [PATCH] Added StreamPipeSource Former-commit-id: 9903e333e6e3f6f689ad487d45ef9f359dac45a4 --- FFMpegCore.Test/Resources/VideoLibrary.cs | 1 + FFMpegCore.Test/VideoTest.cs | 62 +++++++++++++++++++++ FFMpegCore/FFMPEG/Pipes/StreamPipeSource.cs | 46 +++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 FFMpegCore/FFMPEG/Pipes/StreamPipeSource.cs diff --git a/FFMpegCore.Test/Resources/VideoLibrary.cs b/FFMpegCore.Test/Resources/VideoLibrary.cs index 90280f8..f630273 100644 --- a/FFMpegCore.Test/Resources/VideoLibrary.cs +++ b/FFMpegCore.Test/Resources/VideoLibrary.cs @@ -17,6 +17,7 @@ public enum ImageType public static class VideoLibrary { public static readonly FileInfo LocalVideo = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}input.mp4"); + public static readonly FileInfo LocalVideoWebm = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}input.webm"); public static readonly FileInfo LocalVideoAudioOnly = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}audio_only.mp4"); public static readonly FileInfo LocalVideoNoAudio = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}mute.mp4"); public static readonly FileInfo LocalAudio = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}audio.mp3"); diff --git a/FFMpegCore.Test/VideoTest.cs b/FFMpegCore.Test/VideoTest.cs index da6a971..9d7009d 100644 --- a/FFMpegCore.Test/VideoTest.cs +++ b/FFMpegCore.Test/VideoTest.cs @@ -62,6 +62,61 @@ public bool Convert(VideoType type, bool multithreaded = false, VideoSize size = File.Delete(output.FullName); } } + + private void ConvertFromStreamPipe(VideoType type, ArgumentContainer container) + { + var output = Input.OutputLocation(type); + + try + { + var input = VideoInfo.FromFileInfo(VideoLibrary.LocalVideoWebm); + using (var inputStream = System.IO.File.OpenRead(input.FullName)) + { + var pipeSource = new StreamPipeSource(inputStream); + var arguments = new ArgumentContainer { new InputPipeArgument(pipeSource) }; + foreach (var arg in container) + { + arguments.Add(arg.Value); + } + arguments.Add(new OutputArgument(output)); + + var scaling = container.Find(); + + Encoder.Convert(arguments); + + var outputVideo = new VideoInfo(output.FullName); + + Assert.IsTrue(File.Exists(output.FullName)); + Assert.IsTrue(Math.Abs((outputVideo.Duration - input.Duration).TotalMilliseconds) < 1000.0 / input.FrameRate); + + if (scaling == null) + { + Assert.AreEqual(outputVideo.Width, input.Width); + Assert.AreEqual(outputVideo.Height, input.Height); + } + else + { + if (scaling.Value.Width != -1) + { + Assert.AreEqual(outputVideo.Width, scaling.Value.Width); + } + + if (scaling.Value.Height != -1) + { + Assert.AreEqual(outputVideo.Height, scaling.Value.Height); + } + + Assert.AreNotEqual(outputVideo.Width, input.Width); + Assert.AreNotEqual(outputVideo.Height, input.Height); + } + } + } + finally + { + if (File.Exists(output.FullName)) + File.Delete(output.FullName); + } + } public void Convert(VideoType type, ArgumentContainer container) { @@ -193,6 +248,13 @@ public void Video_ToMP4_Args_Pipe() ConvertFromPipe(VideoType.Mp4, container); } + [TestMethod] + public void Video_ToMP4_Args_StreamPipe() + { + var container = new ArgumentContainer { new VideoCodecArgument(VideoCodec.LibX264) }; + ConvertFromStreamPipe(VideoType.Mp4, container); + } + [TestMethod] public void Video_ToTS() { diff --git a/FFMpegCore/FFMPEG/Pipes/StreamPipeSource.cs b/FFMpegCore/FFMPEG/Pipes/StreamPipeSource.cs new file mode 100644 index 0000000..1028562 --- /dev/null +++ b/FFMpegCore/FFMPEG/Pipes/StreamPipeSource.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace FFMpegCore.FFMPEG.Pipes +{ + /// + /// Implementation of used for stream redirection + /// + public class StreamPipeSource : IPipeSource + { + public System.IO.Stream Source { get; private set; } + public int BlockSize { get; set; } = 4096; + + public StreamPipeSource(System.IO.Stream stream) + { + Source = stream; + } + + public void FlushData(System.IO.Stream pipe) + { + var buffer = new byte[BlockSize]; + int read; + while ((read = Source.Read(buffer, 0, buffer.Length)) != 0) + { + pipe.Write(buffer, 0, read); + } + } + + public async Task FlushDataAsync(System.IO.Stream pipe) + { + var buffer = new byte[BlockSize]; + int read; + while ((read = await Source.ReadAsync(buffer, 0, buffer.Length)) != 0) + { + await pipe.WriteAsync(buffer, 0, read); + } + } + + public string GetFormat() + { + return ""; + } + } +}