1use crate::{
12 frame::Frame,
13 packet::Packet,
14 session::{CodecConfig, Receive, SendStatus, SessionError, VideoDecoder, VideoStreamInfo},
15};
16use alloc::boxed::Box;
17use core::{error::Error as StdError, fmt};
18
19use zencodec::operation::{OperationPolicy, OperationReport, PolicySet, resolve_frame};
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23#[non_exhaustive]
24pub enum Stage {
25 Decode,
27 Policy,
29}
30
31pub struct Error {
34 stage: Stage,
35 report: Box<OperationReport>,
36 cause: Box<dyn StdError + Send + Sync>,
37}
38impl Error {
39 fn new(
40 stage: Stage,
41 report: &OperationReport,
42 cause: impl StdError + Send + Sync + 'static,
43 ) -> Self {
44 Self {
45 stage,
46 report: Box::new(report.clone()),
47 cause: Box::new(cause),
48 }
49 }
50 pub const fn stage(&self) -> Stage {
52 self.stage
53 }
54 pub fn report(&self) -> &OperationReport {
56 &self.report
57 }
58}
59impl fmt::Debug for Error {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.debug_struct("VideoPolicyError")
62 .field("stage", &self.stage)
63 .field("report", &self.report)
64 .finish_non_exhaustive()
65 }
66}
67impl fmt::Display for Error {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 write!(f, "controlled video decode failed during {:?}", self.stage)
70 }
71}
72impl StdError for Error {
73 fn source(&self) -> Option<&(dyn StdError + 'static)> {
74 Some(self.cause.as_ref())
75 }
76}
77
78pub struct PolicyDecoder<D, R> {
91 decoder: Option<D>,
92 resolver: R,
93 preset: PolicySet,
94 report: OperationReport,
95}
96impl<D, R> PolicyDecoder<D, R> {
97 pub fn new(decoder: D, resolver: R) -> Self {
101 Self {
102 decoder: Some(decoder),
103 resolver,
104 preset: PolicySet::new(),
105 report: OperationReport::default(),
106 }
107 }
108 #[deprecated(note = "Pass PolicySet or BoundPolicy as the operation policy argument")]
112 pub fn with_policy_set(mut self, preset: PolicySet) -> Self {
113 self.preset = preset;
114 self
115 }
116 pub fn report(&self) -> &OperationReport {
118 &self.report
119 }
120 pub const fn is_failed(&self) -> bool {
122 self.decoder.is_none()
123 }
124}
125impl<D: VideoDecoder, R: OperationPolicy> PolicyDecoder<D, R> {
126 pub fn try_new<E: StdError + Send + Sync + 'static>(
138 factory: impl FnOnce() -> Result<D, E>,
139 resolver: R,
140 pulse: Option<&dyn zencodec::Pulse>,
141 ) -> Result<Self, Error> {
142 let report = OperationReport::default();
143 pulse
144 .unwrap_or(&zencodec::NoPulse)
145 .check()
146 .map_err(|reason| {
147 Error::new(
148 Stage::Policy,
149 &report,
150 SessionError::<core::convert::Infallible>::Cancelled(reason),
151 )
152 })?;
153 if let Some(required) = resolver.requirements() {
154 required
155 .check_workspace(None)
156 .map_err(|cause| Error::new(Stage::Policy, &report, cause))?;
157 }
158 let decoder = factory().map_err(|cause| Error::new(Stage::Decode, &report, cause))?;
159 pulse
160 .unwrap_or(&zencodec::NoPulse)
161 .check()
162 .map_err(|reason| {
163 Error::new(
164 Stage::Policy,
165 &report,
166 SessionError::<core::convert::Infallible>::Cancelled(reason),
167 )
168 })?;
169 Ok(Self::new(decoder, resolver))
170 }
171 fn run<T>(
172 &mut self,
173 pulse: Option<&dyn zencodec::Pulse>,
174 f: impl FnOnce(
175 &mut D,
176 &mut R,
177 PolicySet,
178 &mut OperationReport,
179 ) -> Result<T, SessionError<Error>>,
180 ) -> Result<T, SessionError<Error>> {
181 let mut decoder = self.decoder.take().ok_or(SessionError::Finished)?;
184 pulse.unwrap_or(&zencodec::NoPulse).check()?;
185 for required in [Some(self.preset), self.resolver.requirements()]
188 .into_iter()
189 .flatten()
190 {
191 required.check_workspace(None).map_err(|cause| {
192 SessionError::Codec(Error::new(Stage::Policy, &self.report, cause))
193 })?;
194 }
195 let output = f(
196 &mut decoder,
197 &mut self.resolver,
198 self.preset,
199 &mut self.report,
200 )?;
201 self.decoder = Some(decoder);
202 Ok(output)
203 }
204}
205fn native<E: StdError + Send + Sync + 'static>(
206 error: SessionError<E>,
207 report: &OperationReport,
208) -> SessionError<Error> {
209 error.map_codec(|error| Error::new(Stage::Decode, report, error))
210}
211impl<D: VideoDecoder, R: OperationPolicy> VideoDecoder for PolicyDecoder<D, R> {
212 type Error = Error;
213 fn configure(
214 &mut self,
215 config: &CodecConfig,
216 pulse: Option<&dyn zencodec::Pulse>,
217 ) -> Result<(), SessionError<Error>> {
218 self.run(pulse, |decoder, _, _, report| {
219 decoder
220 .configure(config, pulse)
221 .map_err(|e| native(e, report))
222 })
223 }
224 fn send(
225 &mut self,
226 packet: &mut Packet,
227 pulse: Option<&dyn zencodec::Pulse>,
228 ) -> Result<SendStatus, SessionError<Error>> {
229 self.run(pulse, |decoder, _, _, report| {
230 decoder.send(packet, pulse).map_err(|e| native(e, report))
231 })
232 }
233 fn receive(
234 &mut self,
235 pulse: Option<&dyn zencodec::Pulse>,
236 ) -> Result<Receive<Frame>, SessionError<Error>> {
237 self.run(pulse, |decoder, resolver, preset, report| {
238 let output = decoder.receive(pulse).map_err(|e| native(e, report))?;
239 if let Receive::Ready(frame) = &output {
240 match resolve_frame(
241 frame.interpretation(),
242 frame.timing(),
243 resolver,
244 preset,
245 pulse,
246 ) {
247 Ok(record) => report.record(record),
248 Err(error) => {
249 report.record(error.error().record());
250 return Err(SessionError::Codec(Error::new(
251 Stage::Policy,
252 report,
253 error,
254 )));
255 }
256 }
257 }
258 Ok(output)
259 })
260 }
261 fn end_input(&mut self) -> Result<(), SessionError<Error>> {
262 self.run(None, |decoder, _, _, report| {
263 decoder.end_input().map_err(|e| native(e, report))
264 })
265 }
266 fn reset(&mut self) -> Result<(), SessionError<Error>> {
267 self.run(None, |decoder, _, _, report| {
268 decoder.reset().map_err(|e| native(e, report))
269 })
270 }
271 fn stream_info(&self) -> Option<&VideoStreamInfo> {
272 self.decoder.as_ref().and_then(VideoDecoder::stream_info)
273 }
274}