title: Use EVR to display frames captured by camera device directly using Media Foundation
body: <p>I am trying to write a small app that display video frames captured by camera device directly onto a window. I am using "Source Reader" + "Sink Writer" architecture rather than "Media Session" as I have to deal with those captured samples directly. I have created Source Reader successfully but when I tried to create EVR to display frames, I met some problems... following is my code:</p>
  
  <pre><code>HRESULT CCapture::CreatePreviewEVR(HWND hWindow)
  {
      // m_pPreviewSink, m_pPreviewStream, m_pPresentationClock, and m_pPresentationTimeSource
      // are all defined as Class members
      HRESULT hr = S_OK;
      DWORD sinkCharacteristics = NULL;
      IMFActivate *pPreviewSinkActive = NULL;
      IMFClockStateSink *pClockStateSink = NULL;
      hr = MFCreateVideoRendererActivate(hWindow, &amp;pPreviewSinkActive);
      if(SUCCEEDED(hr))
      {
          hr = pPreviewSinkActive-&gt;ActivateObject(IID_PPV_ARGS(&amp;m_pPreviewSink));
      }
      if(SUCCEEDED(hr))
      {
          hr = m_pPreviewSink-&gt;GetCharacteristics(&amp;sinkCharacteristics); // sinkCharacteristics is 0x18
      }
      if(SUCCEEDED(hr))
      {
          hr = m_pPreviewSink-&gt;GetStreamSinkByIndex(0, &amp;m_pPreviewStream);
      }
      if(SUCCEEDED(hr))
      {
          hr = MFCreatePresentationClock(&amp;m_pPresentationClock);
      }
      if(SUCCEEDED(hr))
      {
          hr = MFCreateSystemTimeSource(&amp;m_pPresentationTimeSource);
      }
      if(SUCCEEDED(hr))
      {
          hr = m_pPresentationTimeSource-&gt;QueryInterface(__uuidof(IMFClockStateSink),(void**)&amp;pClockStateSink);
      }
      if(SUCCEEDED(hr))
      {
          hr = m_pPresentationClock-&gt;SetTimeSource(m_pPresentationTimeSource);
      }
      if(SUCCEEDED(hr))
      {
          hr = m_pPresentationClock-&gt;AddClockStateSink(pClockStateSink);
      }
      if(SUCCEEDED(hr))
      {
          hr = m_pPreviewSink-&gt;SetPresentationClock(m_pPresentationClock);
      }
      return hr;
  }
  
  HRESULT CCapture::ConfigurePreviewEVR()
  {
      // This function is implemented trying to do EVR Media Type Negotiation
      DWORD mediaTypeCount = 0;
      HRESULT hr =S_OK;
      IMFMediaType *pSourceReaderType = NULL;
      IMFMediaType *pSourceReaderTypeValid = NULL;
      IMFMediaType *pPreviewSinkMediaType = NULL;
      IMFMediaTypeHandler  *pPreviewSinkMediaTypeHandler = NULL;
      hr = m_pReader-&gt;GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, &amp;pSourceReaderType);
      if(SUCCEEDED(hr))
      {
          hr = MFCreateMediaType(&amp;pPreviewSinkMediaType);
      }
      if(SUCCEEDED(hr))
      {
          hr = pPreviewSinkMediaType-&gt;SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
      }
      if(SUCCEEDED(hr))
      {
          hr = pPreviewSinkMediaType-&gt;SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
      }
      if(SUCCEEDED(hr))
      {
          hr = pPreviewSinkMediaType-&gt;SetUINT32(MF_MT_AVG_BITRATE, 14000000);
      }
      if(SUCCEEDED(hr))
      {
          hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_FRAME_SIZE);
      }
      if(SUCCEEDED(hr))
      {
          hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_FRAME_RATE);
      }
      if(SUCCEEDED(hr))
      {
          hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_PIXEL_ASPECT_RATIO);
      }
      if(SUCCEEDED(hr))
      {
          hr = CopyAttribute(pSourceReaderType, pPreviewSinkMediaType, MF_MT_INTERLACE_MODE);
      }
      if(SUCCEEDED(hr))
      {
          hr = m_pPreviewStream-&gt;GetMediaTypeHandler(&amp;pPreviewSinkMediaTypeHandler);
      }
      if(SUCCEEDED(hr))
      {
          hr = pPreviewSinkMediaTypeHandler-&gt;GetMediaTypeCount(&amp;mediaTypeCount); // derived mediaTypeCount is 0
      }
      if(SUCCEEDED(hr))
      {
          hr = pPreviewSinkMediaTypeHandler-&gt;IsMediaTypeSupported(pSourceReaderType, &amp;pSourceReaderTypeValid); // Failed to get supported Media Type
      }
      if(SUCCEEDED(hr))
      {
          hr = pPreviewSinkMediaTypeHandler-&gt;SetCurrentMediaType(pSourceReaderTypeValid); // This function still fails if I use pSourceReaderType directly 
      }
      if(SUCCEEDED(hr))
      {
          SafeRelease(&amp;pSourceReaderType);
          SafeRelease(&amp;pPreviewSinkMediaType);
          SafeRelease(&amp;pPreviewSinkMediaTypeHandler);
      }
      return hr;
  }
  </code></pre>
  
  <p>The function "CopyAttribute" is from MFCaptureToFile Sample Code, it can work normally. As the variable "sinkCharacteristics" gives 0x18, it seems I should be able to add a new stream with the media type I wish to use to the mediasink; however I tried AddStreamSink function but it returned error directly.
  The "CCapture" Class inherits from IMFSourceReaderCallBack, and If my understanding is correct, I should use m_pPreviewStream->ProcessSample(pSample) in OnReadSample callback function.
  Thanks a lot if anyone can help on this!
  Best Regards</p>