Sign in to follow this  

Problems with VMR-9, IVMRSurfaceAllocator9 and IVMRImagePresenter9

Recommended Posts

I try to implement a Video Player like mentioned here: Supplying a Custom Allocator-Presenter for VMR-9 But my program hangs in the moment, when the video should be played. Here is my Code:
class VideoAllocatorPresenter
	: public IVMRSurfaceAllocator9,
	  public IVMRImagePresenter9
	    STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { 
				dbglog() << "QueryInterface " << std::endl;
				//return S_OK; //GetOwner()->QueryInterface(riid,ppv);            
				ppv = NULL;
				return E_NOINTERFACE;
			  dbglog() << "AddRef" << std::endl;
        return 1 ;//GetOwner()->AddRef();                            
    STDMETHODIMP_(ULONG) Release() {              
			  dbglog() << "Release" << std::endl;
        return 1;//GetOwner()->Release();                           

	VideoAllocatorPresenter() {};
	virtual ~VideoAllocatorPresenter() {}; 
	/*virtual HRESULT */STDMETHODIMP AdviseNotify( IVMRSurfaceAllocatorNotify9*  lpIVMRSurfAllocNotify ) 
		dbglog() << "AdviseNotify" << std::endl;

		allocNotify_ = lpIVMRSurfAllocNotify;
		return S_OK;

	/*virtual HRESULT */STDMETHODIMP GetSurface( DWORD_PTR  dwUserID, DWORD  SurfaceIndex, DWORD  SurfaceFlags,
											IDirect3DSurface9**  lplpSurface )
		dbglog() << "GetSurface  " << SurfaceIndex << std::endl;

		*lplpSurface = surfaces_[SurfaceIndex];
		dbglog() << "GetSurface  done" << std::endl;
		return S_OK;

	/*virtual HRESULT */STDMETHODIMP InitializeDevice( DWORD_PTR  dwUserID, VMR9AllocationInfo*  lpAllocInfo,
														DWORD*  lpNumBuffers )
		dbglog() << "InitializeDevice" << std::endl;

		surfaces_ = (IDirect3DSurface9**) malloc(sizeof( IDirect3DSurface9*) * (*lpNumBuffers) );
		allocNotify_->AllocateSurfaceHelper( lpAllocInfo, lpNumBuffers, surfaces_ );

		dbglog() << "  number buffers: " << (*lpNumBuffers) << std::endl;
		return S_OK;

	/*virtual HRESULT */STDMETHODIMP TerminateDevice( DWORD_PTR  dwID )
		dbglog() << "TerminateDevice" << std::endl;
		return S_OK;

	/*virtual HRESULT */STDMETHODIMP PresentImage( DWORD_PTR  dwUserID, VMR9PresentationInfo*  lpPresInfo )
		dbglog() << "PresentImage" << std::endl;
		return S_OK;

	/*virtual HRESULT */STDMETHODIMP StartPresenting( DWORD_PTR  dwUserID )
	  dbglog() << "StartPresenting" << std::endl;
		return S_OK;

	/*virtual HRESULT */STDMETHODIMP StopPresenting( DWORD_PTR  dwUserID )
		dbglog() << "StopPresenting" << std::endl;
		return S_OK;

	IVMRSurfaceAllocatorNotify9* allocNotify_;
	IDirect3DSurface9** surfaces_;

IMediaControl *m_pMediaControl;

a little later:
		CoInitializeEx( NULL, 0 );
		static VideoAllocatorPresenter allocPresent;
//create graph manager	
	IGraphBuilder *m_pGraph;
	HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGraph);
	// BUILD the VMR9
	IBaseFilter*				m_pVMRBaseFilter;
	hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &m_pVMRBaseFilter);

	// ADD the VMR9 to the graph
	hr = m_pGraph->AddFilter(m_pVMRBaseFilter, L"VMR9");
		IVMRFilterConfig9*			m_pVMRFilterConfig;
	hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRFilterConfig9, (void**) &m_pVMRFilterConfig);


	IVMRSurfaceAllocatorNotify9 *surfaceNotify;
	hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRSurfaceAllocatorNotify9, (void**) &surfaceNotify);

	DXUTGetD3DDevice()->GetCreationParameters(&params);      // Get parameters of D3D  

  	IDirect3D9* iD3D9;

	DXUTGetD3DDevice()->GetDirect3D( &iD3D9 );
	HMONITOR hMonitor = iD3D9->GetAdapterMonitor( params.AdapterOrdinal );
	surfaceNotify->SetD3DDevice( DXUTGetD3DDevice(), hMonitor );
	surfaceNotify->AdviseSurfaceAllocator( 0,&allocPresent );

	allocPresent.AdviseNotify( surfaceNotify );
	hr = m_pGraph->RenderFile(L"video/intro.avi",L"");	

	hr = m_pGraph->QueryInterface(IID_IMediaControl, (void**)&m_pMediaControl);	
	IMediaEvent *m_pMediaEvent;

	hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void**)&m_pMediaEvent);	


	//long evCode;
	//m_pMediaEvent->WaitForCompletion(INFINITE,  &evCode );

And here is the logging output:
  number buffers: 1
GetSurface  0
GetSurface  done

As you can see it works till GetSurface and then my program hangs. I know I need to put some code in the presenter part, but as this code is not called yet, I haven't done it... Can anybody tell me what the problem is? Thanks a lot?

Share this post

Link to post
Share on other sites
Finally I have found, where my code fails, but I don't see why:

hr = surfaceNotify->AdviseSurfaceAllocator( 42,static_cast<IVMRSurfaceAllocator9*>(&allocPresent) );
if FAILED( hr )
dbglog() << "failure 8 " << hr << std::endl;

Produces the following output in my logfile:
failure 8 -2147467262

What do I miss? Why does this call fail?

Share this post

Link to post
Share on other sites
It seems you're not following the steps correctly:

# Call the IVMRFilterConfig9::SetRenderingMode method with the VMR9Mode_Renderless flag.
# Call the IVMRSurfaceAllocatorNotify9::AdviseSurfaceAllocator method with a pointer to your allocator-presenter.
# Call the IVMRSurfaceAllocatorNotify9::SetD3DDevice method with a pointer to the Direct3D device and a handle to the monitor.

In your code you're seting the device before calling IVMRSurfaceAllocatorNotify9::AdviseSurfaceAllocator.

I'm not sure this is the problem, but you might want to follow the given order precisely, I've had trouble before with VMR filters because of just that.

Good luck.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this