LCOV - code coverage report
Current view: top level - libavcodec - kmvc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 130 219 59.4 %
Date: 2017-12-16 13:57:32 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * KMVC decoder
       3             :  * Copyright (c) 2006 Konstantin Shishkov
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * Karl Morton's Video Codec decoder
      25             :  */
      26             : 
      27             : #include <stdio.h>
      28             : #include <stdlib.h>
      29             : 
      30             : #include "avcodec.h"
      31             : #include "bytestream.h"
      32             : #include "internal.h"
      33             : #include "libavutil/common.h"
      34             : 
      35             : #define KMVC_KEYFRAME 0x80
      36             : #define KMVC_PALETTE  0x40
      37             : #define KMVC_METHOD   0x0F
      38             : #define MAX_PALSIZE   256
      39             : 
      40             : /*
      41             :  * Decoder context
      42             :  */
      43             : typedef struct KmvcContext {
      44             :     AVCodecContext *avctx;
      45             : 
      46             :     int setpal;
      47             :     int palsize;
      48             :     uint32_t pal[MAX_PALSIZE];
      49             :     uint8_t *cur, *prev;
      50             :     uint8_t frm0[320 * 200], frm1[320 * 200];
      51             :     GetByteContext g;
      52             : } KmvcContext;
      53             : 
      54             : typedef struct BitBuf {
      55             :     int bits;
      56             :     int bitbuf;
      57             : } BitBuf;
      58             : 
      59             : #define BLK(data, x, y)  data[av_clip((x) + (y) * 320, 0, 320 * 200 -1)]
      60             : 
      61             : #define kmvc_init_getbits(bb, g)  bb.bits = 7; bb.bitbuf = bytestream2_get_byte(g);
      62             : 
      63             : #define kmvc_getbit(bb, g, res) {\
      64             :     res = 0; \
      65             :     if (bb.bitbuf & (1 << bb.bits)) res = 1; \
      66             :     bb.bits--; \
      67             :     if(bb.bits == -1) { \
      68             :         bb.bitbuf = bytestream2_get_byte(g); \
      69             :         bb.bits = 7; \
      70             :     } \
      71             : }
      72             : 
      73           1 : static int kmvc_decode_intra_8x8(KmvcContext * ctx, int w, int h)
      74             : {
      75             :     BitBuf bb;
      76             :     int res, val;
      77             :     int i, j;
      78             :     int bx, by;
      79             :     int l0x, l1x, l0y, l1y;
      80             :     int mx, my;
      81             : 
      82           1 :     kmvc_init_getbits(bb, &ctx->g);
      83             : 
      84          21 :     for (by = 0; by < h; by += 8)
      85         820 :         for (bx = 0; bx < w; bx += 8) {
      86         800 :             if (!bytestream2_get_bytes_left(&ctx->g)) {
      87           0 :                 av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n");
      88           0 :                 return AVERROR_INVALIDDATA;
      89             :             }
      90         800 :             kmvc_getbit(bb, &ctx->g, res);
      91         800 :             if (!res) {         // fill whole 8x8 block
      92         800 :                 val = bytestream2_get_byte(&ctx->g);
      93       52000 :                 for (i = 0; i < 64; i++)
      94       51200 :                     BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val;
      95             :             } else {            // handle four 4x4 subblocks
      96           0 :                 for (i = 0; i < 4; i++) {
      97           0 :                     l0x = bx + (i & 1) * 4;
      98           0 :                     l0y = by + (i & 2) * 2;
      99           0 :                     kmvc_getbit(bb, &ctx->g, res);
     100           0 :                     if (!res) {
     101           0 :                         kmvc_getbit(bb, &ctx->g, res);
     102           0 :                         if (!res) {     // fill whole 4x4 block
     103           0 :                             val = bytestream2_get_byte(&ctx->g);
     104           0 :                             for (j = 0; j < 16; j++)
     105           0 :                                 BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val;
     106             :                         } else {        // copy block from already decoded place
     107           0 :                             val = bytestream2_get_byte(&ctx->g);
     108           0 :                             mx = val & 0xF;
     109           0 :                             my = val >> 4;
     110           0 :                             if ((l0x-mx) + 320*(l0y-my) < 0 || (l0x-mx) + 320*(l0y-my) > 320*197 - 4) {
     111           0 :                                 av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n");
     112           0 :                                 return AVERROR_INVALIDDATA;
     113             :                             }
     114           0 :                             for (j = 0; j < 16; j++)
     115           0 :                                 BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) =
     116           0 :                                     BLK(ctx->cur, l0x + (j & 3) - mx, l0y + (j >> 2) - my);
     117             :                         }
     118             :                     } else {    // descend to 2x2 sub-sub-blocks
     119           0 :                         for (j = 0; j < 4; j++) {
     120           0 :                             l1x = l0x + (j & 1) * 2;
     121           0 :                             l1y = l0y + (j & 2);
     122           0 :                             kmvc_getbit(bb, &ctx->g, res);
     123           0 :                             if (!res) {
     124           0 :                                 kmvc_getbit(bb, &ctx->g, res);
     125           0 :                                 if (!res) {     // fill whole 2x2 block
     126           0 :                                     val = bytestream2_get_byte(&ctx->g);
     127           0 :                                     BLK(ctx->cur, l1x, l1y) = val;
     128           0 :                                     BLK(ctx->cur, l1x + 1, l1y) = val;
     129           0 :                                     BLK(ctx->cur, l1x, l1y + 1) = val;
     130           0 :                                     BLK(ctx->cur, l1x + 1, l1y + 1) = val;
     131             :                                 } else {        // copy block from already decoded place
     132           0 :                                     val = bytestream2_get_byte(&ctx->g);
     133           0 :                                     mx = val & 0xF;
     134           0 :                                     my = val >> 4;
     135           0 :                                     if ((l1x-mx) + 320*(l1y-my) < 0 || (l1x-mx) + 320*(l1y-my) > 320*199 - 2) {
     136           0 :                                         av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n");
     137           0 :                                         return AVERROR_INVALIDDATA;
     138             :                                     }
     139           0 :                                     BLK(ctx->cur, l1x, l1y) = BLK(ctx->cur, l1x - mx, l1y - my);
     140           0 :                                     BLK(ctx->cur, l1x + 1, l1y) =
     141           0 :                                         BLK(ctx->cur, l1x + 1 - mx, l1y - my);
     142           0 :                                     BLK(ctx->cur, l1x, l1y + 1) =
     143           0 :                                         BLK(ctx->cur, l1x - mx, l1y + 1 - my);
     144           0 :                                     BLK(ctx->cur, l1x + 1, l1y + 1) =
     145           0 :                                         BLK(ctx->cur, l1x + 1 - mx, l1y + 1 - my);
     146             :                                 }
     147             :                             } else {    // read values for block
     148           0 :                                 BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g);
     149           0 :                                 BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g);
     150           0 :                                 BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g);
     151           0 :                                 BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g);
     152             :                             }
     153             :                         }
     154             :                     }
     155             :                 }
     156             :             }
     157             :         }
     158             : 
     159           1 :     return 0;
     160             : }
     161             : 
     162          75 : static int kmvc_decode_inter_8x8(KmvcContext * ctx, int w, int h)
     163             : {
     164             :     BitBuf bb;
     165             :     int res, val;
     166             :     int i, j;
     167             :     int bx, by;
     168             :     int l0x, l1x, l0y, l1y;
     169             :     int mx, my;
     170             : 
     171          75 :     kmvc_init_getbits(bb, &ctx->g);
     172             : 
     173        1575 :     for (by = 0; by < h; by += 8)
     174       61500 :         for (bx = 0; bx < w; bx += 8) {
     175       60000 :             kmvc_getbit(bb, &ctx->g, res);
     176       60000 :             if (!res) {
     177       40230 :                 kmvc_getbit(bb, &ctx->g, res);
     178       40230 :                 if (!res) {     // fill whole 8x8 block
     179       39003 :                     if (!bytestream2_get_bytes_left(&ctx->g)) {
     180           0 :                         av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n");
     181           0 :                         return AVERROR_INVALIDDATA;
     182             :                     }
     183       39003 :                     val = bytestream2_get_byte(&ctx->g);
     184     2535195 :                     for (i = 0; i < 64; i++)
     185     2496192 :                         BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val;
     186             :                 } else {        // copy block from previous frame
     187       79755 :                     for (i = 0; i < 64; i++)
     188      157056 :                         BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) =
     189      157056 :                             BLK(ctx->prev, bx + (i & 0x7), by + (i >> 3));
     190             :                 }
     191             :             } else {            // handle four 4x4 subblocks
     192       19770 :                 if (!bytestream2_get_bytes_left(&ctx->g)) {
     193           0 :                     av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n");
     194           0 :                     return AVERROR_INVALIDDATA;
     195             :                 }
     196       98850 :                 for (i = 0; i < 4; i++) {
     197       79080 :                     l0x = bx + (i & 1) * 4;
     198       79080 :                     l0y = by + (i & 2) * 2;
     199       79080 :                     kmvc_getbit(bb, &ctx->g, res);
     200       79080 :                     if (!res) {
     201       15620 :                         kmvc_getbit(bb, &ctx->g, res);
     202       15620 :                         if (!res) {     // fill whole 4x4 block
     203        6017 :                             val = bytestream2_get_byte(&ctx->g);
     204      102289 :                             for (j = 0; j < 16; j++)
     205       96272 :                                 BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val;
     206             :                         } else {        // copy block
     207        9603 :                             val = bytestream2_get_byte(&ctx->g);
     208        9603 :                             mx = (val & 0xF) - 8;
     209        9603 :                             my = (val >> 4) - 8;
     210        9603 :                             if ((l0x+mx) + 320*(l0y+my) < 0 || (l0x+mx) + 320*(l0y+my) > 320*197 - 4) {
     211           0 :                                 av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n");
     212           0 :                                 return AVERROR_INVALIDDATA;
     213             :                             }
     214      163251 :                             for (j = 0; j < 16; j++)
     215      307296 :                                 BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) =
     216      307296 :                                     BLK(ctx->prev, l0x + (j & 3) + mx, l0y + (j >> 2) + my);
     217             :                         }
     218             :                     } else {    // descend to 2x2 sub-sub-blocks
     219      317300 :                         for (j = 0; j < 4; j++) {
     220      253840 :                             l1x = l0x + (j & 1) * 2;
     221      253840 :                             l1y = l0y + (j & 2);
     222      253840 :                             kmvc_getbit(bb, &ctx->g, res);
     223      253840 :                             if (!res) {
     224      126609 :                                 kmvc_getbit(bb, &ctx->g, res);
     225      126609 :                                 if (!res) {     // fill whole 2x2 block
     226       21343 :                                     val = bytestream2_get_byte(&ctx->g);
     227       21343 :                                     BLK(ctx->cur, l1x, l1y) = val;
     228       21343 :                                     BLK(ctx->cur, l1x + 1, l1y) = val;
     229       21343 :                                     BLK(ctx->cur, l1x, l1y + 1) = val;
     230       21343 :                                     BLK(ctx->cur, l1x + 1, l1y + 1) = val;
     231             :                                 } else {        // copy block
     232      105266 :                                     val = bytestream2_get_byte(&ctx->g);
     233      105266 :                                     mx = (val & 0xF) - 8;
     234      105266 :                                     my = (val >> 4) - 8;
     235      105266 :                                     if ((l1x+mx) + 320*(l1y+my) < 0 || (l1x+mx) + 320*(l1y+my) > 320*199 - 2) {
     236           0 :                                         av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n");
     237           0 :                                         return AVERROR_INVALIDDATA;
     238             :                                     }
     239      105266 :                                     BLK(ctx->cur, l1x, l1y) = BLK(ctx->prev, l1x + mx, l1y + my);
     240      210532 :                                     BLK(ctx->cur, l1x + 1, l1y) =
     241      210532 :                                         BLK(ctx->prev, l1x + 1 + mx, l1y + my);
     242      210532 :                                     BLK(ctx->cur, l1x, l1y + 1) =
     243      210532 :                                         BLK(ctx->prev, l1x + mx, l1y + 1 + my);
     244      210532 :                                     BLK(ctx->cur, l1x + 1, l1y + 1) =
     245      210532 :                                         BLK(ctx->prev, l1x + 1 + mx, l1y + 1 + my);
     246             :                                 }
     247             :                             } else {    // read values for block
     248      127231 :                                 BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g);
     249      127231 :                                 BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g);
     250      127231 :                                 BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g);
     251      127231 :                                 BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g);
     252             :                             }
     253             :                         }
     254             :                     }
     255             :                 }
     256             :             }
     257             :         }
     258             : 
     259          75 :     return 0;
     260             : }
     261             : 
     262          76 : static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame,
     263             :                         AVPacket *avpkt)
     264             : {
     265          76 :     KmvcContext *const ctx = avctx->priv_data;
     266          76 :     AVFrame *frame = data;
     267             :     uint8_t *out, *src;
     268             :     int i, ret;
     269             :     int header;
     270             :     int blocksize;
     271             :     int pal_size;
     272          76 :     const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size);
     273             : 
     274          76 :     bytestream2_init(&ctx->g, avpkt->data, avpkt->size);
     275             : 
     276          76 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
     277           0 :         return ret;
     278             : 
     279          76 :     header = bytestream2_get_byte(&ctx->g);
     280             : 
     281             :     /* blocksize 127 is really palette change event */
     282          76 :     if (bytestream2_peek_byte(&ctx->g) == 127) {
     283           0 :         bytestream2_skip(&ctx->g, 3);
     284           0 :         for (i = 0; i < 127; i++) {
     285           0 :             ctx->pal[i + (header & 0x81)] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g);
     286           0 :             bytestream2_skip(&ctx->g, 1);
     287             :         }
     288           0 :         bytestream2_seek(&ctx->g, -127 * 4 - 3, SEEK_CUR);
     289             :     }
     290             : 
     291          76 :     if (header & KMVC_KEYFRAME) {
     292           1 :         frame->key_frame = 1;
     293           1 :         frame->pict_type = AV_PICTURE_TYPE_I;
     294             :     } else {
     295          75 :         frame->key_frame = 0;
     296          75 :         frame->pict_type = AV_PICTURE_TYPE_P;
     297             :     }
     298             : 
     299          76 :     if (header & KMVC_PALETTE) {
     300           1 :         frame->palette_has_changed = 1;
     301             :         // palette starts from index 1 and has 127 entries
     302         256 :         for (i = 1; i <= ctx->palsize; i++) {
     303         255 :             ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g);
     304             :         }
     305             :     }
     306             : 
     307          76 :     if (pal && pal_size == AVPALETTE_SIZE) {
     308           0 :         frame->palette_has_changed = 1;
     309           0 :         memcpy(ctx->pal, pal, AVPALETTE_SIZE);
     310          76 :     } else if (pal) {
     311           0 :         av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size);
     312             :     }
     313             : 
     314          76 :     if (ctx->setpal) {
     315           0 :         ctx->setpal = 0;
     316           0 :         frame->palette_has_changed = 1;
     317             :     }
     318             : 
     319             :     /* make the palette available on the way out */
     320          76 :     memcpy(frame->data[1], ctx->pal, 1024);
     321             : 
     322          76 :     blocksize = bytestream2_get_byte(&ctx->g);
     323             : 
     324          76 :     if (blocksize != 8 && blocksize != 127) {
     325           0 :         av_log(avctx, AV_LOG_ERROR, "Block size = %i\n", blocksize);
     326           0 :         return AVERROR_INVALIDDATA;
     327             :     }
     328          76 :     memset(ctx->cur, 0, 320 * 200);
     329          76 :     switch (header & KMVC_METHOD) {
     330           0 :     case 0:
     331             :     case 1: // used in palette changed event
     332           0 :         memcpy(ctx->cur, ctx->prev, 320 * 200);
     333           0 :         break;
     334           1 :     case 3:
     335           1 :         kmvc_decode_intra_8x8(ctx, avctx->width, avctx->height);
     336           1 :         break;
     337          75 :     case 4:
     338          75 :         kmvc_decode_inter_8x8(ctx, avctx->width, avctx->height);
     339          75 :         break;
     340           0 :     default:
     341           0 :         av_log(avctx, AV_LOG_ERROR, "Unknown compression method %i\n", header & KMVC_METHOD);
     342           0 :         return AVERROR_INVALIDDATA;
     343             :     }
     344             : 
     345          76 :     out = frame->data[0];
     346          76 :     src = ctx->cur;
     347       12236 :     for (i = 0; i < avctx->height; i++) {
     348       12160 :         memcpy(out, src, avctx->width);
     349       12160 :         src += 320;
     350       12160 :         out += frame->linesize[0];
     351             :     }
     352             : 
     353             :     /* flip buffers */
     354          76 :     if (ctx->cur == ctx->frm0) {
     355          38 :         ctx->cur = ctx->frm1;
     356          38 :         ctx->prev = ctx->frm0;
     357             :     } else {
     358          38 :         ctx->cur = ctx->frm0;
     359          38 :         ctx->prev = ctx->frm1;
     360             :     }
     361             : 
     362          76 :     *got_frame = 1;
     363             : 
     364             :     /* always report that the buffer was completely consumed */
     365          76 :     return avpkt->size;
     366             : }
     367             : 
     368             : 
     369             : 
     370             : /*
     371             :  * Init kmvc decoder
     372             :  */
     373           2 : static av_cold int decode_init(AVCodecContext * avctx)
     374             : {
     375           2 :     KmvcContext *const c = avctx->priv_data;
     376             :     int i;
     377             : 
     378           2 :     c->avctx = avctx;
     379             : 
     380           2 :     if (avctx->width > 320 || avctx->height > 200) {
     381           0 :         av_log(avctx, AV_LOG_ERROR, "KMVC supports frames <= 320x200\n");
     382           0 :         return AVERROR(EINVAL);
     383             :     }
     384             : 
     385           2 :     c->cur = c->frm0;
     386           2 :     c->prev = c->frm1;
     387             : 
     388         514 :     for (i = 0; i < 256; i++) {
     389         512 :         c->pal[i] = 0xFFU << 24 | i * 0x10101;
     390             :     }
     391             : 
     392           2 :     if (avctx->extradata_size < 12) {
     393           0 :         av_log(avctx, AV_LOG_WARNING,
     394             :                "Extradata missing, decoding may not work properly...\n");
     395           0 :         c->palsize = 127;
     396             :     } else {
     397           2 :         c->palsize = AV_RL16(avctx->extradata + 10);
     398           2 :         if (c->palsize >= (unsigned)MAX_PALSIZE) {
     399           0 :             c->palsize = 127;
     400           0 :             av_log(avctx, AV_LOG_ERROR, "KMVC palette too large\n");
     401           0 :             return AVERROR_INVALIDDATA;
     402             :         }
     403             :     }
     404             : 
     405           2 :     if (avctx->extradata_size == 1036) {        // palette in extradata
     406           0 :         uint8_t *src = avctx->extradata + 12;
     407           0 :         for (i = 0; i < 256; i++) {
     408           0 :             c->pal[i] = AV_RL32(src);
     409           0 :             src += 4;
     410             :         }
     411           0 :         c->setpal = 1;
     412             :     }
     413             : 
     414           2 :     avctx->pix_fmt = AV_PIX_FMT_PAL8;
     415             : 
     416           2 :     return 0;
     417             : }
     418             : 
     419             : AVCodec ff_kmvc_decoder = {
     420             :     .name           = "kmvc",
     421             :     .long_name      = NULL_IF_CONFIG_SMALL("Karl Morton's video codec"),
     422             :     .type           = AVMEDIA_TYPE_VIDEO,
     423             :     .id             = AV_CODEC_ID_KMVC,
     424             :     .priv_data_size = sizeof(KmvcContext),
     425             :     .init           = decode_init,
     426             :     .decode         = decode_frame,
     427             :     .capabilities   = AV_CODEC_CAP_DR1,
     428             : };

Generated by: LCOV version 1.13