fix sdl video sources who dont report a proper frame ts
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, ) (push) Has been cancelled
ContinuousDelivery / windows (windows-2022, asan) (push) Has been cancelled
ContinuousIntegration / on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-24.04-arm (push) Has been cancelled
ContinuousIntegration / on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / asan on ubuntu-latest (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled

see gamescope (0fps + constant ts)
This commit is contained in:
Green Sky
2026-01-02 20:47:43 +01:00
parent 940d9e5c2c
commit 22823c5ca2
2 changed files with 35 additions and 4 deletions

View File

@@ -200,7 +200,7 @@ float DebugVideoTap::render(void) {
auto delta = int64_t(new_frame_opt.value().timestampUS) - int64_t(view._v_last_ts);
view._v_last_ts = new_frame_opt.value().timestampUS;
if (view._v_interval_avg == 0) {
if (view._v_interval_avg == 0 || std::isinf(view._v_interval_avg) || std::isnan(view._v_interval_avg)) {
view._v_interval_avg = delta/1'000'000.f;
} else {
const float r = 0.05f;

View File

@@ -1,6 +1,7 @@
#include "./sdl_video_frame_stream2.hpp"
#include <chrono>
#include <algorithm>
#include <iostream>
@@ -128,7 +129,12 @@ std::shared_ptr<FrameStream2I<SDLVideoFrame>> SDLVideo2InputDevice::subscribe(vo
std::cout << "SDLVID: camera format: " << format_name << "\n";
}
_thread = std::thread([this, camera = std::move(camera), fps](void) {
_thread = std::thread([this, camera = std::move(camera)](void) {
bool use_chrono_fallback = false;
Uint64 last_timestampUS = 0;
double intervalUS_avg = 1.;
while (_ref > 0) {
Uint64 timestampNS = 0;
@@ -136,20 +142,45 @@ std::shared_ptr<FrameStream2I<SDLVideoFrame>> SDLVideo2InputDevice::subscribe(vo
SDL_Surface* sdl_frame_next = SDL_AcquireCameraFrame(camera.get(), &timestampNS);
if (sdl_frame_next != nullptr) {
Uint64 timestampUS_correct = timestampNS/1000;
if (!use_chrono_fallback) {
if (timestampNS == 0 || last_timestampUS == timestampUS_correct) {
use_chrono_fallback = true;
std::cerr << "SDLVID: invalid or unreliable timestampNS from sdl, falling back to own mesurements!\n";
timestampUS_correct = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
} else if (last_timestampUS == 0) {
last_timestampUS = timestampUS_correct;
// HACK: skip first frame
std::cerr << "SDLVID: skipping first frame\n";
SDL_ReleaseCameraFrame(camera.get(), sdl_frame_next);
continue;
}
} else {
timestampUS_correct = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
if (last_timestampUS != 0 && timestampUS_correct != 0 && last_timestampUS != timestampUS_correct && last_timestampUS < timestampUS_correct) {
const double r = 0.15;
intervalUS_avg = std::clamp(intervalUS_avg * (1.-r) + (timestampUS_correct-last_timestampUS) * r, 1000., 500.*1000.);
}
SDLVideoFrame new_frame_non_owning {
timestampNS/1000,
timestampUS_correct,
sdl_frame_next
};
// creates surface copies
push(new_frame_non_owning);
last_timestampUS = timestampUS_correct;
SDL_ReleaseCameraFrame(camera.get(), sdl_frame_next);
}
// sleep for interval
// TODO: do we really need half?
std::this_thread::sleep_for(std::chrono::milliseconds(int64_t((1000/fps)*0.5)));
std::this_thread::sleep_for(std::chrono::milliseconds(int64_t((intervalUS_avg/1000)*0.5)));
}
// camera destructor closes device here
});