我正在为使用Direct3D9Ex界面的应用程序设置VideoRenderer,但是当我使用大纹理(桌面分辨率)时,视频开始变慢。
我当时使用DirectShow,但发现H264存在一些问题,因此决定选择Media Foundation。我进行了很多搜索,但是我没有得到如何使用DXVA渲染视频的方法,因此,我使用MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING和MFVideoFormat_RGB32使用IMFSourceReader(Async)读取示例,以便可以复制到我的曲面上,然后使其正常。
这就是我创建SourceReader的方式。
MFCreateAttributes(&m_Attributes, 4);
m_Attributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, GRAPHICSDEVICE->GetDeviceManager());
m_Attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, this);
m_Attributes->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
m_Attributes->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE);
MFCreateSourceReaderFromURL(L"Video.mp4", m_Attributes, &m_SourceReader);
MFCreateMediaType(&m_MediaType);
MFSetAttributeSize(m_MediaType, MF_MT_FRAME_SIZE, m_VideoWidth, m_VideoHeight);
m_MediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
m_MediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
然后,我发布一个ReadSample,并在我的Update方法中这样做:
if (WaitForSingleObject(m_SampleEvent, 0) == WAIT_OBJECT_0)
{
if (m_SourceReader)
{
m_SourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, nullptr, nullptr, nullptr, nullptr);
}
}
这是我的OnReadSample回调的一部分,该回调仅将一个表面复制到另一个表面。
IDirect3DSurface9 * pSampleSurface = nullptr;
if (SUCCEEDED(GetD3DSurfaceFromSample(Sample, &pSampleSurface)))
{
D3DLOCKED_RECT SampleRect;
if (FAILED(pSampleSurface->LockRect(&SampleRect, nullptr, D3DLOCK_READONLY)))
{
pSampleSurface->Release();
goto Quit;
}
BYTE * pVideo = (BYTE*)SampleRect.pBits;
D3DLOCKED_RECT TextureRect;
if (FAILED(m_Texture->LockRect(0, &TextureRect, nullptr, D3DLOCK_DISCARD)))
{
pSampleSurface->UnlockRect();
pSampleSurface->Release();
goto Quit;
}
BYTE * pDest = (BYTE*)TextureRect.pBits;
for (unsigned int i = 0; i < m_VideoHeight; i++)
{
CopyMemory(pDest, pVideo, m_VideoWidth * 4);
pDest += TextureRect.Pitch;
pVideo += SampleRect.Pitch;
}
m_Texture->UnlockRect(0);
pSampleSurface->UnlockRect();
pSampleSurface->Release();
}
因此,我的实际结果对于调试环境是可以接受的,但是当我将应用程序分辨率更改为台式机分辨率(从800x600到1366x768)时,事情开始变慢了很多。
我必须使用DXVA吗?我可以调整当前代码以使其运行得更快吗?在哪里可以找到一些好的样本?
最佳答案
与速度相关的主要因素是,如果可能的话,能够在GPU上解码为纹理,然后使用该纹理而无需将数据下载到系统内存中。
您正在执行MF_SOURCE_READER_D3D_MANAGER
,最终您从纹理读取数据。因此DXVA已经为您服务,并且应该可以很快地工作(也就是说,您本身不需要加速ReadSample
)。 IDirect3DSurface9::LockRect
和访问位大概很慢,您可能需要禁用读取纹理步长并比较性能以进行验证。
关于c++ - 是否有从IMFSample读取ReadSample的更快方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53908469/