topical media & game development

talk show tell print

hush-src-multi-MultiPlayer-MultiGraphSession.cpp / cpp



  //------------------------------------------------------------------------------
  // File: MultiGraphSession.cpp
  //
  // Desc: DirectShow sample code - MultiVMR9 MultiPlayer sample
  //
  // Copyright (c) Microsoft Corporation.  All rights reserved.
  //------------------------------------------------------------------------------
  
  include <stdafx.h>
  include <MultiVMR9.h>
  include <VMR9Subgraph.h>
  include <MultigraphSession.h>
  
  extern HINSTANCE g_hInstance;
  const TCHAR g_achVideoWindowClass[] = TEXT("MultiVMR9 Video Window class");
  
  
****************************Public*Routine******************************\ CMultigraphSession constructor \*************************************************************************

  
  CMultigraphSession::CMultigraphSession()
      : m_hwndVideo( NULL )
      , m_pWizard( NULL )
      , m_pRenderEngine( NULL )
      , m_pMixerControl( NULL )
      , m_pUILayer( NULL )
  {
  }
  
  
****************************Public*Routine******************************\ ~CMultigraphSession destructor \*************************************************************************

  
  CMultigraphSession::~CMultigraphSession()
  {
      Terminate();
  
      RELEASE( m_pWizard );
      RELEASE( m_pRenderEngine );
      RELEASE( m_pMixerControl );
      RELEASE( m_pUILayer );
  }
  
  
****************************Public*Routine******************************\ AddSource adds new source to the list, attaches it to the wizard \*************************************************************************

  
  HRESULT CMultigraphSession::AddSource(WCHAR *wcPath, DWORD_PTR& dwID)
  {
      CVMR9Subgraph *pSubgraph = NULL;
  
      HRESULT hr = S_OK;
      if( !wcPath )
      {
          return E_POINTER;
      }
      if( !m_pWizard )
      {
          return VFW_E_WRONG_STATE;
      }
  
      try
      {
                  // commented lines work fine on XP and NT4
                  /*
          if( INVALID_FILE_ATTRIBUTES == ::GetFileAttributesW( wcPath))
          {
              throw VFW_E_NOT_FOUND;
          }*/
  
                  // Unicode-related workaround for WindowsMe/98
                  {
                          char szPath[MAX_PATH];
                          DWORD dwGFA = 0L;
                          DWORD dwErr = 0L;
  
                          WideCharToMultiByte(CP_ACP, 0, wcPath, -1, szPath, MAX_PATH, NULL, NULL);
                          dwGFA = ::GetFileAttributesA( szPath);
                          if( INVALID_FILE_ATTRIBUTES == dwGFA)
                          {
                                  dwErr = GetLastError();
                                  throw VFW_E_NOT_FOUND;
                          }
                  }
  
          pSubgraph = new CVMR9Subgraph;
          if( !pSubgraph )
          {
              throw E_OUTOFMEMORY;
          }
  
          hr = pSubgraph->BuildAndRender( wcPath, m_pWizard );
          if( FAILED(hr))
          {
              throw hr;
          }
  
          //remember the ID, add to the list
          dwID = pSubgraph->GetID();
  
          m_sources.push_back( pSubgraph );
      }
      catch( HRESULT hr1 )
      {
          if( pSubgraph )
          {
              delete pSubgraph;
          }
          hr = hr1;
      }
      return hr;
  }
  
  
****************************Public*Routine******************************\ DeleteSource deletes a source from the list, detaches it from the wizard \*************************************************************************

  
  HRESULT CMultigraphSession::DeleteSource( DWORD_PTR dwID )
  {
      HRESULT hr = S_OK;
  
      CVMR9Subgraph *pSubgraph = NULL;
  
      try
      {
          if( !m_pWizard )
          {
              throw VFW_E_WRONG_STATE;
          }
  
          pSubgraph = GetSubgraph( dwID );
          if( !pSubgraph )
          {
              throw VFW_E_NOT_FOUND;
          }
  
          hr = pSubgraph->Stop();
          if( FAILED(hr))
          {
              throw hr;
          }
  
          hr = m_pWizard->Detach( pSubgraph->GetID());
          if( FAILED(hr))
          {
              throw hr;
          }
  
          m_sources.remove( pSubgraph );
  
          delete pSubgraph;
          pSubgraph = NULL;
          hr = S_OK;
      }
      catch( HRESULT hr1 )
      {
          hr = hr1;
      }
  
      return hr;
  }
  
  
****************************Public*Routine******************************\ Terminate terminates wizard \*************************************************************************

  
  HRESULT CMultigraphSession::Terminate()
  {
      HRESULT hr = S_OK;
      list<CVMR9Subgraph*>::iterator it;
  
      CVMR9Subgraph* pSubgraph = NULL;
  
      try
      {
          // 1. Detach all the existing subgraphs
          while( false == m_sources.empty())
          {
              it = m_sources.begin();
              pSubgraph = (CVMR9Subgraph*)(*it);
              ASSERT( pSubgraph );
  
              hr = DeleteSource( pSubgraph->GetID());
              if( FAILED(hr))
                  throw hr;
          }
  
          // 2. Terminate Wizard, if there is any
          if( m_pWizard )
          {
              hr = m_pWizard->Terminate();
              if( FAILED(hr))
                  throw hr;
          }
  
          // 3. Destroy video window
          if( IsWindow( m_hwndVideo ))
          {
              ::DestroyWindow( m_hwndVideo );
              m_hwndVideo = NULL;
          }
  
          UnregisterClass( g_achVideoWindowClass, g_hInstance);
      }
      catch( HRESULT hr1)
      {
          hr = hr1;
      }
      return hr;
  }
  
  
****************************Public*Routine******************************\ GetSubgraph find subgraph in the list by dwID \*************************************************************************

  
  CVMR9Subgraph* CMultigraphSession::GetSubgraph(  DWORD_PTR dwID  )
  {
      CVMR9Subgraph* pSubgraph = NULL;
      list<CVMR9Subgraph*>::iterator start, end, it;
  
      start = m_sources.begin();
      end = m_sources.end();
  
      for(it = start; it!= end; it++)
      {
          if( (*it) && (*it)->GetID() == dwID )
          {
              pSubgraph = (CVMR9Subgraph*)(*it);
              break;
          }
      }
      return pSubgraph;
  }
  
  
****************************Public*Routine******************************\ GetWizard \*************************************************************************

  
  IMultiVMR9Wizard* CMultigraphSession::GetWizard( )
  {
      IMultiVMR9Wizard* pRes = NULL;
      if( m_pWizard )
      {
          pRes = m_pWizard;
          pRes->AddRef();
      }
      return pRes;
  }
  
  
****************************Public*Routine******************************\ GetRenderEngine \*************************************************************************

  
  IMultiVMR9RenderEngine* CMultigraphSession::GetRenderEngine( )
  {
      IMultiVMR9RenderEngine* pRes = NULL;
      if( m_pRenderEngine )
      {
          pRes = m_pRenderEngine;
          pRes->AddRef();
      }
      return pRes;
  }
  
  
****************************Public*Routine******************************\ GetMixerControl \*************************************************************************

  
  IMultiVMR9MixerControl* CMultigraphSession::GetMixerControl( )
  {
      IMultiVMR9MixerControl* pRes = NULL;
      if( m_pMixerControl )
      {
          pRes = m_pMixerControl;
          pRes->AddRef();
      }
      return pRes;
  }
  
  
****************************Public*Routine******************************\ GetUILayer \*************************************************************************

  
  IMultiVMR9UILayer* CMultigraphSession::GetUILayer( )
  {
      IMultiVMR9UILayer* pRes = NULL;
      if( m_pUILayer )
      {
          pRes = m_pUILayer;
          pRes->AddRef();
      }
      return pRes;
  }
  
  
****************************Public*Routine******************************\ GetFrameRate \*************************************************************************

  
  int CMultigraphSession::GetFrameRate()
  {
      int nRes = 0;
  
      if( !m_pRenderEngine )
          return 30;
  
      m_pRenderEngine->GetFrameRate( &nRes );
      return nRes;
  }
  
  
****************************Public*Routine******************************\ SetColor \*************************************************************************

  
  HRESULT CMultigraphSession::SetColor( COLORREF color )
  {
      HRESULT hr = S_OK;
  
      if( !m_pMixerControl )
          return E_FAIL;
  
      hr = m_pMixerControl->SetBackgroundColor( color );
  
      return hr;
  }
  
  
****************************Public*Routine******************************\ LoopSources go through the list and reset time to start if movie is close to the end \*************************************************************************

  
  void CMultigraphSession::LoopSources()
  {
      CVMR9Subgraph *pSource = NULL;
      LONGLONG llCur;
      LONGLONG llDur;
  
      list<CVMR9Subgraph*>::iterator start, end, it;
      start = m_sources.begin();
      end = m_sources.end();
  
      for( it = start; it != end; it++)
      {
          pSource = (CVMR9Subgraph*)(*it);
          if( !pSource )
              continue;
  
          pSource->GetTimes( llCur, llDur);
          // 100ms
          if( llDur - llCur < 1000000L )
          {
              pSource->SetTime( 0L );
          }
      }
  }
  
  
****************************Public*Routine******************************\ CreateVideoWindow_ creates video window \*************************************************************************

  
  HRESULT CMultigraphSession::CreateVideoWindow_(UINT Width, UINT Height, DWORD dwStyle)
  {
      HRESULT hr = S_OK;
      WNDCLASSEX wcex;
      RECT rc;
      RECT rcClient;
      int dx, dy;
  
      try
      {
          if( IsWindow( m_hwndVideo ))
              throw E_UNEXPECTED;
  
          wcex.cbSize = sizeof(WNDCLASSEX); 
          wcex.style          = CS_HREDRAW | CS_VREDRAW;
          wcex.lpfnWndProc    = (WNDPROC)CMultigraphSession::VideoWndProc;
          wcex.cbClsExtra     = 0;
          wcex.cbWndExtra     = 0;
          wcex.hInstance      = g_hInstance;
          wcex.hIcon          = NULL;
          wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
          wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
          wcex.lpszMenuName   = TEXT("");
          wcex.lpszClassName  = g_achVideoWindowClass;
          wcex.hIconSm        = NULL;
  
          RegisterClassEx( &wcex);
  
          m_hwndVideo  = CreateWindow(    g_achVideoWindowClass, 
                                          TEXT("VMR9 Custom Allocator-Presenter"), 
                                          dwStyle,
                                          100, 100, 
                                          800, 600, 
                                          NULL, 
                                          NULL, 
                                          g_hInstance, 
                                          NULL);
          if( !IsWindow( m_hwndVideo ))
              throw E_FAIL;
  
          ::SetWindowLong( m_hwndVideo, GWL_USERDATA, (LONG)this);
  
          // resize the window so that client area be 800x600
          ::GetClientRect( m_hwndVideo, &rcClient);
  
          ::GetWindowRect( m_hwndVideo, &rc);
          dx = rc.right - rc.left - rcClient.right;
          dy = rc.bottom - rc.top - rcClient.bottom;
  
          ::SetWindowPos( m_hwndVideo, HWND_TOP, 0, 0, Width+dx, Height+dy, SWP_NOMOVE);
  
      }// try
      catch( HRESULT hr1 )
      {
          hr = hr1;
      }
  
      return hr;
  }
  
  
****************************Public*Routine******************************\ VideoWndProc \*************************************************************************

  
  LRESULT CALLBACK CMultigraphSession::VideoWndProc(
                                          HWND hwnd,      // handle to window
                                          UINT uMsg,      // message identifier
                                          WPARAM wParam,  // first message parameter
                                          LPARAM lParam   // second message parameter
                                          )
  {
      CMultigraphSession* This = NULL;
      IMultiVMR9UILayer* pUI = NULL;
      LRESULT lRes = 0;
  
      This = (CMultigraphSession*)::GetWindowLong( hwnd, GWL_USERDATA);
      if( This )
      {
          pUI = This->GetUILayer();
      }
  
      lRes = DefWindowProc( hwnd, uMsg, wParam, lParam);
  
      if( pUI )
      {
          pUI->ProcessMessage( uMsg, (UINT)wParam, (LONG)lParam);
      }
  
      RELEASE( pUI );
  
      return lRes;
  }
  
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.