Merge remote-tracking branch 'qatar/master'
[ffmpeg.git] / libavcodec / vqavideo.c
index 0a06a9f..ba70a11 100644 (file)
@@ -2,20 +2,20 @@
  * Westwood Studios VQA Video Decoder
  * Copyright (C) 2003 the ffmpeg project
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -138,6 +138,10 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx)
     /* load up the VQA parameters from the header */
     vqa_header = (unsigned char *)s->avctx->extradata;
     s->vqa_version = vqa_header[0];
+    if (s->vqa_version < 1 || s->vqa_version > 3) {
+        av_log(s->avctx, AV_LOG_ERROR, "  VQA video: unsupported version %d\n", s->vqa_version);
+        return -1;
+    }
     s->width = AV_RL16(&vqa_header[6]);
     s->height = AV_RL16(&vqa_header[8]);
     if(av_image_check_size(s->width, s->height, 0, avctx)){
@@ -185,6 +189,7 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx)
     }
     s->next_codebook_buffer_index = 0;
 
+    avcodec_get_frame_defaults(&s->frame);
     s->frame.data[0] = NULL;
 
     return 0;
@@ -236,6 +241,8 @@ static void decode_format80(const unsigned char *src, int src_size,
             src_index += 2;
             av_dlog(NULL, "(1) copy %X bytes from absolute pos %X\n", count, src_pos);
             CHECK_COUNT();
+            if (src_pos + count > dest_size)
+                return;
             for (i = 0; i < count; i++)
                 dest[dest_index + i] = dest[src_pos + i];
             dest_index += count;
@@ -258,6 +265,8 @@ static void decode_format80(const unsigned char *src, int src_size,
             src_index += 2;
             av_dlog(NULL, "(3) copy %X bytes from absolute pos %X\n", count, src_pos);
             CHECK_COUNT();
+            if (src_pos + count > dest_size)
+                return;
             for (i = 0; i < count; i++)
                 dest[dest_index + i] = dest[src_pos + i];
             dest_index += count;
@@ -278,6 +287,8 @@ static void decode_format80(const unsigned char *src, int src_size,
             src_index += 2;
             av_dlog(NULL, "(5) copy %X bytes from relpos %X\n", count, src_pos);
             CHECK_COUNT();
+            if (dest_index < src_pos)
+                return;
             for (i = 0; i < count; i++)
                 dest[dest_index + i] = dest[dest_index - src_pos + i];
             dest_index += count;
@@ -322,10 +333,17 @@ static void vqa_decode_chunk(VqaContext *s)
     int hibytes = s->decode_buffer_size / 2;
 
     /* first, traverse through the frame and find the subchunks */
-    while (index < s->size) {
+    while (index + CHUNK_PREAMBLE_SIZE <= s->size) {
+        unsigned next_index;
 
         chunk_type = AV_RB32(&s->buf[index]);
         chunk_size = AV_RB32(&s->buf[index + 4]);
+        byte_skip = chunk_size & 0x01;
+        next_index = index + CHUNK_PREAMBLE_SIZE + chunk_size + byte_skip;
+        if (next_index > s->size) {
+            av_log(s->avctx, AV_LOG_ERROR, "Dropping incomplete chunk\n");
+            break;
+        }
 
         switch (chunk_type) {
 
@@ -366,9 +384,7 @@ static void vqa_decode_chunk(VqaContext *s)
             chunk_type);
             break;
         }
-
-        byte_skip = chunk_size & 0x01;
-        index += (CHUNK_PREAMBLE_SIZE + chunk_size + byte_skip);
+        index = next_index;
     }
 
     /* next, deal with the palette */
@@ -402,7 +418,8 @@ static void vqa_decode_chunk(VqaContext *s)
             r = s->buf[cpl0_chunk++] * 4;
             g = s->buf[cpl0_chunk++] * 4;
             b = s->buf[cpl0_chunk++] * 4;
-            s->palette[i] = (r << 16) | (g << 8) | (b);
+            s->palette[i] = 0xFF << 24 | r << 16 | g << 8 | b;
+            s->palette[i] |= s->palette[i] >> 6 & 0x30303;
         }
     }