• 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::cell::RefCell;
6 use std::rc::Rc;
7 
8 use v4l2r::ioctl;
9 
10 use crate::backend::v4l2::decoder::stateless::V4l2Picture;
11 use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderBackend;
12 use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderHandle;
13 use crate::backend::v4l2::decoder::V4l2StreamInfo;
14 use crate::backend::v4l2::decoder::ADDITIONAL_REFERENCE_FRAME_BUFFER;
15 use crate::codec::vp9::parser::Header;
16 use crate::codec::vp9::parser::Segmentation;
17 use crate::codec::vp9::parser::ALTREF_FRAME;
18 use crate::codec::vp9::parser::GOLDEN_FRAME;
19 use crate::codec::vp9::parser::LAST_FRAME;
20 use crate::codec::vp9::parser::MAX_SEGMENTS;
21 use crate::codec::vp9::parser::NUM_REF_FRAMES;
22 use crate::decoder::stateless::vp9::StatelessVp9DecoderBackend;
23 use crate::decoder::stateless::vp9::Vp9;
24 use crate::decoder::stateless::NewPictureError;
25 use crate::decoder::stateless::NewPictureResult;
26 use crate::decoder::stateless::NewStatelessDecoderError;
27 use crate::decoder::stateless::StatelessBackendError;
28 use crate::decoder::stateless::StatelessBackendResult;
29 use crate::decoder::stateless::StatelessDecoder;
30 use crate::decoder::stateless::StatelessDecoderBackend;
31 use crate::decoder::stateless::StatelessDecoderBackendPicture;
32 use crate::decoder::BlockingMode;
33 use crate::decoder::DecodedHandle;
34 use crate::device::v4l2::stateless::controls::vp9::V4l2CtrlVp9FrameParams;
35 use crate::device::v4l2::stateless::controls::vp9::Vp9V4l2Control;
36 use crate::video_frame::VideoFrame;
37 use crate::Fourcc;
38 use crate::Rect;
39 use crate::Resolution;
40 
41 impl V4l2StreamInfo for &Header {
min_num_frames(&self) -> usize42     fn min_num_frames(&self) -> usize {
43         NUM_REF_FRAMES + ADDITIONAL_REFERENCE_FRAME_BUFFER
44     }
45 
coded_size(&self) -> Resolution46     fn coded_size(&self) -> Resolution {
47         Resolution::from((self.width, self.height))
48     }
49 
visible_rect(&self) -> Rect50     fn visible_rect(&self) -> Rect {
51         Rect::from(((0, 0), (self.render_width, self.render_height)))
52     }
53 }
54 
55 impl<V: VideoFrame> StatelessDecoderBackendPicture<Vp9> for V4l2StatelessDecoderBackend<V> {
56     type Picture = Rc<RefCell<V4l2Picture<V>>>;
57 }
58 
59 impl<V: VideoFrame> StatelessVp9DecoderBackend for V4l2StatelessDecoderBackend<V> {
new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()>60     fn new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()> {
61         self.new_sequence(header, Fourcc::from(b"VP9F"))
62     }
63 
new_picture( &mut self, _timestamp: u64, alloc_cb: &mut dyn FnMut() -> Option< <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, >, ) -> NewPictureResult<Self::Picture>64     fn new_picture(
65         &mut self,
66         _timestamp: u64,
67         alloc_cb: &mut dyn FnMut() -> Option<
68             <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame,
69         >,
70     ) -> NewPictureResult<Self::Picture> {
71         let timestamp = self.frame_counter;
72         let frame = alloc_cb().ok_or(NewPictureError::OutOfOutputBuffers)?;
73         let request_buffer = match self.device.alloc_request(timestamp, frame) {
74             Ok(buffer) => buffer,
75             _ => return Err(NewPictureError::OutOfOutputBuffers),
76         };
77         let picture = Rc::new(RefCell::new(V4l2Picture::new(request_buffer.clone())));
78         request_buffer
79             .as_ref()
80             .borrow_mut()
81             .set_picture_ref(Rc::<RefCell<V4l2Picture<V>>>::downgrade(&picture));
82 
83         self.frame_counter = self.frame_counter + 1;
84         Ok(picture)
85     }
86 
submit_picture( &mut self, picture: Self::Picture, hdr: &Header, reference_frames: &[Option<Self::Handle>; NUM_REF_FRAMES], bitstream: &[u8], _segmentation: &[Segmentation; MAX_SEGMENTS], ) -> StatelessBackendResult<Self::Handle>87     fn submit_picture(
88         &mut self,
89         picture: Self::Picture,
90         hdr: &Header,
91         reference_frames: &[Option<Self::Handle>; NUM_REF_FRAMES],
92         bitstream: &[u8],
93         _segmentation: &[Segmentation; MAX_SEGMENTS],
94     ) -> StatelessBackendResult<Self::Handle> {
95         let mut vp9_frame_params = V4l2CtrlVp9FrameParams::new();
96 
97         let last_frame_idx = hdr.ref_frame_idx[LAST_FRAME - 1];
98         let golden_frame_idx = hdr.ref_frame_idx[GOLDEN_FRAME - 1];
99         let alt_frame_idx = hdr.ref_frame_idx[ALTREF_FRAME - 1];
100 
101         let last_frame_ts = match &reference_frames[last_frame_idx as usize] {
102             Some(handle) => handle.timestamp(),
103             None => 0,
104         };
105 
106         let golden_frame_ts = match &reference_frames[golden_frame_idx as usize] {
107             Some(handle) => handle.timestamp(),
108             None => 0,
109         };
110 
111         let alt_frame_ts = match &reference_frames[alt_frame_idx as usize] {
112             Some(handle) => handle.timestamp(),
113             None => 0,
114         };
115 
116         vp9_frame_params
117             .set_loop_filter_params(hdr)
118             .set_quantization_params(hdr)
119             .set_segmentation_params(hdr)
120             .set_frame_params(hdr, last_frame_ts, golden_frame_ts, alt_frame_ts);
121 
122         let mut ctrl = Vp9V4l2Control::from(&vp9_frame_params);
123 
124         let request = picture.borrow_mut().request();
125         let mut request = request.as_ref().borrow_mut();
126 
127         // We have to do this manually since v4l2r does not directly support VP9
128         let which = request.which();
129         ioctl::s_ext_ctrls(&self.device, which, &mut ctrl)
130             .map_err(|e| StatelessBackendError::Other(anyhow::anyhow!(e)))?;
131 
132         let mut reference_pictures = Vec::<Rc<RefCell<V4l2Picture<V>>>>::new();
133         for frame in reference_frames {
134             if frame.is_some() {
135                 reference_pictures.push(frame.as_ref().unwrap().picture.clone());
136             }
137         }
138         picture.borrow_mut().set_ref_pictures(reference_pictures);
139 
140         request.write(bitstream);
141         request.submit()?;
142 
143         Ok(V4l2StatelessDecoderHandle {
144             picture: picture.clone(),
145             stream_info: self.stream_info.clone(),
146         })
147     }
148 }
149 
150 impl<V: VideoFrame> StatelessDecoder<Vp9, V4l2StatelessDecoderBackend<V>> {
new_v4l2(blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError>151     pub fn new_v4l2(blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError> {
152         Self::new(V4l2StatelessDecoderBackend::new()?, blocking_mode)
153     }
154 }
155