crosvm/media
Alexandre Courbot 53ade023da virtio: video: decoder: fix timestamp management
Fix the broken timestamp management in the virtio decoder device.

Timestamps are specified by the guest's user-space as a struct timeval,
which is effectively a (seconds, microseconds) pair. This pair is turned
into a u64 with nanoseconds units by V4L2, and passed to the virtio
device in that form.

This is fine so far, save for the fact that libvda works with 32-bit
timestamps. To accomodate that, we divided the original timestamp by
1_000_000_000, passed that truncated timestamp to the decoder backend as
a u32, and when the backend gives us decoded frames, multiplied their
timestamp by 1_000_000_000 again and passed that value as the frame
timestamp to the guest. For some reason, we also used the timestamp as
the key for the `NotifyEndOfBistreamBuffer` event, which forced us to
have a mapping table between an input buffer timestamp and its
corresponding resource ID. This in turn required that each input buffer
has a unique timestamp, lest they collide in the mapping table.

Anyway, the timestamp division by 1_000_000_000 means that any
sub-second timestamp information was lost during the decoding process.
This is not a problem with the Android V4L2 decoder which increases the
timestamp by one second for each frame and does not use sub-second
information, but clients that use *actual* timestamp information (like
ffmpeg) get pretty confused by that and abandon decoding with an error.

Fix this by passing the original 64-bit timestamp to decoder backends,
along with the 32-bit ID of the input resource. This allows backends to
directly send the NotifyEndOfBitstreamBuffer with the currect resource
ID, removing the need for the mapping table and unique timestamps for
input buffers.

More importantly, backends that can work with 64-bit timestamps (all of
them but libvda) can just pass the original timestamp to their decoder
logic and return it as-is in the PictureReady event. Libvda still
requires 32-bit timestamps, so we reproduce the truncation and mapping
table behavior inside the libvda backend (I also tried sending the
32-bit input resource ID as a timestamp to VDA, but it was not happy
with it). At least now that behavior is local to the VDA backend.

Thanks to this change clients other than the Android C2 decoder can get
proper timestamp information. One can argue that the code is also
simpler (except for libvda which adds a simple mapping table that we
were using before anyway).

BUG=b:161774071
TEST=cargo test --features "video-decoder,ffmpeg" -p devices video
TEST=`ffmpeg -codec:v vp8_v4l2m2m -i test-25fps.vp8 test-25fps-%d.png`
in the guest completes successfully with the ffmpeg backend.
TEST=tast arc.VideoDecodeAccel*_vm passes on hatch.

Change-Id: Idb21b4c536acafbdf5458e88cdbc33c9376a405e
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3841480
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
Tested-by: Alexandre Courbot <acourbot@chromium.org>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Reviewed-by: Tatsuyuki Ishi <ishitatsuyuki@google.com>
2022-08-24 00:10:50 +00:00
..
ffmpeg media: ffmpeg: upgrade to ffmpeg 5.0 libraries 2022-08-23 01:47:48 +00:00
libva virtio: video: decoder: fix timestamp management 2022-08-24 00:10:50 +00:00
libvda Remove redundant {self} imports 2022-08-01 21:27:54 +00:00
vp8 Reformat imports 2022-07-28 00:15:50 +00:00