2 * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder
3 * Copyright (c) 2012 Konstantin Shishkov
5 * This file is part of FFmpeg.
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.
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.
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
24 * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder
31 typedef struct MSS1Context
{
37 static void arith_normalise(ArithCoder
*c
)
40 if (c
->high
>= 0x8000) {
41 if (c
->low
< 0x8000) {
42 if (c
->low
>= 0x4000 && c
->high
< 0xC000) {
59 c
->value
|= get_bits1(c
->gbc
.gb
);
65 static int arith_get_bits(ArithCoder
*c
, int bits
)
67 int range
= c
->high
- c
->low
+ 1;
68 int val
= (((c
->value
- c
->low
+ 1) << bits
) - 1) / range
;
69 int prob
= range
* val
;
71 c
->high
= ((prob
+ range
) >> bits
) + c
->low
- 1;
72 c
->low
+= prob
>> bits
;
79 static int arith_get_number(ArithCoder
*c
, int mod_val
)
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
;
85 c
->high
= (prob
+ range
) / mod_val
+ c
->low
- 1;
86 c
->low
+= prob
/ mod_val
;
93 static int arith_get_prob(ArithCoder
*c
, int16_t *probs
)
95 int range
= c
->high
- c
->low
+ 1;
96 int val
= ((c
->value
- c
->low
+ 1) * probs
[0] - 1) / range
;
99 while (probs
[sym
] > val
)
102 c
->high
= range
* probs
[sym
- 1] / probs
[0] + c
->low
- 1;
103 c
->low
+= range
* probs
[sym
] / probs
[0];
108 ARITH_GET_MODEL_SYM(arith
)
110 static void arith_init(ArithCoder
*c
, GetBitContext
*gb
)
114 c
->value
= get_bits(gb
, 16);
116 c
->get_model_sym
= arith_get_model_sym
;
117 c
->get_number
= arith_get_number
;
120 static int decode_pal(MSS12Context
*ctx
, ArithCoder
*acoder
)
122 int i
, ncol
, r
, g
, b
;
123 uint32_t *pal
= ctx
->pal
+ 256 - ctx
->free_colours
;
125 if (!ctx
->free_colours
)
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
;
139 static int mss1_decode_frame(AVCodecContext
*avctx
, void *data
, int *got_frame
,
142 MSS1Context
*ctx
= avctx
->priv_data
;
143 MSS12Context
*c
= &ctx
->ctx
;
149 if ((ret
= init_get_bits8(&gb
, avpkt
->data
, avpkt
->size
)) < 0)
152 arith_init(&acoder
, &gb
);
154 if ((ret
= ff_reget_buffer(avctx
, ctx
->pic
)) < 0)
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
);
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
;
168 return AVERROR_INVALIDDATA
;
169 ctx
->pic
->key_frame
= 0;
170 ctx
->pic
->pict_type
= AV_PICTURE_TYPE_P
;
172 c
->corrupted
= ff_mss12_decode_rect(&ctx
->sc
, &acoder
, 0, 0,
173 avctx
->width
, avctx
->height
);
175 return AVERROR_INVALIDDATA
;
176 memcpy(ctx
->pic
->data
[1], c
->pal
, AVPALETTE_SIZE
);
177 ctx
->pic
->palette_has_changed
= pal_changed
;
179 if ((ret
= av_frame_ref(data
, ctx
->pic
)) < 0)
184 /* always report that the buffer was completely consumed */
188 static av_cold
int mss1_decode_init(AVCodecContext
*avctx
)
190 MSS1Context
* const c
= avctx
->priv_data
;
193 c
->ctx
.avctx
= avctx
;
195 c
->pic
= av_frame_alloc();
197 return AVERROR(ENOMEM
);
199 ret
= ff_mss12_decode_init(&c
->ctx
, 0, &c
->sc
, NULL
);
201 av_frame_free(&c
->pic
);
203 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
208 static av_cold
int mss1_decode_end(AVCodecContext
*avctx
)
210 MSS1Context
* const ctx
= avctx
->priv_data
;
212 av_frame_free(&ctx
->pic
);
213 ff_mss12_decode_end(&ctx
->ctx
);
218 AVCodec ff_mss1_decoder
= {
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
= CODEC_CAP_DR1
,