[FFmpeg-devel,1/2] avcodec/scpr: avoid negative linesize

Submitted by Paul B Mahol on March 12, 2017, 11:40 a.m.

Details

Message ID 20170312114040.25287-1-onemda@gmail.com
State New
Headers show

Commit Message

Paul B Mahol March 12, 2017, 11:40 a.m.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavcodec/scpr.c | 89 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 48 insertions(+), 41 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c
index 465926a..a37e99a 100644
--- a/libavcodec/scpr.c
+++ b/libavcodec/scpr.c
@@ -290,6 +290,14 @@  static int decode_unit(SCPRContext *s, PixelModel *pixel, unsigned step, unsigne
     return 0;
 }
 
+static int vflip(int pos, int h, int linesize)
+{
+    int y = pos / linesize;
+    int x = pos % linesize;
+
+    return (h - y) * linesize + x;
+}
+
 static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
 {
     SCPRContext *s = avctx->priv_data;
@@ -299,6 +307,7 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
     unsigned backstep = linesize - avctx->width;
     const int cxshift = s->cxshift;
     unsigned lx, ly, ptype;
+    const int hy = avctx->height - 1;
 
     reinit_tables(s);
     bytestream2_skip(gb, 2);
@@ -331,7 +340,7 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
         clr = (b << 16) + (g << 8) + r;
         k += run;
         while (run-- > 0) {
-            dst[y * linesize + x] = clr;
+            dst[vflip(y * linesize + x, hy, linesize)] = clr;
             lx = x;
             ly = y;
             x++;
@@ -379,7 +388,7 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
                 if (y >= avctx->height)
                     return AVERROR_INVALIDDATA;
 
-                dst[y * linesize + x] = clr;
+                dst[vflip(y * linesize + x, hy, linesize)] = clr;
                 lx = x;
                 ly = y;
                 x++;
@@ -394,7 +403,7 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
                 if (y >= avctx->height)
                     return AVERROR_INVALIDDATA;
 
-                dst[y * linesize + x] = dst[ly * linesize + lx];
+                dst[vflip(y * linesize + x, hy, linesize)] = dst[vflip(ly * linesize + lx, hy, linesize)];
                 lx = x;
                 ly = y;
                 x++;
@@ -403,15 +412,15 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
                     y++;
                 }
             }
-            clr = dst[ly * linesize + lx];
+            clr = dst[vflip(ly * linesize + lx, hy, linesize)];
             break;
         case 2:
             while (run-- > 0) {
                 if (y < 1 || y >= avctx->height)
                     return AVERROR_INVALIDDATA;
 
-                clr = dst[y * linesize + x + off + 1];
-                dst[y * linesize + x] = clr;
+                clr = dst[vflip(y * linesize + x + off + 1, hy, linesize)];
+                dst[vflip(y * linesize + x, hy, linesize)] = clr;
                 lx = x;
                 ly = y;
                 x++;
@@ -435,17 +444,17 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
                     z = 0;
                 }
 
-                r = odst[(ly * linesize + lx) * 4] +
-                    odst[((y * linesize + x) + off - z) * 4 + 4] -
-                    odst[((y * linesize + x) + off - z) * 4];
-                g = odst[(ly * linesize + lx) * 4 + 1] +
-                    odst[((y * linesize + x) + off - z) * 4 + 5] -
-                    odst[((y * linesize + x) + off - z) * 4 + 1];
-                b = odst[(ly * linesize + lx) * 4 + 2] +
-                    odst[((y * linesize + x) + off - z) * 4 + 6] -
-                    odst[((y * linesize + x) + off - z) * 4 + 2];
+                r = odst[vflip((ly * linesize + lx) * 4, hy, linesize * 4)] +
+                    odst[vflip(((y * linesize + x) + off - z) * 4 + 4, hy, linesize * 4)] -
+                    odst[vflip(((y * linesize + x) + off - z) * 4, hy, linesize * 4)];
+                g = odst[vflip((ly * linesize + lx) * 4 + 1, hy, linesize * 4)] +
+                    odst[vflip(((y * linesize + x) + off - z) * 4 + 5, hy, linesize * 4)] -
+                    odst[vflip(((y * linesize + x) + off - z) * 4 + 1, hy, linesize * 4)];
+                b = odst[vflip((ly * linesize + lx) * 4 + 2, hy, linesize * 4)] +
+                    odst[vflip(((y * linesize + x) + off - z) * 4 + 6, hy, linesize * 4)] -
+                    odst[vflip(((y * linesize + x) + off - z) * 4 + 2, hy, linesize * 4)];
                 clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
-                dst[y * linesize + x] = clr;
+                dst[vflip(y * linesize + x, hy, linesize)] = clr;
                 lx = x;
                 ly = y;
                 x++;
@@ -467,8 +476,8 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
                     z = 0;
                 }
 
-                clr = dst[y * linesize + x + off - z];
-                dst[y * linesize + x] = clr;
+                clr = dst[vflip(y * linesize + x + off - z, hy, linesize)];
+                dst[vflip(y * linesize + x, hy, linesize)] = clr;
                 lx = x;
                 ly = y;
                 x++;
@@ -501,6 +510,7 @@  static int decompress_p(AVCodecContext *avctx,
     int ret, temp, min, max, x, y, cx = 0, cx1 = 0;
     int backstep = linesize - avctx->width;
     const int cxshift = s->cxshift;
+    const int hy = avctx->height - 1;
 
     if (bytestream2_get_byte(gb) == 0)
         return 0;
@@ -567,7 +577,7 @@  static int decompress_p(AVCodecContext *avctx,
 
                 for (i = 0; i < sy2 - sy1 && (by + sy1 + i) < avctx->height && (by + mvy + sy1 + i) < avctx->height; i++) {
                     for (j = 0; j < sx2 - sx1 && (bx + sx1 + j) < avctx->width && (bx + mvx + sx1 + j) < avctx->width; j++) {
-                        dst[(by + i + sy1) * linesize + bx + sx1 + j] = prev[(by + mvy + sy1 + i) * plinesize + bx + sx1 + mvx + j];
+                        dst[vflip((by + i + sy1) * linesize + bx + sx1 + j, hy, linesize)] = prev[vflip((by + mvy + sy1 + i) * plinesize + bx + sx1 + mvx + j, hy, linesize)];
                     }
                 }
             } else {
@@ -607,7 +617,7 @@  static int decompress_p(AVCodecContext *avctx,
                             if (by >= avctx->height)
                                 return AVERROR_INVALIDDATA;
 
-                            dst[by * linesize + bx] = clr;
+                            dst[vflip(by * linesize + bx, hy, linesize)] = clr;
                             bx++;
                             if (bx >= x * 16 + sx2 || bx >= avctx->width) {
                                 bx = x * 16 + sx1;
@@ -628,8 +638,8 @@  static int decompress_p(AVCodecContext *avctx,
                             if (by >= avctx->height)
                                 return AVERROR_INVALIDDATA;
 
-                            clr = dst[by * linesize + bx - 1 - z];
-                            dst[by * linesize + bx] = clr;
+                            clr = dst[vflip(by * linesize + bx - 1 - z, hy, linesize)];
+                            dst[vflip(by * linesize + bx, hy, linesize)] = clr;
                             bx++;
                             if (bx >= x * 16 + sx2 || bx >= avctx->width) {
                                 bx = x * 16 + sx1;
@@ -642,8 +652,8 @@  static int decompress_p(AVCodecContext *avctx,
                             if (by < 1 || by >= avctx->height)
                                 return AVERROR_INVALIDDATA;
 
-                            clr = dst[(by - 1) * linesize + bx];
-                            dst[by * linesize + bx] = clr;
+                            clr = dst[vflip((by - 1) * linesize + bx, hy, linesize)];
+                            dst[vflip(by * linesize + bx, hy, linesize)] = clr;
                             bx++;
                             if (bx >= x * 16 + sx2 || bx >= avctx->width) {
                                 bx = x * 16 + sx1;
@@ -656,8 +666,8 @@  static int decompress_p(AVCodecContext *avctx,
                             if (by >= avctx->height)
                                 return AVERROR_INVALIDDATA;
 
-                            clr = prev[by * plinesize + bx];
-                            dst[by * linesize + bx] = clr;
+                            clr = prev[vflip(by * plinesize + bx, hy, plinesize)];
+                            dst[vflip(by * linesize + bx, hy, linesize)] = clr;
                             bx++;
                             if (bx >= x * 16 + sx2 || bx >= avctx->width) {
                                 bx = x * 16 + sx1;
@@ -678,17 +688,17 @@  static int decompress_p(AVCodecContext *avctx,
                                 z = 0;
                             }
 
-                            r = odst[((by - 1) * linesize + bx) * 4] +
-                                odst[(by * linesize + bx - 1 - z) * 4] -
-                                odst[((by - 1) * linesize + bx - 1 - z) * 4];
-                            g = odst[((by - 1) * linesize + bx) * 4 + 1] +
-                                odst[(by * linesize + bx - 1 - z) * 4 + 1] -
-                                odst[((by - 1) * linesize + bx - 1 - z) * 4 + 1];
-                            b = odst[((by - 1) * linesize + bx) * 4 + 2] +
-                                odst[(by * linesize + bx - 1 - z) * 4 + 2] -
-                                odst[((by - 1) * linesize + bx - 1 - z) * 4 + 2];
+                            r = odst[vflip(((by - 1) * linesize + bx) * 4, hy, linesize * 4)] +
+                                odst[vflip((by * linesize + bx - 1 - z) * 4, hy, linesize * 4)] -
+                                odst[vflip(((by - 1) * linesize + bx - 1 - z) * 4, hy, linesize * 4)];
+                            g = odst[vflip(((by - 1) * linesize + bx) * 4 + 1, hy, linesize * 4)] +
+                                odst[vflip((by * linesize + bx - 1 - z) * 4 + 1, hy, linesize * 4)] -
+                                odst[vflip(((by - 1) * linesize + bx - 1 - z) * 4 + 1, hy, linesize * 4)];
+                            b = odst[vflip(((by - 1) * linesize + bx) * 4 + 2, hy, linesize * 4)] +
+                                odst[vflip((by * linesize + bx - 1 - z) * 4 + 2, hy, linesize * 4)] -
+                                odst[vflip(((by - 1) * linesize + bx - 1 - z) * 4 + 2, hy, linesize * 4)];
                             clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
-                            dst[by * linesize + bx] = clr;
+                            dst[vflip(by * linesize + bx, hy, linesize)] = clr;
                             bx++;
                             if (bx >= x * 16 + sx2 || bx >= avctx->width) {
                                 bx = x * 16 + sx1;
@@ -707,8 +717,8 @@  static int decompress_p(AVCodecContext *avctx,
                                 z = 0;
                             }
 
-                            clr = dst[(by - 1) * linesize + bx - 1 - z];
-                            dst[by * linesize + bx] = clr;
+                            clr = dst[vflip((by - 1) * linesize + bx - 1 - z, hy, linesize)];
+                            dst[vflip(by * linesize + bx, hy, linesize)] = clr;
                             bx++;
                             if (bx >= x * 16 + sx2 || bx >= avctx->width) {
                                 bx = x * 16 + sx1;
@@ -830,9 +840,6 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 
     FFSWAP(AVFrame *, s->current_frame, s->last_frame);
 
-    frame->data[0]     += frame->linesize[0] * (avctx->height - 1);
-    frame->linesize[0] *= -1;
-
     *got_frame = 1;
 
     return avpkt->size;