123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Threading;
- using System.Threading.Tasks;
- using Vinno.IUS.Common.Media.FFmpeg.ArgsBuilder;
- using Vinno.IUS.Common.Media.FFmpeg.Settings;
- namespace Vinno.IUS.Common.Media.FFmpeg.Video
- {
- /// <summary>
- /// Encode Video using FFmpeg
- /// </summary>
- public class FFmpegVideoWriter:IDisposable
- {
- private readonly FFmpegLog _log;
- private ManualResetEvent _waitEvent = new ManualResetEvent(true);
- private readonly Process _ffmpeg;
- public IFFmpegLog Log => _log;
- /// <summary>
- /// Creates a new instance of <see cref="FFmpegVideoWriter"/>.
- /// </summary>
- public FFmpegVideoWriter(FFmpegVideoWriterArgs args, FFmpegSettings settings)
- {
- _log = new FFmpegLog();
- var width = args.Width;
- var height = args.Height;
- var argsBuilder = new FFmpegArgsBuilder();
- argsBuilder.AddStdIn()
- .AddArg("thread_queue_size", 512)
- .AddArg("framerate", args.FrameRate)
- .SetFormat("rawvideo")
- .AddArg("pix_fmt", "rgb32")
- .SetVideoSize(width, height);
- var output = argsBuilder.AddOutputFile(args.Output)
- .SetFrameRate(args.FrameRate);
- args.VideoCodec.Apply(settings, args, output);
-
- if (settings.Resize)
- {
- var resizeWidth = settings.ResizeWidth;
- var resizeHeight = settings.ResizeHeight;
- if (resizeWidth % 2 == 1)
- ++resizeWidth;
- if (resizeHeight % 2 == 1)
- ++resizeHeight;
- output.AddArg("vf", $"scale={resizeWidth}:{resizeHeight}");
- }
- var argument = argsBuilder.GetArgs();
- _log.WriteArgs(argument);
- FFmpegService.StartFFmpeg(out _ffmpeg, argument, _log);
- }
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- _ffmpeg.StandardInput.Close();
- _ffmpeg.Close();
- }
- /// <summary>
- /// Writes an Image frame.
- /// </summary>
- public void WriteFrame(BitmapFrame frame)
- {
- if (_ffmpeg.HasExited)
- {
- throw new FFmpegException(_ffmpeg.ExitCode);
- }
- _waitEvent.Reset();
- bool success = true;
- Exception exception = null;
- Task.Run(()=>
- {
- try
- {
- _ffmpeg.StandardInput.BaseStream.Write(frame.Data);
- _ffmpeg.StandardInput.BaseStream.Flush();
- _waitEvent.Set();
- }
- catch (Exception e) when (_ffmpeg.HasExited)
- {
- Console.WriteLine($"{e}");
- success = false;
- exception = e;
- }
- });
- if(!_waitEvent.WaitOne(5000))
- {
- _waitEvent.Set();
- _ffmpeg.Kill();
- throw new Exception("Cannot connect video pipe to FFmpeg");
- }
- if(!success)
- {
- throw new FFmpegException(_ffmpeg.ExitCode, exception);
- }
- }
- }
- }
|