Decrease normal capture buffer to single image

This commit is contained in:
ns6089
2023-03-29 18:07:20 +03:00
committed by Cameron Gutman
parent 191b929ab0
commit eed27d3c0a
12 changed files with 333 additions and 145 deletions

View File

@@ -125,8 +125,9 @@ namespace platf::dxgi {
public:
int
init(const ::video::config_t &config, const std::string &display_name);
capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override;
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) override;
std::chrono::nanoseconds delay;
@@ -168,7 +169,7 @@ namespace platf::dxgi {
colorspace_to_string(DXGI_COLOR_SPACE_TYPE type);
virtual capture_e
snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) = 0;
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) = 0;
virtual int
complete_img(img_t *img, bool dummy) = 0;
virtual std::vector<DXGI_FORMAT>
@@ -178,7 +179,7 @@ namespace platf::dxgi {
class display_ram_t: public display_base_t {
public:
virtual capture_e
snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override;
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) override;
std::shared_ptr<img_t>
alloc_img() override;
@@ -200,7 +201,7 @@ namespace platf::dxgi {
class display_vram_t: public display_base_t, public std::enable_shared_from_this<display_vram_t> {
public:
virtual capture_e
snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override;
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) override;
std::shared_ptr<img_t>
alloc_img() override;

View File

@@ -92,7 +92,7 @@ namespace platf::dxgi {
}
capture_e
display_base_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) {
display_base_t::capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) {
auto next_frame = std::chrono::steady_clock::now();
// Use CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if supported (Windows 10 1809+)
@@ -110,7 +110,7 @@ namespace platf::dxgi {
CloseHandle(timer);
});
while (img) {
while (true) {
// This will return false if the HDR state changes or for any number of other
// display or GPU changes. We should reinit to examine the updated state of
// the display subsystem. It is recommended to call this once per frame.
@@ -135,16 +135,22 @@ namespace platf::dxgi {
next_frame = std::chrono::steady_clock::now() + delay;
}
auto status = snapshot(img.get(), 1000ms, *cursor);
std::shared_ptr<img_t> img_out;
auto status = snapshot(pull_free_image_cb, img_out, 1000ms, *cursor);
switch (status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
case platf::capture_e::interrupted:
return status;
case platf::capture_e::timeout:
img = snapshot_cb(img, false);
if (!push_captured_image_cb(std::move(img_out), false)) {
return capture_e::ok;
}
break;
case platf::capture_e::ok:
img = snapshot_cb(img, true);
if (!push_captured_image_cb(std::move(img_out), true)) {
return capture_e::ok;
}
break;
default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int) status << ']';

View File

@@ -171,9 +171,7 @@ namespace platf::dxgi {
}
capture_e
display_ram_t::snapshot(::platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) {
auto img = (img_t *) img_base;
display_ram_t::snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) {
HRESULT status;
DXGI_OUTDUPL_FRAME_INFO frame_info;
@@ -269,6 +267,11 @@ namespace platf::dxgi {
}
}
if (!pull_free_image_cb(img_out)) {
return capture_e::interrupted;
}
auto img = (img_t *) img_out.get();
// If we don't know the final capture format yet, encode a dummy image
if (capture_format == DXGI_FORMAT_UNKNOWN) {
BOOST_LOG(debug) << "Capture format is still unknown. Encoding a blank image"sv;

View File

@@ -311,6 +311,16 @@ namespace platf::dxgi {
public:
int
convert(platf::img_t &img_base) override {
// Garbage collect mapped capture images whose weak references have expired
for (auto it = img_ctx_map.begin(); it != img_ctx_map.end();) {
if (it->second.img_weak.expired()) {
it = img_ctx_map.erase(it);
}
else {
it++;
}
}
auto &img = (img_d3d_t &) img_base;
auto &img_ctx = img_ctx_map[img.id];
@@ -342,6 +352,9 @@ namespace platf::dxgi {
// Release encoder mutex to allow capture code to reuse this image
img_ctx.encoder_mutex->ReleaseSync(0);
ID3D11ShaderResourceView *emptyShaderResourceView = nullptr;
device_ctx->PSSetShaderResources(0, 1, &emptyShaderResourceView);
return 0;
}
@@ -650,12 +663,15 @@ namespace platf::dxgi {
shader_res_t encoder_input_res;
keyed_mutex_t encoder_mutex;
std::weak_ptr<const platf::img_t> img_weak;
void
reset() {
capture_texture_p = nullptr;
encoder_texture.reset();
encoder_input_res.reset();
encoder_mutex.reset();
img_weak.reset();
}
};
@@ -699,6 +715,9 @@ namespace platf::dxgi {
}
img_ctx.capture_texture_p = img.capture_texture.get();
img_ctx.img_weak = img.weak_from_this();
return 0;
}
@@ -789,9 +808,7 @@ namespace platf::dxgi {
}
capture_e
display_vram_t::snapshot(platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) {
auto img = (img_d3d_t *) img_base;
display_vram_t::snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) {
HRESULT status;
DXGI_OUTDUPL_FRAME_INFO frame_info;
@@ -839,6 +856,11 @@ namespace platf::dxgi {
cursor_xor.set_pos(frame_info.PointerPosition.Position.x, frame_info.PointerPosition.Position.y, frame_info.PointerPosition.Visible);
}
if (!pull_free_image_cb(img_out)) {
return capture_e::interrupted;
}
auto img = (img_d3d_t *) img_out.get();
if (frame_update_flag) {
texture2d_t src {};
@@ -969,6 +991,12 @@ namespace platf::dxgi {
}
device_ctx->OMSetBlendState(blend_disable.get(), nullptr, 0xFFFFFFFFu);
ID3D11RenderTargetView *emptyRenderTarget = nullptr;
device_ctx->OMSetRenderTargets(1, &emptyRenderTarget, nullptr);
device_ctx->RSSetViewports(0, nullptr);
ID3D11ShaderResourceView *emptyShaderResourceView = nullptr;
device_ctx->PSSetShaderResources(0, 1, &emptyShaderResourceView);
}
// Release the mutex to allow encoding of this frame