Sign in to follow this  
Sparhawk42

Problems with Video replay and Direct3d (IVMRSurfaceAllocator9, IVMRImagePresenter9)

Recommended Posts

Hello, i try to replay a video directly under Direct3D but somehow I don't get the code working. At the moment I'am stuck with an exception outside of my own code. Maybe some one can help me fix my problem. Thanks a lot guys. Code and example videos can be downloaded here Here is my code:
class VideoAllocatorPresenter
	: public IVMRSurfaceAllocator9,
	  public IVMRImagePresenter9
{
public:
	    STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { 
				dbglog() << "QueryInterface " << std::endl;
				*ppv = this;
				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( IDirect3DDevice9* dev ):d3dDevice_(dev) {};
	
		virtual ~VideoAllocatorPresenter() {}; 
	
		/*virtual HRESULT */STDMETHODIMP AdviseNotify( IVMRSurfaceAllocatorNotify9*  lpIVMRSurfAllocNotify ) 
	  {
		  dbglog() << "AdviseNotify " << lpIVMRSurfAllocNotify << 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;
		  SurfaceIndex = 0;
		  *lplpSurface = &surfaces_[SurfaceIndex];
		  dbglog() << "GetSurface  done " << *lplpSurface << std::endl;
		  return S_OK;
	  };

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

		surfaces_ = (IDirect3DSurface9*) malloc(sizeof( IDirect3DSurface9) * (*lpNumBuffers) );
		 	IDirect3D9* iD3D9;
	  D3DDEVICE_CREATION_PARAMETERS params;  
  
	  DXUTGetD3DDevice()->GetCreationParameters(&params); 

	  DXUTGetD3DDevice()->GetDirect3D( &iD3D9 );
	  HMONITOR hMonitor = iD3D9->GetAdapterMonitor( params.AdapterOrdinal );
		HRESULT hr = allocNotify_->SetD3DDevice( d3dDevice_, hMonitor );
		if( FAILED( hr ) ) 
		{
			dbglog() << "SetD3DDevice: " << hr <<  std::endl;
		}
		//lpAllocInfo->dwFlags |= VMR9AllocFlag_TextureSurface;
		hr = allocNotify_->AllocateSurfaceHelper( lpAllocInfo, lpNumBuffers, &surfaces_ ); 
		if( FAILED( hr ) ) 
		{
			dbglog() << "AllocateSurfaceHelper: " << hr <<  std::endl;
		}
		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_;
	IDirect3DDevice9* d3dDevice_;

};
IMediaControl *m_pMediaControl;


std::string getMediaError(HRESULT hr)
{
    if (FAILED(hr))
    {
        TCHAR szErr[MAX_ERROR_TEXT_LEN];
        DWORD res = AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
				std::stringstream result;
        if (res == 0)
        {
   				  result << "Unknown Error: " << hr << " ";
        } else
				{
   				result << szErr;
				}
				return result.str();
    }
		return "";
}

void initVideoRendering()
{
  CoInitializeEx( NULL, 0 );
	static VideoAllocatorPresenter allocPresent( DXUTGetD3DDevice() );

	//create graph manager	
	dbglog() << "Step 0" << std::endl;
	IGraphBuilder *m_pGraph;
	
	HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGraph);
	if FAILED( hr )
		dbglog() << "failure 1 " << getMediaError( hr ) << std::endl;
	
	// BUILD the VMR9
	IBaseFilter*				m_pVMRBaseFilter;
	hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &m_pVMRBaseFilter);
	if FAILED( hr )
		dbglog() << "failure 2 " << getMediaError( hr ) << std::endl;
	
	// ADD the VMR9 to the graph
	hr = m_pGraph->AddFilter(m_pVMRBaseFilter, L"VMR9");
	if FAILED( hr )
		dbglog() << "failure 3 " << getMediaError( hr ) << std::endl;
	
	IVMRFilterConfig9*			m_pVMRFilterConfig;
	hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRFilterConfig9, (void**) &m_pVMRFilterConfig);
  if FAILED( hr )
		dbglog() << "failure 4 " << getMediaError( hr ) << std::endl;

	dbglog() << "Step 1" << std::endl;	

	//m_pVMRFilterConfig->SetNumberOfStreams(2);

	hr = m_pVMRFilterConfig->SetRenderingMode(VMR9Mode_Renderless);
	if FAILED( hr )
		dbglog() << "failure 5 " << getMediaError( hr ) << std::endl;

	IVMRSurfaceAllocatorNotify9 *surfaceNotify;
	hr = m_pVMRBaseFilter->QueryInterface(IID_IVMRSurfaceAllocatorNotify9, (void**) &surfaceNotify);
  if FAILED( hr )
		dbglog() << "failure 6 " << getMediaError( hr ) << std::endl;

	D3DDEVICE_CREATION_PARAMETERS params;  
  
	DXUTGetD3DDevice()->GetCreationParameters(&params);      // Get parameters of D3D  
  
  IDirect3D9* iD3D9;
  DXUTGetD3DDevice()->GetDirect3D( &iD3D9 );
	HMONITOR hMonitor = iD3D9->GetAdapterMonitor( params.AdapterOrdinal );
	hr = surfaceNotify->SetD3DDevice( DXUTGetD3DDevice(), hMonitor );
	if FAILED( hr )
		dbglog() << "failure 7 " << getMediaError( hr ) << std::endl;
	
	hr = surfaceNotify->AdviseSurfaceAllocator( 42,static_cast<IVMRSurfaceAllocator9*>(&allocPresent) );
	if FAILED( hr )
		dbglog() << "failure 8 " << getMediaError( hr ) << std::endl;
	
	hr = allocPresent.AdviseNotify( surfaceNotify );
	if FAILED( hr )
		dbglog() << "failure 9 " << getMediaError( hr ) << std::endl;	
	
	//hr = m_pGraph->RenderFile(L"test_cinepak.avi",L"");	
	hr = m_pGraph->RenderFile(L"test_divx6.avi",L"");	
	if FAILED( hr )
		dbglog() << "failure 10 " << getMediaError( hr ) << std::endl;
	
	hr = m_pGraph->QueryInterface(IID_IMediaControl, (void**)&m_pMediaControl);	
	if FAILED( hr )
		dbglog() << "failure 11 " << getMediaError( hr ) << std::endl;
	
	IMediaEvent *m_pMediaEvent;
  
	dbglog() << "Step 2" << std::endl;

	hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void**)&m_pMediaEvent);	
	if FAILED( hr )
		dbglog() << "failure 12 " << getMediaError( hr ) << std::endl;

	hr =	m_pMediaControl->Run();
	if FAILED( hr )
		dbglog() << "failure 13 " << getMediaError( hr ) << std::endl;

	long evCode;
	m_pMediaEvent->WaitForCompletion(INFINITE,  &evCode );
  dbglog() << "Step done" << std::endl;
}

//--------------------------------------------------------------------------------------
// Rejects any devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
                                  D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
    // Typically want to skip backbuffer formats that don't support alpha blending
    IDirect3D9* pD3D = DXUTGetD3DObject(); 
    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
                    AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
                    D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext )
{
    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_MANAGED resources here 
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
    return S_OK;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_DEFAULT resources here 
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
                                const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
    return S_OK;
}


//--------------------------------------------------------------------------------------
// Handle updates to the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
}


//--------------------------------------------------------------------------------------
// Render the scene 
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;
		static bool firstCall = true;

		if( firstCall )
		{
			firstCall = false;
			initVideoRendering();
		}

    // Clear the render target and the zbuffer 
    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );

    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
        V( pd3dDevice->EndScene() );
    }
}


//--------------------------------------------------------------------------------------
// Handle messages to the application 
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 
                          bool* pbNoFurtherProcessing, void* pUserContext )
{
    return 0;
}


//--------------------------------------------------------------------------------------
// Release resources created in the OnResetDevice callback here 
//--------------------------------------------------------------------------------------
void CALLBACK OnLostDevice( void* pUserContext )
{
}


//--------------------------------------------------------------------------------------
// Release resources created in the OnCreateDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void* pUserContext )
{
}



//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // Set the callback functions
    DXUTSetCallbackDeviceCreated( OnCreateDevice );
    DXUTSetCallbackDeviceReset( OnResetDevice );
    DXUTSetCallbackDeviceLost( OnLostDevice );
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackFrameRender( OnFrameRender );
    DXUTSetCallbackFrameMove( OnFrameMove );
   
    // TODO: Perform any application-level initialization here

    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
    DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"VideoTutorial" );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );


    // Start the render loop
    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here

    return DXUTGetExitCode();
}

And here my Debug-Output:
25.5.2007-12:6:6
Step 0
Step 1
AddRef
QueryInterface 
QueryInterface 
QueryInterface 
AdviseNotify 00F90250
InitializeDevice 00F90250
  number buffers: 1
GetSurface  0
GetSurface  done 001B2D80
Step 2
GetSurface  43056640
GetSurface  done 001B2D80

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