gstreamer/subprojects/gst-plugins-bad/sys/v4l2codecs
Marek Vasut 5d2d602e4a 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].
"
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

A test case using stateless hardware h264 decoder, the WARN/ERROR output
in gstreamer log indicates a failure occurred. With this change, that
error no longer occurs and the WARN/ERROR are not present:
```
pc$ gst-launch-1.0 videotestsrc num-buffers=1001001 pattern=6 ! \
                   video/x-raw,width=16,height=16,format=I420 ! \
                   x264enc ! filesink location=/tmp/test.h264

dut$ GST_DEBUG="*:3" gst-launch-1.0 filesrc location=/tmp/test.h264 ! \
                                    h264parse ! v4l2slh264dec ! fakesink
...
0:03:51.393677606 12111     0x370df400 WARN      \
  v4l2codecs-decoder gstv4l2decoder.c:1157:gst_v4l2_request_set_done:<v4l2decoder2> \
  Requested frame 1000000, but driver returned frame 0.
0:03:51.394140597 12111     0x370df400 WARN      \
  v4l2codecs-decoder gstv4l2decoder.c:1157:gst_v4l2_request_set_done:<v4l2decoder2> \
  Requested frame 1000001, but driver returned frame 1.
0:03:51.394425216 12111     0x370df400 WARN      \
  v4l2codecs-decoder gstv4l2decoder.c:1157:gst_v4l2_request_set_done:<v4l2decoder2> \
  Requested frame 1000002, but driver returned frame 2.
0:03:51.394665211 12111     0x370df400 WARN      \
  v4l2codecs-decoder gstv4l2decoder.c:1157:gst_v4l2_request_set_done:<v4l2decoder2> \
  Requested frame 1000003, but driver returned frame 3.
0:03:51.394785833 12111     0x370df400 WARN      \
  v4l2codecs-h264dec gstv4l2codech264dec.c:1059:gst_v4l2_codec_h264_dec_output_picture:<v4l2slh264dec0> \
  error: Failed to decode frame 1000000
ERROR: from element /GstPipeline:pipeline0/v4l2slh264dec:v4l2slh264dec0: Failed to decode frame 1000000
```

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5598>
2023-11-04 15:51:45 +01:00
..
linux v4l2codecs: Enable Mediatek 10bit 4:2:0 support 2023-08-08 16:08:16 +00:00
gstv4l2codecallocator.c v4l2codecs: Fix segfault when destroying non-detached allocator 2021-11-02 15:25:48 +00:00
gstv4l2codecallocator.h Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codecalphadecodebin.c Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codecalphadecodebin.h Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codecav1dec.c av1decoder: Port to GstCodecPicture struct 2023-09-08 11:51:23 +00:00
gstv4l2codecav1dec.h v4l2codecs: Add AV1 decoder 2023-06-16 01:30:40 +00:00
gstv4l2codecdevice.c v4l2codecs: Warn user when no media devices are found 2022-09-29 19:12:14 +00:00
gstv4l2codecdevice.h Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codech264dec.c h264decoder: Port to GstCodecPicture struct 2023-09-08 11:51:23 +00:00
gstv4l2codech264dec.h Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codech265dec.c v4l2codecs: h265: Fix entry_point_offsets array leak 2023-10-17 15:06:26 -04:00
gstv4l2codech265dec.h v4l2codecs: Add v4l2 stateless H265 decoder 2022-07-22 10:21:02 -04:00
gstv4l2codecmpeg2dec.c mpeg2decoder: Port to GstCodecPicture struct 2023-09-08 11:51:23 +00:00
gstv4l2codecmpeg2dec.h v4l2codecs: mpeg2: Check that the decoder output formats 2021-12-10 21:37:14 +00:00
gstv4l2codecpool.c Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codecpool.h Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codecvp8dec.c vp8decoder: Port to GstCodecPicture struct 2023-09-08 11:51:23 +00:00
gstv4l2codecvp8dec.h Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir 2021-09-24 16:14:36 -03:00
gstv4l2codecvp9dec.c vp9decoder: Port to GstCodecPicture struct 2023-09-08 11:51:23 +00:00
gstv4l2codecvp9dec.h v4l2codecs: vp9: Add alpha decodebin wrapper 2021-12-10 21:37:14 +00:00
gstv4l2decoder.c v4l2codecs: Avoid QBUF/DQBUF struct timeval .tv_usec wrap-around at frame 1000000 2023-11-04 15:51:45 +01:00
gstv4l2decoder.h v4l2codecs: Trace request by it FD 2022-03-25 21:40:28 +00:00
gstv4l2format.c v4l2codecs: Fix tiled formats stride conversion 2023-10-11 14:13:53 +00:00
gstv4l2format.h v4l2codecs: Enable Mediatek 10bit 4:2:0 support 2023-08-08 16:08:16 +00:00
meson.build v4l2codecs: Add AV1 decoder 2023-06-16 01:30:40 +00:00
plugin.c v4l2codecs: Add AV1 decoder 2023-06-16 01:30:40 +00:00