Esempio n. 1
0
 public FFmpegExceptionCatcherTests()
 {
     _sut = new FFmpegExceptionCatcher();
 }
Esempio n. 2
0
        internal Task <bool> RunProcess(
            string args,
            CancellationToken cancellationToken,
            ProcessPriorityClass?priority)
        {
            return(Task.Factory.StartNew(() =>
            {
                _outputLog = new List <string>();
                bool pipedOutput = OnVideoDataReceived != null;
                var process = RunProcess(args, FFmpegPath, priority, true, pipedOutput, true);
                var processId = process.Id;
                using (process)
                {
                    process.ErrorDataReceived += (sender, e) => ProcessOutputData(e, args, processId);
                    process.BeginErrorReadLine();
                    if (pipedOutput)
                    {
                        Task.Run(() => ProcessVideoData(process, cancellationToken), cancellationToken);
                    }
                    var ctr = cancellationToken.Register(() =>
                    {
                        if (Environment.OSVersion.Platform != PlatformID.Win32NT)
                        {
                            try
                            {
                                process.StandardInput.Write("q");
                                Task.Delay(1000 * 5).GetAwaiter().GetResult();

                                if (!process.HasExited)
                                {
                                    process.CloseMainWindow();
                                    process.Kill();
                                    _wasKilled = true;
                                }
                            }
                            catch (InvalidOperationException)
                            {
                            }
                        }
                    });

                    using (ctr)
                    {
                        using (var processEnded = new ManualResetEvent(false))
                        {
                            processEnded.SetSafeWaitHandle(new SafeWaitHandle(process.Handle, false));
                            int index = WaitHandle.WaitAny(new[] { processEnded, cancellationToken.WaitHandle });

                            // If the signal came from the caller cancellation token close the window
                            if (index == 1 &&
                                !process.HasExited)
                            {
                                process.CloseMainWindow();
                                process.Kill();
                                _wasKilled = true;
                            }
                            else if (index == 0 && !process.HasExited)
                            {
                                // Workaround for linux: https://github.com/dotnet/corefx/issues/35544
                                process.WaitForExit();
                            }
                        }

                        cancellationToken.ThrowIfCancellationRequested();
                        if (_wasKilled)
                        {
                            throw new ConversionException("Cannot stop process. Killed it.", args);
                        }

                        if (cancellationToken.IsCancellationRequested)
                        {
                            return false;
                        }

                        string output = string.Join(Environment.NewLine, _outputLog.ToArray());
                        var exceptionsCatcher = new FFmpegExceptionCatcher();
                        exceptionsCatcher.CatchFFmpegErrors(output, args);

                        if (process.ExitCode != 0 && _outputLog.Any() && !_outputLog.Last().Contains("dummy"))
                        {
                            throw new ConversionException(output, args);
                        }
                    }
                }

                return true;
            },
                                         cancellationToken,
                                         TaskCreationOptions.LongRunning,
                                         TaskScheduler.Default));
        }
Esempio n. 3
0
        internal Task <bool> RunProcess(
            string args,
            CancellationToken cancellationToken)
        {
            return(Task.Factory.StartNew(() =>
            {
                _outputLog = new List <string>();
                var process = RunProcess(args, FFmpegPath, Priority, true, true, true);
                using (process)
                {
                    process.ErrorDataReceived += (sender, e) => ProcessOutputData(e, args);
                    process.BeginErrorReadLine();
                    // VSTHRD101: Avoid using async lambda for a void returning delegate type, becaues any exceptions not handled by the delegate will crash the process
                    // https://github.com/Microsoft/vs-threading/blob/master/doc/analyzers/VSTHRD101.md
                    var ctr = cancellationToken.Register(() =>
                    {
                        if (Environment.OSVersion.Platform != PlatformID.Win32NT)
                        {
                            try
                            {
                                process.StandardInput.Write("q");
                                Task.Delay(1000 * 5).ConfigureAwait(false).GetAwaiter().GetResult();
                            }
                            catch (InvalidOperationException)
                            {
                            }
                            finally
                            {
                                if (!process.HasExited)
                                {
                                    process.CloseMainWindow();
                                    process.Kill();
                                    _wasKilled = true;
                                }
                            }
                        }
                    });

                    using (ctr)
                    {
                        using (var processEnded = new ManualResetEvent(false))
                        {
                            processEnded.SetSafeWaitHandle(new SafeWaitHandle(process.Handle, false));
                            int index = WaitHandle.WaitAny(new[] { processEnded, cancellationToken.WaitHandle });

                            // If the signal came from the caller cancellation token close the window
                            if (index == 1 &&
                                !process.HasExited)
                            {
                                process.CloseMainWindow();
                                process.Kill();
                                _wasKilled = true;
                            }
                            else if (index == 0 && !process.HasExited)
                            {
                                // Workaround for linux: https://github.com/dotnet/corefx/issues/35544
                                process.WaitForExit();
                            }
                        }

                        cancellationToken.ThrowIfCancellationRequested();
                        if (_wasKilled)
                        {
                            throw new ConversionException("Cannot stop process. Killed it.", args);
                        }

                        if (cancellationToken.IsCancellationRequested)
                        {
                            return false;
                        }

                        string output = string.Join(Environment.NewLine, _outputLog.ToArray());
                        var exceptionsCatcher = new FFmpegExceptionCatcher();
                        exceptionsCatcher.CatchFFmpegErrors(output, args);

                        if (process.ExitCode != 0)
                        {
                            throw new ConversionException(output, args);
                        }
                    }
                }

                return true;
            },
                                         cancellationToken,
                                         TaskCreationOptions.LongRunning,
                                         TaskScheduler.Default));
        }