2017-06-21 74 views
0

我有一个基本上是视频播放引擎的C++非托管DLL。它使用WMF流式传输视频,并使用TransferVideoFrame将帧绘制到ID3D11Texture2D。从C++发送ID3D11Texture2D到C#UWP MediaPlayer

这一切都工作正常。然而,我的任务是实现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++来创建它,我得到的错误,“不完整的类型是不允许的。”任何想法,见解或帮助表示赞赏。

回答

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 
    }; 
} 

这里是从原产地到管理结构简单的包装:

public static MyStruct TestWrapper() { 
     var ptr = GetVideoTextureSurface(); 
     var myStruct = Marshal.PtrToStructure<MyStruct>(ptr); 
     myStruct.Disposer =() => Marshal.FreeHGlobal(ptr); 
     return myStruct; 
    } 

现在你可以使用

MediaPlayer.CopyFrameToVideoSurface(myStruct); 

希望这有助于。

+0

非常感谢。我会试试这个! –

+0

@GlenRhodes,我也很好奇,看看它是否有效:)让我知道结果,如果它解决了问题,不要忘记检查答案,以便其他人可以看到 –