virtio: video: Tolerate and fixup zero plane encoder SetParam requests.

Per virtio-video spec, if the device encounters a field with value it
does not support, it should update the field with a valid value and then
return that.
It's actually debatable whether an empty plane array is allowed in the
first place, but this seems to be what happens in the case we use a non-
default format (everything but NV12) from FFmpeg v4l2m2m. Moreover, the
guest kernel currently ignores SetParams errors, so it seems justifiable
that we should avoid rejecting this input and instead gracefully handle
it.

With this change + later commit introducing the FFmpeg encoder, FFmpeg
in the guest works with `-pix_fmt yuv420p -c:v vp8/h265_v4l2m2m`. Note
that for VP8 a WebM container should be used. VP9 was not supported as
an encoder accelerator somehow so this was not tested.

BUG=b:239897269
TEST=cargo test --features "video-encoder,video-decoder,ffmpeg" -p devices video
TEST=Linux guest test described above

Change-Id: I843af7cef35cc231b8668efcf716a48a37959c86
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3924264
Commit-Queue: Tatsuyuki Ishi <ishitatsuyuki@google.com>
Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
This commit is contained in:
Tatsuyuki Ishi 2022-09-29 06:37:50 +09:00 committed by crosvm LUCI
parent fbe77b7123
commit 106ae7ada1

View file

@ -1074,11 +1074,6 @@ impl<T: Encoder> EncoderDevice<T> {
return Err(VideoError::InvalidOperation);
}
// There should be at least a single plane.
if plane_formats.is_empty() {
return Err(VideoError::InvalidArgument);
}
let desired_format =
format.or(stream.src_params.format).unwrap_or(Format::NV12);
self.cros_capabilities.populate_src_params(
@ -1086,7 +1081,7 @@ impl<T: Encoder> EncoderDevice<T> {
desired_format,
frame_width,
frame_height,
plane_formats[0].stride,
plane_formats.get(0).map(|fmt| fmt.stride).unwrap_or(0),
)?;
stream.dst_params.frame_width = frame_width;