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