// 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 std::sync::Arc; use crate::backend::v4l2::decoder::V4l2StreamInfo; use crate::decoder::stateless::NewStatelessDecoderError; use crate::decoder::stateless::StatelessBackendResult; use crate::decoder::stateless::StatelessDecoderBackend; use crate::decoder::DecodedHandle; use crate::decoder::StreamInfo; use crate::device::v4l2::stateless::device::V4l2Device; use crate::device::v4l2::stateless::request::V4l2Request; use crate::video_frame::VideoFrame; use crate::DecodedFormat; use crate::Fourcc; use crate::Resolution; pub struct V4l2Picture { request: Rc>>, // To properly decode stream while output and capture queues // are processed independently it's required for v4l2 backend // to maintain DPB buffer recycling. The following vector // is used to prevent reference pictures to be reused while // current picture is still being decoded. ref_pictures: Option>>>>, } impl V4l2Picture { pub fn new(request: Rc>>) -> Self { Self { request, ref_pictures: None } } pub fn video_frame(&self) -> Arc { self.request.as_ref().borrow().result().capture_buffer.borrow().frame.clone() } pub fn timestamp(&self) -> u64 { self.request.as_ref().borrow().timestamp() } pub fn set_ref_pictures( &mut self, ref_pictures: Vec>>>, ) -> &mut Self { self.ref_pictures = Some(ref_pictures); self } pub fn sync(&mut self) -> &mut Self { self.request.as_ref().borrow_mut().sync(); self.ref_pictures = None; self } pub fn request(&mut self) -> Rc>> { self.request.clone() } pub fn drop_references(&mut self) { self.ref_pictures = None; } } pub struct V4l2StatelessDecoderHandle { pub picture: Rc>>, pub stream_info: StreamInfo, } impl Clone for V4l2StatelessDecoderHandle { fn clone(&self) -> Self { Self { picture: Rc::clone(&self.picture), stream_info: self.stream_info.clone() } } } impl DecodedHandle for V4l2StatelessDecoderHandle { type Frame = V; fn video_frame(&self) -> Arc { self.picture.borrow().video_frame() } fn coded_resolution(&self) -> Resolution { self.stream_info.coded_resolution.clone() } fn display_resolution(&self) -> Resolution { self.stream_info.display_resolution.clone() } fn timestamp(&self) -> u64 { self.picture.borrow().timestamp() } fn sync(&self) -> anyhow::Result<()> { self.picture.borrow_mut().sync(); Ok(()) } fn is_ready(&self) -> bool { todo!(); } } pub struct V4l2StatelessDecoderBackend { pub device: V4l2Device, pub stream_info: StreamInfo, pub frame_counter: u64, } impl V4l2StatelessDecoderBackend { pub fn new() -> Result { Ok(Self { device: V4l2Device::new()?, stream_info: StreamInfo { format: DecodedFormat::I420, min_num_frames: 0, coded_resolution: Resolution::from((0, 0)), display_resolution: Resolution::from((0, 0)), }, frame_counter: 0, }) } pub(crate) fn new_sequence( &mut self, stream_params: &StreamData, fourcc: Fourcc, ) -> StatelessBackendResult<()> where for<'a> &'a StreamData: V4l2StreamInfo, { let coded_resolution = stream_params.coded_size().clone(); let min_num_frames = stream_params.min_num_frames(); // TODO: Query the driver for the format self.stream_info.format = DecodedFormat::MM21; self.stream_info.display_resolution = Resolution::from(stream_params.visible_rect()); self.stream_info.coded_resolution = coded_resolution; self.stream_info.min_num_frames = min_num_frames; Ok(self.device.initialize_queues(fourcc, coded_resolution, min_num_frames as u32)?) } } impl StatelessDecoderBackend for V4l2StatelessDecoderBackend { type Handle = V4l2StatelessDecoderHandle; fn stream_info(&self) -> Option<&StreamInfo> { // TODO Some(&self.stream_info) } fn reset_backend(&mut self) -> anyhow::Result<()> { Ok(self.device.reset_queues()?) } }