v4l2codecs: Avoid QBUF/DQBUF struct timeval .tv_usec wrap-around at frame 1000000
When decoding stream using hardware V4L2 decoder element, in any of the currently supported formats, the decoding will fail once frame number 1000000 is reached. The reported error clearly indicates a wrap-around occured, instead of receiving decoded frame 1000000, frame 0 is received from the hardware V4L2 decoder driver.
The problem is actually not in the driver itself, but rather in gstreamer,
which uses struct v4l2_buffer
member .timestamp
in a special way. The
timestamp of buffers with encoded data added to the SINK (input) queue of
the driver is copied by the driver into matching buffers with decoded data
added to the SOURCE (output) queue of the driver. In fact, the timestamp
is not a timestamp at all, but rather in this special case, only part of
it is used as an incrementing frame counter.
The .timestamp
is of type struct timeval
, which is defined in
sys/time.h
[1]. Only the tv_usec
member of this structure is used
for the incrementing frame counter. However, suseconds_t tv_usec [2]
may be limited to range [-1, 1000000]:
[XSI] The type suseconds_t shall be a signed integer type capable of
storing values at least in the range [-1, 1000000]. [Option End]
Therefore, once frame 1000000 is reached, a rollover occurs and decoding fails.
Fix this by using both struct timeval
members, .tv_sec
and .tv_usec
with matching modular arithmetic, this way the failure would occur again
just short of 2^84 frames, which should be plenty.
[1] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html [2] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html