示例#1
0
        public async Task <bool> Detect(MediaInfo mediaInfo)
        {
            if (mediaInfo == null)
            {
                throw new ArgumentNullException(nameof(mediaInfo));
            }
            if (string.IsNullOrWhiteSpace(mediaInfo.FileName))
            {
                throw new ArgumentException($"{nameof(mediaInfo)}.FileName must not be empty or whitespace.", nameof(mediaInfo));
            }
            if (mediaInfo.Duration <= TimeSpan.Zero)
            {
                throw new ArgumentException($"{nameof(mediaInfo)}.Duration is invalid.", nameof(mediaInfo));
            }

            var job = new FFmpegJob()
            {
                HideBanner    = true,
                StartTime     = TimeSpan.FromMilliseconds(mediaInfo.Duration.TotalMilliseconds / 2),
                InputFileName = mediaInfo.FileName,
                FrameCount    = FRAME_COUNT,
                Filters       = new IFilter[]
                {
                    new Filter("idet")
                }
            };
            var             arguments  = _argumentGenerator.GenerateArguments(job);
            FrameStatistics statistics = null;

            try
            {
                var processResult = await _processRunner.Run(_ffmpegFileName, arguments, _timeout);

                //The interlace detection data is written to standard error.
                if (!string.IsNullOrWhiteSpace(processResult.ErrorData))
                {
                    statistics = Parse(processResult.ErrorData);
                }
                else
                {
                    Trace.WriteLine("No ffmpeg data on stderr to parse.");
                }
            }
            catch (ArgumentException ex)
            {
                Trace.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }
            catch (InvalidOperationException ex)
            {
                Trace.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }

            return(statistics != null &&
                   (statistics.TffCount + statistics.BffCount) > (statistics.ProgressiveCount + statistics.UndeterminedCount));
        }
示例#2
0
        public async Task GenerateCallsProcessRunner()
        {
            var args = "generated arguments";

            _argumentGenerator.GenerateArguments(Arg.Any <FFmpegJob>()).Returns(args);

            await _imageGenerator.Generate(_transcodeJob);

            await _processRunner.Received(_imageCount).Run(_ffmpegFileName, args, _timeout);
        }
        public async Task DetectRunsProcess()
        {
            string arguments = "generated";

            _argumentGenerator.GenerateArguments(Arg.Any <FFmpegJob>()).Returns(arguments);

            await _detector.Detect(_mediaInfo);

            await _processRunner.Received().Run(_ffmpegFileName, arguments, _timeout);
        }
示例#4
0
        public void StartPassesCorrectProcessStartInfo()
        {
            string           arguments = "transcode arguments";
            ProcessStartInfo startInfo = null;

            _argumentGenerator.GenerateArguments(Arg.Any <FFmpegJob>()).Returns(arguments);
            _process.Start(Arg.Any <ProcessStartInfo>()).Returns(x => {
                startInfo = x[0] as ProcessStartInfo;
                return(true);
            });

            _transcoder.Start(_transcodeJob);

            Assert.IsNotNull(startInfo);
            Assert.IsTrue(startInfo.CreateNoWindow);
            Assert.AreEqual(_ffmpegFileName, startInfo.FileName);
            Assert.AreEqual(arguments, startInfo.Arguments);
            Assert.IsTrue(startInfo.RedirectStandardOutput);
            Assert.IsTrue(startInfo.RedirectStandardError);
            Assert.IsFalse(startInfo.UseShellExecute);
        }
示例#5
0
        public async Task <CropParameters> Detect(MediaInfo mediaInfo)
        {
            if (mediaInfo == null)
            {
                throw new ArgumentNullException(nameof(mediaInfo));
            }
            if (string.IsNullOrWhiteSpace(mediaInfo.FileName))
            {
                throw new ArgumentException($"{nameof(mediaInfo)}.FileName must not be empty or whitespace.", nameof(mediaInfo));
            }
            if (mediaInfo.Duration <= TimeSpan.Zero)
            {
                throw new ArgumentException($"{nameof(mediaInfo)}.Duration is invalid.", nameof(mediaInfo));
            }

            CropParameters       result    = null;
            IEnumerable <double> positions = GetSeekSeconds(mediaInfo.Duration);
            FFmpegConfig         config    = _configManager.Config;
            string options = string.Empty;

            if (!string.IsNullOrWhiteSpace(config?.Video?.CropDetectOptions))
            {
                options = "=" + config.Video.CropDetectOptions;
            }

            var lockTarget = new object();
            int?minX = null, minY = null, maxWidth = null, maxHeight = null;

            var tasks = positions.Select(async seconds =>
            {
                var job = new FFmpegJob()
                {
                    HideBanner    = true,
                    StartTime     = TimeSpan.FromSeconds(seconds),
                    InputFileName = mediaInfo.FileName,
                    FrameCount    = 2,
                    Filters       = new IFilter[]
                    {
                        new CustomFilter($"cropdetect{options}")
                    }
                };
                var arguments = _argumentGenerator.GenerateArguments(job);

                try
                {
                    var processResult = await _processRunner.Run(_ffmpegFileName, arguments, _timeout);

                    //The crop detection data is written to standard error.
                    if (!string.IsNullOrWhiteSpace(processResult.ErrorData))
                    {
                        var crop = Parse(processResult.ErrorData);

                        if (crop != null)
                        {
                            lock (lockTarget)
                            {
                                minX      = minX.HasValue ? Math.Min(crop.Start.X, minX.Value) : crop.Start.X;
                                minY      = minY.HasValue ? Math.Min(crop.Start.Y, minY.Value) : crop.Start.Y;
                                maxWidth  = maxWidth.HasValue ? Math.Max(crop.Size.Width, maxWidth.Value) : crop.Size.Width;
                                maxHeight = maxHeight.HasValue ? Math.Max(crop.Size.Height, maxHeight.Value) : crop.Size.Height;
                            }
                        }
                    }
                    else
                    {
                        Trace.WriteLine("No ffmpeg data on stderr to parse.");
                    }
                }
                catch (ArgumentException ex)
                {
                    Trace.WriteLine(ex.Message);
                    Debug.WriteLine(ex.StackTrace);
                }
                catch (InvalidOperationException ex)
                {
                    Trace.WriteLine(ex.Message);
                    Debug.WriteLine(ex.StackTrace);
                }
            });

            await Task.WhenAll(tasks);

            if (minX.HasValue && minY.HasValue && maxWidth.HasValue && maxHeight.HasValue)
            {
                result = new CropParameters()
                {
                    Start = new Coordinate <int>(minX.Value, minY.Value),
                    Size  = new Dimensions(maxWidth.Value, maxHeight.Value)
                };
            }

            return(result);
        }
示例#6
0
        protected virtual string GenerateArguments(TranscodeJob job)
        {
            var ffmpegJob = Map(job, _configManager.Config);

            return(_argumentGenerator.GenerateArguments(ffmpegJob));
        }