title: DirectX: The best way to get RGB data from ID3D11Texture2D with DXGI_FORMAT_NV12 format?
body: <p>I'm using DirectX to draw videos. After decoding by Intel Media SDK. And then I draw it by the following Intel's Code:</p>
  
  <pre><code>mfxStatus CD3D11Device::RenderFrame(mfxFrameSurface1 * pSrf, mfxFrameAllocator * pAlloc)
  {
      HRESULT hres = S_OK;
      mfxStatus sts;
  
      sts = CreateVideoProcessor(pSrf);
      MSDK_CHECK_STATUS(sts, "CreateVideoProcessor failed");
  
      hres = m_pSwapChain-&gt;GetBuffer(0, __uuidof( ID3D11Texture2D ), (void**)&amp;m_pDXGIBackBuffer.p);
      if (FAILED(hres))
          return MFX_ERR_DEVICE_FAILED;
  
      D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc;
      if (2 == m_nViews)
      {
          m_pVideoContext-&gt;VideoProcessorSetStreamStereoFormat(m_pVideoProcessor, 0, TRUE,D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_SEPARATE,
              TRUE, TRUE, D3D11_VIDEO_PROCESSOR_STEREO_FLIP_NONE, NULL);
          m_pVideoContext-&gt;VideoProcessorSetOutputStereoMode(m_pVideoProcessor,TRUE);
  
          OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2DARRAY;
          OutputViewDesc.Texture2DArray.ArraySize = 2;
          OutputViewDesc.Texture2DArray.MipSlice = 0;
          OutputViewDesc.Texture2DArray.FirstArraySlice = 0;
      }
      else
      {
          OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
          OutputViewDesc.Texture2D.MipSlice = 0;
      }
  
      if (1 == m_nViews || 0 == pSrf-&gt;Info.FrameId.ViewId)
      {
          hres = m_pDX11VideoDevice-&gt;CreateVideoProcessorOutputView(
              m_pDXGIBackBuffer,
              m_VideoProcessorEnum,
              &amp;OutputViewDesc,
              &amp;m_pOutputView.p );
          if (FAILED(hres))
              return MFX_ERR_DEVICE_FAILED;
      }
  
      D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC InputViewDesc;
      InputViewDesc.FourCC = 0;
      InputViewDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
      InputViewDesc.Texture2D.MipSlice = 0;
      InputViewDesc.Texture2D.ArraySlice = 0;
  
      mfxHDLPair pair = {NULL};
      sts = pAlloc-&gt;GetHDL(pAlloc-&gt;pthis, pSrf-&gt;Data.MemId, (mfxHDL*)&amp;pair);
      MSDK_CHECK_STATUS(sts, "pAlloc-&gt;GetHDL failed");
  
      ID3D11Texture2D  *pRTTexture2D = reinterpret_cast&lt;ID3D11Texture2D*&gt;(pair.first);
      D3D11_TEXTURE2D_DESC RTTexture2DDesc;
  
      if(!m_pTempTexture &amp;&amp; m_nViews == 2)
      {
          pRTTexture2D-&gt;GetDesc(&amp;RTTexture2DDesc);
          hres = m_pD3D11Device-&gt;CreateTexture2D(&amp;RTTexture2DDesc,NULL,&amp;m_pTempTexture.p);
          if (FAILED(hres))
              return MFX_ERR_DEVICE_FAILED;
      }
  
      // Creating input views for left and righ eyes
      if (1 == m_nViews)
      {
          hres = m_pDX11VideoDevice-&gt;CreateVideoProcessorInputView(
              pRTTexture2D,
              m_VideoProcessorEnum,
              &amp;InputViewDesc,
              &amp;m_pInputViewLeft.p );
  
      }
      else if (2 == m_nViews &amp;&amp; 0 == pSrf-&gt;Info.FrameId.ViewId)
      {
          m_pD3D11Ctx-&gt;CopyResource(m_pTempTexture,pRTTexture2D);
          hres = m_pDX11VideoDevice-&gt;CreateVideoProcessorInputView(
              m_pTempTexture,
              m_VideoProcessorEnum,
              &amp;InputViewDesc,
              &amp;m_pInputViewLeft.p );
      }
      else
      {
          hres = m_pDX11VideoDevice-&gt;CreateVideoProcessorInputView(
              pRTTexture2D,
              m_VideoProcessorEnum,
              &amp;InputViewDesc,
              &amp;m_pInputViewRight.p );
      }
      if (FAILED(hres))
          return MFX_ERR_DEVICE_FAILED;
  
      //  NV12 surface to RGB backbuffer
      RECT rect = {0};
      rect.right  = pSrf-&gt;Info.CropW;
      rect.bottom = pSrf-&gt;Info.CropH;
  
      D3D11_VIDEO_PROCESSOR_STREAM StreamData;
  
      if (1 == m_nViews || pSrf-&gt;Info.FrameId.ViewId == 1)
      {
          StreamData.Enable = TRUE;
          StreamData.OutputIndex = 0;
          StreamData.InputFrameOrField = 0;
          StreamData.PastFrames = 0;
          StreamData.FutureFrames = 0;
          StreamData.ppPastSurfaces = NULL;
          StreamData.ppFutureSurfaces = NULL;
          StreamData.pInputSurface = m_pInputViewLeft;
          StreamData.ppPastSurfacesRight = NULL;
          StreamData.ppFutureSurfacesRight = NULL;
          StreamData.pInputSurfaceRight = m_nViews == 2 ? m_pInputViewRight : NULL;
  
          m_pVideoContext-&gt;VideoProcessorSetStreamSourceRect(m_pVideoProcessor, 0, true, &amp;rect);
          m_pVideoContext-&gt;VideoProcessorSetStreamFrameFormat( m_pVideoProcessor, 0, D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE);
          hres = m_pVideoContext-&gt;VideoProcessorBlt( m_pVideoProcessor, m_pOutputView, 0, 1, &amp;StreamData );
          if (FAILED(hres))
              return MFX_ERR_DEVICE_FAILED;
      }
  
      if (1 == m_nViews || 1 == pSrf-&gt;Info.FrameId.ViewId)
      {
          DXGI_PRESENT_PARAMETERS parameters = {0};
          hres = m_pSwapChain-&gt;Present1(0, 0, &amp;parameters);
          if (FAILED(hres))
              return MFX_ERR_DEVICE_FAILED;
      }
  
      return MFX_ERR_NONE;
  }
  </code></pre>
  
  <p>From the code's line:</p>
  
  <pre><code>ID3D11Texture2D  *pRTTexture2D = reinterpret_cast&lt;ID3D11Texture2D*&gt;(pair.first);
  </code></pre>
  
  <p>I had <code>pRTTexture2D</code> is a <code>ID3D11Texture2D</code> with DXGI_FORMAT_NV12 format.</p>
  
  <p>I want to get RGB data from this texture, and I tried to using the below way:</p>
  
  <p>1) Map the texture use <code>d3dContext-&gt;Map(Texture, 0, D3D11_MAP_READ, 0, &amp;mapInfo) =&gt; must copy to the staging resource in my case</code></p>
  
  <p>2) Create a <code>RGB Array</code> on System Memory and calculate to convert from NV12 on <code>mapInfo</code> to <code>RGB Array</code>.</p>
  
  <p>This way worked ok, but I want to do it with the better way. Because I guess that while rendering <code>(RenderFrame() Function)</code> the DirectX converted Texture in to RGB in BackBuffer, and if I can get data form that BackBuffer, that will be great.</p>
  
  <p>Someone can show me the code to do above way. Or is there any better way to implement it?</p>
  
  <p>Thank you very much!</p>