summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2023-12-09 16:08:31 +0100
committerMarek Vasut <marex@denx.de>2023-12-21 20:25:29 +0100
commita15b057f9999c875d88b67e06fef05ed473b5aa4 (patch)
tree7759b3632688315132414743fe55c05802292da8
parent93202b174900af2d19cac0843f5d4b91b8be7de2 (diff)
vp8decoder: Fix multiplication wraparound
The GstVp8Picture system_frame_number is guint32, constant 1000 is guint32, GstV4l2CodecVp8Dec v4l2_vp8_frame.*_frame_ts multiplication result is u64 . ``` u64 result = (u32)((u32)system_frame_number * (u32)1000); ``` behaves the same as ``` u64 result = (u32)(((u32)system_frame_number * (u32)1000) & 0xffffffff); ``` so in case `system_frame_number > 4294967295 / 1000`, the `result` will wrap around. Since the `result` is really used as a cookie used to look up V4L2 buffers related to the currently decoded frame, this wraparound leads to visible corruption during VP8 decoding. At 30 FPS this occurs after cca. 40 hours of playback . Fix this by changing the 1000 from u32 to u64, i.e.: ``` u64 result = (u64)((u32)system_frame_number * (u64)1000ULL); ``` this way, the wraparound is prevented and the correct cookie is used. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5851>
-rw-r--r--subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c
index 6d547c565a..95cde48b30 100644
--- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c
+++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c
@@ -432,15 +432,17 @@ gst_v4l2_codec_vp8_dec_fill_references (GstV4l2CodecVp8Dec * self)
if (decoder->last_picture)
self->frame_header.last_frame_ts =
- decoder->last_picture->system_frame_number * 1000;
+ decoder->last_picture->system_frame_number * G_GUINT64_CONSTANT (1000);
if (decoder->golden_ref_picture)
self->frame_header.golden_frame_ts =
- decoder->golden_ref_picture->system_frame_number * 1000;
+ decoder->golden_ref_picture->system_frame_number *
+ G_GUINT64_CONSTANT (1000);
if (decoder->alt_ref_picture)
self->frame_header.alt_frame_ts =
- decoder->alt_ref_picture->system_frame_number * 1000;
+ decoder->alt_ref_picture->system_frame_number *
+ G_GUINT64_CONSTANT (1000);
GST_DEBUG_OBJECT (self, "Passing references: last %u, golden %u, alt %u",
(guint32) self->frame_header.last_frame_ts / 1000,