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