cros_codecs/encoder/stateless/
av1.rs

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
5use std::rc::Rc;
6
7use crate::codec::av1::parser::FrameHeaderObu;
8use crate::codec::av1::parser::ReferenceFrameType;
9use crate::codec::av1::parser::SequenceHeaderObu;
10use crate::codec::av1::parser::REFS_PER_FRAME;
11use crate::encoder::av1::EncoderConfig;
12use crate::encoder::av1::AV1;
13use crate::encoder::stateless::av1::predictor::LowDelayAV1;
14use crate::encoder::stateless::BitstreamPromise;
15use crate::encoder::stateless::Predictor;
16use crate::encoder::stateless::StatelessBackendResult;
17use crate::encoder::stateless::StatelessCodec;
18use crate::encoder::stateless::StatelessEncoderExecute;
19use crate::encoder::stateless::StatelessVideoEncoderBackend;
20use crate::encoder::EncodeResult;
21use crate::encoder::FrameMetadata;
22use crate::encoder::PredictionStructure;
23use crate::encoder::Tunings;
24use crate::BlockingMode;
25
26mod predictor;
27
28#[cfg(feature = "vaapi")]
29pub mod vaapi;
30
31pub struct BackendRequest<P, R> {
32    /// Current sequence's header OBU
33    sequence: SequenceHeaderObu,
34
35    /// Current frame OBU contains
36    frame: FrameHeaderObu,
37
38    /// Input frame to be encoded
39    input: P,
40
41    /// Input frame metadata
42    input_meta: FrameMetadata,
43
44    /// References for the frame to be encoded
45    /// Use `ReferenceFrameType::Golden - ReferenceFrameType::Last` for indexing
46    references: [Option<Rc<R>>; REFS_PER_FRAME],
47
48    /// The reference frame search priority list. From highest to lowest
49    /// Use [`ReferenceFrameType::Intra`] for invalid
50    ref_frame_ctrl_l0: [ReferenceFrameType; REFS_PER_FRAME],
51    ref_frame_ctrl_l1: [ReferenceFrameType; REFS_PER_FRAME],
52
53    /// Period between intra frames
54    intra_period: u32,
55
56    /// Period between intra frame and P frame
57    ip_period: u32,
58
59    /// [`Tunings`] for the frame
60    tunings: Tunings,
61
62    /// Container for the request output. [`StatelessAV1EncoderBackend`] impl shall move it and
63    /// append the slice data to it. This prevents unnecessary copying of bitstream around.
64    coded_output: Vec<u8>,
65}
66
67impl<Backend> StatelessCodec<Backend> for AV1
68where
69    Backend: StatelessVideoEncoderBackend<AV1>,
70{
71    type Reference = Backend::Reconstructed;
72
73    type Request = BackendRequest<Backend::Picture, Backend::Reconstructed>;
74
75    type CodedPromise = BitstreamPromise<Backend::CodedPromise>;
76
77    type ReferencePromise = Backend::ReconPromise;
78}
79
80/// Trait for stateless encoder backend for H.264
81pub trait StatelessAV1EncoderBackend: StatelessVideoEncoderBackend<AV1> {
82    /// Submit a [`BackendRequest`] to the backend. This operation returns both a
83    /// [`StatelessVideoEncoderBackend::ReconPromise`] and a
84    /// [`StatelessVideoEncoderBackend::CodedPromise`] with resulting slice data.
85    fn encode_tile_group(
86        &mut self,
87        request: BackendRequest<Self::Picture, Self::Reconstructed>,
88    ) -> StatelessBackendResult<(Self::ReconPromise, Self::CodedPromise)>;
89}
90
91pub type StatelessEncoder<Handle, Backend> =
92    crate::encoder::stateless::StatelessEncoder<AV1, Handle, Backend>;
93
94impl<Handle, Backend> StatelessEncoderExecute<AV1, Handle, Backend>
95    for StatelessEncoder<Handle, Backend>
96where
97    Backend: StatelessAV1EncoderBackend,
98{
99    fn execute(
100        &mut self,
101        request: BackendRequest<Backend::Picture, Backend::Reconstructed>,
102    ) -> EncodeResult<()> {
103        let meta = request.input_meta.clone();
104
105        // The [`BackendRequest`] has a frame from predictor. Decresing internal counter.
106        self.predictor_frame_count -= 1;
107
108        log::trace!("submitting new request");
109        let (recon, bitstream) = self.backend.encode_tile_group(request)?;
110
111        // Wrap promise from backend with headers and metadata
112        let tilegroup_promise = BitstreamPromise { bitstream, meta };
113
114        self.output_queue.add_promise(tilegroup_promise);
115
116        self.recon_queue.add_promise(recon);
117
118        Ok(())
119    }
120}
121
122impl<Handle, Backend> StatelessEncoder<Handle, Backend>
123where
124    Backend: StatelessAV1EncoderBackend,
125{
126    fn new_av1(backend: Backend, config: EncoderConfig, mode: BlockingMode) -> EncodeResult<Self> {
127        let predictor: Box<dyn Predictor<_, _, _>> = match config.pred_structure {
128            PredictionStructure::LowDelay { limit } => Box::new(LowDelayAV1::new(config, limit)),
129        };
130
131        Self::new(backend, mode, predictor)
132    }
133}