[FFmpeg-cvslog] avcodec/interplayvideo: properly decode motion vectors

Paul B Mahol git at videolan.org
Fri Oct 25 19:30:16 EEST 2019


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Fri Oct 25 18:18:59 2019 +0200| [0481a1f6e5b8737c4fbc67794fd3a24cfcf34594] | committer: Paul B Mahol

avcodec/interplayvideo: properly decode motion vectors

Fixes #7945

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=0481a1f6e5b8737c4fbc67794fd3a24cfcf34594
---

 libavcodec/interplayvideo.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c
index b0a4953cb0..274641c3d1 100644
--- a/libavcodec/interplayvideo.c
+++ b/libavcodec/interplayvideo.c
@@ -77,9 +77,14 @@ typedef struct IpvideoContext {
 
 static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y)
 {
+    int width = dst->width;
     int current_offset = s->pixel_ptr - dst->data[0];
-    int motion_offset = current_offset + delta_y * dst->linesize[0]
-                       + delta_x * (1 + s->is_16bpp);
+    int x = (current_offset % dst->linesize[0]) / (1 + s->is_16bpp);
+    int y = current_offset / dst->linesize[0];
+    int dx = delta_x + x - ((delta_x + x >= width) - (delta_x + x < 0)) * width;
+    int dy = delta_y + y + (delta_x + x >= width) - (delta_x + x < 0);
+    int motion_offset = dy * src->linesize[0] + dx * (1 + s->is_16bpp);
+
     if (motion_offset < 0) {
         av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset);
         return AVERROR_INVALIDDATA;
@@ -931,12 +936,12 @@ static void ipvideo_format_06_secondpass(IpvideoContext *s, AVFrame *frame, int1
     int off_x, off_y;
 
     if (opcode < 0) {
-        off_x = ((uint16_t)opcode - 0xC000) % frame->linesize[0];
-        off_y = ((uint16_t)opcode - 0xC000) / frame->linesize[0];
+        off_x = ((uint16_t)opcode - 0xC000) % frame->width;
+        off_y = ((uint16_t)opcode - 0xC000) / frame->width;
         copy_from(s, s->last_frame, frame, off_x, off_y);
     } else if (opcode > 0) {
-        off_x = ((uint16_t)opcode - 0x4000) % frame->linesize[0];
-        off_y = ((uint16_t)opcode - 0x4000) / frame->linesize[0];
+        off_x = ((uint16_t)opcode - 0x4000) % frame->width;
+        off_y = ((uint16_t)opcode - 0x4000) / frame->width;
         copy_from(s, frame, frame, off_x, off_y);
     }
 }
@@ -1001,12 +1006,12 @@ static void ipvideo_format_10_secondpass(IpvideoContext *s, AVFrame *frame, int1
     int off_x, off_y;
 
     if (opcode < 0) {
-        off_x = ((uint16_t)opcode - 0xC000) % s->cur_decode_frame->linesize[0];
-        off_y = ((uint16_t)opcode - 0xC000) / s->cur_decode_frame->linesize[0];
+        off_x = ((uint16_t)opcode - 0xC000) % s->cur_decode_frame->width;
+        off_y = ((uint16_t)opcode - 0xC000) / s->cur_decode_frame->width;
         copy_from(s, s->prev_decode_frame, s->cur_decode_frame, off_x, off_y);
     } else if (opcode > 0) {
-        off_x = ((uint16_t)opcode - 0x4000) % s->cur_decode_frame->linesize[0];
-        off_y = ((uint16_t)opcode - 0x4000) / s->cur_decode_frame->linesize[0];
+        off_x = ((uint16_t)opcode - 0x4000) % s->cur_decode_frame->width;
+        off_y = ((uint16_t)opcode - 0x4000) / s->cur_decode_frame->width;
         copy_from(s, s->cur_decode_frame, s->cur_decode_frame, off_x, off_y);
     }
 }



More information about the ffmpeg-cvslog mailing list