I have run the project CapturePreviewCSharp provided as a sample. However, it seems to be able to acquire the device status, etc., but the image is not output to the preview screen.
There are no errors, etc.
It seems that the rendering to D3DImage is not working, but I don't know how to solve this problem.
Does anyone else have a similar problem?
I have asked on the Blackmagic forum but have not gotten an answer.
Development environment.
- Windows 11.
- Visual Studio 2022
- NET framework 4.8
- DeckLink mini-recorder 4K
Here is the code on the Xaml side
<Window x:Class="CapturePreviewCSharp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="clr-namespace:System.Windows.Interop;assembly=PresentationCore"
<!--excerpt code-->
<GroupBox x:Name="groupBoxPreview" Header="Preview" >
<Grid x:Name="gridPreview" Margin="5">
<Image x:Name="imagePreview">
<Image.Source>
<i:D3DImage x:Name="d3dPreview" />
</Image.Source>
</Image>
</Grid>
</GroupBox>
</DockPanel>
</Window>
Code to output images to D3DImage.
public void RenderD3DImage(object sender, EventArgs e)
{
UpdateUIElement(d3dPreview, new Action(() =>
{
var actualWidth = gridPreview.RenderSize.Width;
var actualHeight = gridPreview.RenderSize.Height;
if (d3dPreview.IsFrontBufferAvailable)
{
IntPtr surface = IntPtr.Zero;
if (actualWidth > 0 && actualHeight > 0)
{
new MTAAction(() =>
{
m_previewCallback.PreviewHelper.SetSurfaceSize((uint)actualWidth, (uint)actualHeight);
m_previewCallback.PreviewHelper.GetBackBuffer(out surface);
});
}
if (surface != IntPtr.Zero)
{
d3dPreview.Lock();
d3dPreview.SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface);
new MTAAction(() => m_previewCallback.PreviewHelper.Render());
d3dPreview.AddDirtyRect(new Int32Rect(0, 0, d3dPreview.PixelWidth, d3dPreview.PixelHeight));
d3dPreview.Unlock();
}
}
}));
}
MTAAction class.
namespace CapturePreviewCSharp
{
class MTAAction
{
private ManualResetEvent doneEvent;
private readonly Action action;
public MTAAction(Action action)
{
this.action = action;
doneEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(MTAActionThreadPoolCallback, 0);
doneEvent.WaitOne();
}
public void MTAActionThreadPoolCallback(Object threadContext)
{
action();
doneEvent.Set();
}
}
class MTAFunc<T> where T : struct
{
private T value;
private readonly Func<T> getValueFunc;
private ManualResetEvent doneEvent;
public MTAFunc(Func<T> func)
{
value = default(T);
getValueFunc = func;
doneEvent = new ManualResetEvent(false);
}
public T Value
{
get
{
ThreadPool.QueueUserWorkItem(MTAFuncThreadPoolCallback, 0);
doneEvent.WaitOne();
return (T)value;
}
}
public void MTAFuncThreadPoolCallback(Object threadContext)
{
value = getValueFunc();
doneEvent.Set();
}
}
}
Thank you.