]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mscc.c
avcodec: Constify AVCodecs
[ffmpeg] / libavcodec / mscc.c
index 6e4dbb014da7e31676e569ed40844cb822b707b6..027eb160853c22abb2bddae2125c1b3f9f9582d0 100644 (file)
@@ -37,10 +37,15 @@ typedef struct MSCCContext {
     unsigned int      uncomp_size;
     uint8_t          *uncomp_buf;
     z_stream          zstream;
+
+    uint32_t          pal[256];
 } MSCCContext;
 
-static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteContext *pb, int bpp)
+static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteContext *pb)
 {
+    MSCCContext *s = avctx->priv_data;
+    unsigned x = 0, y = 0;
+
     while (bytestream2_get_bytes_left(gb) > 0) {
         uint32_t fill;
         int j;
@@ -78,19 +83,22 @@ static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteCont
                     break;
                 }
             }
+            x += run;
         } else {
             unsigned copy = bytestream2_get_byte(gb);
 
-            if (copy == 1) {
+            if (copy == 0) {
+                x = 0;
+                y++;
+                bytestream2_seek_p(pb, y * avctx->width * s->bpp, SEEK_SET);
+            } else if (copy == 1) {
                 return 0;
             } else if (copy == 2) {
-                unsigned x, y;
 
-                x = bytestream2_get_byte(gb);
-                y = bytestream2_get_byte(gb);
+                x += bytestream2_get_byte(gb);
+                y += bytestream2_get_byte(gb);
 
-                bytestream2_skip_p(pb, x * bpp);
-                bytestream2_skip_p(pb, y * bpp * avctx->width);
+                bytestream2_seek_p(pb, y * avctx->width * s->bpp + x * s->bpp, SEEK_SET);
             } else {
                 for (j = 0; j < copy; j++) {
                     switch (avctx->bits_per_coded_sample) {
@@ -108,6 +116,10 @@ static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteCont
                         break;
                     }
                 }
+
+                if (s->bpp == 1 && (copy & 1))
+                    bytestream2_skip(gb, 1);
+                x += copy;
             }
         }
     }
@@ -128,7 +140,8 @@ static int decode_frame(AVCodecContext *avctx,
     int ret, j;
 
     if (avpkt->size < 3)
-        return AVERROR_INVALIDDATA;
+        return buf_size;
+
     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
 
@@ -138,6 +151,21 @@ static int decode_frame(AVCodecContext *avctx,
         buf_size -= 2;
     }
 
+    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
+        size_t size;
+        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size);
+
+        if (pal && size == AVPALETTE_SIZE) {
+            frame->palette_has_changed = 1;
+            for (j = 0; j < 256; j++)
+                s->pal[j] = 0xFF000000 | AV_RL32(pal + j * 4);
+        } else if (pal) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Palette size %"SIZE_SPECIFIER" is wrong\n", size);
+        }
+        memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
+    }
+
     ret = inflateReset(&s->zstream);
     if (ret != Z_OK) {
         av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
@@ -156,7 +184,7 @@ static int decode_frame(AVCodecContext *avctx,
     bytestream2_init(&gb, s->decomp_buf, s->zstream.total_out);
     bytestream2_init_writer(&pb, s->uncomp_buf, s->uncomp_size);
 
-    ret = rle_uncompress(avctx, &gb, &pb, s->bpp);
+    ret = rle_uncompress(avctx, &gb, &pb);
     if (ret)
         return ret;
 
@@ -176,10 +204,10 @@ static int decode_frame(AVCodecContext *avctx,
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     MSCCContext *s = avctx->priv_data;
-    int zret;
+    int stride, zret;
 
     switch (avctx->bits_per_coded_sample) {
-    case  8: avctx->pix_fmt = AV_PIX_FMT_GRAY8;  break;
+    case  8: avctx->pix_fmt = AV_PIX_FMT_PAL8;   break;
     case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
     case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24;  break;
     case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA;   break;
@@ -189,13 +217,13 @@ static av_cold int decode_init(AVCodecContext *avctx)
     }
 
     s->bpp = avctx->bits_per_coded_sample >> 3;
-    memset(&s->zstream, 0, sizeof(z_stream));
+    stride = 4 * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
 
-    s->decomp_size = 4 * avctx->height * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
+    s->decomp_size = 2 * avctx->height * stride;
     if (!(s->decomp_buf = av_malloc(s->decomp_size)))
         return AVERROR(ENOMEM);
 
-    s->uncomp_size = 4 * avctx->height * ((avctx->width * avctx->bits_per_coded_sample + 31) / 32);
+    s->uncomp_size = avctx->height * stride;
     if (!(s->uncomp_buf = av_malloc(s->uncomp_size)))
         return AVERROR(ENOMEM);
 
@@ -224,7 +252,7 @@ static av_cold int decode_close(AVCodecContext *avctx)
     return 0;
 }
 
-AVCodec ff_mscc_decoder = {
+const AVCodec ff_mscc_decoder = {
     .name             = "mscc",
     .long_name        = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"),
     .type             = AVMEDIA_TYPE_VIDEO,
@@ -234,9 +262,10 @@ AVCodec ff_mscc_decoder = {
     .close            = decode_close,
     .decode           = decode_frame,
     .capabilities     = AV_CODEC_CAP_DR1,
+    .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP,
 };
 
-AVCodec ff_srgc_decoder = {
+const AVCodec ff_srgc_decoder = {
     .name             = "srgc",
     .long_name        = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"),
     .type             = AVMEDIA_TYPE_VIDEO,
@@ -246,4 +275,5 @@ AVCodec ff_srgc_decoder = {
     .close            = decode_close,
     .decode           = decode_frame,
     .capabilities     = AV_CODEC_CAP_DR1,
+    .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP,
 };