summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2023-12-09 16:26:22 +0100
committerMarek Vasut <marex@denx.de>2023-12-21 20:25:29 +0100
commitcc9aa3f80cf431770504461bf9ff8edbb0cb872f (patch)
tree24fed470c224fe9e91c6c2f1434538d217ecacd7
parentfe15059a0ff5ebb5a30a2143db062b64d01f90a4 (diff)
mpeg2decoder: Fix multiplication wraparound1.20
The GstMpeg2Picture system_frame_number is guint32, constant 1000 is guint32, GstV4l2CodecMpeg2Dec *_ref_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 MPEG2 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/gstv4l2codecmpeg2dec.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c
index e3a31dab53..5d7fb81c38 100644
--- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c
+++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c
@@ -567,8 +567,8 @@ gst_v4l2_codec_mpeg2_dec_start_picture (GstMpeg2Decoder * decoder,
/* *INDENT-OFF* */
self->v4l2_picture = (struct v4l2_ctrl_mpeg2_picture) {
- .backward_ref_ts = next_picture ? next_picture->system_frame_number * 1000 : GST_CLOCK_TIME_NONE,
- .forward_ref_ts = prev_picture ? prev_picture->system_frame_number * 1000 : GST_CLOCK_TIME_NONE,
+ .backward_ref_ts = next_picture ? next_picture->system_frame_number * G_GUINT64_CONSTANT (1000) : GST_CLOCK_TIME_NONE,
+ .forward_ref_ts = prev_picture ? prev_picture->system_frame_number * G_GUINT64_CONSTANT (1000) : GST_CLOCK_TIME_NONE,
.intra_dc_precision = slice->pic_ext ? slice->pic_ext->intra_dc_precision : 0,
.flags = (slice->pic_ext && slice->pic_ext->top_field_first ? V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST : 0) |
(slice->pic_ext && slice->pic_ext->frame_pred_frame_dct ? V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT : 0 ) |