1

Not only that the fps drops form 60 to 20-21 but the image also looks distorted like this. Second image is what it should look like

What it looks like What it should look like

if (captureVideo == 1) {
    pNewTexture = NULL;

    // Use the IDXGISwapChain::GetBuffer API to retrieve a swap chain surface ( use the uuid  ID3D11Texture2D for the result type ).
    pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &pSurface ) ); 

    /* The swap chain buffers are not mapable, so I need to copy it to a staging resource. */

    pSurface->GetDesc( &description ); //Use ID3D11Texture2D::GetDesc to retrieve the surface description

    // Patch it with a D3D11_USAGE_STAGING usage and a cpu access flag of D3D11_CPU_ACCESS_READ
    description.BindFlags = 0;
    description.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    description.Usage = D3D11_USAGE_STAGING;

    // Create a temporary surface ID3D11Device::CreateTexture2D
    HRESULT hr = pDevice->CreateTexture2D( &description, NULL, &pNewTexture );
    if( pNewTexture )
    {
        // Copy to the staging surface ID3D11DeviceContext::CopyResource
        pContext->CopyResource( pNewTexture, pSurface );
        // Now I have a ID3D11Texture2D with the content of your swap chain buffer that allow you to use the ID3D11DeviceContext::Map API to read it on the CPU
        D3D11_MAPPED_SUBRESOURCE resource;
        pContext->Map( pNewTexture, D3D11CalcSubresource( 0, 0, 0), D3D11_MAP_READ, 0, &resource );

        const int pitch = w << 2;
        const unsigned char* source = static_cast< const unsigned char* >( resource.pData );
        unsigned char* dest = static_cast< unsigned char* >(m_lpBits);
        for( int i = 0; i < h; ++i )
        {
            memcpy( dest, source, w * 4 );
            source += pitch;
            dest += pitch;
        }

        AppendNewFrame(w, h, m_lpBits,24);

        pContext->Unmap( pNewTexture, 0);
        pNewTexture->Release();
    }
}
Josh
  • 49
  • 1
  • 6
  • You should check result of `GetBuffer` call as well as other calls here. Note result of `CreateTexture2D` should be checked rather than pointer value. You also don't seem to release `pSurface` after you done using it. – user7860670 Jun 24 '18 at 21:08
  • 1
    I think there are several problems with the code, however the giving the most significant effect one is around the number of 24 in the `AppendNewFrame` line. And you don't show this code... – Roman R. Jun 24 '18 at 21:25
  • AppendNewFrame function works,tested it multiple time.it simply creates the mp4 video file and adds the frame, if it didnt, i wouldnt get any video file to show you the output.I unmap,release both the textures and flush the context now, still same problem... – Josh Jun 24 '18 at 21:48
  • Agree with Roman R - I also believe that this problem is more to do with the pitch, the output you're giving is a give away, I would suspect that you should look here first. On a side note: I would also suggest you rearrange your rendering so that you are not directly rendering to the SwapChain buffer, but instead a texture and resolve resource (or copy if it isnt msaa) into that. The reason being is that you can make your screen capture part of the flow of the rendering pipeline, rather than tacked on. it also means you can reuse the code for other backbuffers you might want to capture. – ErnieDingo Jun 24 '18 at 23:21
  • Hi i dont think that it has anything to do with pitch, because if I remove the loop and just directly do AppendNewFrame(w, h, resource.pData,24); I get the same thing.It seems that the pData I get is at fault, if I change the pitch, I just modify how this pData shows, so the problem is earlier, probably at CreateTexture2D? – Josh Jun 25 '18 at 10:15
  • I'd guess `AppendNewFrame` is actually [this](https://github.com/jujinesy/ScreenCap/blob/581e2011bb84842be40660e69b7703bb903391f3/AviFile.cpp#L206) or alike, and it's indeed the problematic line then. Your texture is 32-bit and this would create a distortion of the kind provided on the question's images. Then I see pitch is guessed, most likely correctly but anyway this makes the code dangerous/inaccurate. The pitch is to be taken from `D3D11_MAPPED_SUBRESOURCE` variable. It's not the pitch which is the original problem though. – Roman R. Jun 25 '18 at 10:49
  • That was the problem, thanks.But now a different problem arised, my red and blue blue values seems to be swapped, and the image is upside down.Is there any way better/faster to correct this, except the obvious loops to swap the bytes? – Josh Jun 25 '18 at 13:50
  • It should be exactly RGB vs BGR issue. You need to easier have GPU swap the bytes or you do it yourself. With the code you have already shown, I think your manual swap of the bytes is simple and acceptable. – Roman R. Jun 25 '18 at 15:50
  • Managed to switch the R with B , but when i flip the image horizontally I lose a lot of fps.How do I make the GPU swap them? – Josh Jun 25 '18 at 18:27
  • @Josh: You are supposed to ask one question at a time here. I suggest that you create a new one and provide a new description, for the new problem as you seem to have fixed already a few. – Roman R. Jun 26 '18 at 10:23

1 Answers1

3

The code snippet even though incomplete shows several potential problems:

  1. Number of 24 in AppendNewFrame line suggests that you are trying to treat the data as 24-bit RGB, and your data is 32-bit RGB. Such mistreatment matches the artifacts exhibited on the attached images;
  2. Pitch/stride is taken as assumed default, while you have the effectively used one in D3D11_MAPPED_SUBRESOURCE structure and you should be using it.
Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • See the ``ScreenGrab`` module in the [DirectX Tool Kit](https://github.com/Microsoft/DirectXTK/blob/master/Src/ScreenGrab.cpp) for a more complete solution. – Chuck Walbourn Jul 27 '18 at 08:04