Skip to content

Commit

Permalink
video: sync capture: resend frame if needed to avoid delay on latest …
Browse files Browse the repository at this point in the history
…frame

* platform: replace generic 1000ms capture delay with real frame delay
* for sync encoding, when avcodec_receive_packet() returns EAGAIN, ensure
  that the next frame is (re)sent regardless of timeout status.

This resolves the issue by which the last captured frame is delayed which
is especially noticeable in low framerate content such as streaming desktop
content.
  • Loading branch information
psyke83 committed Nov 8, 2022
1 parent 4190667 commit 863f3ed
Show file tree
Hide file tree
Showing 8 changed files with 20 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ bl::sources::severity_logger<int> error(4); // Recoverable errors
bl::sources::severity_logger<int> fatal(5); // Unrecoverable errors

bool display_cursor = true;
bool resend_frame = false;

using text_sink = bl::sinks::asynchronous_sink<bl::sinks::text_ostream_backend>;
boost::shared_ptr<text_sink> sink;
Expand Down
1 change: 1 addition & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

extern util::ThreadPool task_pool;
extern bool display_cursor;
extern bool resend_frame;

extern boost::log::sources::severity_logger<int> verbose;
extern boost::log::sources::severity_logger<int> debug;
Expand Down
4 changes: 2 additions & 2 deletions src/platform/linux/kmsgrab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,13 +671,13 @@ class display_ram_t : public display_t {
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
auto status = snapshot(img.get(), std::chrono::duration_cast<std::chrono::milliseconds>(delay), *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
std::this_thread::sleep_for(1ms);
if(resend_frame) img = snapshot_cb(img);
continue;
case platf::capture_e::ok:
img = snapshot_cb(img);
Expand Down
5 changes: 3 additions & 2 deletions src/platform/linux/wlgrab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,13 @@ class wlr_ram_t : public wlr_t {
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
auto status = snapshot(img.get(), std::chrono::duration_cast<std::chrono::milliseconds>(delay), *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
if(resend_frame) img = snapshot_cb(img);
continue;
case platf::capture_e::ok:
img = snapshot_cb(img);
Expand Down Expand Up @@ -366,4 +367,4 @@ std::vector<std::string> wl_display_names() {
return display_names;
}

} // namespace platf
} // namespace platf
4 changes: 2 additions & 2 deletions src/platform/linux/x11grab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,13 +470,13 @@ struct x11_attr_t : public display_t {
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
auto status = snapshot(img.get(), std::chrono::duration_cast<std::chrono::milliseconds>(delay), *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
std::this_thread::sleep_for(1ms);
if(resend_frame) img = snapshot_cb(img);
continue;
case platf::capture_e::ok:
img = snapshot_cb(img);
Expand Down
4 changes: 2 additions & 2 deletions src/platform/windows/display_ram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,13 @@ capture_e display_ram_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
auto status = snapshot(img.get(), std::chrono::duration_cast<std::chrono::milliseconds>(delay), *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
std::this_thread::sleep_for(1ms);
if(resend_frame) img = snapshot_cb(img);
continue;
case platf::capture_e::ok:
img = snapshot_cb(img);
Expand Down
6 changes: 3 additions & 3 deletions src/platform/windows/display_vram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,13 +573,13 @@ capture_e display_vram_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<:
}
next_frame = now + delay;

auto status = snapshot(img.get(), 1000ms, *cursor);
auto status = snapshot(img.get(), std::chrono::duration_cast<std::chrono::milliseconds>(delay), *cursor);
switch(status) {
case platf::capture_e::reinit:
case platf::capture_e::error:
return status;
case platf::capture_e::timeout:
std::this_thread::sleep_for(1ms);
if(resend_frame) img = snapshot_cb(img);
continue;
case platf::capture_e::ok:
img = snapshot_cb(img);
Expand Down Expand Up @@ -885,4 +885,4 @@ int init() {

return 0;
}
} // namespace platf::dxgi
} // namespace platf::dxgi
7 changes: 6 additions & 1 deletion src/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -776,9 +776,14 @@ int encode(int64_t frame_nr, session_t &session, frame_t::pointer frame, safe::m
while(ret >= 0) {
auto packet = std::make_unique<packet_t::element_type>(nullptr);
auto av_packet = packet.get()->av_packet;
resend_frame = false;

ret = avcodec_receive_packet(ctx.get(), av_packet);
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
if(ret == AVERROR(EAGAIN)) {
if(!(encoders.front().flags & PARALLEL_ENCODING)) resend_frame = true;
return 0;
}
else if(ret == AVERROR_EOF) {
return 0;
}
else if(ret < 0) {
Expand Down

0 comments on commit 863f3ed

Please sign in to comment.