Есть ли более быстрый способ чтения образцов из IMFSample?

Я настраиваю VideoRenderer для моего приложения, которое использует интерфейсы Direct3D9Ex, но когда я использую большую текстуру (разрешение рабочего стола), видео начинает замедляться.

Я использовал DirectShow, но обнаружил некоторые проблемы с H264 и решил перейти на Media Foundation. Я много об этом искал, но я не понял, как отобразить видео с помощью DXVA, и поэтому я читаю пример с IMFSourceReader (Async), используя MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING и MFVideoFormat_RGB32, чтобы я мог скопировать его на мою поверхность, а затем сделать это нормально.

Вот как я создаю 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();
}

Итак, мои фактические результаты приемлемы для среды отладки, но когда я изменяю разрешение своего приложения на настольное (от 800×600 до 1366×768), все начинает становиться намного медленнее.

Должен ли я использовать что-то в качестве DXVA? Могу ли я настроить текущий код, чтобы он работал быстрее? Где я могу найти хорошие образцы об этом?

1

Решение

Основным фактором, связанным со скоростью, здесь является возможность декодировать на GPU в текстуру, а затем использовать эту текстуру, не выгружая данные в системную память, если это возможно.

Ты делаешь MF_SOURCE_READER_D3D_MANAGER и в конце концов вы читаете данные из текстуры. Таким образом, DXVA уже работает для вас, и он должен работать прилично быстро (то есть вам не нужно ускоряться ReadSample как таковой). IDirect3DSurface9::LockRect и доступ к битам предположительно делает медленным, вы можете отключить шаг чтения текстуры и сравнить производительность для проверки.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]