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); }
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); }
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; }
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); }
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); */ }