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