Delayed capture buffer trim
This commit is contained in:
+69
-14
@@ -793,36 +793,91 @@ namespace video {
|
|||||||
}
|
}
|
||||||
display_wp = disp;
|
display_wp = disp;
|
||||||
|
|
||||||
constexpr auto capture_buffer_normal_size = 2;
|
|
||||||
constexpr auto capture_buffer_size = 12;
|
constexpr auto capture_buffer_size = 12;
|
||||||
std::list<std::shared_ptr<platf::img_t>> imgs(capture_buffer_size);
|
std::list<std::shared_ptr<platf::img_t>> imgs(capture_buffer_size);
|
||||||
|
|
||||||
|
std::vector<std::optional<std::chrono::steady_clock::time_point>> imgs_used_timestamps;
|
||||||
|
const std::chrono::seconds trim_timeot = 3s;
|
||||||
|
auto trim_imgs = [&]() {
|
||||||
|
// count allocated and used within current pool
|
||||||
|
size_t allocated_count = 0;
|
||||||
|
size_t used_count = 0;
|
||||||
|
for (const auto &img : imgs) {
|
||||||
|
if (img) {
|
||||||
|
allocated_count += 1;
|
||||||
|
if (img.use_count() > 1) {
|
||||||
|
used_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember the timestamp of currently used count
|
||||||
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
if (imgs_used_timestamps.size() <= used_count) {
|
||||||
|
imgs_used_timestamps.resize(used_count + 1);
|
||||||
|
}
|
||||||
|
imgs_used_timestamps[used_count] = now;
|
||||||
|
|
||||||
|
// decide whether to trim allocated unused above the currently used count
|
||||||
|
// based on last used timestamp and universal timeout
|
||||||
|
size_t trim_target = used_count;
|
||||||
|
for (size_t i = used_count; i < imgs_used_timestamps.size(); i++) {
|
||||||
|
if (imgs_used_timestamps[i] && now - *imgs_used_timestamps[i] < trim_timeot) {
|
||||||
|
trim_target = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim allocated unused above the newly decided trim target
|
||||||
|
if (allocated_count > trim_target) {
|
||||||
|
size_t to_trim = allocated_count - trim_target;
|
||||||
|
// prioritize trimming least recently used
|
||||||
|
for (auto it = imgs.rbegin(); it != imgs.rend(); it++) {
|
||||||
|
auto &img = *it;
|
||||||
|
if (img && img.use_count() == 1) {
|
||||||
|
img.reset();
|
||||||
|
to_trim -= 1;
|
||||||
|
if (to_trim == 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// forget timestamps that no longer relevant
|
||||||
|
imgs_used_timestamps.resize(trim_target + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
auto pull_free_image_callback = [&](std::shared_ptr<platf::img_t> &img_out) -> bool {
|
auto pull_free_image_callback = [&](std::shared_ptr<platf::img_t> &img_out) -> bool {
|
||||||
img_out.reset();
|
img_out.reset();
|
||||||
while (capture_ctx_queue->running()) {
|
while (capture_ctx_queue->running()) {
|
||||||
|
// pick first allocated but unused
|
||||||
for (auto it = imgs.begin(); it != imgs.end(); it++) {
|
for (auto it = imgs.begin(); it != imgs.end(); it++) {
|
||||||
// pick first unallocated or unused
|
if (*it && it->use_count() == 1) {
|
||||||
if (!*it || it->use_count() == 1) {
|
|
||||||
if (!*it) {
|
|
||||||
// allocate if unallocated
|
|
||||||
*it = disp->alloc_img();
|
|
||||||
}
|
|
||||||
img_out = *it;
|
img_out = *it;
|
||||||
if (it != imgs.begin()) {
|
if (it != imgs.begin()) {
|
||||||
// move freshly allocated or unused img to the front of the list to prioritize its reusal
|
// move image to the front of the list to prioritize its reusal
|
||||||
imgs.erase(it);
|
imgs.erase(it);
|
||||||
imgs.push_front(img_out);
|
imgs.push_front(img_out);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (img_out) {
|
// otherwise pick first unallocated
|
||||||
// unallocate unused above normal buffer size
|
if (!img_out) {
|
||||||
size_t index = 0;
|
for (auto it = imgs.begin(); it != imgs.end(); it++) {
|
||||||
for (auto &img : imgs) {
|
if (!*it) {
|
||||||
if (index >= capture_buffer_normal_size && img && img.use_count() == 1) img.reset();
|
// allocate image
|
||||||
index++;
|
*it = disp->alloc_img();
|
||||||
|
img_out = *it;
|
||||||
|
if (it != imgs.begin()) {
|
||||||
|
// move image to the front of the list to prioritize its reusal
|
||||||
|
imgs.erase(it);
|
||||||
|
imgs.push_front(img_out);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (img_out) {
|
||||||
|
// trim allocated but unused portion of the pool based on timeouts
|
||||||
|
trim_imgs();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
Reference in New Issue
Block a user