title: Windows Media Foundation - Capture Camera video as raw RBG32
body: <p>I am stacking with this code for more that a week :)</p>
  
  <p>I've changed the sample code included with Windows SDK (<code>CWavSink</code>) which is a custom wave sink to record a PCM data to wav file.</p>
  
  <p>I've made some changes to use that sample as a video sink to record the video stream from a web cam on Windows 8.</p>
  
  <p>I was managed to get the video frames from the <code>IMFSample</code> but the problems I have is:</p>
  
  <ol>
  <li><p>When record the captured frames to test file then try to convert it to avi or any other format using ffmpeg the output has wrong colors and the video is not played OK.</p></li>
  <li><p>What ever I set for the width and height I always get the frames as 320X240.</p></li>
  <li><p>Sample buffer is always 600kb which contains 2 frames (I am setting it to get one frame as the sample size)</p></li>
  <li><p>I've tried to change the format from RGB32 to H263 but it seems that the setting was ignored and I get RGB32 always.</p></li>
  </ol>
  
  <p>I am appreciating any help on that</p>
  
  <p>Here is my code</p>
  
  <pre><code>#include "pch.h"
  #include "VideoSink.h"
  
  #pragma warning( push )
  #pragma warning( disable : 4355 )  // 'this' used in base member initializer list
  
  using namespace VideoRecorder;
  
  const DWORD VIDEO_SINK_STREAM_ID = 1;
  
  
  HRESULT ValidateVideoFormat(const WAVEFORMATEX *pWav, DWORD cbSize);
  
  HRESULT CreateRawVideoType(
      UINT32 frameRate,        // Samples per second
      UINT32 width,     // Bits per sample
      UINT32 hieght,         // Number of channels
      IMFMediaType **ppType     // Receives a pointer to the media type.
      );
  
  
  IFACEMETHODIMP CVideoSink::Initialize()
  {
      IMFByteStream *pStream = nullptr;
  
  
  
      HRESULT hr = S_OK;
  
  
      if (SUCCEEDED(hr))
      {
          hr = this-&gt;Initialize(pStream);
      }
  
      return hr;
  }
  
  CVideoSink::CVideoSink() :
      m_nRefCount(1), m_IsShutdown(FALSE), m_pStream(NULL), m_pClock(NULL)
  {
  
  }
  
  CVideoSink::~CVideoSink()
  {
      TRACE((L"~CVideoSink\n"));
      assert(m_IsShutdown);
  }
  
  IFACEMETHODIMP CVideoSink::GetCharacteristics(DWORD *pdwCharacteristics)
  {
      AutoLock lock(m_critSec);
  
      if (pdwCharacteristics == NULL)
      {
          return E_INVALIDARG;
      }
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          *pdwCharacteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_RATELESS;
      }
  
      return hr;
  }
  
  
  IFACEMETHODIMP CVideoSink::AddStreamSink( 
      DWORD dwStreamSinkIdentifier,
      IMFMediaType *pMediaType,
      IMFStreamSink **ppStreamSink)
  {
      return MF_E_STREAMSINKS_FIXED;
  }
  
  IFACEMETHODIMP CVideoSink::RemoveStreamSink(DWORD dwStreamSinkIdentifier)
  {
      return MF_E_STREAMSINKS_FIXED;
  }
  
  IFACEMETHODIMP CVideoSink::GetStreamSinkCount(DWORD *pcStreamSinkCount)
  {
      AutoLock lock(m_critSec);
  
      if (pcStreamSinkCount == NULL)
      {
          return E_INVALIDARG;
      }
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          *pcStreamSinkCount = 1;  // Fixed number of streams.
      }
  
      return hr;
  
  }
  
  IFACEMETHODIMP CVideoSink::GetStreamSinkByIndex( 
      DWORD dwIndex,
      IMFStreamSink **ppStreamSink)
  {
      AutoLock lock(m_critSec);
  
      if (ppStreamSink == NULL)
      {
          return E_INVALIDARG;
      }
  
      // Fixed stream: Index 0. 
      if (dwIndex &gt; 0)
      {
          return MF_E_INVALIDINDEX;
      }
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          *ppStreamSink = m_pStream;
          (*ppStreamSink)-&gt;AddRef();
      }
  
      return hr;
  }
  
  IFACEMETHODIMP CVideoSink::GetStreamSinkById( 
      DWORD dwStreamSinkIdentifier,
      IMFStreamSink **ppStreamSink)
  {
      AutoLock lock(m_critSec);
  
      if (ppStreamSink == NULL)
      {
          return E_INVALIDARG;
      }
  
      // Fixed stream ID.
      if (dwStreamSinkIdentifier != VIDEO_SINK_STREAM_ID)
      {
          return MF_E_INVALIDSTREAMNUMBER;
      }
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          *ppStreamSink = m_pStream;
          (*ppStreamSink)-&gt;AddRef();
      }
  
      return hr;
  
  }
  
  IFACEMETHODIMP CVideoSink::SetPresentationClock(IMFPresentationClock *pPresentationClock)
  {
      AutoLock lock(m_critSec);
  
      HRESULT hr = CheckShutdown();
  
      // If we already have a clock, remove ourselves from that clock's
      // state notifications.
      if (SUCCEEDED(hr))
      {
          if (m_pClock)
          {
              hr = m_pClock-&gt;RemoveClockStateSink(this);
          }
      }
  
      // Register ourselves to get state notifications from the new clock.
      if (SUCCEEDED(hr))
      {
          if (pPresentationClock)
          {
              hr = pPresentationClock-&gt;AddClockStateSink(this);
          }
      }
  
      if (SUCCEEDED(hr))
      {
          // Release the pointer to the old clock.
          // Store the pointer to the new clock.
  
          SAFE_RELEASE(m_pClock);
          m_pClock = pPresentationClock;
          if (m_pClock)
          {
              m_pClock-&gt;AddRef();
          }
      }
  
      return hr;
  }
  
  IFACEMETHODIMP CVideoSink::GetPresentationClock(IMFPresentationClock **ppPresentationClock)
  {
      AutoLock lock(m_critSec);
  
      if (ppPresentationClock == NULL)
      {
          return E_INVALIDARG;
      }
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          if (m_pClock == NULL)
          {
              hr = MF_E_NO_CLOCK; // There is no presentation clock.
          }
          else
          {
              // Return the pointer to the caller.
              *ppPresentationClock = m_pClock;
              (*ppPresentationClock)-&gt;AddRef();
          }
      }
  
  
      return hr;
  }
  
  IFACEMETHODIMP CVideoSink::Shutdown()
  {
      TRACE((L"CVideoSink::Shutdown\n"));
      AutoLock lock(m_critSec);
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          hr = m_pStream-&gt;Shutdown();
  
          SAFE_RELEASE(m_pClock);
          SAFE_RELEASE(m_pStream);
  
          m_IsShutdown = true;
      }
  
      return hr;
  }
  
  IFACEMETHODIMP CVideoSink::BeginFinalize( 
      IMFAsyncCallback *pCallback,
      IUnknown *punkState)
  {
      TRACE((L"CVideoSink::BeginFinalize\n"));
  
      AutoLock lock(m_critSec);
  
      HRESULT hr = CheckShutdown();
  
      // Tell the stream to finalize.
      if (SUCCEEDED(hr))
      {
          hr = m_pStream-&gt;Finalize(pCallback, punkState);
      }
      return hr;
  }
  
  IFACEMETHODIMP CVideoSink::EndFinalize(IMFAsyncResult *pResult)
  {
      TRACE((L"CVideoSink::EndFinalize\n"));
  
      HRESULT hr = S_OK;
  
      // Return the status code from the async result.
      if (pResult == NULL)
      {
          hr = E_INVALIDARG;
      }
      else
      {
          hr = pResult-&gt;GetStatus();
      }
  
      return hr;
  }
  
  HRESULT CVideoSink::OnClockStart( 
          /* [in] */ MFTIME hnsSystemTime,
          /* [in] */ LONGLONG llClockStartOffset)
  {
      AutoLock lock(m_critSec);
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          hr = m_pStream-&gt;Start(llClockStartOffset);
      }
  
      return hr;
  }    
  
  HRESULT CVideoSink::OnClockStop( 
          /* [in] */ MFTIME hnsSystemTime)
  {
      TRACE((L"CVideoSink::OnClockStop\n"));
      AutoLock lock(m_critSec);
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          hr = m_pStream-&gt;Stop();
      }
  
      return hr;
  }    
  
  HRESULT CVideoSink::OnClockPause( 
          /* [in] */ MFTIME hnsSystemTime)
  {
      AutoLock lock(m_critSec);
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          hr = m_pStream-&gt;Pause();
      }
  
      return hr;
  }
  
  
  HRESULT CVideoSink::OnClockRestart( 
          /* [in] */ MFTIME hnsSystemTime)
  {
      AutoLock lock(m_critSec);
  
      HRESULT hr = CheckShutdown();
  
      if (SUCCEEDED(hr))
      {
          hr = m_pStream-&gt;Restart();
      }
  
      return hr;
  }
  
  HRESULT CVideoSink::OnClockSetRate( 
          /* [in] */ MFTIME hnsSystemTime,
          /* [in] */ float flRate)
  {
      return S_OK;
  }
  
  HRESULT CVideoSink::Initialize(IMFByteStream *pByteStream)
  {
      HRESULT hr = S_OK;
  
      m_pStream = new CVideoStream();
      if (m_pStream == NULL)
      {
          hr = E_OUTOFMEMORY;
      }
  
      IMFMediaTypeHandler* typeHandler;
      IMFMediaType* type;
  
  
      // Initialize the stream.
      if (SUCCEEDED(hr))
      {
          hr = m_pStream-&gt;Initialize(this, pByteStream);
      }
  
  
      return hr;
  }
  </code></pre>
  
  <p>I will add the second part as another post ( sorry it is long code :) )</p>
  
  <p># not allowed :) get it from here <a href="https://github.com/Felixsoft/VideoSink" rel="nofollow">https://github.com/Felixsoft/VideoSink</a></p>