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