Here is the Zoom Effect that I use with my video program.
A rectangle is sent to the effect and it cuts and sizes that. Like on the left there. I zoomed "OK."
One caveat is the "cutRectangle" property, a Rect structure, must be both fully within the bounds of the original video frame, and the same aspect ratio as it.
How it works: Within this effect itself, the Atlas canvas.effect is used to get an inset from the input frame. Then the Scale canvas.effect grows that image and puts it into the output frame to be displayed at full size.
The mixture of these two native hardware-driven effects makes for quick processing. I put a timer on it, and it reports in milliseconds like this: 0, 0, 0, 11, 18, 0, 0, 0, 8, 13, 0, 0, 0 ... as typical output.
Here is the code for the effect:
public sealed class ZoomEffect : IBasicVideoEffect
{
private float ratio;
private Rect cutRect;
private int bWidth, bHeight;
public bool TimeIndependent { get { return true; } }
public MediaMemoryTypes SupportedMemoryTypes { get { return MediaMemoryTypes.Gpu; } }
public bool IsReadOnly { get { return false; } }
private CanvasDevice canvasDevice;
public IReadOnlyList<VideoEncodingProperties> SupportedEncodingProperties
{
get
{
var encodingProperties = new VideoEncodingProperties();
encodingProperties.Subtype = "ARGB32";
return new List<VideoEncodingProperties>() { encodingProperties };
}
}
public void SetEncodingProperties(VideoEncodingProperties encodingProperties, IDirect3DDevice device)
{
canvasDevice = CanvasDevice.CreateFromDirect3D11Device(device);
}
private IPropertySet configuration;
public void SetProperties(IPropertySet configuration)
{
this.configuration = configuration;
if (configuration.TryGetValue("CutRect", out object cr))
{
cutRect = (Rect)cr;
}
else
{
cutRect = new Rect(0, 0, 0, 0);
}
bWidth = 0;
}
public void DiscardQueuedFrames()
{
}
public void Close(MediaEffectClosedReason reason)
{
}
public void ProcessFrame(ProcessVideoFrameContext context)
{
using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromDirect3D11Surface(canvasDevice, context.InputFrame.Direct3DSurface))
using (CanvasRenderTarget renderTarget = CanvasRenderTarget.CreateFromDirect3D11Surface(canvasDevice, context.OutputFrame.Direct3DSurface))
{
if ((bWidth != inputBitmap.SizeInPixels.Width) | (bHeight != inputBitmap.SizeInPixels.Height))
{
bWidth = (int)inputBitmap.SizeInPixels.Width;
bHeight = (int)inputBitmap.SizeInPixels.Height;
if (cutRect.Width == 0)
{
cutRect = new Rect(0, 0, bWidth, bHeight);
}
ratio = (float)(bWidth / cutRect.Width);
}
using (CanvasDrawingSession nsx = renderTarget.CreateDrawingSession())
{
var brf = new AtlasEffect
{ Source = inputBitmap, SourceRectangle = cutRect };
var scX = new ScaleEffect
{ Source = brf, Scale = new Vector2(ratio, ratio) };
nsx.DrawImage(scX);
}
}
}
}
Note about code listing. When copied the right arrow (<) and left arrow (>) may not show up properly, and instead be represented by the string literals (<) and (>) respectively. Replace those four character literals with the correct arrow in that case.
Disclaimer: This is free for personal use only. Place of origin, California, US.