100l: sometime palette was not copied to output frame
[libav.git] / libavcodec / msrle.c
index f0564a9..ce5c4c0 100644 (file)
@@ -26,7 +26,7 @@
  * The MS RLE decoder outputs PAL8 colorspace data.
  *
  * Note that this decoder expects the palette colors from the end of the
- * BITMAPINFO header passed through extradata.
+ * BITMAPINFO header passed through palctrl.
  */
 
 #include <stdio.h>
@@ -46,13 +46,12 @@ typedef struct MsrleContext {
     unsigned char *buf;
     int size;
 
-    unsigned int palette[256];
 } MsrleContext;
 
 #define FETCH_NEXT_STREAM_BYTE() \
     if (stream_ptr >= s->size) \
     { \
-      printf(" MS RLE: stream ptr just went out of bounds (1)\n"); \
+      av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (1)\n"); \
       return; \
     } \
     stream_byte = s->buf[stream_ptr++];
@@ -68,6 +67,13 @@ static void msrle_decode_pal8(MsrleContext *s)
     int row_ptr = (s->avctx->height - 1) * row_dec;
     int frame_size = row_dec * s->avctx->height;
 
+    /* make the palette available */
+    memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
+    if (s->avctx->palctrl->palette_changed) {
+        s->frame.palette_has_changed = 1;
+        s->avctx->palctrl->palette_changed = 0;
+    }
+
     while (row_ptr >= 0) {
         FETCH_NEXT_STREAM_BYTE();
         rle_code = stream_byte;
@@ -91,14 +97,14 @@ static void msrle_decode_pal8(MsrleContext *s)
                 /* copy pixels from encoded stream */
                 if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
                     (row_ptr < 0)) {
-                    printf(" MS RLE: frame ptr just went out of bounds (1)\n");
+                    av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (1)\n");
                     return;
                 }
 
                 rle_code = stream_byte;
                 extra_byte = stream_byte & 0x01;
                 if (stream_ptr + rle_code + extra_byte > s->size) {
-                    printf(" MS RLE: stream ptr just went out of bounds (2)\n");
+                    av_log(s->avctx, AV_LOG_ERROR, " MS RLE: stream ptr just went out of bounds (2)\n");
                     return;
                 }
 
@@ -116,7 +122,7 @@ static void msrle_decode_pal8(MsrleContext *s)
             /* decode a run of data */
             if ((row_ptr + pixel_ptr + stream_byte > frame_size) ||
                 (row_ptr < 0)) {
-                printf(" MS RLE: frame ptr just went out of bounds (2)\n");
+                av_log(s->avctx, AV_LOG_ERROR, " MS RLE: frame ptr just went out of bounds (2)\n");
                 return;
             }
 
@@ -129,20 +135,15 @@ static void msrle_decode_pal8(MsrleContext *s)
         }
     }
 
-    /* make the palette available */
-    memcpy(s->frame.data[1], s->palette, 256 * 4);
-
     /* one last sanity check on the way out */
     if (stream_ptr < s->size)
-        printf(" MS RLE: ended frame decode with bytes left over (%d < %d)\n",
+        av_log(s->avctx, AV_LOG_ERROR, " MS RLE: ended frame decode with bytes left over (%d < %d)\n",
             stream_ptr, s->size);
 }
 
 static int msrle_decode_init(AVCodecContext *avctx)
 {
     MsrleContext *s = (MsrleContext *)avctx->priv_data;
-    int i, j;
-    unsigned char *palette;
 
     s->avctx = avctx;
 
@@ -150,15 +151,6 @@ static int msrle_decode_init(AVCodecContext *avctx)
     avctx->has_b_frames = 0;
     s->frame.data[0] = s->prev_frame.data[0] = NULL;
 
-    /* convert palette */
-    palette = (unsigned char *)s->avctx->extradata;
-    memset (s->palette, 0, 256 * 4);
-    for (i = 0, j = 0; i < s->avctx->extradata_size / 4; i++, j += 4)
-        s->palette[i] = 
-            (palette[j + 2] << 16) |
-            (palette[j + 1] <<  8) |
-            (palette[j + 0] <<  0);
-
     return 0;
 }
 
@@ -171,11 +163,17 @@ static int msrle_decode_frame(AVCodecContext *avctx,
     s->buf = buf;
     s->size = buf_size;
 
+    s->frame.reference = 1;
     if (avctx->get_buffer(avctx, &s->frame)) {
-        printf ("  MS RLE: get_buffer() failed\n");
+        av_log(avctx, AV_LOG_ERROR, "  MS RLE: get_buffer() failed\n");
         return -1;
     }
 
+    if (s->prev_frame.data[0] && (s->frame.linesize[0] != s->prev_frame.linesize[0]))
+        av_log(avctx, AV_LOG_ERROR, "  MS RLE: Buffer linesize changed: current %u, previous %u.\n"
+                "          Expect wrong image and/or crash!\n",
+                s->frame.linesize[0], s->prev_frame.linesize[0]);
+
     /* grossly inefficient, but...oh well */
     if (s->prev_frame.data[0] != NULL)
        memcpy(s->frame.data[0], s->prev_frame.data[0], 
@@ -183,8 +181,8 @@ static int msrle_decode_frame(AVCodecContext *avctx,
 
     msrle_decode_pal8(s);
 
-    if (s->frame.data[0])
-        avctx->release_buffer(avctx, &s->frame);
+    if (s->prev_frame.data[0])
+        avctx->release_buffer(avctx, &s->prev_frame);
 
     /* shuffle frames */
     s->prev_frame = s->frame;