use std::time::{Duration, Instant};
use str0m::media::{KeyframeRequestKind, Mid, Rid};
use super::tracks::TrackOut;
use super::Client;
use crate::ids::SfuMid;
use crate::keyframe::SfuKeyframeRequest;
use crate::propagate::Propagated;
const KEYFRAME_REQUEST_MIN_GAP: Duration = Duration::from_secs(1);
impl Client {
pub(super) fn request_keyframe_throttled(
&mut self,
mid: Mid,
rid: Option<Rid>,
kind: KeyframeRequestKind,
) {
let Some(mut writer) = self.rtc.writer(mid) else {
return;
};
let Some(entry) = self.tracks_in.iter_mut().find(|t| t.id.mid == mid) else {
return;
};
if entry
.last_keyframe_request
.map(|t| t.elapsed() < KEYFRAME_REQUEST_MIN_GAP)
.unwrap_or(false)
{
return;
}
let _ = writer.request_keyframe(rid, kind);
entry.last_keyframe_request = Some(Instant::now());
}
pub(super) fn incoming_keyframe_req(
&self,
mut req: str0m::media::KeyframeRequest,
) -> Propagated {
let Some(track_out): Option<&TrackOut> =
self.tracks_out.iter().find(|t| t.mid() == Some(req.mid))
else {
return Propagated::Noop;
};
let Some(track_in) = track_out.track_in.upgrade() else {
return Propagated::Noop;
};
req.rid = self.chosen_rid;
if track_in.relay_source {
return Propagated::UpstreamKeyframeRequest {
source_relay_id: track_in.origin,
req: SfuKeyframeRequest::from_str0m(req),
source_mid: SfuMid::from_str0m(track_in.mid),
};
}
Propagated::KeyframeRequest(
self.id,
SfuKeyframeRequest::from_str0m(req),
track_in.origin,
SfuMid::from_str0m(track_in.mid),
)
}
pub fn handle_keyframe_request(&mut self, req: SfuKeyframeRequest, mid_in: SfuMid) {
let mid_in = mid_in.to_str0m();
if !self.tracks_in.iter().any(|i| i.id.mid == mid_in) {
return;
}
let Some(mut writer) = self.rtc.writer(mid_in) else {
return;
};
let rid = req.rid().map(|r| r.to_str0m());
let kind = req.kind().to_str0m();
if let Err(e) = writer.request_keyframe(rid, kind) {
tracing::info!(client = *self.id, error = ?e, "request_keyframe failed");
}
}
}
#[cfg(any(test, feature = "test-utils"))]
impl Client {
pub fn incoming_keyframe_req_for_tests(
&self,
req: str0m::media::KeyframeRequest,
) -> crate::propagate::Propagated {
self.incoming_keyframe_req(req)
}
}