blob: 6484c1d63d81289b91f35ddef6a3ac626aa46be3 [file] [log] [blame]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::cell::RefCell;
use std::rc::Rc;
use v4l2r::bindings::v4l2_ctrl_vp8_frame;
use v4l2r::controls::SafeExtControl;
use crate::backend::v4l2::decoder::stateless::BackendHandle;
use crate::backend::v4l2::decoder::stateless::V4l2Picture;
use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderBackend;
use crate::backend::v4l2::decoder::stateless::V4l2StatelessDecoderHandle;
use crate::backend::v4l2::decoder::V4l2StreamInfo;
use crate::codec::vp8::parser::Header;
use crate::codec::vp8::parser::MbLfAdjustments;
use crate::codec::vp8::parser::Segmentation;
use crate::decoder::stateless::vp8::StatelessVp8DecoderBackend;
use crate::decoder::stateless::vp8::Vp8;
use crate::decoder::stateless::NewPictureError;
use crate::decoder::stateless::NewPictureResult;
use crate::decoder::stateless::StatelessBackendResult;
use crate::decoder::stateless::StatelessDecoder;
use crate::decoder::stateless::StatelessDecoderBackendPicture;
use crate::decoder::BlockingMode;
use crate::device::v4l2::stateless::controls::vp8::V4l2CtrlVp8FrameParams;
use crate::Resolution;
/// The number of frames to allocate for this codec. Same as GStreamer's vavp8dec.
const NUM_FRAMES: usize = 7;
impl V4l2StreamInfo for &Header {
fn min_num_frames(&self) -> usize {
NUM_FRAMES
}
fn coded_size(&self) -> Resolution {
Resolution::from((self.width as u32, self.height as u32))
}
fn visible_rect(&self) -> ((u32, u32), (u32, u32)) {
((0, 0), self.coded_size().into())
}
}
impl StatelessDecoderBackendPicture<Vp8> for V4l2StatelessDecoderBackend {
type Picture = Rc<RefCell<V4l2Picture>>;
}
impl StatelessVp8DecoderBackend for V4l2StatelessDecoderBackend {
fn new_sequence(&mut self, _: &Header) -> StatelessBackendResult<()> {
Ok(())
}
fn new_picture(&mut self, timestamp: u64) -> NewPictureResult<Self::Picture> {
let request_buffer = match self.device.alloc_request(timestamp) {
Ok(buffer) => buffer,
_ => return Err(NewPictureError::OutOfOutputBuffers),
};
Ok(Rc::new(RefCell::new(V4l2Picture::new(request_buffer))))
}
fn submit_picture(
&mut self,
picture: Self::Picture,
hdr: &Header,
_: &Option<Self::Handle>,
_: &Option<Self::Handle>,
_: &Option<Self::Handle>,
_: &[u8],
segmentation: &Segmentation,
mb_lf_adjust: &MbLfAdjustments,
) -> StatelessBackendResult<Self::Handle> {
let mut vp8_frame_params = V4l2CtrlVp8FrameParams::new();
vp8_frame_params
.set_loop_filter_params(hdr, mb_lf_adjust)
.set_quantization_params(hdr)
.set_segmentation_params(segmentation)
.set_entropy_params(hdr);
let handle = Rc::new(RefCell::new(BackendHandle {
picture: picture.clone(),
}));
println!(
"{:<20} {:?}\n",
"submit_picture",
picture.borrow().timestamp()
);
picture.borrow_mut().request().submit();
Ok(V4l2StatelessDecoderHandle { handle })
}
}
impl StatelessDecoder<Vp8, V4l2StatelessDecoderBackend> {
// Creates a new instance of the decoder using the v4l2 backend.
pub fn new_v4l2(blocking_mode: BlockingMode) -> Self {
Self::new(V4l2StatelessDecoderBackend::new(), blocking_mode)
.expect("Failed to create v4l2 stateless decoder backend")
}
}