]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/flicvideo.c
Add MxPEG decoder
[ffmpeg] / libavcodec / flicvideo.c
index 46aa3fc030ac66242575ff0843d6880dcd1817f7..7d2fd87647e5c099d144ca6bda157014878a86b8 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 /**
- * @file flic.c
+ * @file
  * Autodesk Animator FLI/FLC Video Decoder
  * by Mike Melanson (melanson@pcisys.net)
  * for more information on the .fli/.flc file format and all of its many
@@ -38,9 +38,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 
-#include "libavutil/bswap.h"
+#include "libavutil/intreadwrite.h"
 #include "avcodec.h"
 
 #define FLI_256_COLOR 4
@@ -62,9 +61,9 @@
 
 #define CHECK_PIXEL_PTR(n) \
     if (pixel_ptr + n > pixel_limit) { \
-        av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \
+        av_log (s->avctx, AV_LOG_ERROR, "Invalid pixel_ptr = %d > pixel_limit = %d\n", \
         pixel_ptr + n, pixel_limit); \
-        return -1; \
+        return AVERROR_INVALIDDATA; \
     } \
 
 typedef struct FlicDecodeContext {
@@ -160,7 +159,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     int pixel_skip;
     int pixel_countdown;
     unsigned char *pixels;
-    int pixel_limit;
+    unsigned int pixel_limit;
 
     s->frame.reference = 1;
     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
@@ -182,6 +181,11 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
     /* iterate through the chunks */
     while ((frame_size > 0) && (num_chunks > 0)) {
         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 += 4;
         chunk_type = AV_RL16(&buf[stream_ptr]);
         stream_ptr += 2;
@@ -254,10 +258,13 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                     av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
                 } else if ((line_packets & 0xC000) == 0x8000) {
                     // "last byte" opcode
-                    pixels[y_ptr + s->frame.linesize[0] - 1] = line_packets & 0xff;
+                    pixel_ptr= y_ptr + s->frame.linesize[0] - 1;
+                    CHECK_PIXEL_PTR(0);
+                    pixels[pixel_ptr] = line_packets & 0xff;
                 } else {
                     compressed_lines--;
                     pixel_ptr = y_ptr;
+                    CHECK_PIXEL_PTR(0);
                     pixel_countdown = s->avctx->width;
                     for (i = 0; i < line_packets; i++) {
                         /* account for the skip bytes */
@@ -269,7 +276,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                             byte_run = -byte_run;
                             palette_idx1 = buf[stream_ptr++];
                             palette_idx2 = buf[stream_ptr++];
-                            CHECK_PIXEL_PTR(byte_run);
+                            CHECK_PIXEL_PTR(byte_run * 2);
                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
                                 pixels[pixel_ptr++] = palette_idx1;
                                 pixels[pixel_ptr++] = palette_idx2;
@@ -299,6 +306,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
             stream_ptr += 2;
             while (compressed_lines > 0) {
                 pixel_ptr = y_ptr;
+                CHECK_PIXEL_PTR(0);
                 pixel_countdown = s->avctx->width;
                 line_packets = buf[stream_ptr++];
                 if (line_packets > 0) {
@@ -454,7 +462,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
     int pixel_countdown;
     unsigned char *pixels;
     int pixel;
-    int pixel_limit;
+    unsigned int pixel_limit;
 
     s->frame.reference = 1;
     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
@@ -504,6 +512,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                 } else {
                     compressed_lines--;
                     pixel_ptr = y_ptr;
+                    CHECK_PIXEL_PTR(0);
                     pixel_countdown = s->avctx->width;
                     for (i = 0; i < line_packets; i++) {
                         /* account for the skip bytes */
@@ -515,13 +524,13 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                             byte_run = -byte_run;
                             pixel    = AV_RL16(&buf[stream_ptr]);
                             stream_ptr += 2;
-                            CHECK_PIXEL_PTR(byte_run);
+                            CHECK_PIXEL_PTR(2 * byte_run);
                             for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
                                 *((signed short*)(&pixels[pixel_ptr])) = pixel;
                                 pixel_ptr += 2;
                             }
                         } else {
-                            CHECK_PIXEL_PTR(byte_run);
+                            CHECK_PIXEL_PTR(2 * byte_run);
                             for (j = 0; j < byte_run; j++, pixel_countdown--) {
                                 *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]);
                                 stream_ptr += 2;
@@ -586,7 +595,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                  * 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.
                  */
-#ifdef WORDS_BIGENDIAN
+#if HAVE_BIGENDIAN
                 pixel_ptr = y_ptr;
                 pixel_countdown = s->avctx->width;
                 while (pixel_countdown > 0) {
@@ -612,7 +621,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                     if (byte_run > 0) {
                         pixel    = AV_RL16(&buf[stream_ptr]);
                         stream_ptr += 2;
-                        CHECK_PIXEL_PTR(byte_run);
+                        CHECK_PIXEL_PTR(2 * byte_run);
                         for (j = 0; j < byte_run; j++) {
                             *((signed short*)(&pixels[pixel_ptr])) = pixel;
                             pixel_ptr += 2;
@@ -623,7 +632,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                         }
                     } else {  /* copy pixels if byte_run < 0 */
                         byte_run = -byte_run;
-                        CHECK_PIXEL_PTR(byte_run);
+                        CHECK_PIXEL_PTR(2 * byte_run);
                         for (j = 0; j < byte_run; j++) {
                             *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]);
                             stream_ptr += 2;
@@ -701,8 +710,10 @@ static int flic_decode_frame_24BPP(AVCodecContext *avctx,
 
 static int flic_decode_frame(AVCodecContext *avctx,
                              void *data, int *data_size,
-                             const uint8_t *buf, int buf_size)
+                             AVPacket *avpkt)
 {
+    const uint8_t *buf = avpkt->data;
+    int buf_size = avpkt->size;
     if (avctx->pix_fmt == PIX_FMT_PAL8) {
       return flic_decode_frame_8BPP(avctx, data, data_size,
                                     buf, buf_size);
@@ -736,9 +747,9 @@ static av_cold int flic_decode_end(AVCodecContext *avctx)
     return 0;
 }
 
-AVCodec flic_decoder = {
+AVCodec ff_flic_decoder = {
     "flic",
-    CODEC_TYPE_VIDEO,
+    AVMEDIA_TYPE_VIDEO,
     CODEC_ID_FLIC,
     sizeof(FlicDecodeContext),
     flic_decode_init,
@@ -750,5 +761,5 @@ AVCodec flic_decoder = {
     NULL,
     NULL,
     NULL,
-    .long_name = "Autodesk Animator Flic video",
+    .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
 };