Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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 "avcodec.h" | |
31 | #include "mss12.h" | |
32 | ||
33 | enum SplitMode { | |
34 | SPLIT_VERT = 0, | |
35 | SPLIT_HOR, | |
36 | SPLIT_NONE | |
37 | }; | |
38 | ||
39 | static const int sec_order_sizes[4] = { 1, 7, 6, 1 }; | |
40 | ||
41 | enum ContextDirection { | |
42 | TOP_LEFT = 0, | |
43 | TOP, | |
44 | TOP_RIGHT, | |
45 | LEFT | |
46 | }; | |
47 | ||
48 | static int model_calc_threshold(Model *m) | |
49 | { | |
50 | int thr; | |
51 | ||
52 | thr = 2 * m->weights[m->num_syms] - 1; | |
53 | thr = ((thr >> 1) + 4 * m->cum_prob[0]) / thr; | |
54 | ||
55 | return FFMIN(thr, 0x3FFF); | |
56 | } | |
57 | ||
58 | static void model_reset(Model *m) | |
59 | { | |
60 | int i; | |
61 | ||
62 | for (i = 0; i <= m->num_syms; i++) { | |
63 | m->weights[i] = 1; | |
64 | m->cum_prob[i] = m->num_syms - i; | |
65 | } | |
66 | m->weights[0] = 0; | |
67 | for (i = 0; i < m->num_syms; i++) | |
68 | m->idx2sym[i + 1] = i; | |
69 | } | |
70 | ||
71 | static av_cold void model_init(Model *m, int num_syms, int thr_weight) | |
72 | { | |
73 | m->num_syms = num_syms; | |
74 | m->thr_weight = thr_weight; | |
75 | m->threshold = num_syms * thr_weight; | |
76 | } | |
77 | ||
78 | static void model_rescale_weights(Model *m) | |
79 | { | |
80 | int i; | |
81 | int cum_prob; | |
82 | ||
83 | if (m->thr_weight == THRESH_ADAPTIVE) | |
84 | m->threshold = model_calc_threshold(m); | |
85 | while (m->cum_prob[0] > m->threshold) { | |
86 | cum_prob = 0; | |
87 | for (i = m->num_syms; i >= 0; i--) { | |
88 | m->cum_prob[i] = cum_prob; | |
89 | m->weights[i] = (m->weights[i] + 1) >> 1; | |
90 | cum_prob += m->weights[i]; | |
91 | } | |
92 | } | |
93 | } | |
94 | ||
95 | void ff_mss12_model_update(Model *m, int val) | |
96 | { | |
97 | int i; | |
98 | ||
99 | if (m->weights[val] == m->weights[val - 1]) { | |
100 | for (i = val; m->weights[i - 1] == m->weights[val]; i--); | |
101 | if (i != val) { | |
102 | int sym1, sym2; | |
103 | ||
104 | sym1 = m->idx2sym[val]; | |
105 | sym2 = m->idx2sym[i]; | |
106 | ||
107 | m->idx2sym[val] = sym2; | |
108 | m->idx2sym[i] = sym1; | |
109 | ||
110 | val = i; | |
111 | } | |
112 | } | |
113 | m->weights[val]++; | |
114 | for (i = val - 1; i >= 0; i--) | |
115 | m->cum_prob[i]++; | |
116 | model_rescale_weights(m); | |
117 | } | |
118 | ||
119 | static void pixctx_reset(PixContext *ctx) | |
120 | { | |
121 | int i, j; | |
122 | ||
123 | if (!ctx->special_initial_cache) | |
124 | for (i = 0; i < ctx->cache_size; i++) | |
125 | ctx->cache[i] = i; | |
126 | else { | |
127 | ctx->cache[0] = 1; | |
128 | ctx->cache[1] = 2; | |
129 | ctx->cache[2] = 4; | |
130 | } | |
131 | ||
132 | model_reset(&ctx->cache_model); | |
133 | model_reset(&ctx->full_model); | |
134 | ||
135 | for (i = 0; i < 15; i++) | |
136 | for (j = 0; j < 4; j++) | |
137 | model_reset(&ctx->sec_models[i][j]); | |
138 | } | |
139 | ||
140 | static av_cold void pixctx_init(PixContext *ctx, int cache_size, | |
141 | int full_model_syms, int special_initial_cache) | |
142 | { | |
143 | int i, j, k, idx; | |
144 | ||
145 | ctx->cache_size = cache_size + 4; | |
146 | ctx->num_syms = cache_size; | |
147 | ctx->special_initial_cache = special_initial_cache; | |
148 | ||
149 | model_init(&ctx->cache_model, ctx->num_syms + 1, THRESH_LOW); | |
150 | model_init(&ctx->full_model, full_model_syms, THRESH_HIGH); | |
151 | ||
152 | for (i = 0, idx = 0; i < 4; i++) | |
153 | for (j = 0; j < sec_order_sizes[i]; j++, idx++) | |
154 | for (k = 0; k < 4; k++) | |
155 | model_init(&ctx->sec_models[idx][k], 2 + i, | |
156 | i ? THRESH_LOW : THRESH_ADAPTIVE); | |
157 | } | |
158 | ||
159 | static av_always_inline int decode_pixel(ArithCoder *acoder, PixContext *pctx, | |
160 | uint8_t *ngb, int num_ngb, int any_ngb) | |
161 | { | |
162 | int i, val, pix; | |
163 | ||
164 | val = acoder->get_model_sym(acoder, &pctx->cache_model); | |
165 | if (val < pctx->num_syms) { | |
166 | if (any_ngb) { | |
167 | int idx, j; | |
168 | ||
169 | idx = 0; | |
170 | for (i = 0; i < pctx->cache_size; i++) { | |
171 | for (j = 0; j < num_ngb; j++) | |
172 | if (pctx->cache[i] == ngb[j]) | |
173 | break; | |
174 | if (j == num_ngb) { | |
175 | if (idx == val) | |
176 | break; | |
177 | idx++; | |
178 | } | |
179 | } | |
180 | val = FFMIN(i, pctx->cache_size - 1); | |
181 | } | |
182 | pix = pctx->cache[val]; | |
183 | } else { | |
184 | pix = acoder->get_model_sym(acoder, &pctx->full_model); | |
185 | for (i = 0; i < pctx->cache_size - 1; i++) | |
186 | if (pctx->cache[i] == pix) | |
187 | break; | |
188 | val = i; | |
189 | } | |
190 | if (val) { | |
191 | for (i = val; i > 0; i--) | |
192 | pctx->cache[i] = pctx->cache[i - 1]; | |
193 | pctx->cache[0] = pix; | |
194 | } | |
195 | ||
196 | return pix; | |
197 | } | |
198 | ||
199 | static int decode_pixel_in_context(ArithCoder *acoder, PixContext *pctx, | |
200 | uint8_t *src, int stride, int x, int y, | |
201 | int has_right) | |
202 | { | |
203 | uint8_t neighbours[4]; | |
204 | uint8_t ref_pix[4]; | |
205 | int nlen; | |
206 | int layer = 0, sub; | |
207 | int pix; | |
208 | int i, j; | |
209 | ||
210 | if (!y) { | |
211 | memset(neighbours, src[-1], 4); | |
212 | } else { | |
213 | neighbours[TOP] = src[-stride]; | |
214 | if (!x) { | |
215 | neighbours[TOP_LEFT] = neighbours[LEFT] = neighbours[TOP]; | |
216 | } else { | |
217 | neighbours[TOP_LEFT] = src[-stride - 1]; | |
218 | neighbours[ LEFT] = src[-1]; | |
219 | } | |
220 | if (has_right) | |
221 | neighbours[TOP_RIGHT] = src[-stride + 1]; | |
222 | else | |
223 | neighbours[TOP_RIGHT] = neighbours[TOP]; | |
224 | } | |
225 | ||
226 | sub = 0; | |
227 | if (x >= 2 && src[-2] == neighbours[LEFT]) | |
228 | sub = 1; | |
229 | if (y >= 2 && src[-2 * stride] == neighbours[TOP]) | |
230 | sub |= 2; | |
231 | ||
232 | nlen = 1; | |
233 | ref_pix[0] = neighbours[0]; | |
234 | for (i = 1; i < 4; i++) { | |
235 | for (j = 0; j < nlen; j++) | |
236 | if (ref_pix[j] == neighbours[i]) | |
237 | break; | |
238 | if (j == nlen) | |
239 | ref_pix[nlen++] = neighbours[i]; | |
240 | } | |
241 | ||
242 | switch (nlen) { | |
243 | case 1: | |
244 | layer = 0; | |
245 | break; | |
246 | case 2: | |
247 | if (neighbours[TOP] == neighbours[TOP_LEFT]) { | |
248 | if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) | |
249 | layer = 1; | |
250 | else if (neighbours[LEFT] == neighbours[TOP_LEFT]) | |
251 | layer = 2; | |
252 | else | |
253 | layer = 3; | |
254 | } else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) { | |
255 | if (neighbours[LEFT] == neighbours[TOP_LEFT]) | |
256 | layer = 4; | |
257 | else | |
258 | layer = 5; | |
259 | } else if (neighbours[LEFT] == neighbours[TOP_LEFT]) { | |
260 | layer = 6; | |
261 | } else { | |
262 | layer = 7; | |
263 | } | |
264 | break; | |
265 | case 3: | |
266 | if (neighbours[TOP] == neighbours[TOP_LEFT]) | |
267 | layer = 8; | |
268 | else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) | |
269 | layer = 9; | |
270 | else if (neighbours[LEFT] == neighbours[TOP_LEFT]) | |
271 | layer = 10; | |
272 | else if (neighbours[TOP_RIGHT] == neighbours[TOP]) | |
273 | layer = 11; | |
274 | else if (neighbours[TOP] == neighbours[LEFT]) | |
275 | layer = 12; | |
276 | else | |
277 | layer = 13; | |
278 | break; | |
279 | case 4: | |
280 | layer = 14; | |
281 | break; | |
282 | } | |
283 | ||
284 | pix = acoder->get_model_sym(acoder, | |
285 | &pctx->sec_models[layer][sub]); | |
286 | if (pix < nlen) | |
287 | return ref_pix[pix]; | |
288 | else | |
289 | return decode_pixel(acoder, pctx, ref_pix, nlen, 1); | |
290 | } | |
291 | ||
292 | static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_pic, | |
293 | int x, int y, int width, int height, int stride, | |
294 | int rgb_stride, PixContext *pctx, const uint32_t *pal) | |
295 | { | |
296 | int i, j, p; | |
297 | uint8_t *rgb_dst = rgb_pic + x * 3 + y * rgb_stride; | |
298 | ||
299 | dst += x + y * stride; | |
300 | ||
301 | for (j = 0; j < height; j++) { | |
302 | for (i = 0; i < width; i++) { | |
303 | if (!i && !j) | |
304 | p = decode_pixel(acoder, pctx, NULL, 0, 0); | |
305 | else | |
306 | p = decode_pixel_in_context(acoder, pctx, dst + i, stride, | |
307 | i, j, width - i - 1); | |
308 | dst[i] = p; | |
309 | ||
310 | if (rgb_pic) | |
311 | AV_WB24(rgb_dst + i * 3, pal[p]); | |
312 | } | |
313 | dst += stride; | |
314 | rgb_dst += rgb_stride; | |
315 | } | |
316 | ||
317 | return 0; | |
318 | } | |
319 | ||
320 | static void copy_rectangles(MSS12Context const *c, | |
321 | int x, int y, int width, int height) | |
322 | { | |
323 | int j; | |
324 | ||
325 | if (c->last_rgb_pic) | |
326 | for (j = y; j < y + height; j++) { | |
327 | memcpy(c->rgb_pic + j * c->rgb_stride + x * 3, | |
328 | c->last_rgb_pic + j * c->rgb_stride + x * 3, | |
329 | width * 3); | |
330 | memcpy(c->pal_pic + j * c->pal_stride + x, | |
331 | c->last_pal_pic + j * c->pal_stride + x, | |
332 | width); | |
333 | } | |
334 | } | |
335 | ||
336 | static int motion_compensation(MSS12Context const *c, | |
337 | int x, int y, int width, int height) | |
338 | { | |
339 | if (x + c->mvX < 0 || x + c->mvX + width > c->avctx->width || | |
340 | y + c->mvY < 0 || y + c->mvY + height > c->avctx->height || | |
341 | !c->rgb_pic) | |
342 | return -1; | |
343 | else { | |
344 | uint8_t *dst = c->pal_pic + x + y * c->pal_stride; | |
345 | uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride; | |
346 | uint8_t *src; | |
347 | uint8_t *rgb_src; | |
348 | int j; | |
349 | x += c->mvX; | |
350 | y += c->mvY; | |
351 | if (c->last_rgb_pic) { | |
352 | src = c->last_pal_pic + x + y * c->pal_stride; | |
353 | rgb_src = c->last_rgb_pic + x * 3 + y * c->rgb_stride; | |
354 | } else { | |
355 | src = c->pal_pic + x + y * c->pal_stride; | |
356 | rgb_src = c->rgb_pic + x * 3 + y * c->rgb_stride; | |
357 | } | |
358 | for (j = 0; j < height; j++) { | |
359 | memmove(dst, src, width); | |
360 | memmove(rgb_dst, rgb_src, width * 3); | |
361 | dst += c->pal_stride; | |
362 | src += c->pal_stride; | |
363 | rgb_dst += c->rgb_stride; | |
364 | rgb_src += c->rgb_stride; | |
365 | } | |
366 | } | |
367 | return 0; | |
368 | } | |
369 | ||
370 | static int decode_region_masked(MSS12Context const *c, ArithCoder *acoder, | |
371 | uint8_t *dst, int stride, uint8_t *mask, | |
372 | int mask_stride, int x, int y, | |
373 | int width, int height, | |
374 | PixContext *pctx) | |
375 | { | |
376 | int i, j, p; | |
377 | uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride; | |
378 | ||
379 | dst += x + y * stride; | |
380 | mask += x + y * mask_stride; | |
381 | ||
382 | for (j = 0; j < height; j++) { | |
383 | for (i = 0; i < width; i++) { | |
384 | if (c->avctx->err_recognition & AV_EF_EXPLODE && | |
385 | ( c->rgb_pic && mask[i] != 0x01 && mask[i] != 0x02 && mask[i] != 0x04 || | |
386 | !c->rgb_pic && mask[i] != 0x80 && mask[i] != 0xFF)) | |
387 | return -1; | |
388 | ||
389 | if (mask[i] == 0x02) { | |
390 | copy_rectangles(c, x + i, y + j, 1, 1); | |
391 | } else if (mask[i] == 0x04) { | |
392 | if (motion_compensation(c, x + i, y + j, 1, 1)) | |
393 | return -1; | |
394 | } else if (mask[i] != 0x80) { | |
395 | if (!i && !j) | |
396 | p = decode_pixel(acoder, pctx, NULL, 0, 0); | |
397 | else | |
398 | p = decode_pixel_in_context(acoder, pctx, dst + i, stride, | |
399 | i, j, width - i - 1); | |
400 | dst[i] = p; | |
401 | if (c->rgb_pic) | |
402 | AV_WB24(rgb_dst + i * 3, c->pal[p]); | |
403 | } | |
404 | } | |
405 | dst += stride; | |
406 | mask += mask_stride; | |
407 | rgb_dst += c->rgb_stride; | |
408 | } | |
409 | ||
410 | return 0; | |
411 | } | |
412 | ||
413 | static av_cold void slicecontext_init(SliceContext *sc, | |
414 | int version, int full_model_syms) | |
415 | { | |
416 | model_init(&sc->intra_region, 2, THRESH_ADAPTIVE); | |
417 | model_init(&sc->inter_region, 2, THRESH_ADAPTIVE); | |
418 | model_init(&sc->split_mode, 3, THRESH_HIGH); | |
419 | model_init(&sc->edge_mode, 2, THRESH_HIGH); | |
420 | model_init(&sc->pivot, 3, THRESH_LOW); | |
421 | ||
422 | pixctx_init(&sc->intra_pix_ctx, 8, full_model_syms, 0); | |
423 | ||
424 | pixctx_init(&sc->inter_pix_ctx, version ? 3 : 2, | |
425 | full_model_syms, version ? 1 : 0); | |
426 | } | |
427 | ||
428 | void ff_mss12_slicecontext_reset(SliceContext *sc) | |
429 | { | |
430 | model_reset(&sc->intra_region); | |
431 | model_reset(&sc->inter_region); | |
432 | model_reset(&sc->split_mode); | |
433 | model_reset(&sc->edge_mode); | |
434 | model_reset(&sc->pivot); | |
435 | pixctx_reset(&sc->intra_pix_ctx); | |
436 | pixctx_reset(&sc->inter_pix_ctx); | |
437 | } | |
438 | ||
439 | static int decode_pivot(SliceContext *sc, ArithCoder *acoder, int base) | |
440 | { | |
441 | int val, inv; | |
442 | ||
443 | inv = acoder->get_model_sym(acoder, &sc->edge_mode); | |
444 | val = acoder->get_model_sym(acoder, &sc->pivot) + 1; | |
445 | ||
446 | if (val > 2) { | |
447 | if ((base + 1) / 2 - 2 <= 0) | |
448 | return -1; | |
449 | ||
450 | val = acoder->get_number(acoder, (base + 1) / 2 - 2) + 3; | |
451 | } | |
452 | ||
453 | if ((unsigned)val >= base) | |
454 | return -1; | |
455 | ||
456 | return inv ? base - val : val; | |
457 | } | |
458 | ||
459 | static int decode_region_intra(SliceContext *sc, ArithCoder *acoder, | |
460 | int x, int y, int width, int height) | |
461 | { | |
462 | MSS12Context const *c = sc->c; | |
463 | int mode; | |
464 | ||
465 | mode = acoder->get_model_sym(acoder, &sc->intra_region); | |
466 | ||
467 | if (!mode) { | |
468 | int i, j, pix, rgb_pix; | |
469 | int stride = c->pal_stride; | |
470 | int rgb_stride = c->rgb_stride; | |
471 | uint8_t *dst = c->pal_pic + x + y * stride; | |
472 | uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * rgb_stride; | |
473 | ||
474 | pix = decode_pixel(acoder, &sc->intra_pix_ctx, NULL, 0, 0); | |
475 | rgb_pix = c->pal[pix]; | |
476 | for (i = 0; i < height; i++, dst += stride, rgb_dst += rgb_stride) { | |
477 | memset(dst, pix, width); | |
478 | if (c->rgb_pic) | |
479 | for (j = 0; j < width * 3; j += 3) | |
480 | AV_WB24(rgb_dst + j, rgb_pix); | |
481 | } | |
482 | } else { | |
483 | return decode_region(acoder, c->pal_pic, c->rgb_pic, | |
484 | x, y, width, height, c->pal_stride, c->rgb_stride, | |
485 | &sc->intra_pix_ctx, &c->pal[0]); | |
486 | } | |
487 | ||
488 | return 0; | |
489 | } | |
490 | ||
491 | static int decode_region_inter(SliceContext *sc, ArithCoder *acoder, | |
492 | int x, int y, int width, int height) | |
493 | { | |
494 | MSS12Context const *c = sc->c; | |
495 | int mode; | |
496 | ||
497 | mode = acoder->get_model_sym(acoder, &sc->inter_region); | |
498 | ||
499 | if (!mode) { | |
500 | mode = decode_pixel(acoder, &sc->inter_pix_ctx, NULL, 0, 0); | |
501 | ||
502 | if (c->avctx->err_recognition & AV_EF_EXPLODE && | |
503 | ( c->rgb_pic && mode != 0x01 && mode != 0x02 && mode != 0x04 || | |
504 | !c->rgb_pic && mode != 0x80 && mode != 0xFF)) | |
505 | return -1; | |
506 | ||
507 | if (mode == 0x02) | |
508 | copy_rectangles(c, x, y, width, height); | |
509 | else if (mode == 0x04) | |
510 | return motion_compensation(c, x, y, width, height); | |
511 | else if (mode != 0x80) | |
512 | return decode_region_intra(sc, acoder, x, y, width, height); | |
513 | } else { | |
514 | if (decode_region(acoder, c->mask, NULL, | |
515 | x, y, width, height, c->mask_stride, 0, | |
516 | &sc->inter_pix_ctx, &c->pal[0]) < 0) | |
517 | return -1; | |
518 | return decode_region_masked(c, acoder, c->pal_pic, | |
519 | c->pal_stride, c->mask, | |
520 | c->mask_stride, | |
521 | x, y, width, height, | |
522 | &sc->intra_pix_ctx); | |
523 | } | |
524 | ||
525 | return 0; | |
526 | } | |
527 | ||
528 | int ff_mss12_decode_rect(SliceContext *sc, ArithCoder *acoder, | |
529 | int x, int y, int width, int height) | |
530 | { | |
531 | int mode, pivot; | |
532 | ||
533 | mode = acoder->get_model_sym(acoder, &sc->split_mode); | |
534 | ||
535 | switch (mode) { | |
536 | case SPLIT_VERT: | |
537 | if ((pivot = decode_pivot(sc, acoder, height)) < 1) | |
538 | return -1; | |
539 | if (ff_mss12_decode_rect(sc, acoder, x, y, width, pivot)) | |
540 | return -1; | |
541 | if (ff_mss12_decode_rect(sc, acoder, x, y + pivot, width, height - pivot)) | |
542 | return -1; | |
543 | break; | |
544 | case SPLIT_HOR: | |
545 | if ((pivot = decode_pivot(sc, acoder, width)) < 1) | |
546 | return -1; | |
547 | if (ff_mss12_decode_rect(sc, acoder, x, y, pivot, height)) | |
548 | return -1; | |
549 | if (ff_mss12_decode_rect(sc, acoder, x + pivot, y, width - pivot, height)) | |
550 | return -1; | |
551 | break; | |
552 | case SPLIT_NONE: | |
553 | if (sc->c->keyframe) | |
554 | return decode_region_intra(sc, acoder, x, y, width, height); | |
555 | else | |
556 | return decode_region_inter(sc, acoder, x, y, width, height); | |
557 | default: | |
558 | return -1; | |
559 | } | |
560 | ||
561 | return 0; | |
562 | } | |
563 | ||
564 | av_cold int ff_mss12_decode_init(MSS12Context *c, int version, | |
565 | SliceContext* sc1, SliceContext *sc2) | |
566 | { | |
567 | AVCodecContext *avctx = c->avctx; | |
568 | int i; | |
569 | ||
570 | if (avctx->extradata_size < 52 + 256 * 3) { | |
571 | av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d\n", | |
572 | avctx->extradata_size); | |
573 | return AVERROR_INVALIDDATA; | |
574 | } | |
575 | ||
576 | if (AV_RB32(avctx->extradata) < avctx->extradata_size) { | |
577 | av_log(avctx, AV_LOG_ERROR, | |
578 | "Insufficient extradata size: expected %"PRIu32" got %d\n", | |
579 | AV_RB32(avctx->extradata), | |
580 | avctx->extradata_size); | |
581 | return AVERROR_INVALIDDATA; | |
582 | } | |
583 | ||
584 | avctx->coded_width = AV_RB32(avctx->extradata + 20); | |
585 | avctx->coded_height = AV_RB32(avctx->extradata + 24); | |
586 | if (avctx->coded_width > 4096 || avctx->coded_height > 4096) { | |
587 | av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too large", | |
588 | avctx->coded_width, avctx->coded_height); | |
589 | return AVERROR_INVALIDDATA; | |
590 | } | |
591 | if (avctx->coded_width < 1 || avctx->coded_height < 1) { | |
592 | av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too small", | |
593 | avctx->coded_width, avctx->coded_height); | |
594 | return AVERROR_INVALIDDATA; | |
595 | } | |
596 | ||
597 | av_log(avctx, AV_LOG_DEBUG, "Encoder version %"PRIu32".%"PRIu32"\n", | |
598 | AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8)); | |
599 | if (version != AV_RB32(avctx->extradata + 4) > 1) { | |
600 | av_log(avctx, AV_LOG_ERROR, | |
601 | "Header version doesn't match codec tag\n"); | |
602 | return -1; | |
603 | } | |
604 | ||
605 | c->free_colours = AV_RB32(avctx->extradata + 48); | |
606 | if ((unsigned)c->free_colours > 256) { | |
607 | av_log(avctx, AV_LOG_ERROR, | |
608 | "Incorrect number of changeable palette entries: %d\n", | |
609 | c->free_colours); | |
610 | return AVERROR_INVALIDDATA; | |
611 | } | |
612 | av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours); | |
613 | ||
614 | av_log(avctx, AV_LOG_DEBUG, "Display dimensions %"PRIu32"x%"PRIu32"\n", | |
615 | AV_RB32(avctx->extradata + 12), AV_RB32(avctx->extradata + 16)); | |
616 | av_log(avctx, AV_LOG_DEBUG, "Coded dimensions %dx%d\n", | |
617 | avctx->coded_width, avctx->coded_height); | |
618 | av_log(avctx, AV_LOG_DEBUG, "%g frames per second\n", | |
619 | av_int2float(AV_RB32(avctx->extradata + 28))); | |
620 | av_log(avctx, AV_LOG_DEBUG, "Bitrate %"PRIu32" bps\n", | |
621 | AV_RB32(avctx->extradata + 32)); | |
622 | av_log(avctx, AV_LOG_DEBUG, "Max. lead time %g ms\n", | |
623 | av_int2float(AV_RB32(avctx->extradata + 36))); | |
624 | av_log(avctx, AV_LOG_DEBUG, "Max. lag time %g ms\n", | |
625 | av_int2float(AV_RB32(avctx->extradata + 40))); | |
626 | av_log(avctx, AV_LOG_DEBUG, "Max. seek time %g ms\n", | |
627 | av_int2float(AV_RB32(avctx->extradata + 44))); | |
628 | ||
629 | if (version) { | |
630 | if (avctx->extradata_size < 60 + 256 * 3) { | |
631 | av_log(avctx, AV_LOG_ERROR, | |
632 | "Insufficient extradata size %d for v2\n", | |
633 | avctx->extradata_size); | |
634 | return AVERROR_INVALIDDATA; | |
635 | } | |
636 | ||
637 | c->slice_split = AV_RB32(avctx->extradata + 52); | |
638 | av_log(avctx, AV_LOG_DEBUG, "Slice split %d\n", c->slice_split); | |
639 | ||
640 | c->full_model_syms = AV_RB32(avctx->extradata + 56); | |
641 | if (c->full_model_syms < 2 || c->full_model_syms > 256) { | |
642 | av_log(avctx, AV_LOG_ERROR, | |
643 | "Incorrect number of used colours %d\n", | |
644 | c->full_model_syms); | |
645 | return AVERROR_INVALIDDATA; | |
646 | } | |
647 | av_log(avctx, AV_LOG_DEBUG, "Used colours %d\n", | |
648 | c->full_model_syms); | |
649 | } else { | |
650 | c->slice_split = 0; | |
651 | c->full_model_syms = 256; | |
652 | } | |
653 | ||
654 | for (i = 0; i < 256; i++) | |
655 | c->pal[i] = 0xFFU << 24 | AV_RB24(avctx->extradata + 52 + | |
656 | (version ? 8 : 0) + i * 3); | |
657 | ||
658 | c->mask_stride = FFALIGN(avctx->width, 16); | |
659 | c->mask = av_malloc(c->mask_stride * avctx->height); | |
660 | if (!c->mask) { | |
661 | av_log(avctx, AV_LOG_ERROR, "Cannot allocate mask plane\n"); | |
662 | return AVERROR(ENOMEM); | |
663 | } | |
664 | ||
665 | sc1->c = c; | |
666 | slicecontext_init(sc1, version, c->full_model_syms); | |
667 | if (c->slice_split) { | |
668 | sc2->c = c; | |
669 | slicecontext_init(sc2, version, c->full_model_syms); | |
670 | } | |
671 | c->corrupted = 1; | |
672 | ||
673 | return 0; | |
674 | } | |
675 | ||
676 | av_cold int ff_mss12_decode_end(MSS12Context *c) | |
677 | { | |
678 | av_freep(&c->mask); | |
679 | ||
680 | return 0; | |
681 | } |