You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.9 KiB

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<byte[]> 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<byte[]>();
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
}
}