Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev v4l2 stateless #83

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Conversation

semigle
Copy link
Collaborator

@semigle semigle commented Jul 2, 2024

This PR provides initial implementation of the v4l2 stateless decoder backend implemented on top of the v4l2r library. It depends on the Gnurou/v4l2r#36.

TODOs:

  • handle video device path (it's temporary set to /dev/video-dec0)
  • probe media device path (it's temporary set to /dev/video-med0)
  • handle memory backends other than mmap
  • handle video formats other than h264
  • handle queue start/stop at runtime
  • handle DRC at runtime

semigle and others added 7 commits July 3, 2024 09:26
This commit provides some extra V4L2 fields to the SliceHeader
which are calculated by parser while processing h264 stream.
This commit provides initial implementation of v4l2 stateless
device implemented on top of the v4l2r library. This abstraction
layer is intended to be used directly by v4l2 backend implementation.

TODO:
* handle video device path (it's temporary set to /dev/video-dec0)
* probe  media device path (it's temporary set to /dev/video-med0)
* handle memory backends other than mmap
* handle video formats other than h264
* handle queue start/stop at runtime
* handle DRC at runtime
Initial implementation of v4l2 stateless decoder backend.
Initial implementation of h264 decoder on top of v4l2 stateless backend

TODO:
* Add support for scaling matrix
…4l2CtrlH264Pps` wrapper types

We can achieve the same result through existing `From` implementations.
This RefCell was there to provide interior mutability because some of
the methods did not take Self as mutable. With proper mutability
parameters, and a use of std::mem::take, it can be removed.
Copy link
Collaborator

@Gnurou Gnurou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my initial comments - there are a few things I'd like to see if we cannot simplify, notably the weak buffers, so I'll take more time to review the rest.

One general comment, is that we should not use expect or panic in library code except to indicate a bug in our code (and even there, as a last resort). Please define errors using thiserror and return them wherever relevant - this makes the code a bit more verbose (although the ? operator limits this) but also more solid.

@@ -266,6 +266,10 @@ pub struct SliceHeader {
/// the bottom field of a coded frame specified in clause 8.2.1.
pub delta_pic_order_cnt: [i32; 2],

/// This value is required by V4L2 stateless decode params so it is calculated
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter which backend requires this - the parser should be backend-agnostic, so no need to mention V4L2 here.

@@ -315,6 +319,10 @@ pub struct SliceHeader {
/// Decoded reference picture marking parsed using 7.3.3.3
pub dec_ref_pic_marking: RefPicMarking,

/// This value is required by V4L2 stateless decode params so it is calculated
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@@ -0,0 +1,187 @@
// Copyright 2024 The ChromiumOS Authors
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we should be able to integrate this into the existing ccdec instead of creating a new program. I did a recent change that made the decoders codec and backend agnostic, so you should be able to plug a V4L2 stateless decoder there without any problem - please let me know if you see any blocker though.

use v4l2r::controls::codec::H264Sps;
use v4l2r::controls::SafeExtControl;

impl From<&Sps> for v4l2_ctrl_h264_sps {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! That's exactly what the From trait is for.

}
}

#[derive(Default)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think V4l2CtrlH264Sps and V4l2CtrlH264Pps are unneeded. They only wrap v4l2_ctrl_h264_{sps,pps} temporarily in order to convert a Sps or Pps into a SafeControl. You should be able to achieve the same result with existing methods.

It is a bit difficult to explain though, so I've written a CL on top of your series that shows what I mean - please check if that works, and squash it into this CL if it does.

buffer,
}
}
fn ioctl<C, T>(&mut self, ctrl: C) -> &mut Self
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not tell us which ioctl we are doing. add_ctrl is probably a better name.

ioctl::s_ext_ctrls(&self.device, which, &mut ctrl).expect("Failed to set output control");
self
}
fn write(&mut self, data: &[u8]) -> &mut Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe write_input_buffer?

}

#[derive(Default)]
enum RequestHandle {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be named RequestState.

}

pub struct V4l2Request {
handle: RefCell<RequestHandle>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a RefCell without a Rc usually indicates something is wrong with the mutability of your interface. I think this can be simplified - please see the follow-up CL I've added to your series, and squash it if you agree.

Init(Queue<Output, QueueInit>),
Streaming(Queue<Output, BuffersAllocated<Vec<MmapHandle>>>),
#[default]
Unknown,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is more Invalid than Unknown?

{
match self {
Self::Init(handle) => handle.ioctl(ctrl),
_ => panic!("ERROR"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to avoid these runtime panics, you can use something called the typestate pattern to ensure that all state transitions of RequestHandle are valid at compile-time: https://cliffle.com/blog/rust-typestate/

This also makes me think that maybe your Request type could be useful beyond the stateless decoder. Let's see how this turns out, but maybe we can move it into v4l2r to make it useful for other use-cases as well.

@Gnurou
Copy link
Collaborator

Gnurou commented Jul 9, 2024

Also your PR has revealed a few design issues with cros-codecs and v4l2r:

  1. The stateless decoders check the number of available output buffers before submitting a picture to the backend. This is needed for VAAPI, but not for V4L2 stateless. I have opened issue decoder/stateless: backends should check the number of available output buffers, if needed. #85 to fix this.

  2. In v4l2r, the lifetime that QBuffer has on its queue is preventing us from working properly - that's why you introduced QBufferWeak, but this also has problems - it's basically a different version of QBuffer, and the current design makes it possible to submit a buffer to a queue different from the one that produced it. I think we can actually fix QBuffer to handle both cases nicely - I'll try and come with a proposal this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants