|
Вывод видео на поверхность DirectX |
Здесь хочу рассказать как сопоставить видео поток с поверхностью Direct3D.
DirectShow работает с медиа данными с помощью построителя графов GraphBuilder. GraphBuilder добавляет фильтр для нужной работы с медиа файлом
IBaseFilter *pBaseFilter GraphBuilder->AddFilter(pBaseFilter);и загружает медиа файл
GraphBuilder->RenderFile("wFileName.avi”).
Play Stop и Pause медиа файла получаем из ImediaControl который запрашиваем из GraphBuilder
pGraphBuilder->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&m_pMediaControl));
Теперь собственнно о медиа в сурфейс. Как было сказано GraphBuilder адд-ит фильтр к-рый мы настроили для нужной нам работы. В нашем случае создаётся VMR9 фильтр
CComPtrpFilterVMR9 pFilterVMR9.CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER);
способный управлять аппаратными средствами Direct3D (ну а первоначальная версия 7 для DirectDraw) т.е. мы можем получить доступ к поверхности IDirect3DSurface9.
Запросим интерфейс IVMRSurfaceAllocatorNotify9 для реализации VMR9:
IVMRSurfaceAllocatorNotify9 *pIVMRSurfAllocNotify; pFilterVMR9->QueryInterface(IID_IVMRSurfaceAllocatorNotify9, reinterpret_cast<void**>(&pIVMRSurfAllocNotify));
IVMRSurfaceAllocatorNotify9::AdviseSurfaceAllocator() создаст объект allocator-presenter для указания VMR-у использовать этот объект во время работы с сурфейсами
pIVMRSurfAllocNotify->AdviseSurfaceAllocator( UserID, pVMRSurfaceAllocator);
А allocator-presenter в свою очередь вызовет AdviseNotify с указателем IVMRSurfaceAllocatorNotify9
pVMRSurfaceAllocator->AdviseNotify(pIVMRSurfAllocNotify);
Последние два шага устанавливают взаимодействие между VMR и allocator-presenter.
И как только мы этот фильтр добавим к GraphBuilder-у и загрузим медиа файл управление получит метод объекта allocator-presenter AdviseNotify. Объект cоздан на базе IVMRSurfaceAllocator9 и IVMRImagePresenter9
Он содержит методы реализующие управления аппаратными средствами Direct3D парой VMR и allocator-presenter:
1. InitializeDevise
создаёт поверхность размерами полученными из входной структуры VMR9AllocationInfo
VMR9AllocationInfo *lpAllocInfo; // in parametr pIVMRSurfaceAllocatorNotify9->AllocateSurfaceHelper (lpAllocInfo, lpNumBuffers, &pd3dSurface );
2. AdviseNotify устанавливает устройство д3д
HMONITOR hMonitor = pD3D->GetAdapterMonitor(D3DADAPTER_DEFAULT); pIVMRSurfaceAllocatorNotify9->SetD3DDevice(pd3dDevice, hMonitor);
3. GetSurface() здесь VMR9 получает сурфейс от allocator-presenter
4. PresentHelper() здесь VMR9 указывает allocator-presenter-у обработать сурфейс как видео фрейм
Источник: сэмпл DirectX SDK: DirectX 9.0\Samples\C++\DirectShow\VMR9\VMR9Allocator.