vp9: add mxext versions of the single-block (w=4,npx=8) h/v loopfilters.
[ffmpeg.git] / libavcodec / flicvideo.c
index eb70249..c9c6c24 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * FLI/FLC Animation Video Decoder
- * Copyright (C) 2003, 2004 the ffmpeg project
+ * Copyright (C) 2003, 2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -42,6 +42,7 @@
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
 #include "bytestream.h"
+#include "internal.h"
 #include "mathops.h"
 
 #define FLI_256_COLOR 4
@@ -70,7 +71,7 @@
 
 typedef struct FlicDecodeContext {
     AVCodecContext *avctx;
-    AVFrame frame;
+    AVFrame *frame;
 
     unsigned int palette[256];
     int new_palette;
@@ -132,16 +133,18 @@ static av_cold int flic_decode_init(AVCodecContext *avctx)
         case 8  : avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
         case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
         case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break;
-        case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */
-                  av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n");
+        case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; /* Supposedly BGR, but no files to test with */
+                  avpriv_request_sample(avctx, "24Bpp FLC/FLX");
                   return AVERROR_PATCHWELCOME;
         default :
                   av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
                   return AVERROR_INVALIDDATA;
     }
 
-    avcodec_get_frame_defaults(&s->frame);
-    s->frame.data[0] = NULL;
+    s->frame = av_frame_alloc();
+    if (!s->frame)
+        return AVERROR(ENOMEM);
+
     s->new_palette = 0;
 
     return 0;
@@ -185,16 +188,12 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
 
     bytestream2_init(&g2, buf, buf_size);
 
-    s->frame.reference = 3;
-    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-    if ((ret = avctx->reget_buffer(avctx, &s->frame)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
         return ret;
-    }
 
-    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))
+    pixels = s->frame->data[0];
+    pixel_limit = s->avctx->height * s->frame->linesize[0];
+    if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + AV_INPUT_BUFFER_PADDING_SIZE))
         return AVERROR_INVALIDDATA;
     frame_size = bytestream2_get_le32(&g2);
     if (frame_size > buf_size)
@@ -206,7 +205,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     frame_size -= 16;
 
     /* iterate through the chunks */
-    while ((frame_size >= 6) && (num_chunks > 0)) {
+    while ((frame_size >= 6) && (num_chunks > 0) &&
+            bytestream2_get_bytes_left(&g2) >= 4) {
         int stream_ptr_after_chunk;
         chunk_size = bytestream2_get_le32(&g2);
         if (chunk_size > frame_size) {
@@ -276,12 +276,12 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                 if ((line_packets & 0xC000) == 0xC000) {
                     // line skip opcode
                     line_packets = -line_packets;
-                    y_ptr += line_packets * s->frame.linesize[0];
+                    y_ptr += line_packets * s->frame->linesize[0];
                 } else if ((line_packets & 0xC000) == 0x4000) {
                     av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
                 } else if ((line_packets & 0xC000) == 0x8000) {
                     // "last byte" opcode
-                    pixel_ptr= y_ptr + s->frame.linesize[0] - 1;
+                    pixel_ptr= y_ptr + s->frame->linesize[0] - 1;
                     CHECK_PIXEL_PTR(0);
                     pixels[pixel_ptr] = line_packets & 0xff;
                 } else {
@@ -316,7 +316,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                         }
                     }
 
-                    y_ptr += s->frame.linesize[0];
+                    y_ptr += s->frame->linesize[0];
                 }
             }
             break;
@@ -325,7 +325,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
             /* line compressed */
             starting_line = bytestream2_get_le16(&g2);
             y_ptr = 0;
-            y_ptr += starting_line * s->frame.linesize[0];
+            y_ptr += starting_line * s->frame->linesize[0];
 
             compressed_lines = bytestream2_get_le16(&g2);
             while (compressed_lines > 0) {
@@ -362,7 +362,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     }
                 }
 
-                y_ptr += s->frame.linesize[0];
+                y_ptr += s->frame->linesize[0];
                 compressed_lines--;
             }
             break;
@@ -370,7 +370,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
         case FLI_BLACK:
             /* set the whole frame to color 0 (which is usually black) */
             memset(pixels, 0,
-                s->frame.linesize[0] * s->avctx->height);
+                s->frame->linesize[0] * s->avctx->height);
             break;
 
         case FLI_BRUN:
@@ -387,6 +387,11 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk)
                         break;
                     byte_run = sign_extend(bytestream2_get_byte(&g2), 8);
+                    if (!byte_run) {
+                        av_log(avctx, AV_LOG_ERROR, "Invalid byte run value.\n");
+                        return AVERROR_INVALIDDATA;
+                    }
+
                     if (byte_run > 0) {
                         palette_idx1 = bytestream2_get_byte(&g2);
                         CHECK_PIXEL_PTR(byte_run);
@@ -412,21 +417,23 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     }
                 }
 
-                y_ptr += s->frame.linesize[0];
+                y_ptr += s->frame->linesize[0];
             }
             break;
 
         case FLI_COPY:
             /* copy the chunk (uncompressed frame) */
-            if (chunk_size - 6 != s->avctx->width * s->avctx->height) {
+            if (chunk_size - 6 != FFALIGN(s->avctx->width, 4) * s->avctx->height) {
                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
                        "has incorrect size, skipping chunk\n", chunk_size - 6);
                 bytestream2_skip(&g2, chunk_size - 6);
             } else {
-                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
-                     y_ptr += s->frame.linesize[0]) {
+                for (y_ptr = 0; y_ptr < s->frame->linesize[0] * s->avctx->height;
+                     y_ptr += s->frame->linesize[0]) {
                     bytestream2_get_buffer(&g2, &pixels[y_ptr],
                                            s->avctx->width);
+                    if (s->avctx->width & 3)
+                        bytestream2_skip(&g2, 4 - (s->avctx->width & 3));
                 }
             }
             break;
@@ -455,14 +462,16 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                buf_size - bytestream2_get_bytes_left(&g2));
 
     /* make the palette available on the way out */
-    memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
+    memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
     if (s->new_palette) {
-        s->frame.palette_has_changed = 1;
+        s->frame->palette_has_changed = 1;
         s->new_palette = 0;
     }
 
+    if ((ret = av_frame_ref(data, s->frame)) < 0)
+        return ret;
+
     *got_frame = 1;
-    *(AVFrame*)data = s->frame;
 
     return buf_size;
 }
@@ -500,15 +509,11 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
 
     bytestream2_init(&g2, buf, buf_size);
 
-    s->frame.reference = 3;
-    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-    if ((ret = avctx->reget_buffer(avctx, &s->frame)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
         return ret;
-    }
 
-    pixels = s->frame.data[0];
-    pixel_limit = s->avctx->height * s->frame.linesize[0];
+    pixels = s->frame->data[0];
+    pixel_limit = s->avctx->height * s->frame->linesize[0];
 
     frame_size = bytestream2_get_le32(&g2);
     bytestream2_skip(&g2, 2);  /* skip the magic number */
@@ -520,7 +525,8 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
     frame_size -= 16;
 
     /* iterate through the chunks */
-    while ((frame_size > 0) && (num_chunks > 0)) {
+    while ((frame_size > 0) && (num_chunks > 0) &&
+            bytestream2_get_bytes_left(&g2) >= 4) {
         int stream_ptr_after_chunk;
         chunk_size = bytestream2_get_le32(&g2);
         if (chunk_size > frame_size) {
@@ -539,7 +545,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
             /* For some reason, it seems that non-palettized flics do
              * include one of these chunks in their first frame.
              * Why I do not know, it seems rather extraneous. */
-            av_dlog(avctx,
+            ff_dlog(avctx,
                     "Unexpected Palette chunk %d in non-palettized FLC\n",
                     chunk_type);
             bytestream2_skip(&g2, chunk_size - 6);
@@ -555,7 +561,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                 line_packets = bytestream2_get_le16(&g2);
                 if (line_packets < 0) {
                     line_packets = -line_packets;
-                    y_ptr += line_packets * s->frame.linesize[0];
+                    y_ptr += line_packets * s->frame->linesize[0];
                 } else {
                     compressed_lines--;
                     pixel_ptr = y_ptr;
@@ -588,20 +594,20 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                         }
                     }
 
-                    y_ptr += s->frame.linesize[0];
+                    y_ptr += s->frame->linesize[0];
                 }
             }
             break;
 
         case FLI_LC:
-            av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n");
+            av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-palettized FLC\n");
             bytestream2_skip(&g2, chunk_size - 6);
             break;
 
         case FLI_BLACK:
             /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */
             memset(pixels, 0x0000,
-                   s->frame.linesize[0] * s->avctx->height);
+                   s->frame->linesize[0] * s->avctx->height);
             break;
 
         case FLI_BRUN:
@@ -656,7 +662,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                     pixel_ptr += 2;
                 }
 #endif
-                y_ptr += s->frame.linesize[0];
+                y_ptr += s->frame->linesize[0];
             }
             break;
 
@@ -700,21 +706,21 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                     }
                 }
 
-                y_ptr += s->frame.linesize[0];
+                y_ptr += s->frame->linesize[0];
             }
             break;
 
         case FLI_COPY:
         case FLI_DTA_COPY:
             /* copy the chunk (uncompressed frame) */
-            if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
+            if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*2) {
                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
                        "bigger than image, skipping chunk\n", chunk_size - 6);
                 bytestream2_skip(&g2, chunk_size - 6);
             } else {
 
-                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
-                     y_ptr += s->frame.linesize[0]) {
+                for (y_ptr = 0; y_ptr < s->frame->linesize[0] * s->avctx->height;
+                     y_ptr += s->frame->linesize[0]) {
 
                     pixel_countdown = s->avctx->width;
                     pixel_ptr = 0;
@@ -723,6 +729,8 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                       pixel_ptr += 2;
                       pixel_countdown--;
                     }
+                    if (s->avctx->width & 1)
+                        bytestream2_skip(&g2, 2);
                 }
             }
             break;
@@ -747,9 +755,10 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
         av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
                "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2));
 
+    if ((ret = av_frame_ref(data, s->frame)) < 0)
+        return ret;
 
     *got_frame = 1;
-    *(AVFrame*)data = s->frame;
 
     return buf_size;
 }
@@ -784,10 +793,10 @@ static int flic_decode_frame(AVCodecContext *avctx,
 
     /* Should not get  here, ever as the pix_fmt is processed */
     /* in flic_decode_init and the above if should deal with */
-    /* the finite set of possibilites allowable by here. */
+    /* the finite set of possibilities allowable by here. */
     /* But in case we do, just error out. */
     av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
-    return AVERROR_INVALIDDATA;
+    return AVERROR_BUG;
 }
 
 
@@ -795,20 +804,19 @@ static av_cold int flic_decode_end(AVCodecContext *avctx)
 {
     FlicDecodeContext *s = avctx->priv_data;
 
-    if (s->frame.data[0])
-        avctx->release_buffer(avctx, &s->frame);
+    av_frame_free(&s->frame);
 
     return 0;
 }
 
 AVCodec ff_flic_decoder = {
     .name           = "flic",
+    .long_name      = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_FLIC,
     .priv_data_size = sizeof(FlicDecodeContext),
     .init           = flic_decode_init,
     .close          = flic_decode_end,
     .decode         = flic_decode_frame,
-    .capabilities   = CODEC_CAP_DR1,
-    .long_name      = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
+    .capabilities   = AV_CODEC_CAP_DR1,
 };