예제 #1
0
        protected virtual Codec GetVideoCodec(FFmpegConfig config,
                                              VideoStreamInfo sourceStream,
                                              VideoOutputStream outputStream)
        {
            VideoFormat format    = outputStream.Format;
            VideoCodec  codec     = config?.Video?.Codecs.GetValueOrDefault(format);
            string      codecName = GetVideoCodecName(format);
            X26xCodec   result    = format == VideoFormat.Hevc ? new X265Codec(codecName) : new X26xCodec(codecName);

            result.Preset = codec?.Preset;
            result.Crf    = outputStream.Quality;

            if (outputStream.DynamicRange == DynamicRange.High)
            {
                if (outputStream.Format != VideoFormat.Hevc)
                {
                    throw new NotSupportedException($"HDR is not supported with the video format {outputStream.Format}.");
                }

                var options = new List <Option>()
                {
                    new Option("colorprim", "bt2020"),
                    new Option("colormatrix", "bt2020nc"),
                    new Option("transfer", "smpte2084")
                };

                if (outputStream.CopyHdrMetadata)
                {
                    if (sourceStream.MasterDisplayProperties != null)
                    {
                        var properties = sourceStream.MasterDisplayProperties;
                        var value      = string.Format("\"G{0}B{1}R{2}WP{3}L({4},{5})\"",
                                                       properties.Green,
                                                       properties.Blue,
                                                       properties.Red,
                                                       properties.WhitePoint,
                                                       properties.Luminance.Max,
                                                       properties.Luminance.Min);

                        options.Add(new Option("master-display", value));
                    }

                    if (sourceStream.LightLevelProperties != null)
                    {
                        var properties = sourceStream.LightLevelProperties;

                        options.Add(new Option("max-cll", $"\"{properties.MaxCll},{properties.MaxFall}\""));
                    }
                }

                ((X265Codec)result).Options = options;
            }

            return(result);
        }
예제 #2
0
        protected override MappedVideoStream MapVideoStream(FFmpegConfig config,
                                                            VideoStreamInfo sourceStream,
                                                            VideoOutputStream outputStream)
        {
            var result = base.MapVideoStream(config, sourceStream, outputStream);

            result.Codec = GetVideoCodec(config, sourceStream, outputStream);
            result.Tag   = outputStream.Tag;

            return(result);
        }
예제 #3
0
        public void Setup()
        {
            _ffmpegFileName    = "usr/sbin/ffmpeg";
            _process           = Substitute.For <IProcess>();
            _argumentGenerator = Substitute.For <IFFmpegArgumentGenerator>();
            _configManager     = Substitute.For <IConfigManager <FFmpegConfig> >();
            _transcoder        = new MediaTranscoder(_ffmpegFileName,
                                                     () => _process,
                                                     _configManager,
                                                     _argumentGenerator);

            _argumentGenerator.When(x => x.GenerateArguments(Arg.Any <FFmpegJob>()))
            .Do(x => _ffmpegJob = x[0] as FFmpegJob);

            _videoSource = new VideoStreamInfo()
            {
                Index = 0
            };
            _videoOutput = new VideoOutputStream()
            {
                SourceStreamIndex = 0
            };
            _transcodeJob = new TranscodeJob()
            {
                SourceInfo = new MediaInfo()
                {
                    FileName = "source",
                    Streams  = new List <StreamInfo>()
                    {
                        _videoSource
                    }
                },
                OutputFileName = "destination",
                Streams        = new List <OutputStream>()
                {
                    _videoOutput
                }
            };
            _ffmpegJob = null;
        }
예제 #4
0
        protected virtual IList <IFilter> GetVideoFilters(FFmpegConfig config,
                                                          VideoStreamInfo sourceStream,
                                                          VideoOutputStream outputStream,
                                                          SubtitleInfo subtitleInfo)
        {
            var result = new List <IFilter>();

            if (subtitleInfo != null)
            {
                if (subtitleInfo.SubtitleType == SubtitleType.Graphic)
                {
                    const string SUB_LABEL = "sub";
                    const string REF_LABEL = "ref";

                    result.Add(GetScale2RefFilter(sourceStream, subtitleInfo.AbsoluteIndex, SUB_LABEL, REF_LABEL));
                    result.Add(GetOverlayFilter(sourceStream, REF_LABEL, SUB_LABEL));
                }
                else
                {
                    result.Add(GetSubtitlesFilter(subtitleInfo));
                }
            }

            bool setSampleAspectRatio = false;

            if ((outputStream.CropParameters != null) &&
                ((outputStream.CropParameters.Size.Width < sourceStream.Dimensions.Width) ||
                 (outputStream.CropParameters.Size.Height < sourceStream.Dimensions.Height)))
            {
                result.Add(GetCropFilter(outputStream.CropParameters));

                setSampleAspectRatio = true;
            }

            if (outputStream.ScaledDimensions.HasValue)
            {
                result.Add(GetScaleFilter(outputStream.ScaledDimensions.Value));

                setSampleAspectRatio = true;
            }

            if (setSampleAspectRatio)
            {
                result.Add(GetSampleAspectRatioFilter(1, 1));
            }

            if (outputStream.Deinterlace)
            {
                result.Add(GetDeinterlaceFilter(config));
            }

            if (outputStream.Denoise)
            {
                result.Add(GetDenoiseFilter(config));
            }

            if (outputStream.Tonemap)
            {
                AddTonemapFilters(result, config);
            }

            return(result);
        }
예제 #5
0
        public void WriteToStream(MemoryStream output)
        {
            var converter = new Converter(PakSupplier.Index);

            StoreItem[] weekly = new StoreItem[Store.Weekly.Length];
            for (int i = 0; i < weekly.Length; i++)
            {
                try
                {
                    weekly[i] = converter.ConvertItem(Store.Weekly[i]);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
            StoreItem[] daily = new StoreItem[Store.Daily.Length];
            for (int i = 0; i < daily.Length; i++)
            {
                try
                {
                    daily[i] = converter.ConvertItem(Store.Daily[i]);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw e;
                }
            }
            // number of featured categories
            var weeklies = Converter.GetCategorySlots(weekly, out var count, out var sizes, out var size);

            Config.SelectedCategory = count;
            var gc = new GlobalCache(converter.Index);

            // TODO: making it any larger doesn't affect the text or icon resolution :(
            // might have to do with the canvas only writing 1080p pixels on a 4k (e.g) image
            const int w = 1280;
            const int h = 720;

            using var ret    = new SKBitmap(w, h, SKColorType.Rgba8888, SKAlphaType.Opaque);
            using var stream = new VideoOutputStream(ret, 30, 1024 * 1024 * 5, output, true);
            using (var c = new SKCanvas(ret))
            {
                if (!string.IsNullOrWhiteSpace(Background) && File.Exists(Background))
                {
                    try
                    {
                        // TODO: make this permanent or part of drawing the cache (maybe?) just do something
                        using var bmp = SKBitmap.Decode(Background);
                        c.DrawBitmap(bmp, new SKRect(0, 0, w, h), new SKPaint {
                            FilterQuality = SKFilterQuality.High, IsAntialias = true
                        });
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
                c.SetMatrix(SKMatrix.MakeScale(w / 1920f, h / 1080f));
                for (int i = 0; i < size; i++)
                {
                    gc.GetSection(DrawType.DAILY).Draw(c, daily);
                    gc.GetSection(DrawType.FEATURED).Draw(c, weeklies[i]);
                    gc.GetSection(DrawType.FEATURED).InitializeCategory(c, weeklies[i], sizes, i + 1, 0);
                    float tickAmt = 1 / 150f;
                    for (int j = 0; j < 150; j++)
                    {
                        gc.GetSection(DrawType.DAILY).DrawBorder(c, daily, j);
                        gc.GetSection(DrawType.FEATURED).DrawBorder(c, weeklies[i], j + i * 150);
                        stream.EncodeFrame();
                        gc.GetSection(DrawType.FEATURED).TickCategory(c, weeklies[i], sizes, j * tickAmt, tickAmt);
                    }
                }
            }

            /*
             * using var bmp = new SKBitmap(1280, 720, SKColorType.Rgba8888, SKAlphaType.Opaque);
             * using var stream = new VideoOutputStream(bmp, 30, 1024 * 1024 * 4, output, true);
             * using var c = new SKCanvas(bmp);
             */
        }