]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/flicvideo.c
h264: fix cur_chroma_format_idc with slice multithreading.
[ffmpeg] / libavcodec / flicvideo.c
index be1ea50f759410e418821b72bd08b1d961646db3..9111d17d82b85d448adfdd0245d80260b005a650 100644 (file)
@@ -81,6 +81,12 @@ static av_cold int flic_decode_init(AVCodecContext *avctx)
     unsigned char *fli_header = (unsigned char *)avctx->extradata;
     int depth;
 
+    if (avctx->extradata_size != 12 &&
+        avctx->extradata_size != 128) {
+        av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     s->avctx = avctx;
 
     s->fli_type = AV_RL16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */
@@ -90,9 +96,6 @@ static av_cold int flic_decode_init(AVCodecContext *avctx)
         /* special case for magic carpet FLIs */
         s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
         depth = 8;
-    } else if (s->avctx->extradata_size != 128) {
-        av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
-        return -1;
     } else {
         depth = AV_RL16(&fli_header[12]);
     }
@@ -131,7 +134,6 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     FlicDecodeContext *s = avctx->priv_data;
 
     int stream_ptr = 0;
-    int stream_ptr_after_color_chunk;
     int pixel_ptr;
     int palette_ptr;
     unsigned char palette_idx1;
@@ -161,7 +163,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     unsigned char *pixels;
     unsigned int pixel_limit;
 
-    s->frame.reference = 1;
+    s->frame.reference = 3;
     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
@@ -171,7 +173,11 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     pixels = s->frame.data[0];
     pixel_limit = s->avctx->height * s->frame.linesize[0];
 
+    if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + FF_INPUT_BUFFER_PADDING_SIZE))
+        return AVERROR_INVALIDDATA;
     frame_size = AV_RL32(&buf[stream_ptr]);
+    if (frame_size > buf_size)
+        frame_size = buf_size;
     stream_ptr += 6;  /* skip the magic number */
     num_chunks = AV_RL16(&buf[stream_ptr]);
     stream_ptr += 10;  /* skip padding */
@@ -179,13 +185,16 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     frame_size -= 16;
 
     /* iterate through the chunks */
-    while ((frame_size > 0) && (num_chunks > 0)) {
+    while ((frame_size >= 6) && (num_chunks > 0)) {
+        int stream_ptr_after_chunk;
         chunk_size = AV_RL32(&buf[stream_ptr]);
         if (chunk_size > frame_size) {
             av_log(avctx, AV_LOG_WARNING,
                    "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);
             chunk_size = frame_size;
         }
+        stream_ptr_after_chunk = stream_ptr + chunk_size;
+
         stream_ptr += 4;
         chunk_type = AV_RL16(&buf[stream_ptr]);
         stream_ptr += 2;
@@ -193,8 +202,6 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
         switch (chunk_type) {
         case FLI_256_COLOR:
         case FLI_COLOR:
-            stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
-
             /* check special case: If this file is from the Magic Carpet
              * game and uses 6-bit colors even though it reports 256-color
              * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
@@ -218,6 +225,9 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                 if (color_changes == 0)
                     color_changes = 256;
 
+                if (stream_ptr + color_changes * 3 > stream_ptr_after_chunk)
+                    break;
+
                 for (j = 0; j < color_changes; j++) {
                     unsigned int entry;
 
@@ -228,19 +238,14 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     r = buf[stream_ptr++] << color_shift;
                     g = buf[stream_ptr++] << color_shift;
                     b = buf[stream_ptr++] << color_shift;
-                    entry = (r << 16) | (g << 8) | b;
+                    entry = 0xFF << 24 | r << 16 | g << 8 | b;
+                    if (color_shift == 2)
+                        entry |= entry >> 6 & 0x30303;
                     if (s->palette[palette_ptr] != entry)
                         s->new_palette = 1;
                     s->palette[palette_ptr++] = entry;
                 }
             }
-
-            /* color chunks sometimes have weird 16-bit alignment issues;
-             * therefore, take the hardline approach and set the stream_ptr
-             * to the value calculated w.r.t. the size specified by the color
-             * chunk header */
-            stream_ptr = stream_ptr_after_color_chunk;
-
             break;
 
         case FLI_DELTA:
@@ -248,6 +253,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
             compressed_lines = AV_RL16(&buf[stream_ptr]);
             stream_ptr += 2;
             while (compressed_lines > 0) {
+                if (stream_ptr + 2 > stream_ptr_after_chunk)
+                    break;
                 line_packets = AV_RL16(&buf[stream_ptr]);
                 stream_ptr += 2;
                 if ((line_packets & 0xC000) == 0xC000) {
@@ -267,6 +274,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     CHECK_PIXEL_PTR(0);
                     pixel_countdown = s->avctx->width;
                     for (i = 0; i < line_packets; i++) {
+                        if (stream_ptr + 2 > stream_ptr_after_chunk)
+                            break;
                         /* account for the skip bytes */
                         pixel_skip = buf[stream_ptr++];
                         pixel_ptr += pixel_skip;
@@ -283,6 +292,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                             }
                         } else {
                             CHECK_PIXEL_PTR(byte_run * 2);
+                            if (stream_ptr + byte_run * 2 > stream_ptr_after_chunk)
+                                break;
                             for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
                                 palette_idx1 = buf[stream_ptr++];
                                 pixels[pixel_ptr++] = palette_idx1;
@@ -309,6 +320,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                 CHECK_PIXEL_PTR(0);
                 pixel_countdown = s->avctx->width;
                 line_packets = buf[stream_ptr++];
+                if (stream_ptr + 2 * line_packets > stream_ptr_after_chunk)
+                    break;
                 if (line_packets > 0) {
                     for (i = 0; i < line_packets; i++) {
                         /* account for the skip bytes */
@@ -318,6 +331,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                         byte_run = (signed char)(buf[stream_ptr++]);
                         if (byte_run > 0) {
                             CHECK_PIXEL_PTR(byte_run);
+                            if (stream_ptr + byte_run > stream_ptr_after_chunk)
+                                break;
                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
                                 palette_idx1 = buf[stream_ptr++];
                                 pixels[pixel_ptr++] = palette_idx1;
@@ -355,6 +370,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                 stream_ptr++;
                 pixel_countdown = s->avctx->width;
                 while (pixel_countdown > 0) {
+                    if (stream_ptr + 1 > stream_ptr_after_chunk)
+                        break;
                     byte_run = (signed char)(buf[stream_ptr++]);
                     if (byte_run > 0) {
                         palette_idx1 = buf[stream_ptr++];
@@ -369,6 +386,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     } else {  /* copy bytes if byte_run < 0 */
                         byte_run = -byte_run;
                         CHECK_PIXEL_PTR(byte_run);
+                        if (stream_ptr + byte_run > stream_ptr_after_chunk)
+                            break;
                         for (j = 0; j < byte_run; j++) {
                             palette_idx1 = buf[stream_ptr++];
                             pixels[pixel_ptr++] = palette_idx1;
@@ -386,10 +405,9 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
 
         case FLI_COPY:
             /* copy the chunk (uncompressed frame) */
-            if (chunk_size - 6 > s->avctx->width * s->avctx->height) {
+            if (chunk_size - 6 != s->avctx->width * s->avctx->height) {
                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
-                       "bigger than image, skipping chunk\n", chunk_size - 6);
-                stream_ptr += chunk_size - 6;
+                       "has incorrect size, skipping chunk\n", chunk_size - 6);
             } else {
                 for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
                      y_ptr += s->frame.linesize[0]) {
@@ -402,7 +420,6 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
 
         case FLI_MINI:
             /* some sort of a thumbnail? disregard this chunk... */
-            stream_ptr += chunk_size - 6;
             break;
 
         default:
@@ -410,6 +427,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
             break;
         }
 
+        stream_ptr = stream_ptr_after_chunk;
+
         frame_size -= chunk_size;
         num_chunks--;
     }
@@ -464,7 +483,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
     int pixel;
     unsigned int pixel_limit;
 
-    s->frame.reference = 1;
+    s->frame.reference = 3;
     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
     if (avctx->reget_buffer(avctx, &s->frame) < 0) {
         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");