FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/mss12.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 360 405 88.9%
Functions: 21 21 100.0%
Branches: 218 289 75.4%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2012 Konstantin Shishkov
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * Common functions for Microsoft Screen 1 and 2
24 */
25
26 #include <inttypes.h>
27
28 #include "libavutil/intfloat.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/mem.h"
31 #include "avcodec.h"
32 #include "mss12.h"
33
34 enum SplitMode {
35 SPLIT_VERT = 0,
36 SPLIT_HOR,
37 SPLIT_NONE
38 };
39
40 static const int sec_order_sizes[4] = { 1, 7, 6, 1 };
41
42 enum ContextDirection {
43 TOP_LEFT = 0,
44 TOP,
45 TOP_RIGHT,
46 LEFT
47 };
48
49 3046381 static int model_calc_threshold(Model *m)
50 {
51 int thr;
52
53 3046381 thr = 2 * m->weights[m->num_syms] - 1;
54 3046381 thr = ((thr >> 1) + 4 * m->cum_prob[0]) / thr;
55
56 3046381 return FFMIN(thr, 0x3FFF);
57 }
58
59 1419 static void model_reset(Model *m)
60 {
61 int i;
62
63
2/2
✓ Branch 0 taken 11900 times.
✓ Branch 1 taken 1419 times.
13319 for (i = 0; i <= m->num_syms; i++) {
64 11900 m->weights[i] = 1;
65 11900 m->cum_prob[i] = m->num_syms - i;
66 }
67 1419 m->weights[0] = 0;
68
2/2
✓ Branch 0 taken 10481 times.
✓ Branch 1 taken 1419 times.
11900 for (i = 0; i < m->num_syms; i++)
69 10481 m->idx2sym[i + 1] = i;
70 1419 }
71
72 2580 static av_cold void model_init(Model *m, int num_syms, int thr_weight)
73 {
74 2580 m->num_syms = num_syms;
75 2580 m->thr_weight = thr_weight;
76 2580 m->threshold = num_syms * thr_weight;
77 2580 }
78
79 3320751 static void model_rescale_weights(Model *m)
80 {
81 int i;
82 int cum_prob;
83
84
2/2
✓ Branch 0 taken 3046381 times.
✓ Branch 1 taken 274370 times.
3320751 if (m->thr_weight == THRESH_ADAPTIVE)
85 3046381 m->threshold = model_calc_threshold(m);
86
2/2
✓ Branch 0 taken 30268 times.
✓ Branch 1 taken 3320751 times.
3351019 while (m->cum_prob[0] > m->threshold) {
87 30268 cum_prob = 0;
88
2/2
✓ Branch 0 taken 104542 times.
✓ Branch 1 taken 30268 times.
134810 for (i = m->num_syms; i >= 0; i--) {
89 104542 m->cum_prob[i] = cum_prob;
90 104542 m->weights[i] = (m->weights[i] + 1) >> 1;
91 104542 cum_prob += m->weights[i];
92 }
93 }
94 3320751 }
95
96 3320751 void ff_mss12_model_update(Model *m, int val)
97 {
98 int i;
99
100
2/2
✓ Branch 0 taken 6675 times.
✓ Branch 1 taken 3314076 times.
3320751 if (m->weights[val] == m->weights[val - 1]) {
101
2/2
✓ Branch 0 taken 40616 times.
✓ Branch 1 taken 6675 times.
47291 for (i = val; m->weights[i - 1] == m->weights[val]; i--);
102
1/2
✓ Branch 0 taken 6675 times.
✗ Branch 1 not taken.
6675 if (i != val) {
103 int sym1, sym2;
104
105 6675 sym1 = m->idx2sym[val];
106 6675 sym2 = m->idx2sym[i];
107
108 6675 m->idx2sym[val] = sym2;
109 6675 m->idx2sym[i] = sym1;
110
111 6675 val = i;
112 }
113 }
114 3320751 m->weights[val]++;
115
2/2
✓ Branch 0 taken 3453210 times.
✓ Branch 1 taken 3320751 times.
6773961 for (i = val - 1; i >= 0; i--)
116 3453210 m->cum_prob[i]++;
117 3320751 model_rescale_weights(m);
118 3320751 }
119
120 22 static void pixctx_reset(PixContext *ctx)
121 {
122 int i, j;
123
124
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9 times.
22 if (!ctx->special_initial_cache)
125
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 13 times.
157 for (i = 0; i < ctx->cache_size; i++)
126 144 ctx->cache[i] = i;
127 else {
128 9 ctx->cache[0] = 1;
129 9 ctx->cache[1] = 2;
130 9 ctx->cache[2] = 4;
131 }
132
133 22 model_reset(&ctx->cache_model);
134 22 model_reset(&ctx->full_model);
135
136
2/2
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 22 times.
352 for (i = 0; i < 15; i++)
137
2/2
✓ Branch 0 taken 1320 times.
✓ Branch 1 taken 330 times.
1650 for (j = 0; j < 4; j++)
138 1320 model_reset(&ctx->sec_models[i][j]);
139 22 }
140
141 40 static av_cold void pixctx_init(PixContext *ctx, int cache_size,
142 int full_model_syms, int special_initial_cache)
143 {
144 int i, j, k, idx;
145
146 40 ctx->cache_size = cache_size + 4;
147 40 ctx->num_syms = cache_size;
148 40 ctx->special_initial_cache = special_initial_cache;
149
150 40 model_init(&ctx->cache_model, ctx->num_syms + 1, THRESH_LOW);
151 40 model_init(&ctx->full_model, full_model_syms, THRESH_HIGH);
152
153
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 40 times.
200 for (i = 0, idx = 0; i < 4; i++)
154
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 160 times.
760 for (j = 0; j < sec_order_sizes[i]; j++, idx++)
155
2/2
✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 600 times.
3000 for (k = 0; k < 4; k++)
156
2/2
✓ Branch 0 taken 2240 times.
✓ Branch 1 taken 160 times.
2400 model_init(&ctx->sec_models[idx][k], 2 + i,
157 i ? THRESH_LOW : THRESH_ADAPTIVE);
158 40 }
159
160 28184 static av_always_inline int decode_pixel(ArithCoder *acoder, PixContext *pctx,
161 uint8_t *ngb, int num_ngb, int any_ngb)
162 {
163 int i, val, pix;
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28184 times.
28184 if (acoder->overread > MAX_OVERREAD)
166 return AVERROR_INVALIDDATA;
167 28184 val = acoder->get_model_sym(acoder, &pctx->cache_model);
168
2/2
✓ Branch 0 taken 26641 times.
✓ Branch 1 taken 1543 times.
28184 if (val < pctx->num_syms) {
169
2/2
✓ Branch 0 taken 23987 times.
✓ Branch 1 taken 2654 times.
26641 if (any_ngb) {
170 int idx, j;
171
172 23987 idx = 0;
173
1/2
✓ Branch 0 taken 44946 times.
✗ Branch 1 not taken.
44946 for (i = 0; i < pctx->cache_size; i++) {
174
2/2
✓ Branch 0 taken 56712 times.
✓ Branch 1 taken 34305 times.
91017 for (j = 0; j < num_ngb; j++)
175
2/2
✓ Branch 0 taken 10641 times.
✓ Branch 1 taken 46071 times.
56712 if (pctx->cache[i] == ngb[j])
176 10641 break;
177
2/2
✓ Branch 0 taken 34305 times.
✓ Branch 1 taken 10641 times.
44946 if (j == num_ngb) {
178
2/2
✓ Branch 0 taken 23987 times.
✓ Branch 1 taken 10318 times.
34305 if (idx == val)
179 23987 break;
180 10318 idx++;
181 }
182 }
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23987 times.
23987 val = FFMIN(i, pctx->cache_size - 1);
184 }
185 26641 pix = pctx->cache[val];
186 } else {
187 1543 pix = acoder->get_model_sym(acoder, &pctx->full_model);
188
2/2
✓ Branch 0 taken 16874 times.
✓ Branch 1 taken 1445 times.
18319 for (i = 0; i < pctx->cache_size - 1; i++)
189
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 16776 times.
16874 if (pctx->cache[i] == pix)
190 98 break;
191 1543 val = i;
192 }
193
2/2
✓ Branch 0 taken 14609 times.
✓ Branch 1 taken 13575 times.
28184 if (val) {
194
2/2
✓ Branch 0 taken 39926 times.
✓ Branch 1 taken 14609 times.
54535 for (i = val; i > 0; i--)
195 39926 pctx->cache[i] = pctx->cache[i - 1];
196 14609 pctx->cache[0] = pix;
197 }
198
199 28184 return pix;
200 }
201
202 3281310 static int decode_pixel_in_context(ArithCoder *acoder, PixContext *pctx,
203 uint8_t *src, ptrdiff_t stride, int x, int y,
204 int has_right)
205 {
206 uint8_t neighbours[4];
207 uint8_t ref_pix[4];
208 int nlen;
209 3281310 int layer = 0, sub;
210 int pix;
211 int i, j;
212
213
2/2
✓ Branch 0 taken 49701 times.
✓ Branch 1 taken 3231609 times.
3281310 if (!y) {
214 49701 memset(neighbours, src[-1], 4);
215 } else {
216 3231609 neighbours[TOP] = src[-stride];
217
2/2
✓ Branch 0 taken 27645 times.
✓ Branch 1 taken 3203964 times.
3231609 if (!x) {
218 27645 neighbours[TOP_LEFT] = neighbours[LEFT] = neighbours[TOP];
219 } else {
220 3203964 neighbours[TOP_LEFT] = src[-stride - 1];
221 3203964 neighbours[ LEFT] = src[-1];
222 }
223
2/2
✓ Branch 0 taken 3204017 times.
✓ Branch 1 taken 27592 times.
3231609 if (has_right)
224 3204017 neighbours[TOP_RIGHT] = src[-stride + 1];
225 else
226 27592 neighbours[TOP_RIGHT] = neighbours[TOP];
227 }
228
229 3281310 sub = 0;
230
4/4
✓ Branch 0 taken 3229393 times.
✓ Branch 1 taken 51917 times.
✓ Branch 2 taken 3110971 times.
✓ Branch 3 taken 118422 times.
3281310 if (x >= 2 && src[-2] == neighbours[LEFT])
231 3110971 sub = 1;
232
4/4
✓ Branch 0 taken 3194825 times.
✓ Branch 1 taken 86485 times.
✓ Branch 2 taken 3066878 times.
✓ Branch 3 taken 127947 times.
3281310 if (y >= 2 && src[-2 * stride] == neighbours[TOP])
233 3066878 sub |= 2;
234
235 3281310 nlen = 1;
236 3281310 ref_pix[0] = neighbours[0];
237
2/2
✓ Branch 0 taken 9843930 times.
✓ Branch 1 taken 3281310 times.
13125240 for (i = 1; i < 4; i++) {
238
2/2
✓ Branch 0 taken 9989103 times.
✓ Branch 1 taken 249661 times.
10238764 for (j = 0; j < nlen; j++)
239
2/2
✓ Branch 0 taken 9594269 times.
✓ Branch 1 taken 394834 times.
9989103 if (ref_pix[j] == neighbours[i])
240 9594269 break;
241
2/2
✓ Branch 0 taken 249661 times.
✓ Branch 1 taken 9594269 times.
9843930 if (j == nlen)
242 249661 ref_pix[nlen++] = neighbours[i];
243 }
244
245
4/5
✓ Branch 0 taken 3043674 times.
✓ Branch 1 taken 226680 times.
✓ Branch 2 taken 9887 times.
✓ Branch 3 taken 1069 times.
✗ Branch 4 not taken.
3281310 switch (nlen) {
246 3043674 case 1:
247 3043674 layer = 0;
248 3043674 break;
249 226680 case 2:
250
2/2
✓ Branch 0 taken 120171 times.
✓ Branch 1 taken 106509 times.
226680 if (neighbours[TOP] == neighbours[TOP_LEFT]) {
251
2/2
✓ Branch 0 taken 56286 times.
✓ Branch 1 taken 63885 times.
120171 if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT])
252 56286 layer = 1;
253
2/2
✓ Branch 0 taken 49534 times.
✓ Branch 1 taken 14351 times.
63885 else if (neighbours[LEFT] == neighbours[TOP_LEFT])
254 49534 layer = 2;
255 else
256 14351 layer = 3;
257
2/2
✓ Branch 0 taken 43236 times.
✓ Branch 1 taken 63273 times.
106509 } else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) {
258
2/2
✓ Branch 0 taken 15455 times.
✓ Branch 1 taken 27781 times.
43236 if (neighbours[LEFT] == neighbours[TOP_LEFT])
259 15455 layer = 4;
260 else
261 27781 layer = 5;
262
2/2
✓ Branch 0 taken 40999 times.
✓ Branch 1 taken 22274 times.
63273 } else if (neighbours[LEFT] == neighbours[TOP_LEFT]) {
263 40999 layer = 6;
264 } else {
265 22274 layer = 7;
266 }
267 226680 break;
268 9887 case 3:
269
2/2
✓ Branch 0 taken 694 times.
✓ Branch 1 taken 9193 times.
9887 if (neighbours[TOP] == neighbours[TOP_LEFT])
270 694 layer = 8;
271
2/2
✓ Branch 0 taken 3171 times.
✓ Branch 1 taken 6022 times.
9193 else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT])
272 3171 layer = 9;
273
2/2
✓ Branch 0 taken 1932 times.
✓ Branch 1 taken 4090 times.
6022 else if (neighbours[LEFT] == neighbours[TOP_LEFT])
274 1932 layer = 10;
275
2/2
✓ Branch 0 taken 1280 times.
✓ Branch 1 taken 2810 times.
4090 else if (neighbours[TOP_RIGHT] == neighbours[TOP])
276 1280 layer = 11;
277
2/2
✓ Branch 0 taken 2500 times.
✓ Branch 1 taken 310 times.
2810 else if (neighbours[TOP] == neighbours[LEFT])
278 2500 layer = 12;
279 else
280 310 layer = 13;
281 9887 break;
282 1069 case 4:
283 1069 layer = 14;
284 1069 break;
285 }
286
287 3281310 pix = acoder->get_model_sym(acoder,
288 &pctx->sec_models[layer][sub]);
289
2/2
✓ Branch 0 taken 3255834 times.
✓ Branch 1 taken 25476 times.
3281310 if (pix < nlen)
290 3255834 return ref_pix[pix];
291 else
292 25476 return decode_pixel(acoder, pctx, ref_pix, nlen, 1);
293 }
294
295 606 static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_dst,
296 int x, int y, int width, int height, ptrdiff_t stride,
297 ptrdiff_t rgb_stride, PixContext *pctx,
298 const uint32_t *pal)
299 {
300 int i, j, p;
301
302
2/2
✓ Branch 0 taken 262 times.
✓ Branch 1 taken 344 times.
606 rgb_stride = rgb_dst ? rgb_stride : 0;
303
2/2
✓ Branch 0 taken 262 times.
✓ Branch 1 taken 344 times.
606 rgb_dst = rgb_dst ? rgb_dst + x * 3 + y * rgb_stride : NULL;
304 606 dst += x + y * stride;
305
306
2/2
✓ Branch 0 taken 28145 times.
✓ Branch 1 taken 606 times.
28751 for (j = 0; j < height; j++) {
307
2/2
✓ Branch 0 taken 3281487 times.
✓ Branch 1 taken 28145 times.
3309632 for (i = 0; i < width; i++) {
308
4/4
✓ Branch 0 taken 28145 times.
✓ Branch 1 taken 3253342 times.
✓ Branch 2 taken 606 times.
✓ Branch 3 taken 27539 times.
3281487 if (!i && !j)
309 606 p = decode_pixel(acoder, pctx, NULL, 0, 0);
310 else
311 3280881 p = decode_pixel_in_context(acoder, pctx, dst + i, stride,
312 3280881 i, j, width - i - 1);
313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3281487 times.
3281487 if (p < 0)
314 return p;
315 3281487 dst[i] = p;
316
317
2/2
✓ Branch 0 taken 3093607 times.
✓ Branch 1 taken 187880 times.
3281487 if (rgb_dst)
318 3093607 AV_WB24(rgb_dst + i * 3, pal[p]);
319 }
320 28145 dst += stride;
321
2/2
✓ Branch 0 taken 21585 times.
✓ Branch 1 taken 6560 times.
28145 rgb_dst = FF_PTR_ADD(rgb_dst, rgb_stride);
322 }
323
324 606 return 0;
325 }
326
327 2806 static void copy_rectangles(MSS12Context const *c,
328 int x, int y, int width, int height)
329 {
330 int j;
331
332
2/2
✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 1461 times.
2806 if (c->last_rgb_pic)
333
2/2
✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 1345 times.
2690 for (j = y; j < y + height; j++) {
334 1345 memcpy(c->rgb_pic + j * c->rgb_stride + x * 3,
335 1345 c->last_rgb_pic + j * c->rgb_stride + x * 3,
336 1345 width * 3);
337 1345 memcpy(c->pal_pic + j * c->pal_stride + x,
338 1345 c->last_pal_pic + j * c->pal_stride + x,
339 width);
340 }
341 2806 }
342
343 132 static int motion_compensation(MSS12Context const *c,
344 int x, int y, int width, int height)
345 {
346
2/4
✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
132 if (x + c->mvX < 0 || x + c->mvX + width > c->avctx->width ||
347
2/4
✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
132 y + c->mvY < 0 || y + c->mvY + height > c->avctx->height ||
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
132 !c->rgb_pic)
349 return -1;
350 else {
351 132 uint8_t *dst = c->pal_pic + x + y * c->pal_stride;
352 132 uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride;
353 uint8_t *src;
354 uint8_t *rgb_src;
355 int j;
356 132 x += c->mvX;
357 132 y += c->mvY;
358
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 57 times.
132 if (c->last_rgb_pic) {
359 75 src = c->last_pal_pic + x + y * c->pal_stride;
360 75 rgb_src = c->last_rgb_pic + x * 3 + y * c->rgb_stride;
361 } else {
362 57 src = c->pal_pic + x + y * c->pal_stride;
363 57 rgb_src = c->rgb_pic + x * 3 + y * c->rgb_stride;
364 }
365
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 132 times.
264 for (j = 0; j < height; j++) {
366 132 memmove(dst, src, width);
367 132 memmove(rgb_dst, rgb_src, width * 3);
368 132 dst += c->pal_stride;
369 132 src += c->pal_stride;
370 132 rgb_dst += c->rgb_stride;
371 132 rgb_src += c->rgb_stride;
372 }
373 }
374 132 return 0;
375 }
376
377 5 static int decode_region_masked(MSS12Context const *c, ArithCoder *acoder,
378 uint8_t *dst, ptrdiff_t stride, uint8_t *mask,
379 ptrdiff_t mask_stride, int x, int y,
380 int width, int height,
381 PixContext *pctx)
382 {
383 int i, j, p;
384 5 uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride;
385
386 5 dst += x + y * stride;
387 5 mask += x + y * mask_stride;
388
389
2/2
✓ Branch 0 taken 614 times.
✓ Branch 1 taken 5 times.
619 for (j = 0; j < height; j++) {
390
2/2
✓ Branch 0 taken 3334 times.
✓ Branch 1 taken 614 times.
3948 for (i = 0; i < width; i++) {
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3334 times.
3334 if (c->avctx->err_recognition & AV_EF_EXPLODE &&
392 ( c->rgb_pic && mask[i] != 0x01 && mask[i] != 0x02 && mask[i] != 0x04 ||
393 !c->rgb_pic && mask[i] != 0x80 && mask[i] != 0xFF))
394 return -1;
395
396
2/2
✓ Branch 0 taken 2772 times.
✓ Branch 1 taken 562 times.
3334 if (mask[i] == 0x02) {
397 2772 copy_rectangles(c, x + i, y + j, 1, 1);
398
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 430 times.
562 } else if (mask[i] == 0x04) {
399
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
132 if (motion_compensation(c, x + i, y + j, 1, 1))
400 return -1;
401
1/2
✓ Branch 0 taken 430 times.
✗ Branch 1 not taken.
430 } else if (mask[i] != 0x80) {
402
4/4
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 323 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 106 times.
430 if (!i && !j)
403 1 p = decode_pixel(acoder, pctx, NULL, 0, 0);
404 else
405 429 p = decode_pixel_in_context(acoder, pctx, dst + i, stride,
406 429 i, j, width - i - 1);
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 430 times.
430 if (p < 0)
408 return p;
409 430 dst[i] = p;
410
1/2
✓ Branch 0 taken 430 times.
✗ Branch 1 not taken.
430 if (c->rgb_pic)
411 430 AV_WB24(rgb_dst + i * 3, c->pal[p]);
412 }
413 }
414 614 dst += stride;
415 614 mask += mask_stride;
416 614 rgb_dst += c->rgb_stride;
417 }
418
419 5 return 0;
420 }
421
422 20 static av_cold void slicecontext_init(SliceContext *sc,
423 int version, int full_model_syms)
424 {
425 20 model_init(&sc->intra_region, 2, THRESH_ADAPTIVE);
426 20 model_init(&sc->inter_region, 2, THRESH_ADAPTIVE);
427 20 model_init(&sc->split_mode, 3, THRESH_HIGH);
428 20 model_init(&sc->edge_mode, 2, THRESH_HIGH);
429 20 model_init(&sc->pivot, 3, THRESH_LOW);
430
431 20 pixctx_init(&sc->intra_pix_ctx, 8, full_model_syms, 0);
432
433
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
20 pixctx_init(&sc->inter_pix_ctx, version ? 3 : 2,
434 full_model_syms, version ? 1 : 0);
435 20 }
436
437 11 void ff_mss12_slicecontext_reset(SliceContext *sc)
438 {
439 11 model_reset(&sc->intra_region);
440 11 model_reset(&sc->inter_region);
441 11 model_reset(&sc->split_mode);
442 11 model_reset(&sc->edge_mode);
443 11 model_reset(&sc->pivot);
444 11 pixctx_reset(&sc->intra_pix_ctx);
445 11 pixctx_reset(&sc->inter_pix_ctx);
446 11 }
447
448 1721 static int decode_pivot(SliceContext *sc, ArithCoder *acoder, int base)
449 {
450 int val, inv;
451
452 1721 inv = acoder->get_model_sym(acoder, &sc->edge_mode);
453 1721 val = acoder->get_model_sym(acoder, &sc->pivot) + 1;
454
455
2/2
✓ Branch 0 taken 1051 times.
✓ Branch 1 taken 670 times.
1721 if (val > 2) {
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1051 times.
1051 if ((base + 1) / 2 - 2 <= 0)
457 return -1;
458
459 1051 val = acoder->get_number(acoder, (base + 1) / 2 - 2) + 3;
460 }
461
462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1721 times.
1721 if ((unsigned)val >= base)
463 return -1;
464
465
2/2
✓ Branch 0 taken 837 times.
✓ Branch 1 taken 884 times.
1721 return inv ? base - val : val;
466 }
467
468 1656 static int decode_region_intra(SliceContext *sc, ArithCoder *acoder,
469 int x, int y, int width, int height)
470 {
471 1656 MSS12Context const *c = sc->c;
472 int mode;
473
474 1656 mode = acoder->get_model_sym(acoder, &sc->intra_region);
475
476
2/2
✓ Branch 0 taken 1055 times.
✓ Branch 1 taken 601 times.
1656 if (!mode) {
477 int i, j, pix, rgb_pix;
478 1055 ptrdiff_t stride = c->pal_stride;
479 1055 ptrdiff_t rgb_stride = c->rgb_stride;
480 1055 uint8_t *dst = c->pal_pic + x + y * stride;
481
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 589 times.
1055 uint8_t *rgb_dst = c->rgb_pic ? c->rgb_pic + x * 3 + y * rgb_stride : NULL;
482
483 1055 pix = decode_pixel(acoder, &sc->intra_pix_ctx, NULL, 0, 0);
484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1055 times.
1055 if (pix < 0)
485 return pix;
486 1055 rgb_pix = c->pal[pix];
487
2/2
✓ Branch 0 taken 53375 times.
✓ Branch 1 taken 1055 times.
54430 for (i = 0; i < height; i++, dst += stride) {
488 53375 memset(dst, pix, width);
489
2/2
✓ Branch 0 taken 42108 times.
✓ Branch 1 taken 11267 times.
53375 if (rgb_dst) {
490
2/2
✓ Branch 0 taken 3602107 times.
✓ Branch 1 taken 42108 times.
3644215 for (j = 0; j < width * 3; j += 3)
491 3602107 AV_WB24(rgb_dst + j, rgb_pix);
492 42108 rgb_dst += rgb_stride;
493 }
494 }
495 } else {
496 601 return decode_region(acoder, c->pal_pic, c->rgb_pic,
497 601 x, y, width, height, c->pal_stride, c->rgb_stride,
498 &sc->intra_pix_ctx, &c->pal[0]);
499 }
500
501 1055 return 0;
502 }
503
504 1051 static int decode_region_inter(SliceContext *sc, ArithCoder *acoder,
505 int x, int y, int width, int height)
506 {
507 1051 MSS12Context const *c = sc->c;
508 int mode;
509
510 1051 mode = acoder->get_model_sym(acoder, &sc->inter_region);
511
512
2/2
✓ Branch 0 taken 1046 times.
✓ Branch 1 taken 5 times.
1051 if (!mode) {
513 1046 mode = decode_pixel(acoder, &sc->inter_pix_ctx, NULL, 0, 0);
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1046 times.
1046 if (mode < 0)
515 return mode;
516
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1046 times.
1046 if (c->avctx->err_recognition & AV_EF_EXPLODE &&
518 ( c->rgb_pic && mode != 0x01 && mode != 0x02 && mode != 0x04 ||
519 !c->rgb_pic && mode != 0x80 && mode != 0xFF))
520 return -1;
521
522
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1012 times.
1046 if (mode == 0x02)
523 34 copy_rectangles(c, x, y, width, height);
524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1012 times.
1012 else if (mode == 0x04)
525 return motion_compensation(c, x, y, width, height);
526
2/2
✓ Branch 0 taken 863 times.
✓ Branch 1 taken 149 times.
1012 else if (mode != 0x80)
527 863 return decode_region_intra(sc, acoder, x, y, width, height);
528 } else {
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (decode_region(acoder, c->mask, NULL,
530 5 x, y, width, height, c->mask_stride, 0,
531 &sc->inter_pix_ctx, &c->pal[0]) < 0)
532 return -1;
533 5 return decode_region_masked(c, acoder, c->pal_pic,
534 5 c->pal_stride, c->mask,
535 5 c->mask_stride,
536 x, y, width, height,
537 &sc->intra_pix_ctx);
538 }
539
540 183 return 0;
541 }
542
543 3565 int ff_mss12_decode_rect(SliceContext *sc, ArithCoder *acoder,
544 int x, int y, int width, int height)
545 {
546 int mode, pivot;
547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3565 times.
3565 if (acoder->overread > MAX_OVERREAD)
548 return AVERROR_INVALIDDATA;
549
550 3565 mode = acoder->get_model_sym(acoder, &sc->split_mode);
551
552
3/4
✓ Branch 0 taken 851 times.
✓ Branch 1 taken 870 times.
✓ Branch 2 taken 1844 times.
✗ Branch 3 not taken.
3565 switch (mode) {
553 851 case SPLIT_VERT:
554
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 851 times.
851 if ((pivot = decode_pivot(sc, acoder, height)) < 1)
555 return -1;
556
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 851 times.
851 if (ff_mss12_decode_rect(sc, acoder, x, y, width, pivot))
557 return -1;
558
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 851 times.
851 if (ff_mss12_decode_rect(sc, acoder, x, y + pivot, width, height - pivot))
559 return -1;
560 851 break;
561 870 case SPLIT_HOR:
562
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 870 times.
870 if ((pivot = decode_pivot(sc, acoder, width)) < 1)
563 return -1;
564
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 870 times.
870 if (ff_mss12_decode_rect(sc, acoder, x, y, pivot, height))
565 return -1;
566
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 870 times.
870 if (ff_mss12_decode_rect(sc, acoder, x + pivot, y, width - pivot, height))
567 return -1;
568 870 break;
569 1844 case SPLIT_NONE:
570
2/2
✓ Branch 0 taken 793 times.
✓ Branch 1 taken 1051 times.
1844 if (sc->c->keyframe)
571 793 return decode_region_intra(sc, acoder, x, y, width, height);
572 else
573 1051 return decode_region_inter(sc, acoder, x, y, width, height);
574 default:
575 return -1;
576 }
577
578 1721 return 0;
579 }
580
581 14 av_cold int ff_mss12_decode_init(MSS12Context *c, int version,
582 SliceContext* sc1, SliceContext *sc2)
583 {
584 14 AVCodecContext *avctx = c->avctx;
585 int i;
586
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (avctx->extradata_size < 52 + 256 * 3) {
588 av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d\n",
589 avctx->extradata_size);
590 return AVERROR_INVALIDDATA;
591 }
592
593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (AV_RB32(avctx->extradata) < avctx->extradata_size) {
594 av_log(avctx, AV_LOG_ERROR,
595 "Insufficient extradata size: expected %"PRIu32" got %d\n",
596 AV_RB32(avctx->extradata),
597 avctx->extradata_size);
598 return AVERROR_INVALIDDATA;
599 }
600
601 14 avctx->coded_width = FFMAX(AV_RB32(avctx->extradata + 20), avctx->width);
602 14 avctx->coded_height = FFMAX(AV_RB32(avctx->extradata + 24), avctx->height);
603
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (avctx->coded_width > 4096 || avctx->coded_height > 4096) {
604 av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too large",
605 avctx->coded_width, avctx->coded_height);
606 return AVERROR_INVALIDDATA;
607 }
608
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if (avctx->coded_width < 1 || avctx->coded_height < 1) {
609 av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too small",
610 avctx->coded_width, avctx->coded_height);
611 return AVERROR_INVALIDDATA;
612 }
613
614 14 av_log(avctx, AV_LOG_DEBUG, "Encoder version %"PRIu32".%"PRIu32"\n",
615 14 AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8));
616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (version != AV_RB32(avctx->extradata + 4) > 1) {
617 av_log(avctx, AV_LOG_ERROR,
618 "Header version doesn't match codec tag\n");
619 return -1;
620 }
621
622 14 c->free_colours = AV_RB32(avctx->extradata + 48);
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if ((unsigned)c->free_colours > 256) {
624 av_log(avctx, AV_LOG_ERROR,
625 "Incorrect number of changeable palette entries: %d\n",
626 c->free_colours);
627 return AVERROR_INVALIDDATA;
628 }
629 14 av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours);
630
631 14 av_log(avctx, AV_LOG_DEBUG, "Display dimensions %"PRIu32"x%"PRIu32"\n",
632 14 AV_RB32(avctx->extradata + 12), AV_RB32(avctx->extradata + 16));
633 14 av_log(avctx, AV_LOG_DEBUG, "Coded dimensions %dx%d\n",
634 avctx->coded_width, avctx->coded_height);
635 14 av_log(avctx, AV_LOG_DEBUG, "%g frames per second\n",
636 14 av_int2float(AV_RB32(avctx->extradata + 28)));
637 14 av_log(avctx, AV_LOG_DEBUG, "Bitrate %"PRIu32" bps\n",
638 14 AV_RB32(avctx->extradata + 32));
639 14 av_log(avctx, AV_LOG_DEBUG, "Max. lead time %g ms\n",
640 14 av_int2float(AV_RB32(avctx->extradata + 36)));
641 14 av_log(avctx, AV_LOG_DEBUG, "Max. lag time %g ms\n",
642 14 av_int2float(AV_RB32(avctx->extradata + 40)));
643 14 av_log(avctx, AV_LOG_DEBUG, "Max. seek time %g ms\n",
644 14 av_int2float(AV_RB32(avctx->extradata + 44)));
645
646
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
14 if (version) {
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (avctx->extradata_size < 60 + 256 * 3) {
648 av_log(avctx, AV_LOG_ERROR,
649 "Insufficient extradata size %d for v2\n",
650 avctx->extradata_size);
651 return AVERROR_INVALIDDATA;
652 }
653
654 12 c->slice_split = AV_RB32(avctx->extradata + 52);
655 12 av_log(avctx, AV_LOG_DEBUG, "Slice split %d\n", c->slice_split);
656
657 12 c->full_model_syms = AV_RB32(avctx->extradata + 56);
658
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (c->full_model_syms < 2 || c->full_model_syms > 256) {
659 av_log(avctx, AV_LOG_ERROR,
660 "Incorrect number of used colours %d\n",
661 c->full_model_syms);
662 return AVERROR_INVALIDDATA;
663 }
664 12 av_log(avctx, AV_LOG_DEBUG, "Used colours %d\n",
665 c->full_model_syms);
666 } else {
667 2 c->slice_split = 0;
668 2 c->full_model_syms = 256;
669 }
670
671
2/2
✓ Branch 0 taken 3584 times.
✓ Branch 1 taken 14 times.
3598 for (i = 0; i < 256; i++)
672
6/6
✓ Branch 0 taken 3072 times.
✓ Branch 1 taken 512 times.
✓ Branch 2 taken 3072 times.
✓ Branch 3 taken 512 times.
✓ Branch 4 taken 3072 times.
✓ Branch 5 taken 512 times.
3584 c->pal[i] = 0xFFU << 24 | AV_RB24(avctx->extradata + 52 +
673 (version ? 8 : 0) + i * 3);
674
675 14 c->mask_stride = FFALIGN(avctx->width, 16);
676 14 c->mask = av_malloc_array(c->mask_stride, avctx->height);
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!c->mask) {
678 av_log(avctx, AV_LOG_ERROR, "Cannot allocate mask plane\n");
679 return AVERROR(ENOMEM);
680 }
681
682 14 sc1->c = c;
683 14 slicecontext_init(sc1, version, c->full_model_syms);
684
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (c->slice_split) {
685 6 sc2->c = c;
686 6 slicecontext_init(sc2, version, c->full_model_syms);
687 }
688 14 c->corrupted = 1;
689
690 14 return 0;
691 }
692
693 14 av_cold int ff_mss12_decode_end(MSS12Context *c)
694 {
695 14 av_freep(&c->mask);
696
697 14 return 0;
698 }
699