vp9: add mxext versions of the single-block (w=4,npx=8) h/v loopfilters.
[ffmpeg.git] / libavcodec / flicvideo.c
index 79695da..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,23 +133,25 @@ 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");
-                  return -1;
+        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 -1;
+                  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;
 }
 
 static int flic_decode_frame_8BPP(AVCodecContext *avctx,
-                                  void *data, int *data_size,
+                                  void *data, int *got_frame,
                                   const uint8_t *buf, int buf_size)
 {
     FlicDecodeContext *s = avctx->priv_data;
@@ -165,7 +168,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     unsigned int chunk_size;
     int chunk_type;
 
-    int i, j;
+    int i, j, ret;
 
     int color_packets;
     int color_changes;
@@ -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 (avctx->reget_buffer(avctx, &s->frame) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
-        return -1;
-    }
+    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) {
@@ -256,7 +256,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     r = bytestream2_get_byte(&g2) << color_shift;
                     g = bytestream2_get_byte(&g2) << color_shift;
                     b = bytestream2_get_byte(&g2) << color_shift;
-                    entry = 0xFF << 24 | r << 16 | g << 8 | b;
+                    entry = 0xFFU << 24 | r << 16 | g << 8 | b;
                     if (color_shift == 2)
                         entry |= entry >> 6 & 0x30303;
                     if (s->palette[palette_ptr] != entry)
@@ -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,20 +462,22 @@ 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;
     }
 
-    *data_size=sizeof(AVFrame);
-    *(AVFrame*)data = s->frame;
+    if ((ret = av_frame_ref(data, s->frame)) < 0)
+        return ret;
+
+    *got_frame = 1;
 
     return buf_size;
 }
 
 static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
-                                      void *data, int *data_size,
+                                      void *data, int *got_frame,
                                       const uint8_t *buf, int buf_size)
 {
     /* Note, the only difference between the 15Bpp and 16Bpp */
@@ -485,7 +494,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
     unsigned int chunk_size;
     int chunk_type;
 
-    int i, j;
+    int i, j, ret;
 
     int lines;
     int compressed_lines;
@@ -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 (avctx->reget_buffer(avctx, &s->frame) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
-        return -1;
-    }
+    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:
@@ -644,7 +650,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                 }
 
                 /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
-                 * This does not give us any good oportunity to perform word endian conversion
+                 * This does not give us any good opportunity to perform word endian conversion
                  * during decompression. So if it is required (i.e., this is not a LE target, we do
                  * a second pass over the line here, swapping the bytes.
                  */
@@ -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,47 +755,48 @@ 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;
 
-    *data_size=sizeof(AVFrame);
-    *(AVFrame*)data = s->frame;
+    *got_frame = 1;
 
     return buf_size;
 }
 
 static int flic_decode_frame_24BPP(AVCodecContext *avctx,
-                                   void *data, int *data_size,
+                                   void *data, int *got_frame,
                                    const uint8_t *buf, int buf_size)
 {
   av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
-  return -1;
+  return AVERROR_PATCHWELCOME;
 }
 
 static int flic_decode_frame(AVCodecContext *avctx,
-                             void *data, int *data_size,
+                             void *data, int *got_frame,
                              AVPacket *avpkt)
 {
     const uint8_t *buf = avpkt->data;
     int buf_size = avpkt->size;
     if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-      return flic_decode_frame_8BPP(avctx, data, data_size,
+      return flic_decode_frame_8BPP(avctx, data, got_frame,
                                     buf, buf_size);
     }
     else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) ||
              (avctx->pix_fmt == AV_PIX_FMT_RGB565)) {
-      return flic_decode_frame_15_16BPP(avctx, data, data_size,
+      return flic_decode_frame_15_16BPP(avctx, data, got_frame,
                                         buf, buf_size);
     }
     else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) {
-      return flic_decode_frame_24BPP(avctx, data, data_size,
+      return flic_decode_frame_24BPP(avctx, data, got_frame,
                                      buf, buf_size);
     }
 
     /* 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 -1;
+    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,
 };