Problems with VMR-9, IVMRSurfaceAllocator9 and IVMRImagePresenter9

Started by
2 comments, last by Sparhawk42 18 years, 4 months ago
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
{
public:
	    STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { 
				dbglog() << "QueryInterface " << std::endl;
				//return S_OK; //GetOwner()->QueryInterface(riid,ppv);            
				ppv = NULL;
				return E_NOINTERFACE;
    };                                                          
    STDMETHODIMP_(ULONG) AddRef() { 
			  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;
	};

private:
	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);

	m_pVMRFilterConfig->SetRenderingMode(VMR9Mode_Renderless);
//m_pVMRFilterConfig->SetNumberOfStreams(2);


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

	D3DDEVICE_CREATION_PARAMETERS params;  
  
	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);	


		m_pMediaControl->Run();

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


And here is the logging output:

27.10.2005-12:47:23
AddRef
QueryInterface 
AdviseNotify
InitializeDevice
  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?
Advertisement
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?

It seems you're not following the steps correctly:

Quote:# 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.
I've tried the correct order but than I can't even query the IVMRSurfaceAllocatorNotify9

This topic is closed to new replies.

Advertisement