Skip to main content

sim_lib_view_device/
split.rs

1//! Content-rate encoding plus device-rate local adaptation.
2
3use std::rc::Rc;
4
5use sim_kernel::{Cx, Expr, Result};
6use sim_lib_view::{SurfaceCaps, SurfaceCodec};
7
8use crate::{DeviceProfile, EncodedScene, LocalAdapter};
9
10/// Runs one content encode and then many local adaptations.
11///
12/// The helper keeps device state out of the content encoder API. State is only
13/// accepted by [`Split::adapt_many`] and the free [`drive`] function, both of
14/// which operate on an already encoded [`EncodedScene`].
15#[derive(Clone, Debug)]
16pub struct Split<A> {
17    adapter: A,
18    profile: DeviceProfile,
19}
20
21impl<A> Split<A> {
22    /// Builds a split driver for one local adapter and device profile.
23    pub fn new(adapter: A, profile: DeviceProfile) -> Self {
24        Self { adapter, profile }
25    }
26
27    /// Returns the local adapter.
28    pub fn adapter(&self) -> &A {
29        &self.adapter
30    }
31
32    /// Returns the device profile used for local adaptations.
33    pub fn profile(&self) -> &DeviceProfile {
34        &self.profile
35    }
36}
37
38impl<A: LocalAdapter> Split<A> {
39    /// Encodes content once through a [`SurfaceCodec`].
40    pub fn encode_once<C: SurfaceCodec + ?Sized>(
41        &self,
42        codec: &C,
43        cx: &mut Cx,
44        value: &Expr,
45        caps: &SurfaceCaps,
46    ) -> Result<EncodedScene> {
47        codec.encode(cx, value, caps).map(EncodedScene::new)
48    }
49
50    /// Adapts one already encoded Scene using the latest device state.
51    pub fn adapt_one(&self, encoded: &EncodedScene, state: &A::State) -> Result<Rc<Expr>> {
52        self.adapter.adapt(encoded, state, &self.profile)
53    }
54
55    /// Adapts one already encoded Scene for each device state.
56    pub fn adapt_many(&self, encoded: &EncodedScene, states: &[A::State]) -> Result<Vec<Rc<Expr>>> {
57        drive(encoded, &self.adapter, states, &self.profile)
58    }
59
60    /// Runs the full split: one encode followed by local adaptations.
61    pub fn run<C: SurfaceCodec + ?Sized>(
62        &self,
63        codec: &C,
64        cx: &mut Cx,
65        value: &Expr,
66        caps: &SurfaceCaps,
67        states: &[A::State],
68    ) -> Result<SplitRun> {
69        let encoded = self.encode_once(codec, cx, value, caps)?;
70        let frames = self.adapt_many(&encoded, states)?;
71        Ok(SplitRun { encoded, frames })
72    }
73}
74
75/// Result of a split run.
76#[derive(Clone, Debug, PartialEq)]
77pub struct SplitRun {
78    /// The single content-rate encoded Scene.
79    pub encoded: EncodedScene,
80    /// Device-rate local adaptation outputs.
81    pub frames: Vec<Rc<Expr>>,
82}
83
84/// Adapts an already encoded Scene for many device states.
85pub fn drive<A: LocalAdapter>(
86    encoded: &EncodedScene,
87    adapter: &A,
88    states: &[A::State],
89    profile: &DeviceProfile,
90) -> Result<Vec<Rc<Expr>>> {
91    states
92        .iter()
93        .map(|state| adapter.adapt(encoded, state, profile))
94        .collect()
95}