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