2016-07-02 14 views
2

Ich modifiziere die Desktop-Duplizierung api-Beispiel kindly provided by Microsoft, um den Bildschirm zu erfassen und Updates über das Netzwerk an meine Anwendung zu senden. Ich weiß, wie man die Daten tatsächlich sendet; Mein Problem ist, die Daten vom ID3D11Texture2D Objekt zu bekommen.Abrufen von ID3D11Texture2D-Daten zum Senden über das Netzwerk

ID3D11Texture2D* m_AcquiredDesktopImage; 
IDXGIResource* desktopResource = nullptr; 
DXGI_OUTDUPL_FRAME_INFO FrameInfo; 

// Get new frame 
HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &desktopResource); 

// QI for IDXGIResource 
hr = desktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage)); 

An diesem Punkt denke ich, das Bildschirm-Updates in m_AcquiredDesktopImage ist. Ich muss diese Daten über die Leitung übertragen (so effizient wie möglich).

This answer scheint auf dem richtigen Weg zu sein, aber ich bin neu in Windows-Programmierung, also brauche ich etwas zusätzliche Hilfe.

Dies ist die einzige Lösung, die ich vorstellen kann IDXGIObject::GetPrivateData

Antwort

2

Private Daten verwenden, sind nicht das, was Sie überhaupt suchen. Sie dienen nur dazu, benutzerdefinierte Werte an d3d-Objekte anzuhängen.

Sobald Sie das ID3D11Texture2D Objekt haben, müssen Sie das Bild aus lesen, müssen Sie eine zweite in der Bereitstellung Speicherpool aus dem ID3D11Device erstellen (Holen Sie sich die ursprüngliche Beschreibung, ändern Sie den Pool, und entfernen Sie die Bindung).

Dann müssen Sie die ID3D11DeviceContext verwenden, um die Textur mit CopyResource auf die Staging-Ebene zu kopieren. Dann können Sie den Kontext Map und Unmap API verwenden, um das Bild zu lesen.

+0

Dank. Ich denke, dass ich das vielleicht kann. In welchem ​​Format werden die resultierenden Daten gespeichert? (Da ich die entsprechenden Bildschirmbereiche auf dem Client aktualisieren muss) Auch einige Pseudocode wäre enorm hilfreich. – cilki

+1

'ID3D11Texture2D :: GetDesc' bekommt Sie das Format. Es wird im Grunde das gleiche Format haben, weil ['ID3D11DeviceContext :: CopyResource'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ff476392) begrenzte Konvertierungsfähigkeiten hat:" Muss kompatible DXGI-Formate haben , was bedeutet, dass die Formate identisch oder zumindest aus der gleichen Typengruppe sein müssen ". –

+0

@RomanR. Das macht Sinn. Ich bin zuversichtlich, aber ich habe Probleme mit der Erstellung eines zweiten ID2D11Texture2D im "Staging-Speicher-Pool". Welche Methoden brauche ich, um das zu erreichen? Ich weiß, wie man die alte Beschreibung bekommt, aber ich bin verloren mit "ändern Sie den Pool und entfernen Sie die Bindung." Ist das die richtige Methode: 'ID3D11Device :: CreateTexture2D' – cilki

2

bekam ich eine gute Verbindung, die das tut .. für die SaveTextureToBmp Methode Schauen

[...] 

// map the texture 
ComPtr<ID3D11Texture2D> mappedTexture; 
D3D11_MAPPED_SUBRESOURCE mapInfo; 
mapInfo.RowPitch; 
hr = d3dContext->Map(
     Texture, 
     0, // Subresource 
     D3D11_MAP_READ, 
     0, // MapFlags 
     &mapInfo); 

if (FAILED(hr)) { 
    // If we failed to map the texture, copy it to a staging resource 
    if (hr == E_INVALIDARG) { 
     D3D11_TEXTURE2D_DESC desc2; 
     desc2.Width = desc.Width; 
     desc2.Height = desc.Height; 
     desc2.MipLevels = desc.MipLevels; 
     desc2.ArraySize = desc.ArraySize; 
     desc2.Format = desc.Format; 
     desc2.SampleDesc = desc.SampleDesc; 
     desc2.Usage = D3D11_USAGE_STAGING; 
     desc2.BindFlags = 0; 
     desc2.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 
     desc2.MiscFlags = 0; 

     ComPtr<ID3D11Texture2D> stagingTexture; 
     hr = d3dDevice->CreateTexture2D(&desc2, nullptr, &stagingTexture); 
     if (FAILED(hr)) { 
      throw MyException::Make(hr, L"Failed to create staging texture"); 
     } 

     // copy the texture to a staging resource 
     d3dContext->CopyResource(stagingTexture.Get(), Texture); 

     // now, map the staging resource 
     hr = d3dContext->Map(
       stagingTexture.Get(), 
       0, 
       D3D11_MAP_READ, 
       0, 
       &mapInfo); 
     if (FAILED(hr)) { 
      throw MyException::Make(hr, L"Failed to map staging texture"); 
     } 

     mappedTexture = std::move(stagingTexture); 
    } else { 
     throw MyException::Make(hr, L"Failed to map texture."); 
    } 
} else { 
    mappedTexture = Texture; 
} 
auto unmapResource = Finally([&] { 
    d3dContext->Unmap(mappedTexture.Get(), 0); 
    }); 

    [...] 

    hr = frameEncode->WritePixels(
      desc.Height, 
      mapInfo.RowPitch, 
      desc.Height * mapInfo.RowPitch, 
      reinterpret_cast<BYTE*>(mapInfo.pData)); 
    if (FAILED(hr)) { 
     throw MyException::Make(hr, L"frameEncode->WritePixels(...) failed."); 
    }