stop gap toxav video sending interval
Some checks are pending
ContinuousDelivery / linux-ubuntu (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousDelivery / windows (push) Waiting to run
ContinuousDelivery / windows-asan (push) Waiting to run
ContinuousDelivery / dumpsyms (push) Blocked by required conditions
ContinuousDelivery / release (push) Blocked by required conditions
ContinuousIntegration / linux (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousIntegration / macos (push) Waiting to run
ContinuousIntegration / windows (push) Waiting to run

This commit is contained in:
Green Sky 2025-03-07 16:56:24 +01:00
parent e618732f43
commit 03f2c904ce
No known key found for this signature in database
GPG Key ID: DBE05085D874AB4A
4 changed files with 39 additions and 8 deletions

View File

@ -647,7 +647,7 @@ Screen* MainScreen::tick(float time_delta, bool& quit) {
//const float av_interval = std::pow(tav.toxavIterationInterval(), 1.18)/1000.f; //const float av_interval = std::pow(tav.toxavIterationInterval(), 1.18)/1000.f;
const float av_interval = tav.toxavIterationInterval()/1000.f; const float av_interval = tav.toxavIterationInterval()/1000.f;
tavvoip.tick(); const float av_voip_interval = tavvoip.tick();
#endif #endif
tcm.iterate(time_delta); // compute tcm.iterate(time_delta); // compute
@ -694,6 +694,10 @@ Screen* MainScreen::tick(float time_delta, bool& quit) {
_min_tick_interval, _min_tick_interval,
av_interval av_interval
); );
_min_tick_interval = std::min<float>(
_min_tick_interval,
av_voip_interval
);
#endif #endif
//std::cout << "MS: min tick interval: " << _min_tick_interval << "\n"; //std::cout << "MS: min tick interval: " << _min_tick_interval << "\n";

View File

@ -109,6 +109,9 @@ struct ToxAVI : public ToxAVEventProviderI {
ToxAVI(Tox* tox); ToxAVI(Tox* tox);
virtual ~ToxAVI(void); virtual ~ToxAVI(void);
// NOTE: interval timers are only interesting for receiving streams
// if we are only sending, it will always report 195ms
// interface // interface
// if iterate is called on a different thread, it will fire events there // if iterate is called on a different thread, it will fire events there
uint32_t toxavIterationInterval(void) const; uint32_t toxavIterationInterval(void) const;

View File

@ -104,6 +104,7 @@ struct ToxAVCallVideoSink : public FrameStream2SinkI<SDLVideoFrame> {
uint32_t _fid; uint32_t _fid;
std::shared_ptr<stream_type> _writer; std::shared_ptr<stream_type> _writer;
uint64_t _last_ts {0};
ToxAVCallVideoSink(ToxAVI& toxav, uint32_t fid) : _toxav(toxav), _fid(fid) {} ToxAVCallVideoSink(ToxAVI& toxav, uint32_t fid) : _toxav(toxav), _fid(fid) {}
~ToxAVCallVideoSink(void) { ~ToxAVCallVideoSink(void) {
@ -139,6 +140,7 @@ struct ToxAVCallVideoSink : public FrameStream2SinkI<SDLVideoFrame> {
if (sub == _writer) { if (sub == _writer) {
_writer = nullptr; _writer = nullptr;
_last_ts = 0;
/*auto err = */_toxav.toxavVideoSetBitRate(_fid, 0); /*auto err = */_toxav.toxavVideoSetBitRate(_fid, 0);
// print warning? on error? // print warning? on error?
@ -350,7 +352,7 @@ void ToxAVVoIPModel::audio_thread_tick(void) {
//* `((sample rate) * (audio length) / 1000)`, where audio length can be //* `((sample rate) * (audio length) / 1000)`, where audio length can be
//* 2.5, 5, 10, 20, 40 or 60 milliseconds. //* 2.5, 5, 10, 20, 40 or 60 milliseconds.
// we likely needs to subdivide/repackage // we likely need to subdivide/repackage
// frame size should be an option exposed to the user // frame size should be an option exposed to the user
// with 10ms as a default ? // with 10ms as a default ?
// the larger the frame size, the less overhead but the more delay // the larger the frame size, the less overhead but the more delay
@ -372,7 +374,7 @@ void ToxAVVoIPModel::audio_thread_tick(void) {
void ToxAVVoIPModel::video_thread_tick(void) { void ToxAVVoIPModel::video_thread_tick(void) {
//for (const auto& [oc, vsink] : _os.registry().view<ToxAVCallVideoSink*>().each()) { //for (const auto& [oc, vsink] : _os.registry().view<ToxAVCallVideoSink*>().each()) {
std::lock_guard lg{_video_sinks_mutex}; std::lock_guard lg{_video_sinks_mutex};
for (const auto* vsink : _video_sinks) { for (auto* vsink : _video_sinks) {
if (!vsink->_writer) { if (!vsink->_writer) {
continue; continue;
} }
@ -389,6 +391,15 @@ void ToxAVVoIPModel::video_thread_tick(void) {
continue; continue;
} }
// interval estimate based on 2 frames
if (vsink->_last_ts != 0 && vsink->_last_ts < new_frame.timestampUS) {
const auto interval_us = new_frame.timestampUS - vsink->_last_ts;
if (_video_recent_interval > interval_us) {
_video_recent_interval = interval_us;
}
}
vsink->_last_ts = new_frame.timestampUS;
// conversion is done in the sink's stream // conversion is done in the sink's stream
SDL_Surface* surf = new_frame.surface.get(); SDL_Surface* surf = new_frame.surface.get();
assert(surf != nullptr); assert(surf != nullptr);
@ -519,7 +530,7 @@ ToxAVVoIPModel::~ToxAVVoIPModel(void) {
} }
} }
void ToxAVVoIPModel::tick(void) { float ToxAVVoIPModel::tick(void) {
std::lock_guard lg{_e_queue_mutex}; std::lock_guard lg{_e_queue_mutex};
while (!_e_queue.empty()) { while (!_e_queue.empty()) {
const auto& e_var = _e_queue.front(); const auto& e_var = _e_queue.front();
@ -536,6 +547,14 @@ void ToxAVVoIPModel::tick(void) {
_e_queue.pop_front(); _e_queue.pop_front();
} }
// TODO: audio (ez, just do 60ms if sending audio)
auto interval = _video_recent_interval/1'000'000.f;
// funky if tickrate momentarily higher than frame rate
_video_recent_interval = 10'000'000;
return interval;
} }
ObjectHandle ToxAVVoIPModel::enter(const Contact4 c, const Components::VoIP::DefaultConfig& defaults) { ObjectHandle ToxAVVoIPModel::enter(const Contact4 c, const Components::VoIP::DefaultConfig& defaults) {

View File

@ -10,6 +10,7 @@
#include <variant> #include <variant>
#include <deque> #include <deque>
#include <mutex> #include <mutex>
#include <atomic>
// fwd // fwd
struct ToxAVCallAudioSink; struct ToxAVCallAudioSink;
@ -42,6 +43,11 @@ class ToxAVVoIPModel : protected ToxAVEventI, public VoIPModelI {
std::mutex _video_sinks_mutex; std::mutex _video_sinks_mutex;
uint64_t _pad3; uint64_t _pad3;
// filled with min() in video_thread_tick()
// ms, 10sec means none
std::atomic<uint64_t> _video_recent_interval{10'000'000};
uint64_t _pad4;
// for faster lookup // for faster lookup
std::unordered_map<uint32_t, ObjectHandle> _audio_sources; std::unordered_map<uint32_t, ObjectHandle> _audio_sources;
std::unordered_map<uint32_t, ObjectHandle> _video_sources; std::unordered_map<uint32_t, ObjectHandle> _video_sources;
@ -54,8 +60,7 @@ class ToxAVVoIPModel : protected ToxAVEventI, public VoIPModelI {
void destroySession(ObjectHandle session); void destroySession(ObjectHandle session);
// TODO: this needs to move to the toxav thread // we use "events" as pre/post audio/video iterate...
// we could use "events" as pre/post audio/video iterate...
void audio_thread_tick(void); void audio_thread_tick(void);
void video_thread_tick(void); void video_thread_tick(void);
@ -67,7 +72,7 @@ class ToxAVVoIPModel : protected ToxAVEventI, public VoIPModelI {
~ToxAVVoIPModel(void); ~ToxAVVoIPModel(void);
// handle events coming from toxav thread(s) // handle events coming from toxav thread(s)
void tick(void); float tick(void);
public: // voip model public: // voip model
ObjectHandle enter(const Contact4 c, const Components::VoIP::DefaultConfig& defaults) override; ObjectHandle enter(const Contact4 c, const Components::VoIP::DefaultConfig& defaults) override;