1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2012 Konstantin Shishkov 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "avcodec.h" 28cabdff1aSopenharmony_ci#include "codec_internal.h" 29cabdff1aSopenharmony_ci#include "internal.h" 30cabdff1aSopenharmony_ci#include "mss12.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_citypedef struct MSS1Context { 33cabdff1aSopenharmony_ci MSS12Context ctx; 34cabdff1aSopenharmony_ci AVFrame *pic; 35cabdff1aSopenharmony_ci SliceContext sc; 36cabdff1aSopenharmony_ci} MSS1Context; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_cistatic void arith_normalise(ArithCoder *c) 39cabdff1aSopenharmony_ci{ 40cabdff1aSopenharmony_ci for (;;) { 41cabdff1aSopenharmony_ci if (c->high >= 0x8000) { 42cabdff1aSopenharmony_ci if (c->low < 0x8000) { 43cabdff1aSopenharmony_ci if (c->low >= 0x4000 && c->high < 0xC000) { 44cabdff1aSopenharmony_ci c->value -= 0x4000; 45cabdff1aSopenharmony_ci c->low -= 0x4000; 46cabdff1aSopenharmony_ci c->high -= 0x4000; 47cabdff1aSopenharmony_ci } else { 48cabdff1aSopenharmony_ci return; 49cabdff1aSopenharmony_ci } 50cabdff1aSopenharmony_ci } else { 51cabdff1aSopenharmony_ci c->value -= 0x8000; 52cabdff1aSopenharmony_ci c->low -= 0x8000; 53cabdff1aSopenharmony_ci c->high -= 0x8000; 54cabdff1aSopenharmony_ci } 55cabdff1aSopenharmony_ci } 56cabdff1aSopenharmony_ci c->value <<= 1; 57cabdff1aSopenharmony_ci c->low <<= 1; 58cabdff1aSopenharmony_ci c->high <<= 1; 59cabdff1aSopenharmony_ci c->high |= 1; 60cabdff1aSopenharmony_ci if (get_bits_left(c->gbc.gb) < 1) 61cabdff1aSopenharmony_ci c->overread++; 62cabdff1aSopenharmony_ci c->value |= get_bits1(c->gbc.gb); 63cabdff1aSopenharmony_ci } 64cabdff1aSopenharmony_ci} 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ciARITH_GET_BIT(arith) 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_cistatic int arith_get_bits(ArithCoder *c, int bits) 69cabdff1aSopenharmony_ci{ 70cabdff1aSopenharmony_ci int range = c->high - c->low + 1; 71cabdff1aSopenharmony_ci int val = (((c->value - c->low + 1) << bits) - 1) / range; 72cabdff1aSopenharmony_ci int prob = range * val; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci c->high = ((prob + range) >> bits) + c->low - 1; 75cabdff1aSopenharmony_ci c->low += prob >> bits; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci arith_normalise(c); 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci return val; 80cabdff1aSopenharmony_ci} 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_cistatic int arith_get_number(ArithCoder *c, int mod_val) 83cabdff1aSopenharmony_ci{ 84cabdff1aSopenharmony_ci int range = c->high - c->low + 1; 85cabdff1aSopenharmony_ci int val = ((c->value - c->low + 1) * mod_val - 1) / range; 86cabdff1aSopenharmony_ci int prob = range * val; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci c->high = (prob + range) / mod_val + c->low - 1; 89cabdff1aSopenharmony_ci c->low += prob / mod_val; 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci arith_normalise(c); 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci return val; 94cabdff1aSopenharmony_ci} 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_cistatic int arith_get_prob(ArithCoder *c, int16_t *probs) 97cabdff1aSopenharmony_ci{ 98cabdff1aSopenharmony_ci int range = c->high - c->low + 1; 99cabdff1aSopenharmony_ci int val = ((c->value - c->low + 1) * probs[0] - 1) / range; 100cabdff1aSopenharmony_ci int sym = 1; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci while (probs[sym] > val) 103cabdff1aSopenharmony_ci sym++; 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci c->high = range * probs[sym - 1] / probs[0] + c->low - 1; 106cabdff1aSopenharmony_ci c->low += range * probs[sym] / probs[0]; 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci return sym; 109cabdff1aSopenharmony_ci} 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ciARITH_GET_MODEL_SYM(arith) 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_cistatic void arith_init(ArithCoder *c, GetBitContext *gb) 114cabdff1aSopenharmony_ci{ 115cabdff1aSopenharmony_ci c->low = 0; 116cabdff1aSopenharmony_ci c->high = 0xFFFF; 117cabdff1aSopenharmony_ci c->value = get_bits(gb, 16); 118cabdff1aSopenharmony_ci c->overread = 0; 119cabdff1aSopenharmony_ci c->gbc.gb = gb; 120cabdff1aSopenharmony_ci c->get_model_sym = arith_get_model_sym; 121cabdff1aSopenharmony_ci c->get_number = arith_get_number; 122cabdff1aSopenharmony_ci} 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_cistatic int decode_pal(MSS12Context *ctx, ArithCoder *acoder) 125cabdff1aSopenharmony_ci{ 126cabdff1aSopenharmony_ci int i, ncol, r, g, b; 127cabdff1aSopenharmony_ci uint32_t *pal = ctx->pal + 256 - ctx->free_colours; 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci if (!ctx->free_colours) 130cabdff1aSopenharmony_ci return 0; 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci ncol = arith_get_number(acoder, ctx->free_colours + 1); 133cabdff1aSopenharmony_ci for (i = 0; i < ncol; i++) { 134cabdff1aSopenharmony_ci r = arith_get_bits(acoder, 8); 135cabdff1aSopenharmony_ci g = arith_get_bits(acoder, 8); 136cabdff1aSopenharmony_ci b = arith_get_bits(acoder, 8); 137cabdff1aSopenharmony_ci *pal++ = (0xFFU << 24) | (r << 16) | (g << 8) | b; 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci return !!ncol; 141cabdff1aSopenharmony_ci} 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_cistatic int mss1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, 144cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 145cabdff1aSopenharmony_ci{ 146cabdff1aSopenharmony_ci MSS1Context *ctx = avctx->priv_data; 147cabdff1aSopenharmony_ci MSS12Context *c = &ctx->ctx; 148cabdff1aSopenharmony_ci GetBitContext gb; 149cabdff1aSopenharmony_ci ArithCoder acoder; 150cabdff1aSopenharmony_ci int pal_changed = 0; 151cabdff1aSopenharmony_ci int ret; 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0) 154cabdff1aSopenharmony_ci return ret; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci arith_init(&acoder, &gb); 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci if ((ret = ff_reget_buffer(avctx, ctx->pic, 0)) < 0) 159cabdff1aSopenharmony_ci return ret; 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci c->pal_pic = ctx->pic->data[0] + ctx->pic->linesize[0] * (avctx->height - 1); 162cabdff1aSopenharmony_ci c->pal_stride = -ctx->pic->linesize[0]; 163cabdff1aSopenharmony_ci c->keyframe = !arith_get_bit(&acoder); 164cabdff1aSopenharmony_ci if (c->keyframe) { 165cabdff1aSopenharmony_ci c->corrupted = 0; 166cabdff1aSopenharmony_ci ff_mss12_slicecontext_reset(&ctx->sc); 167cabdff1aSopenharmony_ci pal_changed = decode_pal(c, &acoder); 168cabdff1aSopenharmony_ci ctx->pic->key_frame = 1; 169cabdff1aSopenharmony_ci ctx->pic->pict_type = AV_PICTURE_TYPE_I; 170cabdff1aSopenharmony_ci } else { 171cabdff1aSopenharmony_ci if (c->corrupted) 172cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 173cabdff1aSopenharmony_ci ctx->pic->key_frame = 0; 174cabdff1aSopenharmony_ci ctx->pic->pict_type = AV_PICTURE_TYPE_P; 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci c->corrupted = ff_mss12_decode_rect(&ctx->sc, &acoder, 0, 0, 177cabdff1aSopenharmony_ci avctx->width, avctx->height); 178cabdff1aSopenharmony_ci if (c->corrupted) 179cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 180cabdff1aSopenharmony_ci memcpy(ctx->pic->data[1], c->pal, AVPALETTE_SIZE); 181cabdff1aSopenharmony_ci ctx->pic->palette_has_changed = pal_changed; 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ci if ((ret = av_frame_ref(rframe, ctx->pic)) < 0) 184cabdff1aSopenharmony_ci return ret; 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci *got_frame = 1; 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci /* always report that the buffer was completely consumed */ 189cabdff1aSopenharmony_ci return avpkt->size; 190cabdff1aSopenharmony_ci} 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_cistatic av_cold int mss1_decode_init(AVCodecContext *avctx) 193cabdff1aSopenharmony_ci{ 194cabdff1aSopenharmony_ci MSS1Context * const c = avctx->priv_data; 195cabdff1aSopenharmony_ci int ret; 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci c->ctx.avctx = avctx; 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci c->pic = av_frame_alloc(); 200cabdff1aSopenharmony_ci if (!c->pic) 201cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci ret = ff_mss12_decode_init(&c->ctx, 0, &c->sc, NULL); 204cabdff1aSopenharmony_ci if (ret < 0) 205cabdff1aSopenharmony_ci av_frame_free(&c->pic); 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_PAL8; 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci return ret; 210cabdff1aSopenharmony_ci} 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_cistatic av_cold int mss1_decode_end(AVCodecContext *avctx) 213cabdff1aSopenharmony_ci{ 214cabdff1aSopenharmony_ci MSS1Context * const ctx = avctx->priv_data; 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci av_frame_free(&ctx->pic); 217cabdff1aSopenharmony_ci ff_mss12_decode_end(&ctx->ctx); 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci return 0; 220cabdff1aSopenharmony_ci} 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ciconst FFCodec ff_mss1_decoder = { 223cabdff1aSopenharmony_ci .p.name = "mss1", 224cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("MS Screen 1"), 225cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 226cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_MSS1, 227cabdff1aSopenharmony_ci .priv_data_size = sizeof(MSS1Context), 228cabdff1aSopenharmony_ci .init = mss1_decode_init, 229cabdff1aSopenharmony_ci .close = mss1_decode_end, 230cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(mss1_decode_frame), 231cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 232cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 233cabdff1aSopenharmony_ci}; 234