Skip to content

Commit

Permalink
Decrease normal capture buffer to single image
Browse files Browse the repository at this point in the history
  • Loading branch information
ns6089 authored and cgutman committed Apr 11, 2023
1 parent 191b929 commit eed27d3
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 146 deletions.
30 changes: 22 additions & 8 deletions src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ namespace platf {
virtual ~deinit_t() = default;
};

struct img_t {
struct img_t: std::enable_shared_from_this<img_t> {
public:
img_t() = default;

Expand Down Expand Up @@ -245,6 +245,7 @@ namespace platf {
ok,
reinit,
timeout,
interrupted,
error
};

Expand All @@ -255,20 +256,33 @@ namespace platf {
* If a frame was captured, frame_captured will be true. If a timeout occurred, it will be false.
*
* On Break Request -->
* Returns nullptr
* Returns false
*
* On Success -->
* Returns the image object that should be filled next.
* This may or may not be the image send with the callback
* Returns true
*/
using snapshot_cb_t = std::function<std::shared_ptr<img_t>(std::shared_ptr<img_t> &img, bool frame_captured)>;
using push_captured_image_cb_t = std::function<bool(std::shared_ptr<img_t> &&img, bool frame_captured)>;

/**
* Use to get free image from the pool. Calls must be synchronized.
* Blocks until there is free image in the pool or capture is interrupted.
*
* Returns:
* 'true' on success, img_out contains free image
* 'false' when capture has been interrupted, img_out contains nullptr
*/
using pull_free_image_cb_t = std::function<bool(std::shared_ptr<img_t> &img_out)>;

display_t() noexcept:
offset_x { 0 }, offset_y { 0 } {}

/**
* snapshot_cb --> the callback
* std::shared_ptr<img_t> img --> The first image to use
* push_captured_image_cb --> The callback that is called with captured image,
* must be called from the same thread as capture()
* pull_free_image_cb --> Capture backends call this callback to get empty image
* from the pool. If backend uses multiple threads, calls to this
* callback must be synchronized. Calls to this callback and
* push_captured_image_cb must be synchronized as well.
* bool *cursor --> A pointer to the flag that indicates wether the cursor should be captured as well
*
* Returns either:
Expand All @@ -277,7 +291,7 @@ namespace platf {
* capture_e::reinit when need of reinitialization
*/
virtual capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) = 0;
capture(const push_captured_image_cb_t &push_captured_image_cb, const pull_free_image_cb_t &pull_free_image_cb, bool *cursor) = 0;

virtual std::shared_ptr<img_t>
alloc_img() = 0;
Expand Down
32 changes: 25 additions & 7 deletions src/platform/linux/cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,9 +504,16 @@ namespace cuda {
}

platf::capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::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 {
auto next_frame = std::chrono::steady_clock::now();

{
// We must create at least one texture on this thread before calling NvFBCToCudaSetUp()
// Otherwise it fails with "Unable to register an OpenGL buffer to a CUDA resource (result: 201)" message
std::shared_ptr<platf::img_t> img_dummy;
pull_free_image_cb(img_dummy);
}

// Force display_t::capture to initialize handle_t::capture
cursor_visible = !*cursor;

Expand All @@ -515,7 +522,7 @@ namespace cuda {
handle.reset();
});

while (img) {
while (true) {
auto now = std::chrono::steady_clock::now();
if (next_frame > now) {
std::this_thread::sleep_for((next_frame - now) / 3 * 2);
Expand All @@ -526,16 +533,22 @@ namespace cuda {
}
next_frame = now + delay;

auto status = snapshot(img.get(), 150ms, *cursor);
std::shared_ptr<platf::img_t> img_out;
auto status = snapshot(pull_free_image_cb, img_out, 150ms, *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 platf::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 platf::capture_e::ok;
}
break;
default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int) status << ']';
Expand Down Expand Up @@ -618,7 +631,7 @@ namespace cuda {
}

platf::capture_e
snapshot(platf::img_t *img, std::chrono::milliseconds timeout, bool cursor) {
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) {
if (cursor != cursor_visible) {
auto status = reinit(cursor);
if (status != platf::capture_e::ok) {
Expand Down Expand Up @@ -646,7 +659,12 @@ namespace cuda {
return platf::capture_e::error;
}

if (((img_t *) img)->tex.copy((std::uint8_t *) device_ptr, img->height, img->row_pitch)) {
if (!pull_free_image_cb(img_out)) {
return platf::capture_e::interrupted;
}
auto img = (img_t *) img_out.get();

if (img->tex.copy((std::uint8_t *) device_ptr, img->height, img->row_pitch)) {
return platf::capture_e::error;
}

Expand Down
4 changes: 2 additions & 2 deletions src/platform/linux/cuda.cu
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ using namespace std::literals;
* Therefore, some declarations need to be added explicitely
*/
namespace platf {
struct img_t {
struct img_t: std::enable_shared_from_this<img_t> {
public:
std::uint8_t *data {};
std::int32_t width {};
Expand Down Expand Up @@ -70,7 +70,7 @@ struct alignas(16) color_extern_t {

static_assert(sizeof(video::color_t) == sizeof(video::color_extern_t), "color matrix struct mismatch");

extern color_t colors[4];
extern color_t colors[6];
} // namespace video

//////////////////// End special declarations
Expand Down
62 changes: 45 additions & 17 deletions src/platform/linux/kmsgrab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,10 +723,10 @@ namespace platf {
}

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 {
auto next_frame = std::chrono::steady_clock::now();

while (img) {
while (true) {
auto now = std::chrono::steady_clock::now();

if (next_frame > now) {
Expand All @@ -738,16 +738,22 @@ namespace platf {
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
std::shared_ptr<platf::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 platf::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 platf::capture_e::ok;
}
break;
default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int) status << ']';
Expand All @@ -768,7 +774,7 @@ namespace platf {
}

capture_e
snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
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) {
file_t fb_fd[4];

egl::surface_descriptor_t sd;
Expand All @@ -793,10 +799,14 @@ namespace platf {
gl::ctx.GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
BOOST_LOG(debug) << "width and height: w "sv << w << " h "sv << h;

gl::ctx.GetTextureSubImage(rgb->tex[0], 0, img_offset_x, img_offset_y, 0, width, height, 1, GL_BGRA, GL_UNSIGNED_BYTE, img_out_base->height * img_out_base->row_pitch, img_out_base->data);
if (!pull_free_image_cb(img_out)) {
return platf::capture_e::interrupted;
}

gl::ctx.GetTextureSubImage(rgb->tex[0], 0, img_offset_x, img_offset_y, 0, width, height, 1, GL_BGRA, GL_UNSIGNED_BYTE, img_out->height * img_out->row_pitch, img_out->data);

if (cursor_opt && cursor) {
cursor_opt->blend(*img_out_base, img_offset_x, img_offset_y);
cursor_opt->blend(*img_out, img_offset_x, img_offset_y);
}

return capture_e::ok;
Expand Down Expand Up @@ -855,14 +865,23 @@ namespace platf {

int
dummy_img(platf::img_t *img) override {
return snapshot(img, 1s, false) != capture_e::ok;
// TODO: stop cheating and give black image
if (!img) {
return -1;
};
auto pull_dummy_img_callback = [&img](std::shared_ptr<platf::img_t> &img_out) -> bool {
img_out = img->shared_from_this();
return true;
};
std::shared_ptr<platf::img_t> img_out;
return snapshot(pull_dummy_img_callback, img_out, 1s, false) != platf::capture_e::ok;
}

capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) {
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();

while (img) {
while (true) {
auto now = std::chrono::steady_clock::now();

if (next_frame > now) {
Expand All @@ -874,16 +893,22 @@ namespace platf {
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
std::shared_ptr<platf::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 platf::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 platf::capture_e::ok;
}
break;
default:
BOOST_LOG(error) << "Unrecognized capture status ["sv << (int) status << ']';
Expand All @@ -895,10 +920,13 @@ namespace platf {
}

capture_e
snapshot(img_t *img_out_base, std::chrono::milliseconds /* timeout */, bool cursor) {
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) {
file_t fb_fd[4];

auto img = (egl::img_descriptor_t *) img_out_base;
if (!pull_free_image_cb(img_out)) {
return platf::capture_e::interrupted;
}
auto img = (egl::img_descriptor_t *) img_out.get();
img->reset();

auto status = refresh(fb_fd, &img->sd);
Expand All @@ -909,7 +937,7 @@ namespace platf {
img->sequence = ++sequence;

if (!cursor || !cursor_opt) {
img_out_base->data = nullptr;
img->data = nullptr;

for (auto x = 0; x < 4; ++x) {
fb_fd[x].release();
Expand Down
Loading

0 comments on commit eed27d3

Please sign in to comment.