我有一个C ++非托管DLL,基本上是一个视频播放引擎。它使用WMF流式传输视频,并使用TransferVideoFrame将帧绘制到ID3D11Texture2D。
这一切都很好。
但是,我的任务是实现MPEG_DASH流切换,因此我创建了一个使用MediaPlayer和AdaptiveStreaming类的C#包装器,以使DASH和HLS流工作。
我想弄清楚的是,如何将来自MediaPlayer的帧像素数据发送到C ++ DLL中以将其绘制到ID3DTexture2D。
在C ++中,我有一个函数返回指向ID3D11Texture2D的指针,
ID3D11Texture2D* VideoPlayer::GetVideoTextureSurface()
{
if (_ctxt.m_spVideoTexSRV) // ComPtr<ID3D11ShaderResourceView>
{
return _ctxt.m_spVideoTex.Get(); // ComPtr<ID3D11Texture2D>
}
else return nullptr;
}
我从C#调用并获取为IntPtr。
[DllImport("VideoPlayer")]
private static extern IntPtr GetVideoTextureSurface();
在C#中,MediaPlayer有一个方法:
MediaPlayer.CopyFrameToVideoSurface(IDirect3DSurface destination)
我想用它来使MediaPlayer将其框架绘制到C ++ ID3D11Texture3D中。但我不知道如何将IntPtr传递给它。我试图通过直接绘制纹理来避免多次复制帧缓冲区。
我甚至不确定这是否是最佳方法。我可以直接从C ++使用MediaPlayer,但我甚至不确定如何实例化它。在C#中它只是:
MediaPlayer _mediaPlayer = new MediaPlayer();
但是当我尝试用C ++创建它时,我得到错误,&#34;不允许不完整类型&#34;。任何想法,见解或帮助都表示赞赏。
答案 0 :(得分:0)
DllImport
没有问题。
[DllImport("VideoPlayer")]
private static extern IntPtr GetVideoTextureSurface();
您需要将返回的指针编组为ID3D11Texture2D类型的struct。请查看结构here的布局。当您搜索基础纹理资源类型时,您将结束here。因此它是指向描述2D纹理资源的D3D11_TEXTURE2D_DESC
结构的指针。
typedef struct D3D11_TEXTURE2D_DESC {
UINT Width;
UINT Height;
UINT MipLevels;
UINT ArraySize;
DXGI_FORMAT Format;
DXGI_SAMPLE_DESC SampleDesc;
D3D11_USAGE Usage;
UINT BindFlags;
UINT CPUAccessFlags;
UINT MiscFlags;
} D3D11_TEXTURE2D_DESC;
让我们定义我们自己的托管结构
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct : IDirect3DSurface {
public int Width { get; set; }
public int Height { get; set; }
public int MipLevels { get; set; }
public uint ArraySize { get; set; }
public DirectXPixelFormat Format { get; set; }
public Direct3DMultisampleDescription SampleDesc { get; set; }
public Direct3DUsage Usage { get; set; }
public uint BindFlags { get; set; }
public uint CPUAccessFlags { get; set; }
public uint MiscFlags { get; set; }
#region I Do not know about this part
public Action Disposer { get; set; }
public void Dispose() {
Disposer();
}
#endregion I Do not know about this part
public Direct3DSurfaceDescription Description => new Direct3DSurfaceDescription {
Format = Format,
Height = Height,
Width = Width,
MultisampleDescription = SampleDesc
};
}
这是一个从native到managed struct的简单包装器:
public static MyStruct TestWrapper() {
var ptr = GetVideoTextureSurface();
var myStruct = Marshal.PtrToStructure<MyStruct>(ptr);
myStruct.Disposer = () => Marshal.FreeHGlobal(ptr);
return myStruct;
}
现在你可以使用
MediaPlayer.CopyFrameToVideoSurface(myStruct);
希望这有帮助。