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.

Choose a reason for hiding this comment

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

Makes sense. If it is only needed for V4L2 purpose, it might not be a right place to calculate here in the first place. My todo to check and move this if relevant.

@@ -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.

Choose a reason for hiding this comment

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

already done by Alex. I plan to keep it separate for the history.

1af2ce1

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?

@Gnurou Gnurou force-pushed the dev-v4l2_stateless branch from 57c9560 to f51face Compare July 8, 2024 07:56
{
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.

@stevecho321
Copy link

stevecho321 commented Oct 31, 2024

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.

Alex, I will be commenting here on some of your comments. I don't expect response as I know you can't reply or contribute here.

I hope to reflect some of these comments here in this fork or in a separate fork I created. I am checking Slawomir's preference here.

It is just for my record and potentially getting Slawomir's comment here if relevant. Hope this is not too disturbing for you and please feel free to ignore/turn off any notification on this. :)

@stevecho321
Copy link

stevecho321 commented Oct 31, 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.

IIRC, I saw the patch for 2. Will add here later.

@stevecho321
Copy link

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

health check (build) failed, but I can't find details in the link. Will try it again or I will try to reproduce it locally once I first get the build working for vaapi.

https://github.com/chromeos/cros-codecs/actions/runs/9835702975/job/27149880132?pr=83

@stevecho321
Copy link

stevecho321 commented Nov 2, 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 QBufferhas 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 different queue from the one that produced it. I think we can actually fix QBufferto handle both cases nicely - I'll try and come with a proposal this week.

IIRC, I saw the patch for 2. Will add here later.

I think we can actually fix QBufferto handle both cases nicely - I'll try and come with a proposal this week.

Link for the this change.

Gnurou/v4l2r#36 (comment)

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.

3 participants