Skip to main content

o_sfu_core/engine/room/source_policy/
action.rs

1use super::super::media_graph::SubscriptionKey;
2use crate::engine::{
3    ConnectionId, UserId,
4    media_transport::{
5        ConsumerActivity, ConsumerRouteControl, SourcePacketGate, TransportConsumerRoute,
6    },
7    source_model::{
8        ConsumerSourceSelection, PolicyPauseReason, PublishedSourceId,
9        ReceiverVideoBudgetDiagnostics, SourceSelector,
10    },
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub(super) enum RouteBudgetOutcome {
15    Degraded,
16    Paused,
17    Resumed,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub(in crate::engine::room) struct ConsumerPacketSelectionUpdate {
22    pub(super) key: SubscriptionKey,
23    pub(super) source_id: PublishedSourceId,
24    pub(in crate::engine::room) route: TransportConsumerRoute,
25    pub(super) selector: SourceSelector,
26    pub(super) policy_pause_reason: Option<PolicyPauseReason>,
27    pub(super) budget: ReceiverVideoBudgetDiagnostics,
28    pub(super) outcome: Option<RouteBudgetOutcome>,
29    pub(super) pressure_observations: u8,
30    pub(super) upgrade_observations: u8,
31    pub(super) packet_gate: Option<SourcePacketGate>,
32    pub(super) route_activity_changed: bool,
33    pub(super) request_keyframe: bool,
34}
35
36impl ConsumerPacketSelectionUpdate {
37    pub(in crate::engine::room) fn route_activity(
38        key: SubscriptionKey,
39        source_id: PublishedSourceId,
40        route: TransportConsumerRoute,
41        current_selection: ConsumerSourceSelection,
42        policy_pause_reason: Option<PolicyPauseReason>,
43    ) -> Option<Self> {
44        (policy_pause_reason != current_selection.policy_pause_reason()).then(|| Self {
45            key,
46            source_id,
47            route,
48            selector: current_selection.selector(),
49            policy_pause_reason,
50            budget: current_selection.budget(),
51            outcome: None,
52            pressure_observations: current_selection.pressure_observations(),
53            upgrade_observations: current_selection.upgrade_observations(),
54            packet_gate: None,
55            route_activity_changed: true,
56            request_keyframe: false,
57        })
58    }
59
60    pub(super) const fn requires_media_transport_effect(&self) -> bool {
61        self.packet_gate.is_some() || self.route_activity_changed || self.request_keyframe
62    }
63
64    pub(super) const fn requires_follow_up(&self) -> bool {
65        self.pressure_observations > 0 || self.upgrade_observations > 0
66    }
67
68    pub(in crate::engine::room) fn route_control(&self) -> ConsumerRouteControl {
69        let mut control =
70            ConsumerRouteControl::new(self.route.clone()).request_keyframe(self.request_keyframe);
71        if self.route_activity_changed {
72            control = control.activity(ConsumerActivity::from_active(self.route_active()));
73        }
74        if let Some(packet_gate) = &self.packet_gate {
75            control = control.packet_gate(packet_gate.clone());
76        }
77        control
78    }
79
80    pub(in crate::engine::room) const fn route_active(&self) -> bool {
81        self.policy_pause_reason.is_none()
82    }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub(super) struct FeaturedUserUpdate {
87    pub(super) user_id: UserId,
88    pub(super) connection_id: ConnectionId,
89    pub(super) featured: Option<bool>,
90}
91
92impl FeaturedUserUpdate {
93    #[must_use]
94    pub(super) fn new(
95        user_id: UserId,
96        connection_id: ConnectionId,
97        featured: Option<bool>,
98    ) -> Self {
99        Self {
100            user_id,
101            connection_id,
102            featured,
103        }
104    }
105}