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::bindings::v4l2_ctrl_h264_pps; 9 use v4l2r::bindings::v4l2_ctrl_h264_scaling_matrix; 10 use v4l2r::bindings::v4l2_ctrl_h264_sps; 11 use v4l2r::controls::codec::H264Pps; 12 use v4l2r::controls::codec::H264ScalingMatrix; 13 use v4l2r::controls::codec::H264Sps; 14 use v4l2r::controls::SafeExtControl; 15 16 use crate::backend::v4l2::decoder::stateless::V4l2Picture; 17 use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderBackend; 18 use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderHandle; 19 use crate::backend::v4l2::decoder::V4l2StreamInfo; 20 use crate::backend::v4l2::decoder::ADDITIONAL_REFERENCE_FRAME_BUFFER; 21 use crate::codec::h264::dpb::Dpb; 22 use crate::codec::h264::dpb::DpbEntry; 23 use crate::codec::h264::parser::Pps; 24 use crate::codec::h264::parser::Slice; 25 use crate::codec::h264::parser::SliceHeader; 26 use crate::codec::h264::parser::Sps; 27 use crate::codec::h264::picture::PictureData; 28 use crate::decoder::stateless::h264::StatelessH264DecoderBackend; 29 use crate::decoder::stateless::h264::H264; 30 use crate::decoder::stateless::NewPictureError; 31 use crate::decoder::stateless::NewPictureResult; 32 use crate::decoder::stateless::NewStatelessDecoderError; 33 use crate::decoder::stateless::StatelessBackendResult; 34 use crate::decoder::stateless::StatelessDecoder; 35 use crate::decoder::stateless::StatelessDecoderBackend; 36 use crate::decoder::stateless::StatelessDecoderBackendPicture; 37 use crate::decoder::BlockingMode; 38 use crate::decoder::DecodedHandle; 39 use crate::device::v4l2::stateless::controls::h264::V4l2CtrlH264DecodeMode; 40 use crate::device::v4l2::stateless::controls::h264::V4l2CtrlH264DecodeParams; 41 use crate::device::v4l2::stateless::controls::h264::V4l2CtrlH264DpbEntry; 42 use crate::device::v4l2::stateless::controls::h264::V4l2CtrlH264StartCode; 43 use crate::video_frame::VideoFrame; 44 use crate::Fourcc; 45 use crate::Rect; 46 use crate::Resolution; 47 48 impl V4l2StreamInfo for &Rc<Sps> { min_num_frames(&self) -> usize49 fn min_num_frames(&self) -> usize { 50 self.max_dpb_frames() + ADDITIONAL_REFERENCE_FRAME_BUFFER 51 } 52 coded_size(&self) -> Resolution53 fn coded_size(&self) -> Resolution { 54 Resolution::from((self.width(), self.height())) 55 } 56 visible_rect(&self) -> Rect57 fn visible_rect(&self) -> Rect { 58 let rect = self.visible_rectangle(); 59 60 Rect { x: rect.min.x, y: rect.min.y, width: rect.max.x, height: rect.max.y } 61 } 62 } 63 64 impl<V: VideoFrame> StatelessDecoderBackendPicture<H264> for V4l2StatelessDecoderBackend<V> { 65 type Picture = Rc<RefCell<V4l2Picture<V>>>; 66 } 67 68 impl<V: VideoFrame> StatelessH264DecoderBackend for V4l2StatelessDecoderBackend<V> { new_sequence(&mut self, sps: &Rc<Sps>) -> StatelessBackendResult<()>69 fn new_sequence(&mut self, sps: &Rc<Sps>) -> StatelessBackendResult<()> { 70 self.new_sequence(sps, Fourcc::from(b"S264")) 71 } 72 new_picture( &mut self, timestamp: u64, alloc_cb: &mut dyn FnMut() -> Option< <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, >, ) -> NewPictureResult<Self::Picture>73 fn new_picture( 74 &mut self, 75 timestamp: u64, 76 alloc_cb: &mut dyn FnMut() -> Option< 77 <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, 78 >, 79 ) -> NewPictureResult<Self::Picture> { 80 let frame = alloc_cb().ok_or(NewPictureError::OutOfOutputBuffers)?; 81 let request_buffer = match self.device.alloc_request(timestamp, frame) { 82 Ok(buffer) => buffer, 83 _ => return Err(NewPictureError::OutOfOutputBuffers), 84 }; 85 86 let picture = Rc::new(RefCell::new(V4l2Picture::new(request_buffer.clone()))); 87 request_buffer 88 .as_ref() 89 .borrow_mut() 90 .set_picture_ref(Rc::<RefCell<V4l2Picture<V>>>::downgrade(&picture)); 91 Ok(picture) 92 } 93 new_field_picture(&mut self, _: u64, _: &Self::Handle) -> NewPictureResult<Self::Picture>94 fn new_field_picture(&mut self, _: u64, _: &Self::Handle) -> NewPictureResult<Self::Picture> { 95 todo!() 96 } 97 start_picture( &mut self, picture: &mut Self::Picture, picture_data: &PictureData, sps: &Sps, pps: &Pps, dpb: &Dpb<Self::Handle>, slice_header: &SliceHeader, ) -> StatelessBackendResult<()>98 fn start_picture( 99 &mut self, 100 picture: &mut Self::Picture, 101 picture_data: &PictureData, 102 sps: &Sps, 103 pps: &Pps, 104 dpb: &Dpb<Self::Handle>, 105 slice_header: &SliceHeader, 106 ) -> StatelessBackendResult<()> { 107 let mut dpb_entries = Vec::<V4l2CtrlH264DpbEntry>::new(); 108 let mut ref_pictures = Vec::<Rc<RefCell<V4l2Picture<V>>>>::new(); 109 for entry in dpb.entries() { 110 let ref_picture = match &entry.reference { 111 Some(handle) => handle.picture.clone(), 112 None => todo!(), 113 }; 114 dpb_entries.push(V4l2CtrlH264DpbEntry { 115 timestamp: ref_picture.borrow().timestamp(), 116 pic: entry.pic.clone(), 117 }); 118 ref_pictures.push(ref_picture); 119 } 120 121 let mut h264_decode_params = V4l2CtrlH264DecodeParams::new(); 122 let h264_sps = SafeExtControl::<H264Sps>::from(v4l2_ctrl_h264_sps::from(sps)); 123 let h264_pps = SafeExtControl::<H264Pps>::from(v4l2_ctrl_h264_pps::from(pps)); 124 let h264_scaling_matrix = 125 SafeExtControl::<H264ScalingMatrix>::from(v4l2_ctrl_h264_scaling_matrix::from(pps)); 126 127 h264_decode_params 128 .set_picture_data(picture_data) 129 .set_dpb_entries(dpb_entries) 130 .set_slice_header(slice_header); 131 let mut picture = picture.borrow_mut(); 132 133 let request = picture.request(); 134 let mut request = request.as_ref().borrow_mut(); 135 request 136 .ioctl(h264_sps)? 137 .ioctl(h264_pps)? 138 .ioctl(h264_scaling_matrix)? 139 .ioctl(&h264_decode_params)? 140 .ioctl(V4l2CtrlH264DecodeMode::FrameBased)? 141 .ioctl(V4l2CtrlH264StartCode::AnnexB)?; 142 picture.set_ref_pictures(ref_pictures); 143 Ok(()) 144 } 145 decode_slice( &mut self, picture: &mut Self::Picture, slice: &Slice, _: &Sps, _: &Pps, _: &[&DpbEntry<Self::Handle>], _: &[&DpbEntry<Self::Handle>], ) -> StatelessBackendResult<()>146 fn decode_slice( 147 &mut self, 148 picture: &mut Self::Picture, 149 slice: &Slice, 150 _: &Sps, 151 _: &Pps, 152 _: &[&DpbEntry<Self::Handle>], 153 _: &[&DpbEntry<Self::Handle>], 154 ) -> StatelessBackendResult<()> { 155 const START_CODE: [u8; 3] = [0, 0, 1]; 156 157 let request = picture.borrow_mut().request(); 158 let mut request = request.as_ref().borrow_mut(); 159 160 request.write(&START_CODE); 161 request.write(slice.nalu.as_ref()); 162 Ok(()) 163 } 164 submit_picture(&mut self, picture: Self::Picture) -> StatelessBackendResult<Self::Handle>165 fn submit_picture(&mut self, picture: Self::Picture) -> StatelessBackendResult<Self::Handle> { 166 let request = picture.borrow_mut().request(); 167 let mut request = request.as_ref().borrow_mut(); 168 request.submit()?; 169 Ok(V4l2StatelessDecoderHandle { 170 picture: picture.clone(), 171 stream_info: self.stream_info.clone(), 172 }) 173 } 174 } 175 176 impl<V: VideoFrame> StatelessDecoder<H264, V4l2StatelessDecoderBackend<V>> { new_v4l2(blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError>177 pub fn new_v4l2(blocking_mode: BlockingMode) -> Result<Self, NewStatelessDecoderError> { 178 Self::new(V4l2StatelessDecoderBackend::new()?, blocking_mode) 179 } 180 } 181