From 6f74818a0771c22b3551042c5d4efd3148f9dc89 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 9 Dec 2023 16:08:31 +0100 Subject: [PATCH] vp9decoder: Fix multiplication wraparound The GstVp9Picture system_frame_number is guint32, constant 1000 is guint32, GstV4l2CodecVp9Dec v4l2_vp9_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 VP9 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: --- .../gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c index 807b3f8960..fe012adf87 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c @@ -274,19 +274,19 @@ gst_v4l2_codecs_vp9_dec_fill_refs (GstV4l2CodecVp9Dec * self, if (reference_frames && reference_frames->pic_list[h->ref_frame_idx[0]]) { ref_pic = reference_frames->pic_list[h->ref_frame_idx[0]]; self->v4l2_vp9_frame.last_frame_ts = - GST_CODEC_PICTURE_FRAME_NUMBER (ref_pic) * 1000; + GST_CODEC_PICTURE_FRAME_NUMBER (ref_pic) * G_GUINT64_CONSTANT (1000); } if (reference_frames && reference_frames->pic_list[h->ref_frame_idx[1]]) { ref_pic = reference_frames->pic_list[h->ref_frame_idx[1]]; self->v4l2_vp9_frame.golden_frame_ts = - GST_CODEC_PICTURE_FRAME_NUMBER (ref_pic) * 1000; + GST_CODEC_PICTURE_FRAME_NUMBER (ref_pic) * G_GUINT64_CONSTANT (1000); } if (reference_frames && reference_frames->pic_list[h->ref_frame_idx[2]]) { ref_pic = reference_frames->pic_list[h->ref_frame_idx[2]]; self->v4l2_vp9_frame.alt_frame_ts = - GST_CODEC_PICTURE_FRAME_NUMBER (ref_pic) * 1000; + GST_CODEC_PICTURE_FRAME_NUMBER (ref_pic) * G_GUINT64_CONSTANT (1000); } }