LCOV - code coverage report
Current view: top level - libavcodec - mss12.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 348 387 89.9 %
Date: 2017-12-15 18:13:28 Functions: 21 21 100.0 %

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

Generated by: LCOV version 1.13