У меня есть неуправляемая DLL C ++, которая в основном является движком воспроизведения видео. Он передает потоковое видео с использованием WMF и рисует кадры с помощью TransferVideoFrame для ID3D11Texture2D.
Это все работает нормально.
Однако мне было поручено реализовать переключение потоков MPEG_DASH, и поэтому я создаю оболочку C #, которая использует MediaPlayer и классы AdaptiveStreaming для обеспечения работы потоков 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 в это. Я пытаюсь избежать многократного копирования кадровых буферов, рисуя прямо в текстуру.
Я даже не уверен, что это лучший подход. Я мог бы использовать MediaPlayer напрямую из C ++, но я даже не уверен, как его создать. В C # это просто:
MediaPlayer _mediaPlayer = new MediaPlayer();
Но когда я пытаюсь создать его в C ++, я получаю сообщение об ошибке: «Incomplete Type is not позволен». Любые идеи, понимание или помощь приветствуется.
Там нет проблем с DllImport
,
[DllImport("VideoPlayer")]
private static extern IntPtr GetVideoTextureSurface();
Вам нужно маршалировать возвращаемый указатель на тип структуры ID3D11Texture2D. Пожалуйста, посмотрите на структуру структуры Вот. Когда вы будете искать базовый тип ресурса текстуры, вы в конечном итоге Вот. Так что это указатель на D3D11_TEXTURE2D_DESC
структура, которая описывает 2D текстурный ресурс.
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);
Надеюсь это поможет.
Других решений пока нет …