00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "libavutil/intfloat.h"
00027 #include "libavutil/intreadwrite.h"
00028 #include "avcodec.h"
00029 #include "mss12.h"
00030
00031 enum SplitMode {
00032 SPLIT_VERT = 0,
00033 SPLIT_HOR,
00034 SPLIT_NONE
00035 };
00036
00037 static const int sec_order_sizes[4] = { 1, 7, 6, 1 };
00038
00039 enum ContextDirection {
00040 TOP_LEFT = 0,
00041 TOP,
00042 TOP_RIGHT,
00043 LEFT
00044 };
00045
00046 static int model_calc_threshold(Model *m)
00047 {
00048 int thr;
00049
00050 thr = 2 * m->weights[m->num_syms] - 1;
00051 thr = ((thr >> 1) + 4 * m->cum_prob[0]) / thr;
00052
00053 return FFMIN(thr, 0x3FFF);
00054 }
00055
00056 static void model_reset(Model *m)
00057 {
00058 int i;
00059
00060 for (i = 0; i <= m->num_syms; i++) {
00061 m->weights[i] = 1;
00062 m->cum_prob[i] = m->num_syms - i;
00063 }
00064 m->weights[0] = 0;
00065 for (i = 0; i < m->num_syms; i++)
00066 m->idx2sym[i + 1] = i;
00067 }
00068
00069 static av_cold void model_init(Model *m, int num_syms, int thr_weight)
00070 {
00071 m->num_syms = num_syms;
00072 m->thr_weight = thr_weight;
00073 m->threshold = num_syms * thr_weight;
00074 }
00075
00076 static void model_rescale_weights(Model *m)
00077 {
00078 int i;
00079 int cum_prob;
00080
00081 if (m->thr_weight == THRESH_ADAPTIVE)
00082 m->threshold = model_calc_threshold(m);
00083 while (m->cum_prob[0] > m->threshold) {
00084 cum_prob = 0;
00085 for (i = m->num_syms; i >= 0; i--) {
00086 m->cum_prob[i] = cum_prob;
00087 m->weights[i] = (m->weights[i] + 1) >> 1;
00088 cum_prob += m->weights[i];
00089 }
00090 }
00091 }
00092
00093 void ff_mss12_model_update(Model *m, int val)
00094 {
00095 int i;
00096
00097 if (m->weights[val] == m->weights[val - 1]) {
00098 for (i = val; m->weights[i - 1] == m->weights[val]; i--);
00099 if (i != val) {
00100 int sym1, sym2;
00101
00102 sym1 = m->idx2sym[val];
00103 sym2 = m->idx2sym[i];
00104
00105 m->idx2sym[val] = sym2;
00106 m->idx2sym[i] = sym1;
00107
00108 val = i;
00109 }
00110 }
00111 m->weights[val]++;
00112 for (i = val - 1; i >= 0; i--)
00113 m->cum_prob[i]++;
00114 model_rescale_weights(m);
00115 }
00116
00117 static void pixctx_reset(PixContext *ctx)
00118 {
00119 int i, j;
00120
00121 if (!ctx->special_initial_cache)
00122 for (i = 0; i < ctx->cache_size; i++)
00123 ctx->cache[i] = i;
00124 else {
00125 ctx->cache[0] = 1;
00126 ctx->cache[1] = 2;
00127 ctx->cache[2] = 4;
00128 }
00129
00130 model_reset(&ctx->cache_model);
00131 model_reset(&ctx->full_model);
00132
00133 for (i = 0; i < 15; i++)
00134 for (j = 0; j < 4; j++)
00135 model_reset(&ctx->sec_models[i][j]);
00136 }
00137
00138 static av_cold void pixctx_init(PixContext *ctx, int cache_size,
00139 int full_model_syms, int special_initial_cache)
00140 {
00141 int i, j, k, idx;
00142
00143 ctx->cache_size = cache_size + 4;
00144 ctx->num_syms = cache_size;
00145 ctx->special_initial_cache = special_initial_cache;
00146
00147 model_init(&ctx->cache_model, ctx->num_syms + 1, THRESH_LOW);
00148 model_init(&ctx->full_model, full_model_syms, THRESH_HIGH);
00149
00150 for (i = 0, idx = 0; i < 4; i++)
00151 for (j = 0; j < sec_order_sizes[i]; j++, idx++)
00152 for (k = 0; k < 4; k++)
00153 model_init(&ctx->sec_models[idx][k], 2 + i,
00154 i ? THRESH_LOW : THRESH_ADAPTIVE);
00155 }
00156
00157 static av_always_inline int decode_pixel(ArithCoder *acoder, PixContext *pctx,
00158 uint8_t *ngb, int num_ngb, int any_ngb)
00159 {
00160 int i, val, pix;
00161
00162 val = acoder->get_model_sym(acoder, &pctx->cache_model);
00163 if (val < pctx->num_syms) {
00164 if (any_ngb) {
00165 int idx, j;
00166
00167 idx = 0;
00168 for (i = 0; i < pctx->cache_size; i++) {
00169 for (j = 0; j < num_ngb; j++)
00170 if (pctx->cache[i] == ngb[j])
00171 break;
00172 if (j == num_ngb) {
00173 if (idx == val)
00174 break;
00175 idx++;
00176 }
00177 }
00178 val = FFMIN(i, pctx->cache_size - 1);
00179 }
00180 pix = pctx->cache[val];
00181 } else {
00182 pix = acoder->get_model_sym(acoder, &pctx->full_model);
00183 for (i = 0; i < pctx->cache_size - 1; i++)
00184 if (pctx->cache[i] == pix)
00185 break;
00186 val = i;
00187 }
00188 if (val) {
00189 for (i = val; i > 0; i--)
00190 pctx->cache[i] = pctx->cache[i - 1];
00191 pctx->cache[0] = pix;
00192 }
00193
00194 return pix;
00195 }
00196
00197 static int decode_pixel_in_context(ArithCoder *acoder, PixContext *pctx,
00198 uint8_t *src, int stride, int x, int y,
00199 int has_right)
00200 {
00201 uint8_t neighbours[4];
00202 uint8_t ref_pix[4];
00203 int nlen;
00204 int layer = 0, sub;
00205 int pix;
00206 int i, j;
00207
00208 if (!y) {
00209 memset(neighbours, src[-1], 4);
00210 } else {
00211 neighbours[TOP] = src[-stride];
00212 if (!x) {
00213 neighbours[TOP_LEFT] = neighbours[LEFT] = neighbours[TOP];
00214 } else {
00215 neighbours[TOP_LEFT] = src[-stride - 1];
00216 neighbours[ LEFT] = src[-1];
00217 }
00218 if (has_right)
00219 neighbours[TOP_RIGHT] = src[-stride + 1];
00220 else
00221 neighbours[TOP_RIGHT] = neighbours[TOP];
00222 }
00223
00224 sub = 0;
00225 if (x >= 2 && src[-2] == neighbours[LEFT])
00226 sub = 1;
00227 if (y >= 2 && src[-2 * stride] == neighbours[TOP])
00228 sub |= 2;
00229
00230 nlen = 1;
00231 ref_pix[0] = neighbours[0];
00232 for (i = 1; i < 4; i++) {
00233 for (j = 0; j < nlen; j++)
00234 if (ref_pix[j] == neighbours[i])
00235 break;
00236 if (j == nlen)
00237 ref_pix[nlen++] = neighbours[i];
00238 }
00239
00240 switch (nlen) {
00241 case 1:
00242 layer = 0;
00243 break;
00244 case 2:
00245 if (neighbours[TOP] == neighbours[TOP_LEFT]) {
00246 if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT])
00247 layer = 1;
00248 else if (neighbours[LEFT] == neighbours[TOP_LEFT])
00249 layer = 2;
00250 else
00251 layer = 3;
00252 } else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) {
00253 if (neighbours[LEFT] == neighbours[TOP_LEFT])
00254 layer = 4;
00255 else
00256 layer = 5;
00257 } else if (neighbours[LEFT] == neighbours[TOP_LEFT]) {
00258 layer = 6;
00259 } else {
00260 layer = 7;
00261 }
00262 break;
00263 case 3:
00264 if (neighbours[TOP] == neighbours[TOP_LEFT])
00265 layer = 8;
00266 else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT])
00267 layer = 9;
00268 else if (neighbours[LEFT] == neighbours[TOP_LEFT])
00269 layer = 10;
00270 else if (neighbours[TOP_RIGHT] == neighbours[TOP])
00271 layer = 11;
00272 else if (neighbours[TOP] == neighbours[LEFT])
00273 layer = 12;
00274 else
00275 layer = 13;
00276 break;
00277 case 4:
00278 layer = 14;
00279 break;
00280 }
00281
00282 pix = acoder->get_model_sym(acoder,
00283 &pctx->sec_models[layer][sub]);
00284 if (pix < nlen)
00285 return ref_pix[pix];
00286 else
00287 return decode_pixel(acoder, pctx, ref_pix, nlen, 1);
00288 }
00289
00290 static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_pic,
00291 int x, int y, int width, int height, int stride,
00292 int rgb_stride, PixContext *pctx, const uint32_t *pal)
00293 {
00294 int i, j, p;
00295 uint8_t *rgb_dst = rgb_pic + x * 3 + y * rgb_stride;
00296
00297 dst += x + y * stride;
00298
00299 for (j = 0; j < height; j++) {
00300 for (i = 0; i < width; i++) {
00301 if (!i && !j)
00302 p = decode_pixel(acoder, pctx, NULL, 0, 0);
00303 else
00304 p = decode_pixel_in_context(acoder, pctx, dst + i, stride,
00305 i, j, width - i - 1);
00306 dst[i] = p;
00307
00308 if (rgb_pic)
00309 AV_WB24(rgb_dst + i * 3, pal[p]);
00310 }
00311 dst += stride;
00312 rgb_dst += rgb_stride;
00313 }
00314
00315 return 0;
00316 }
00317
00318 static void copy_rectangles(MSS12Context const *c,
00319 int x, int y, int width, int height)
00320 {
00321 int j;
00322
00323 if (c->last_rgb_pic)
00324 for (j = y; j < y + height; j++) {
00325 memcpy(c->rgb_pic + j * c->rgb_stride + x * 3,
00326 c->last_rgb_pic + j * c->rgb_stride + x * 3,
00327 width * 3);
00328 memcpy(c->pal_pic + j * c->pal_stride + x,
00329 c->last_pal_pic + j * c->pal_stride + x,
00330 width);
00331 }
00332 }
00333
00334 static int motion_compensation(MSS12Context const *c,
00335 int x, int y, int width, int height)
00336 {
00337 if (x + c->mvX < 0 || x + c->mvX + width > c->avctx->width ||
00338 y + c->mvY < 0 || y + c->mvY + height > c->avctx->height ||
00339 !c->rgb_pic)
00340 return -1;
00341 else {
00342 uint8_t *dst = c->pal_pic + x + y * c->pal_stride;
00343 uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride;
00344 uint8_t *src;
00345 uint8_t *rgb_src;
00346 int j;
00347 x += c->mvX;
00348 y += c->mvY;
00349 if (c->last_rgb_pic) {
00350 src = c->last_pal_pic + x + y * c->pal_stride;
00351 rgb_src = c->last_rgb_pic + x * 3 + y * c->rgb_stride;
00352 } else {
00353 src = c->pal_pic + x + y * c->pal_stride;
00354 rgb_src = c->rgb_pic + x * 3 + y * c->rgb_stride;
00355 }
00356 for (j = 0; j < height; j++) {
00357 memmove(dst, src, width);
00358 memmove(rgb_dst, rgb_src, width * 3);
00359 dst += c->pal_stride;
00360 src += c->pal_stride;
00361 rgb_dst += c->rgb_stride;
00362 rgb_src += c->rgb_stride;
00363 }
00364 }
00365 return 0;
00366 }
00367
00368 static int decode_region_masked(MSS12Context const *c, ArithCoder *acoder,
00369 uint8_t *dst, int stride, uint8_t *mask,
00370 int mask_stride, int x, int y,
00371 int width, int height,
00372 PixContext *pctx)
00373 {
00374 int i, j, p;
00375 uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride;
00376
00377 dst += x + y * stride;
00378 mask += x + y * mask_stride;
00379
00380 for (j = 0; j < height; j++) {
00381 for (i = 0; i < width; i++) {
00382 if (c->avctx->err_recognition & AV_EF_EXPLODE &&
00383 ( c->rgb_pic && mask[i] != 0x01 && mask[i] != 0x02 && mask[i] != 0x04 ||
00384 !c->rgb_pic && mask[i] != 0x80 && mask[i] != 0xFF))
00385 return -1;
00386
00387 if (mask[i] == 0x02) {
00388 copy_rectangles(c, x + i, y + j, 1, 1);
00389 } else if (mask[i] == 0x04) {
00390 if (motion_compensation(c, x + i, y + j, 1, 1))
00391 return -1;
00392 } else if (mask[i] != 0x80) {
00393 if (!i && !j)
00394 p = decode_pixel(acoder, pctx, NULL, 0, 0);
00395 else
00396 p = decode_pixel_in_context(acoder, pctx, dst + i, stride,
00397 i, j, width - i - 1);
00398 dst[i] = p;
00399 if (c->rgb_pic)
00400 AV_WB24(rgb_dst + i * 3, c->pal[p]);
00401 }
00402 }
00403 dst += stride;
00404 mask += mask_stride;
00405 rgb_dst += c->rgb_stride;
00406 }
00407
00408 return 0;
00409 }
00410
00411 static av_cold void slicecontext_init(SliceContext *sc,
00412 int version, int full_model_syms)
00413 {
00414 model_init(&sc->intra_region, 2, THRESH_ADAPTIVE);
00415 model_init(&sc->inter_region, 2, THRESH_ADAPTIVE);
00416 model_init(&sc->split_mode, 3, THRESH_HIGH);
00417 model_init(&sc->edge_mode, 2, THRESH_HIGH);
00418 model_init(&sc->pivot, 3, THRESH_LOW);
00419
00420 pixctx_init(&sc->intra_pix_ctx, 8, full_model_syms, 0);
00421
00422 pixctx_init(&sc->inter_pix_ctx, version ? 3 : 2,
00423 full_model_syms, version ? 1 : 0);
00424 }
00425
00426 void ff_mss12_slicecontext_reset(SliceContext *sc)
00427 {
00428 model_reset(&sc->intra_region);
00429 model_reset(&sc->inter_region);
00430 model_reset(&sc->split_mode);
00431 model_reset(&sc->edge_mode);
00432 model_reset(&sc->pivot);
00433 pixctx_reset(&sc->intra_pix_ctx);
00434 pixctx_reset(&sc->inter_pix_ctx);
00435 }
00436
00437 static int decode_pivot(SliceContext *sc, ArithCoder *acoder, int base)
00438 {
00439 int val, inv;
00440
00441 inv = acoder->get_model_sym(acoder, &sc->edge_mode);
00442 val = acoder->get_model_sym(acoder, &sc->pivot) + 1;
00443
00444 if (val > 2) {
00445 if ((base + 1) / 2 - 2 <= 0)
00446 return -1;
00447
00448 val = acoder->get_number(acoder, (base + 1) / 2 - 2) + 3;
00449 }
00450
00451 if ((unsigned)val >= base)
00452 return -1;
00453
00454 return inv ? base - val : val;
00455 }
00456
00457 static int decode_region_intra(SliceContext *sc, ArithCoder *acoder,
00458 int x, int y, int width, int height)
00459 {
00460 MSS12Context const *c = sc->c;
00461 int mode;
00462
00463 mode = acoder->get_model_sym(acoder, &sc->intra_region);
00464
00465 if (!mode) {
00466 int i, j, pix, rgb_pix;
00467 int stride = c->pal_stride;
00468 int rgb_stride = c->rgb_stride;
00469 uint8_t *dst = c->pal_pic + x + y * stride;
00470 uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * rgb_stride;
00471
00472 pix = decode_pixel(acoder, &sc->intra_pix_ctx, NULL, 0, 0);
00473 rgb_pix = c->pal[pix];
00474 for (i = 0; i < height; i++, dst += stride, rgb_dst += rgb_stride) {
00475 memset(dst, pix, width);
00476 if (c->rgb_pic)
00477 for (j = 0; j < width * 3; j += 3)
00478 AV_WB24(rgb_dst + j, rgb_pix);
00479 }
00480 } else {
00481 return decode_region(acoder, c->pal_pic, c->rgb_pic,
00482 x, y, width, height, c->pal_stride, c->rgb_stride,
00483 &sc->intra_pix_ctx, &c->pal[0]);
00484 }
00485
00486 return 0;
00487 }
00488
00489 static int decode_region_inter(SliceContext *sc, ArithCoder *acoder,
00490 int x, int y, int width, int height)
00491 {
00492 MSS12Context const *c = sc->c;
00493 int mode;
00494
00495 mode = acoder->get_model_sym(acoder, &sc->inter_region);
00496
00497 if (!mode) {
00498 mode = decode_pixel(acoder, &sc->inter_pix_ctx, NULL, 0, 0);
00499
00500 if (c->avctx->err_recognition & AV_EF_EXPLODE &&
00501 ( c->rgb_pic && mode != 0x01 && mode != 0x02 && mode != 0x04 ||
00502 !c->rgb_pic && mode != 0x80 && mode != 0xFF))
00503 return -1;
00504
00505 if (mode == 0x02)
00506 copy_rectangles(c, x, y, width, height);
00507 else if (mode == 0x04)
00508 return motion_compensation(c, x, y, width, height);
00509 else if (mode != 0x80)
00510 return decode_region_intra(sc, acoder, x, y, width, height);
00511 } else {
00512 if (decode_region(acoder, c->mask, NULL,
00513 x, y, width, height, c->mask_stride, 0,
00514 &sc->inter_pix_ctx, &c->pal[0]) < 0)
00515 return -1;
00516 return decode_region_masked(c, acoder, c->pal_pic,
00517 c->pal_stride, c->mask,
00518 c->mask_stride,
00519 x, y, width, height,
00520 &sc->intra_pix_ctx);
00521 }
00522
00523 return 0;
00524 }
00525
00526 int ff_mss12_decode_rect(SliceContext *sc, ArithCoder *acoder,
00527 int x, int y, int width, int height)
00528 {
00529 int mode, pivot;
00530
00531 mode = acoder->get_model_sym(acoder, &sc->split_mode);
00532
00533 switch (mode) {
00534 case SPLIT_VERT:
00535 if ((pivot = decode_pivot(sc, acoder, height)) < 1)
00536 return -1;
00537 if (ff_mss12_decode_rect(sc, acoder, x, y, width, pivot))
00538 return -1;
00539 if (ff_mss12_decode_rect(sc, acoder, x, y + pivot, width, height - pivot))
00540 return -1;
00541 break;
00542 case SPLIT_HOR:
00543 if ((pivot = decode_pivot(sc, acoder, width)) < 1)
00544 return -1;
00545 if (ff_mss12_decode_rect(sc, acoder, x, y, pivot, height))
00546 return -1;
00547 if (ff_mss12_decode_rect(sc, acoder, x + pivot, y, width - pivot, height))
00548 return -1;
00549 break;
00550 case SPLIT_NONE:
00551 if (sc->c->keyframe)
00552 return decode_region_intra(sc, acoder, x, y, width, height);
00553 else
00554 return decode_region_inter(sc, acoder, x, y, width, height);
00555 default:
00556 return -1;
00557 }
00558
00559 return 0;
00560 }
00561
00562 av_cold int ff_mss12_decode_init(MSS12Context *c, int version,
00563 SliceContext* sc1, SliceContext *sc2)
00564 {
00565 AVCodecContext *avctx = c->avctx;
00566 int i;
00567
00568 if (avctx->extradata_size < 52 + 256 * 3) {
00569 av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d\n",
00570 avctx->extradata_size);
00571 return AVERROR_INVALIDDATA;
00572 }
00573
00574 if (AV_RB32(avctx->extradata) < avctx->extradata_size) {
00575 av_log(avctx, AV_LOG_ERROR,
00576 "Insufficient extradata size: expected %d got %d\n",
00577 AV_RB32(avctx->extradata),
00578 avctx->extradata_size);
00579 return AVERROR_INVALIDDATA;
00580 }
00581
00582 avctx->coded_width = AV_RB32(avctx->extradata + 20);
00583 avctx->coded_height = AV_RB32(avctx->extradata + 24);
00584 if (avctx->coded_width > 4096 || avctx->coded_height > 4096) {
00585 av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too large",
00586 avctx->coded_width, avctx->coded_height);
00587 return AVERROR_INVALIDDATA;
00588 }
00589
00590 av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d\n",
00591 AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8));
00592 if (version != AV_RB32(avctx->extradata + 4) > 1) {
00593 av_log(avctx, AV_LOG_ERROR,
00594 "Header version doesn't match codec tag\n");
00595 return -1;
00596 }
00597
00598 c->free_colours = AV_RB32(avctx->extradata + 48);
00599 if ((unsigned)c->free_colours > 256) {
00600 av_log(avctx, AV_LOG_ERROR,
00601 "Incorrect number of changeable palette entries: %d\n",
00602 c->free_colours);
00603 return AVERROR_INVALIDDATA;
00604 }
00605 av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours);
00606
00607 av_log(avctx, AV_LOG_DEBUG, "Display dimensions %dx%d\n",
00608 AV_RB32(avctx->extradata + 12), AV_RB32(avctx->extradata + 16));
00609 av_log(avctx, AV_LOG_DEBUG, "Coded dimensions %dx%d\n",
00610 avctx->coded_width, avctx->coded_height);
00611 av_log(avctx, AV_LOG_DEBUG, "%g frames per second\n",
00612 av_int2float(AV_RB32(avctx->extradata + 28)));
00613 av_log(avctx, AV_LOG_DEBUG, "Bitrate %d bps\n",
00614 AV_RB32(avctx->extradata + 32));
00615 av_log(avctx, AV_LOG_DEBUG, "Max. lead time %g ms\n",
00616 av_int2float(AV_RB32(avctx->extradata + 36)));
00617 av_log(avctx, AV_LOG_DEBUG, "Max. lag time %g ms\n",
00618 av_int2float(AV_RB32(avctx->extradata + 40)));
00619 av_log(avctx, AV_LOG_DEBUG, "Max. seek time %g ms\n",
00620 av_int2float(AV_RB32(avctx->extradata + 44)));
00621
00622 if (version) {
00623 if (avctx->extradata_size < 60 + 256 * 3) {
00624 av_log(avctx, AV_LOG_ERROR,
00625 "Insufficient extradata size %d for v2\n",
00626 avctx->extradata_size);
00627 return AVERROR_INVALIDDATA;
00628 }
00629
00630 c->slice_split = AV_RB32(avctx->extradata + 52);
00631 av_log(avctx, AV_LOG_DEBUG, "Slice split %d\n", c->slice_split);
00632
00633 c->full_model_syms = AV_RB32(avctx->extradata + 56);
00634 if (c->full_model_syms < 2 || c->full_model_syms > 256) {
00635 av_log(avctx, AV_LOG_ERROR,
00636 "Incorrect number of used colours %d\n",
00637 c->full_model_syms);
00638 return AVERROR_INVALIDDATA;
00639 }
00640 av_log(avctx, AV_LOG_DEBUG, "Used colours %d\n",
00641 c->full_model_syms);
00642 } else {
00643 c->slice_split = 0;
00644 c->full_model_syms = 256;
00645 }
00646
00647 for (i = 0; i < 256; i++)
00648 c->pal[i] = 0xFF << 24 | AV_RB24(avctx->extradata + 52 +
00649 (version ? 8 : 0) + i * 3);
00650
00651 c->mask_stride = FFALIGN(avctx->width, 16);
00652 c->mask = av_malloc(c->mask_stride * avctx->height);
00653 if (!c->mask) {
00654 av_log(avctx, AV_LOG_ERROR, "Cannot allocate mask plane\n");
00655 return AVERROR(ENOMEM);
00656 }
00657
00658 sc1->c = c;
00659 slicecontext_init(sc1, version, c->full_model_syms);
00660 if (c->slice_split) {
00661 sc2->c = c;
00662 slicecontext_init(sc2, version, c->full_model_syms);
00663 }
00664 c->corrupted = 1;
00665
00666 return 0;
00667 }
00668
00669 av_cold int ff_mss12_decode_end(MSS12Context *c)
00670 {
00671 av_freep(&c->mask);
00672
00673 return 0;
00674 }