Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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