LCOV - code coverage report
Current view: top level - libavcodec - mss1.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 101 109 92.7 %
Date: 2017-12-12 11:08:38 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder
       3             :  * Copyright (c) 2012 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             :  * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder
      25             :  */
      26             : 
      27             : #include "avcodec.h"
      28             : #include "internal.h"
      29             : #include "mss12.h"
      30             : 
      31             : typedef struct MSS1Context {
      32             :     MSS12Context   ctx;
      33             :     AVFrame       *pic;
      34             :     SliceContext   sc;
      35             : } MSS1Context;
      36             : 
      37      290860 : static void arith_normalise(ArithCoder *c)
      38             : {
      39             :     for (;;) {
      40      380756 :         if (c->high >= 0x8000) {
      41      261731 :             if (c->low < 0x8000) {
      42      231213 :                 if (c->low >= 0x4000 && c->high < 0xC000) {
      43       30249 :                     c->value -= 0x4000;
      44       30249 :                     c->low   -= 0x4000;
      45       30249 :                     c->high  -= 0x4000;
      46             :                 } else {
      47      401928 :                     return;
      48             :                 }
      49             :             } else {
      50       30518 :                 c->value -= 0x8000;
      51       30518 :                 c->low   -= 0x8000;
      52       30518 :                 c->high  -= 0x8000;
      53             :             }
      54             :         }
      55       89896 :         c->value <<= 1;
      56       89896 :         c->low   <<= 1;
      57       89896 :         c->high  <<= 1;
      58       89896 :         c->high   |= 1;
      59       89896 :         c->value  |= get_bits1(c->gbc.gb);
      60             :     }
      61             : }
      62             : 
      63          20 : ARITH_GET_BIT(arith)
      64             : 
      65           6 : static int arith_get_bits(ArithCoder *c, int bits)
      66             : {
      67           6 :     int range = c->high - c->low + 1;
      68           6 :     int val   = (((c->value - c->low + 1) << bits) - 1) / range;
      69           6 :     int prob  = range * val;
      70             : 
      71           6 :     c->high   = ((prob + range) >> bits) + c->low - 1;
      72           6 :     c->low   += prob >> bits;
      73             : 
      74           6 :     arith_normalise(c);
      75             : 
      76           6 :     return val;
      77             : }
      78             : 
      79         409 : static int arith_get_number(ArithCoder *c, int mod_val)
      80             : {
      81         409 :     int range = c->high - c->low + 1;
      82         409 :     int val   = ((c->value - c->low + 1) * mod_val - 1) / range;
      83         409 :     int prob  = range * val;
      84             : 
      85         409 :     c->high   = (prob + range) / mod_val + c->low - 1;
      86         409 :     c->low   += prob / mod_val;
      87             : 
      88         409 :     arith_normalise(c);
      89             : 
      90         409 :     return val;
      91             : }
      92             : 
      93      200529 : static int arith_get_prob(ArithCoder *c, int16_t *probs)
      94             : {
      95      200529 :     int range = c->high - c->low + 1;
      96      200529 :     int val   = ((c->value - c->low + 1) * probs[0] - 1) / range;
      97      200529 :     int sym   = 1;
      98             : 
      99      483249 :     while (probs[sym] > val)
     100       82191 :         sym++;
     101             : 
     102      200529 :     c->high = range * probs[sym - 1] / probs[0] + c->low - 1;
     103      200529 :     c->low += range * probs[sym]     / probs[0];
     104             : 
     105      200529 :     return sym;
     106             : }
     107             : 
     108      200529 : ARITH_GET_MODEL_SYM(arith)
     109             : 
     110          20 : static void arith_init(ArithCoder *c, GetBitContext *gb)
     111             : {
     112          20 :     c->low           = 0;
     113          20 :     c->high          = 0xFFFF;
     114          20 :     c->value         = get_bits(gb, 16);
     115          20 :     c->gbc.gb        = gb;
     116          20 :     c->get_model_sym = arith_get_model_sym;
     117          20 :     c->get_number    = arith_get_number;
     118          20 : }
     119             : 
     120           2 : static int decode_pal(MSS12Context *ctx, ArithCoder *acoder)
     121             : {
     122             :     int i, ncol, r, g, b;
     123           2 :     uint32_t *pal = ctx->pal + 256 - ctx->free_colours;
     124             : 
     125           2 :     if (!ctx->free_colours)
     126           0 :         return 0;
     127             : 
     128           2 :     ncol = arith_get_number(acoder, ctx->free_colours + 1);
     129           4 :     for (i = 0; i < ncol; i++) {
     130           2 :         r = arith_get_bits(acoder, 8);
     131           2 :         g = arith_get_bits(acoder, 8);
     132           2 :         b = arith_get_bits(acoder, 8);
     133           2 :         *pal++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
     134             :     }
     135             : 
     136           2 :     return !!ncol;
     137             : }
     138             : 
     139          20 : static int mss1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     140             :                              AVPacket *avpkt)
     141             : {
     142          20 :     MSS1Context *ctx = avctx->priv_data;
     143          20 :     MSS12Context *c = &ctx->ctx;
     144             :     GetBitContext gb;
     145             :     ArithCoder acoder;
     146          20 :     int pal_changed = 0;
     147             :     int ret;
     148             : 
     149          20 :     if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
     150           0 :         return ret;
     151             : 
     152          20 :     arith_init(&acoder, &gb);
     153             : 
     154          20 :     if ((ret = ff_reget_buffer(avctx, ctx->pic)) < 0)
     155           0 :         return ret;
     156             : 
     157          20 :     c->pal_pic    =  ctx->pic->data[0] + ctx->pic->linesize[0] * (avctx->height - 1);
     158          20 :     c->pal_stride = -ctx->pic->linesize[0];
     159          20 :     c->keyframe   = !arith_get_bit(&acoder);
     160          20 :     if (c->keyframe) {
     161           2 :         c->corrupted = 0;
     162           2 :         ff_mss12_slicecontext_reset(&ctx->sc);
     163           2 :         pal_changed        = decode_pal(c, &acoder);
     164           2 :         ctx->pic->key_frame = 1;
     165           2 :         ctx->pic->pict_type = AV_PICTURE_TYPE_I;
     166             :     } else {
     167          18 :         if (c->corrupted)
     168           0 :             return AVERROR_INVALIDDATA;
     169          18 :         ctx->pic->key_frame = 0;
     170          18 :         ctx->pic->pict_type = AV_PICTURE_TYPE_P;
     171             :     }
     172          20 :     c->corrupted = ff_mss12_decode_rect(&ctx->sc, &acoder, 0, 0,
     173             :                                         avctx->width, avctx->height);
     174          20 :     if (c->corrupted)
     175           0 :         return AVERROR_INVALIDDATA;
     176          20 :     memcpy(ctx->pic->data[1], c->pal, AVPALETTE_SIZE);
     177          20 :     ctx->pic->palette_has_changed = pal_changed;
     178             : 
     179          20 :     if ((ret = av_frame_ref(data, ctx->pic)) < 0)
     180           0 :         return ret;
     181             : 
     182          20 :     *got_frame      = 1;
     183             : 
     184             :     /* always report that the buffer was completely consumed */
     185          20 :     return avpkt->size;
     186             : }
     187             : 
     188           2 : static av_cold int mss1_decode_init(AVCodecContext *avctx)
     189             : {
     190           2 :     MSS1Context * const c = avctx->priv_data;
     191             :     int ret;
     192             : 
     193           2 :     c->ctx.avctx       = avctx;
     194             : 
     195           2 :     c->pic = av_frame_alloc();
     196           2 :     if (!c->pic)
     197           0 :         return AVERROR(ENOMEM);
     198             : 
     199           2 :     ret = ff_mss12_decode_init(&c->ctx, 0, &c->sc, NULL);
     200           2 :     if (ret < 0)
     201           0 :         av_frame_free(&c->pic);
     202             : 
     203           2 :     avctx->pix_fmt = AV_PIX_FMT_PAL8;
     204             : 
     205           2 :     return ret;
     206             : }
     207             : 
     208           2 : static av_cold int mss1_decode_end(AVCodecContext *avctx)
     209             : {
     210           2 :     MSS1Context * const ctx = avctx->priv_data;
     211             : 
     212           2 :     av_frame_free(&ctx->pic);
     213           2 :     ff_mss12_decode_end(&ctx->ctx);
     214             : 
     215           2 :     return 0;
     216             : }
     217             : 
     218             : AVCodec ff_mss1_decoder = {
     219             :     .name           = "mss1",
     220             :     .long_name      = NULL_IF_CONFIG_SMALL("MS Screen 1"),
     221             :     .type           = AVMEDIA_TYPE_VIDEO,
     222             :     .id             = AV_CODEC_ID_MSS1,
     223             :     .priv_data_size = sizeof(MSS1Context),
     224             :     .init           = mss1_decode_init,
     225             :     .close          = mss1_decode_end,
     226             :     .decode         = mss1_decode_frame,
     227             :     .capabilities   = AV_CODEC_CAP_DR1,
     228             : };

Generated by: LCOV version 1.13