• 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::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