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 31typedef struct MSS1Context { 32 MSS12Context ctx; 33 AVFrame *pic; 34 SliceContext sc; 35} MSS1Context; 36 37static 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 63ARITH_GET_BIT(arith) 64 65static 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 79static 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 93static 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 108ARITH_GET_MODEL_SYM(arith) 109 110static 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 120static 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 139static int mss1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, 140 AVPacket *avpkt) 141{ 142 MSS1Context *ctx = avctx->priv_data; 143 MSS12Context *c = &ctx->ctx; 144 GetBitContext gb; 145 ArithCoder acoder; 146 int pal_changed = 0; 147 int ret; 148 149 if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0) 150 return ret; 151 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 avpkt->size; 186} 187 188static 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 c->pic = av_frame_alloc(); 196 if (!c->pic) 197 return AVERROR(ENOMEM); 198 199 ret = ff_mss12_decode_init(&c->ctx, 0, &c->sc, NULL); 200 201 avctx->pix_fmt = AV_PIX_FMT_PAL8; 202 203 return ret; 204} 205 206static av_cold int mss1_decode_end(AVCodecContext *avctx) 207{ 208 MSS1Context * const ctx = avctx->priv_data; 209 210 av_frame_free(&ctx->pic); 211 ff_mss12_decode_end(&ctx->ctx); 212 213 return 0; 214} 215 216AVCodec ff_mss1_decoder = { 217 .name = "mss1", 218 .long_name = NULL_IF_CONFIG_SMALL("MS Screen 1"), 219 .type = AVMEDIA_TYPE_VIDEO, 220 .id = AV_CODEC_ID_MSS1, 221 .priv_data_size = sizeof(MSS1Context), 222 .init = mss1_decode_init, 223 .close = mss1_decode_end, 224 .decode = mss1_decode_frame, 225 .capabilities = CODEC_CAP_DR1, 226}; 227