using System.Diagnostics; using System.IO; using System; using System.Collections.Generic; using System.Threading; using System.Collections; namespace FFmpegOut { // A stream pipe class that invokes ffmpeg and connect to it. public class FFmpegPipe { #region Public properties public enum Codec { ProRes, H264, VP8 } public string Filename { get; private set; } public string Error { get; private set; } #endregion List writeByteList; static Thread thread; #region Public methods public FFmpegPipe(string name, int width, int height, int framerate, Codec codec) { //name += DateTime.Now.ToString(" yyyy MMdd HHmmss"); //Filename = name.Replace(" ", "_") + GetSuffix(codec); Filename = name + GetSuffix(codec); var opt = "-y -f rawvideo -vcodec rawvideo -pixel_format rgb24"; opt += " -video_size " + width + "x" + height; opt += " -framerate " + framerate; opt += " -loglevel warning -i - " + GetOptions(codec); opt += " " + Filename; if (writeByteList == null) writeByteList = new List(); writeByteList.Clear(); GC.Collect(); recording = true; var info = new ProcessStartInfo(FFmpegConfig.BinaryPath, opt); info.UseShellExecute = false; info.CreateNoWindow = true; info.RedirectStandardInput = true; info.RedirectStandardOutput = true; info.RedirectStandardError = true; _subprocess = Process.Start(info); _stdin = new BinaryWriter(_subprocess.StandardInput.BaseStream); thread = new Thread(() => WriteStdin()); thread.Start(); } public void Write(byte[] data) { if (_subprocess == null) return; lock (writeByteList) writeByteList.Add(data); //_stdin.Write(data); //_stdin.Flush(); } private static bool recording; public void WriteStdin() { while (recording) { lock (_stdin) { lock (writeByteList) { while (writeByteList.Count > 0) { _stdin.Write(writeByteList[0]); _stdin.Flush(); writeByteList.RemoveAt(0); } } } } Thread.CurrentThread.Abort(); } public IEnumerator Close() { if (_subprocess == null) yield break; recording = false; while (thread.IsAlive) { yield return null; } _subprocess.StandardInput.Close(); _subprocess.WaitForExit(); var outputReader = _subprocess.StandardError; Error = outputReader.ReadToEnd(); _subprocess.Close(); _subprocess.Dispose(); outputReader.Close(); outputReader.Dispose(); _subprocess = null; _stdin = null; } #endregion #region Private members Process _subprocess; BinaryWriter _stdin; static string [] _suffixes = { ".mov", ".mp4", ".webm" }; static string [] _options = { "-c:v prores_ks -pix_fmt yuv422p10le", "-pix_fmt yuv420p", "-c:v libvpx" }; public static string GetSuffix(Codec codec) { return _suffixes[(int)codec]; } static string GetOptions(Codec codec) { return _options[(int)codec]; } #endregion } }