protected void Copy(VideoFrame frame, VideoFrame res, YUVPlanes[] planes) { using (frame) { Parallel.ForEach(planes, plane => OverlayUtils.CopyPlane(frame, res, plane)); } }
protected override VideoFrame GetFrame(int n) { var allPlanes = OverlayUtils.GetPlanes(GetVideoInfo().pixel_type); if (Smooth > 0) { return(Copy(GetFrameWithSmooth(n))); } var output = NewVideoFrame(StaticEnv); using (var src = Source.GetFrame(n, StaticEnv)) using (var over = Overlay.GetFrame(n, StaticEnv)) { if (GetVideoInfo().IsRGB() && realChannels.Length < 3 || Source.IsRealPlanar() && planes.Length < 3) { Parallel.ForEach(allPlanes, parallelOptions, plane => OverlayUtils.CopyPlane(src, output, plane)); } unsafe { Parallel.ForEach(planes, parallelOptions, plane => { var pixelSize = GetVideoInfo().IsRGB() ? 3 : 1; var size = new Size(src.GetRowSize(plane), src.GetHeight(plane)); var srcStride = src.GetPitch(plane); var overStride = over.GetPitch(plane); Parallel.ForEach(realChannels, parallelOptions, channel => { Parallel.For(0, size.Height, parallelOptions, y => { var srcData = (byte *)src.GetReadPtr(plane) + y * srcStride + channel; var overData = (byte *)over.GetReadPtr(plane) + y * overStride + channel; var writer = (byte *)output.GetWritePtr(plane) + y * output.GetPitch(plane) + channel; for (var x = 0; x < size.Width; x += pixelSize) { var srcComplexity = GetComplexity(srcData, x, y, pixelSize, srcStride, size, Steps); var overComplexity = GetComplexity(overData, x, y, pixelSize, overStride, size, Steps); var diff = srcComplexity - overComplexity; var srcPreferred = diff > Preference; if (Mask) { writer[x] = srcPreferred ? byte.MinValue : byte.MaxValue; } else { writer[x] = srcPreferred ? srcData[x] : overData[x]; } } }); }); }); } } return(output); }