dxtory: Factorize the buffer loading
[libav.git] / libavcodec / dxtory.c
index 23a3c6f..dd0d512 100644 (file)
@@ -192,6 +192,56 @@ static inline uint8_t decode_sym(GetBitContext *gb, uint8_t lru[8])
     return val;
 }
 
+static int check_slice_size(AVCodecContext *avctx,
+                            const uint8_t *src, int src_size,
+                            int slice_size, int off)
+{
+    int cur_slice_size;
+
+    if (slice_size > src_size - off) {
+        av_log(avctx, AV_LOG_ERROR,
+               "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
+               slice_size, src_size - off);
+        return AVERROR_INVALIDDATA;
+    }
+    if (slice_size <= 16) {
+        av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n",
+               slice_size);
+        return AVERROR_INVALIDDATA;
+    }
+
+    cur_slice_size = AV_RL32(src + off);
+    if (cur_slice_size != slice_size - 16) {
+        av_log(avctx, AV_LOG_ERROR,
+               "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
+               cur_slice_size, slice_size - 16);
+    }
+
+    return 0;
+}
+
+static int load_buffer(AVCodecContext *avctx,
+                       const uint8_t *src, int src_size,
+                       GetByteContext *gb,
+                       int *nslices, int *off)
+{
+    bytestream2_init(gb, src, src_size);
+    *nslices = bytestream2_get_le16(gb);
+    *off = FFALIGN(*nslices * 4 + 2, 16);
+    if (src_size < *off) {
+        av_log(avctx, AV_LOG_ERROR, "no slice data\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (!*nslices || avctx->height % *nslices) {
+        avpriv_request_sample(avctx, "%d slices for %dx%d", *nslices,
+                              avctx->width, avctx->height);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    return 0;
+}
+
 static inline uint8_t decode_sym_565(GetBitContext *gb, uint8_t lru[8],
                                      int bits)
 {
@@ -247,19 +297,9 @@ static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic,
     uint8_t *dst;
     int ret;
 
-    bytestream2_init(&gb, src, src_size);
-    nslices = bytestream2_get_le16(&gb);
-    off = FFALIGN(nslices * 4 + 2, 16);
-    if (src_size < off) {
-        av_log(avctx, AV_LOG_ERROR, "no slice data\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (!nslices || avctx->height % nslices) {
-        avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
-                              avctx->width, avctx->height);
-        return AVERROR_PATCHWELCOME;
-    }
+    ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off);
+    if (ret < 0)
+        return ret;
 
     slice_height = avctx->height / nslices;
     avctx->pix_fmt = AV_PIX_FMT_RGB24;
@@ -269,22 +309,11 @@ static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic,
     dst = pic->data[0];
     for (slice = 0; slice < nslices; slice++) {
         slice_size = bytestream2_get_le32(&gb);
-        if (slice_size > src_size - off) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
-                   slice_size, src_size - off);
-            return AVERROR_INVALIDDATA;
-        }
-        if (slice_size <= 16) {
-            av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
-            return AVERROR_INVALIDDATA;
-        }
 
-        if (AV_RL32(src + off) != slice_size - 16) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
-                   AV_RL32(src + off), slice_size - 16);
-        }
+        ret = check_slice_size(avctx, src, src_size, slice_size, off);
+        if (ret < 0)
+            return ret;
+
         init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
         dx2_decode_slice_565(&gb2, avctx->width, slice_height, dst,
                              pic->linesize[0], is_565);
@@ -328,19 +357,9 @@ static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic,
     uint8_t *dst;
     int ret;
 
-    bytestream2_init(&gb, src, src_size);
-    nslices = bytestream2_get_le16(&gb);
-    off = FFALIGN(nslices * 4 + 2, 16);
-    if (src_size < off) {
-        av_log(avctx, AV_LOG_ERROR, "no slice data\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (!nslices || avctx->height % nslices) {
-        avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
-                              avctx->width, avctx->height);
-        return AVERROR_PATCHWELCOME;
-    }
+    ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off);
+    if (ret < 0)
+        return ret;
 
     slice_height = avctx->height / nslices;
     avctx->pix_fmt = AV_PIX_FMT_BGR24;
@@ -350,23 +369,11 @@ static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic,
     dst = pic->data[0];
     for (slice = 0; slice < nslices; slice++) {
         slice_size = bytestream2_get_le32(&gb);
-        if (slice_size > src_size - off) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
-                   slice_size, src_size - off);
-            return AVERROR_INVALIDDATA;
-        }
-        if (slice_size <= 16) {
-            av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n",
-                   slice_size);
-            return AVERROR_INVALIDDATA;
-        }
 
-        if (AV_RL32(src + off) != slice_size - 16) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
-                   AV_RL32(src + off), slice_size - 16);
-        }
+        ret = check_slice_size(avctx, src, src_size, slice_size, off);
+        if (ret < 0)
+            return ret;
+
         init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
         dx2_decode_slice_rgb(&gb2, avctx->width, slice_height, dst,
                              pic->linesize[0]);
@@ -416,19 +423,9 @@ static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic,
     uint8_t *Y, *U, *V;
     int ret;
 
-    bytestream2_init(&gb, src, src_size);
-    nslices = bytestream2_get_le16(&gb);
-    off = FFALIGN(nslices * 4 + 2, 16);
-    if (src_size < off) {
-        av_log(avctx, AV_LOG_ERROR, "no slice data\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (!nslices || avctx->height % nslices) {
-        avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
-                              avctx->width, avctx->height);
-        return AVERROR_PATCHWELCOME;
-    }
+    ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off);
+    if (ret < 0)
+        return ret;
 
     ref_slice_height = avctx->height / nslices;
     if ((avctx->width & 3) || (avctx->height & 3)) {
@@ -449,22 +446,11 @@ static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic,
     for (slice = 0; slice < nslices; slice++) {
         slice_size   = bytestream2_get_le32(&gb);
         slice_height = (next_y & ~3) - (cur_y & ~3);
-        if (slice_size > src_size - off) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
-                   slice_size, src_size - off);
-            return AVERROR_INVALIDDATA;
-        }
-        if (slice_size <= 16) {
-            av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
-            return AVERROR_INVALIDDATA;
-        }
 
-        if (AV_RL32(src + off) != slice_size - 16) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
-                   AV_RL32(src + off), slice_size - 16);
-        }
+        ret = check_slice_size(avctx, src, src_size, slice_size, off);
+        if (ret < 0)
+            return ret;
+
         init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
         dx2_decode_slice_410(&gb2, avctx->width, slice_height, Y, U, V,
                              pic->linesize[0], pic->linesize[1],
@@ -520,19 +506,9 @@ static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic,
     uint8_t *Y, *U, *V;
     int ret;
 
-    bytestream2_init(&gb, src, src_size);
-    nslices = bytestream2_get_le16(&gb);
-    off = FFALIGN(nslices * 4 + 2, 16);
-    if (src_size < off) {
-        av_log(avctx, AV_LOG_ERROR, "no slice data\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (!nslices || avctx->height % nslices) {
-        avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
-                              avctx->width, avctx->height);
-        return AVERROR_PATCHWELCOME;
-    }
+    ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off);
+    if (ret < 0)
+        return ret;
 
     ref_slice_height = avctx->height / nslices;
     if ((avctx->width & 1) || (avctx->height & 1)) {
@@ -553,22 +529,11 @@ static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic,
     for (slice = 0; slice < nslices; slice++) {
         slice_size   = bytestream2_get_le32(&gb);
         slice_height = (next_y & ~1) - (cur_y & ~1);
-        if (slice_size > src_size - off) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
-                   slice_size, src_size - off);
-            return AVERROR_INVALIDDATA;
-        }
-        if (slice_size <= 16) {
-            av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
-            return AVERROR_INVALIDDATA;
-        }
 
-        if (AV_RL32(src + off) != slice_size - 16) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
-                   AV_RL32(src + off), slice_size - 16);
-        }
+        ret = check_slice_size(avctx, src, src_size, slice_size, off);
+        if (ret < 0)
+            return ret;
+
         init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
         dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V,
                              pic->linesize[0], pic->linesize[1],
@@ -620,19 +585,9 @@ static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic,
     uint8_t *Y, *U, *V;
     int ret;
 
-    bytestream2_init(&gb, src, src_size);
-    nslices = bytestream2_get_le16(&gb);
-    off = FFALIGN(nslices * 4 + 2, 16);
-    if (src_size < off) {
-        av_log(avctx, AV_LOG_ERROR, "no slice data\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (!nslices || avctx->height % nslices) {
-        avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
-                              avctx->width, avctx->height);
-        return AVERROR_PATCHWELCOME;
-    }
+    ret = load_buffer(avctx, src, src_size, &gb, &nslices, &off);
+    if (ret < 0)
+        return ret;
 
     slice_height = avctx->height / nslices;
 
@@ -646,22 +601,11 @@ static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic,
 
     for (slice = 0; slice < nslices; slice++) {
         slice_size = bytestream2_get_le32(&gb);
-        if (slice_size > src_size - off) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
-                   slice_size, src_size - off);
-            return AVERROR_INVALIDDATA;
-        }
-        if (slice_size <= 16) {
-            av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
-            return AVERROR_INVALIDDATA;
-        }
 
-        if (AV_RL32(src + off) != slice_size - 16) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
-                   AV_RL32(src + off), slice_size - 16);
-        }
+        ret = check_slice_size(avctx, src, src_size, slice_size, off);
+        if (ret < 0)
+            return ret;
+
         init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
         dx2_decode_slice_444(&gb2, avctx->width, slice_height, Y, U, V,
                              pic->linesize[0], pic->linesize[1],