common: Limit the maximum latency frame rate feature can add

This commit is contained in:
Joni Räsänen 2022-09-20 08:06:32 +03:00
parent 08c603f6da
commit 58fcad5086
3 changed files with 32 additions and 20 deletions

View File

@ -254,6 +254,7 @@ enum RTP_CTX_ENABLE_FLAGS {
RCE_ZRTP_MULTISTREAM_NO_DH = 1 << 17,
/** Force uvgRTP to send packets at certain framerate (default 30 fps) */
RCE_FRAME_RATE = 1 << 18,
RCE_FRAMERATE = 1 << 18,
/** Paces the sending of frame fragments within frame interval (default 1/30 s) */

View File

@ -279,41 +279,43 @@ rtp_error_t uvgrtp::frame_queue::flush_queue()
/* set the marker bit of the last packet to 1 */
if (active_->packets.size() > 1)
((uint8_t *)&active_->rtp_headers[active_->rtphdr_ptr - 1])[1] |= (1 << 7);
std::chrono::high_resolution_clock::time_point this_frame_time_slot = this_frame_time();
if ((rce_flags_ & RCE_FRAMERATE) && fps_)
if ((rce_flags_ & RCE_FRAME_RATE) && fps_)
{
std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
// allow us to be 1 ms late and not sync
if (this_frame_time_slot < now - std::chrono::milliseconds(1) || frames_since_sync_ == 0)
std::chrono::nanoseconds wait_time = this_frame_time() - std::chrono::high_resolution_clock::now();
if (wait_time.count() > 0 && frames_since_sync_ != 0)
{
UVG_LOG_DEBUG("Updating framerate sync point");
// we cap the sleep at 0.9 interval so we slowly catch up to highest latency so far
if (wait_time > 0.9 * frame_interval_)
{
std::this_thread::sleep_for(0.9 * frame_interval_);
frames_since_sync_ = 0;
fps_sync_point_ = std::chrono::high_resolution_clock::now();
/* Update the sync point so we solify our latency gains,
we may do the same for next frame until 0.9 has been achieved */
update_sync_point();
}
else
{
std::this_thread::sleep_for(wait_time);
}
}
else if (this_frame_time_slot > now + std::chrono::milliseconds(1))
else
{
// wait until it is time to send this frame
std::this_thread::sleep_for(this_frame_time_slot - now - std::chrono::milliseconds(1));
update_sync_point();
}
++frames_since_sync_;
}
if ((rce_flags_ & RCE_PACE_FRAGMENT_SENDING) && fps_)
{
if (!(rce_flags_ & RCE_FRAMERATE))
{
// if framerate is not use, we just use this moment as synchronization moment
this_frame_time_slot = std::chrono::high_resolution_clock::now();
}
std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
std::chrono::nanoseconds packet_interval = frame_interval_/ active_->packets.size();
for (size_t i = 0; i < active_->packets.size(); ++i)
{
std::chrono::high_resolution_clock::time_point next_packet = this_frame_time_slot + i * packet_interval;
std::chrono::high_resolution_clock::time_point next_packet = now + i * packet_interval;
// sleep until next packet time
std::this_thread::sleep_for(next_packet - std::chrono::high_resolution_clock::now());
@ -396,3 +398,10 @@ void uvgrtp::frame_queue::enqueue_finalize(uvgrtp::buf_vec& tmp)
rtp_->inc_sequence();
rtp_->inc_sent_pkts();
}
inline void uvgrtp::frame_queue::update_sync_point()
{
//UVG_LOG_DEBUG("Updating framerate sync point");
frames_since_sync_ = 0;
fps_sync_point_ = std::chrono::high_resolution_clock::now();
}

View File

@ -161,6 +161,8 @@ namespace uvgrtp {
inline std::chrono::high_resolution_clock::time_point this_frame_time();
inline void update_sync_point();
transaction_t *active_;
/* Deallocation hook is stored here and copied to transaction upon initialization */