• 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 crate::backend::v4l2::decoder::stateless::V4l2Picture;
9 use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderBackend;
10 use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderHandle;
11 use crate::backend::v4l2::decoder::V4l2StreamInfo;
12 use crate::backend::v4l2::decoder::ADDITIONAL_REFERENCE_FRAME_BUFFER;
13 use crate::codec::vp8::parser::Header;
14 use crate::codec::vp8::parser::MbLfAdjustments;
15 use crate::codec::vp8::parser::Segmentation;
16 use crate::decoder::stateless::vp8::StatelessVp8DecoderBackend;
17 use crate::decoder::stateless::vp8::Vp8;
18 use crate::decoder::stateless::NewPictureError;
19 use crate::decoder::stateless::NewPictureResult;
20 use crate::decoder::stateless::NewStatelessDecoderError;
21 use crate::decoder::stateless::StatelessBackendResult;
22 use crate::decoder::stateless::StatelessDecoder;
23 use crate::decoder::stateless::StatelessDecoderBackend;
24 use crate::decoder::stateless::StatelessDecoderBackendPicture;
25 use crate::decoder::BlockingMode;
26 use crate::decoder::DecodedHandle;
27 use crate::device::v4l2::stateless::controls::vp8::V4l2CtrlVp8FrameParams;
28 use crate::video_frame::VideoFrame;
29 use crate::Fourcc;
30 use crate::Rect;
31 use crate::Resolution;
32 
33 const NUM_REF_FRAMES: usize = 3;
34 
35 impl V4l2StreamInfo for &Header {
min_num_frames(&self) -> usize36     fn min_num_frames(&self) -> usize {
37         NUM_REF_FRAMES + ADDITIONAL_REFERENCE_FRAME_BUFFER
38     }
39 
coded_size(&self) -> Resolution40     fn coded_size(&self) -> Resolution {
41         Resolution::from((self.width as u32, self.height as u32))
42     }
43 
visible_rect(&self) -> Rect44     fn visible_rect(&self) -> Rect {
45         Rect::from(self.coded_size())
46     }
47 }
48 
49 impl<V: VideoFrame> StatelessDecoderBackendPicture<Vp8> for V4l2StatelessDecoderBackend<V> {
50     type Picture = Rc<RefCell<V4l2Picture<V>>>;
51 }
52 
53 impl<V: VideoFrame> StatelessVp8DecoderBackend for V4l2StatelessDecoderBackend<V> {
new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()>54     fn new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()> {
55         self.new_sequence(header, Fourcc::from(b"VP8F"))
56     }
57 
new_picture( &mut self, timestamp: u64, alloc_cb: &mut dyn FnMut() -> Option< <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, >, ) -> NewPictureResult<Self::Picture>58     fn new_picture(
59         &mut self,
60         timestamp: u64,
61         alloc_cb: &mut dyn FnMut() -> Option<
62             <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame,
63         >,
64     ) -> NewPictureResult<Self::Picture> {
65         let frame = alloc_cb().ok_or(NewPictureError::OutOfOutputBuffers)?;
66         let request_buffer = match self.device.alloc_request(timestamp, frame) {
67             Ok(buffer) => buffer,
68             _ => return Err(NewPictureError::OutOfOutputBuffers),
69         };
70         let picture = Rc::new(RefCell::new(V4l2Picture::new(request_buffer.clone())));
71         request_buffer
72             .as_ref()
73             .borrow_mut()
74             .set_picture_ref(Rc::<RefCell<V4l2Picture<V>>>::downgrade(&picture));
75         Ok(picture)
76     }
77 
submit_picture( &mut self, picture: Self::Picture, hdr: &Header, last_ref: &Option<Self::Handle>, golden_ref: &Option<Self::Handle>, alt_ref: &Option<Self::Handle>, bitstream: &[u8], segmentation: &Segmentation, mb_lf_adjust: &MbLfAdjustments, ) -> StatelessBackendResult<Self::Handle>78     fn submit_picture(
79         &mut self,
80         picture: Self::Picture,
81         hdr: &Header,
82         last_ref: &Option<Self::Handle>,
83         golden_ref: &Option<Self::Handle>,
84         alt_ref: &Option<Self::Handle>,
85         bitstream: &[u8],
86         segmentation: &Segmentation,
87         mb_lf_adjust: &MbLfAdjustments,
88     ) -> StatelessBackendResult<Self::Handle> {
89         let mut ref_pictures = Vec::<Rc<RefCell<V4l2Picture<V>>>>::new();
90 
91         let last_frame_ts = match &last_ref {
92             Some(handle) => {
93                 ref_pictures.push(handle.picture.clone());
94                 handle.timestamp()
95             }
96             None => 0,
97         };
98 
99         let golden_frame_ts = match &golden_ref {
100             Some(handle) => {
101                 ref_pictures.push(handle.picture.clone());
102                 handle.timestamp()
103             }
104             None => 0,
105         };
106 
107         let alt_frame_ts = match &alt_ref {
108             Some(handle) => {
109                 ref_pictures.push(handle.picture.clone());
110                 handle.timestamp()
111             }
112             None => 0,
113         };
114 
115         picture.borrow_mut().set_ref_pictures(ref_pictures);
116 
117         let mut vp8_frame_params = V4l2CtrlVp8FrameParams::new();
118         vp8_frame_params
119             .set_loop_filter_params(hdr, mb_lf_adjust)
120             .set_quantization_params(hdr)
121             .set_segmentation_params(segmentation)
122             .set_entropy_params(hdr)
123             .set_bool_ctx(hdr)
124             .set_frame_params(hdr, last_frame_ts, golden_frame_ts, alt_frame_ts);
125 
126         let request = picture.borrow_mut().request();
127         let mut request = request.as_ref().borrow_mut();
128         request.write(bitstream);
129         request.ioctl(&vp8_frame_params)?;
130         request.submit()?;
131 
132         Ok(V4l2StatelessDecoderHandle {
133             picture: picture.clone(),
134             stream_info: self.stream_info.clone(),
135         })
136     }
137 }
138 
139 impl<V: VideoFrame> StatelessDecoder<Vp8, V4l2StatelessDecoderBackend<V>> {
new_v4l2(blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError>140     pub fn new_v4l2(blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError> {
141         Self::new(V4l2StatelessDecoderBackend::new()?, blocking_mode)
142     }
143 }
144