• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::rc::Rc;
6 
7 use crate::codec::vp9::parser::Header;
8 use crate::encoder::stateless::vp9::predictor::LowDelayVP9;
9 use crate::encoder::stateless::BitstreamPromise;
10 use crate::encoder::stateless::Predictor;
11 use crate::encoder::stateless::StatelessBackendResult;
12 use crate::encoder::stateless::StatelessCodec;
13 use crate::encoder::stateless::StatelessEncoderExecute;
14 use crate::encoder::stateless::StatelessVideoEncoderBackend;
15 use crate::encoder::vp9::EncoderConfig;
16 use crate::encoder::vp9::VP9;
17 use crate::encoder::EncodeResult;
18 use crate::encoder::FrameMetadata;
19 use crate::encoder::PredictionStructure;
20 use crate::encoder::Tunings;
21 use crate::BlockingMode;
22 
23 mod predictor;
24 
25 #[cfg(feature = "vaapi")]
26 pub mod vaapi;
27 
28 /// Determines how reference frame shall be used
29 pub enum ReferenceUse {
30     /// The frame will be used for single prediction
31     Single,
32     /// The frame will be used for compound prediction
33     Compound,
34     /// The frame will be used for both single and compound prediction
35     Hybrid,
36 }
37 
38 pub struct BackendRequest<P, R> {
39     header: Header,
40 
41     /// Input frame to be encoded
42     input: P,
43 
44     /// Input frame metadata
45     input_meta: FrameMetadata,
46 
47     /// Reference frames
48     last_frame_ref: Option<(Rc<R>, ReferenceUse)>,
49     golden_frame_ref: Option<(Rc<R>, ReferenceUse)>,
50     altref_frame_ref: Option<(Rc<R>, ReferenceUse)>,
51 
52     /// [`Tunings`] for the frame
53     tunings: Tunings,
54 
55     /// Container for the request output. [`StatelessVP9EncoderBackend`] impl shall move it and
56     /// append the slice data to it. This prevents unnecessary copying of bitstream around.
57     coded_output: Vec<u8>,
58 }
59 
60 impl<Backend> StatelessCodec<Backend> for VP9
61 where
62     Backend: StatelessVideoEncoderBackend<VP9>,
63 {
64     type Reference = Backend::Reconstructed;
65 
66     type Request = BackendRequest<Backend::Picture, Backend::Reconstructed>;
67 
68     type CodedPromise = BitstreamPromise<Backend::CodedPromise>;
69 
70     type ReferencePromise = Backend::ReconPromise;
71 }
72 
73 pub trait StatelessVP9EncoderBackend: StatelessVideoEncoderBackend<VP9> {
encode_frame( &mut self, request: BackendRequest<Self::Picture, Self::Reconstructed>, ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>74     fn encode_frame(
75         &mut self,
76         request: BackendRequest<Self::Picture, Self::Reconstructed>,
77     ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>;
78 }
79 
80 pub type StatelessEncoder<Handle, Backend> =
81     crate::encoder::stateless::StatelessEncoder<VP9, Handle, Backend>;
82 
83 impl<Handle, Backend> StatelessEncoderExecute<VP9, Handle, Backend>
84     for StatelessEncoder<Handle, Backend>
85 where
86     Backend: StatelessVP9EncoderBackend,
87 {
execute( &mut self, request: BackendRequest<Backend::Picture, Backend::Reconstructed>, ) -> EncodeResult<()>88     fn execute(
89         &mut self,
90         request: BackendRequest<Backend::Picture, Backend::Reconstructed>,
91     ) -> EncodeResult<()> {
92         let meta = request.input_meta.clone();
93 
94         // The [`BackendRequest`] has a frame from predictor. Decresing internal counter.
95         self.predictor_frame_count -= 1;
96 
97         log::trace!("submitting new request");
98         let (recon, bitstream) = self.backend.encode_frame(request)?;
99 
100         // Wrap promise from backend with headers and metadata
101         let slice_promise = BitstreamPromise { bitstream, meta };
102 
103         self.output_queue.add_promise(slice_promise);
104 
105         self.recon_queue.add_promise(recon);
106 
107         Ok(())
108     }
109 }
110 
111 impl<Handle, Backend> StatelessEncoder<Handle, Backend>
112 where
113     Backend: StatelessVP9EncoderBackend,
114 {
new_vp9(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self>115     fn new_vp9(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self> {
116         let predictor: Box<dyn Predictor<_, _, _>> = match config.pred_structure {
117             PredictionStructure::LowDelay { limit } => Box::new(LowDelayVP9::new(config, limit)),
118         };
119 
120         Self::new(backend, mode, predictor)
121     }
122 }
123