LCOV - code coverage report
Current view: top level - libavcodec - intrax8.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 363 380 95.5 %
Date: 2017-12-10 21:22:29 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This file is part of FFmpeg.
       3             :  *
       4             :  * FFmpeg is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Lesser General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2.1 of the License, or (at your option) any later version.
       8             :  *
       9             :  * FFmpeg is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Lesser General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public
      15             :  * License along with FFmpeg; if not, write to the Free Software
      16             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      17             :  */
      18             : 
      19             : /**
      20             :  * @file
      21             :  * @brief IntraX8 (J-Frame) subdecoder, used by WMV2 and VC-1
      22             :  */
      23             : 
      24             : #include "libavutil/avassert.h"
      25             : #include "avcodec.h"
      26             : #include "get_bits.h"
      27             : #include "idctdsp.h"
      28             : #include "msmpeg4data.h"
      29             : #include "intrax8huf.h"
      30             : #include "intrax8.h"
      31             : #include "intrax8dsp.h"
      32             : #include "mpegutils.h"
      33             : 
      34             : #define MAX_TABLE_DEPTH(table_bits, max_bits) \
      35             :     ((max_bits + table_bits - 1) / table_bits)
      36             : 
      37             : #define DC_VLC_BITS 9
      38             : #define AC_VLC_BITS 9
      39             : #define OR_VLC_BITS 7
      40             : 
      41             : #define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS)
      42             : #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS)
      43             : #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS)
      44             : 
      45             : static VLC j_ac_vlc[2][2][8];  // [quant < 13], [intra / inter], [select]
      46             : static VLC j_dc_vlc[2][8];     // [quant], [select]
      47             : static VLC j_orient_vlc[2][4]; // [quant], [select]
      48             : 
      49          48 : static av_cold int x8_vlc_init(void)
      50             : {
      51             :     int i;
      52          48 :     int offset = 0;
      53          48 :     int sizeidx = 0;
      54             :     static const uint16_t sizes[8 * 4 + 8 * 2 + 2 + 4] = {
      55             :         576, 548, 582, 618, 546, 616, 560, 642,
      56             :         584, 582, 704, 664, 512, 544, 656, 640,
      57             :         512, 648, 582, 566, 532, 614, 596, 648,
      58             :         586, 552, 584, 590, 544, 578, 584, 624,
      59             : 
      60             :         528, 528, 526, 528, 536, 528, 526, 544,
      61             :         544, 512, 512, 528, 528, 544, 512, 544,
      62             : 
      63             :         128, 128, 128, 128, 128, 128,
      64             :     };
      65             : 
      66             :     static VLC_TYPE table[28150][2];
      67             : 
      68             : // set ac tables
      69             : #define init_ac_vlc(dst, src)                                                 \
      70             :     do {                                                                      \
      71             :         dst.table           = &table[offset];                                 \
      72             :         dst.table_allocated = sizes[sizeidx];                                 \
      73             :         offset             += sizes[sizeidx++];                               \
      74             :         init_vlc(&dst, AC_VLC_BITS, 77, &src[1], 4, 2, &src[0], 4, 2,         \
      75             :                  INIT_VLC_USE_NEW_STATIC);                                    \
      76             :     } while(0)
      77             : 
      78         432 :     for (i = 0; i < 8; i++) {
      79         384 :         init_ac_vlc(j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0]);
      80         384 :         init_ac_vlc(j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0]);
      81         384 :         init_ac_vlc(j_ac_vlc[1][0][i], x8_ac0_lowquant_table[i][0]);
      82         384 :         init_ac_vlc(j_ac_vlc[1][1][i], x8_ac1_lowquant_table[i][0]);
      83             :     }
      84             : #undef init_ac_vlc
      85             : 
      86             : // set dc tables
      87             : #define init_dc_vlc(dst, src)                                                 \
      88             :     do {                                                                      \
      89             :         dst.table           = &table[offset];                                 \
      90             :         dst.table_allocated = sizes[sizeidx];                                 \
      91             :         offset             += sizes[sizeidx++];                               \
      92             :         init_vlc(&dst, DC_VLC_BITS, 34, &src[1], 4, 2, &src[0], 4, 2,         \
      93             :                  INIT_VLC_USE_NEW_STATIC);                                    \
      94             :     } while(0)
      95             : 
      96         432 :     for (i = 0; i < 8; i++) {
      97         384 :         init_dc_vlc(j_dc_vlc[0][i], x8_dc_highquant_table[i][0]);
      98         384 :         init_dc_vlc(j_dc_vlc[1][i], x8_dc_lowquant_table[i][0]);
      99             :     }
     100             : #undef init_dc_vlc
     101             : 
     102             : // set orient tables
     103             : #define init_or_vlc(dst, src)                                                 \
     104             :     do {                                                                      \
     105             :         dst.table           = &table[offset];                                 \
     106             :         dst.table_allocated = sizes[sizeidx];                                 \
     107             :         offset             += sizes[sizeidx++];                               \
     108             :         init_vlc(&dst, OR_VLC_BITS, 12, &src[1], 4, 2, &src[0], 4, 2,         \
     109             :                  INIT_VLC_USE_NEW_STATIC);                                    \
     110             :     } while(0)
     111             : 
     112         144 :     for (i = 0; i < 2; i++)
     113          96 :         init_or_vlc(j_orient_vlc[0][i], x8_orient_highquant_table[i][0]);
     114         240 :     for (i = 0; i < 4; i++)
     115         192 :         init_or_vlc(j_orient_vlc[1][i], x8_orient_lowquant_table[i][0]);
     116             : #undef init_or_vlc
     117             : 
     118          48 :     if (offset != sizeof(table) / sizeof(VLC_TYPE) / 2) {
     119           0 :         av_log(NULL, AV_LOG_ERROR, "table size %"SIZE_SPECIFIER" does not match needed %i\n",
     120             :                sizeof(table) / sizeof(VLC_TYPE) / 2, offset);
     121           0 :         return AVERROR_INVALIDDATA;
     122             :     }
     123             : 
     124          48 :     return 0;
     125             : }
     126             : 
     127           3 : static void x8_reset_vlc_tables(IntraX8Context *w)
     128             : {
     129           3 :     memset(w->j_dc_vlc, 0, sizeof(w->j_dc_vlc));
     130           3 :     memset(w->j_ac_vlc, 0, sizeof(w->j_ac_vlc));
     131           3 :     w->j_orient_vlc = NULL;
     132           3 : }
     133             : 
     134        3909 : static inline void x8_select_ac_table(IntraX8Context *const w, int mode)
     135             : {
     136             :     int table_index;
     137             : 
     138             :     av_assert2(mode < 4);
     139             : 
     140        3909 :     if (w->j_ac_vlc[mode])
     141        3897 :         return;
     142             : 
     143          12 :     table_index       = get_bits(w->gb, 3);
     144             :     // 2 modes use same tables
     145          12 :     w->j_ac_vlc[mode] = &j_ac_vlc[w->quant < 13][mode >> 1][table_index];
     146             :     av_assert2(w->j_ac_vlc[mode]);
     147             : }
     148             : 
     149        1304 : static inline int x8_get_orient_vlc(IntraX8Context *w)
     150             : {
     151        1304 :     if (!w->j_orient_vlc) {
     152           3 :         int table_index = get_bits(w->gb, 1 + (w->quant < 13));
     153           3 :         w->j_orient_vlc = &j_orient_vlc[w->quant < 13][table_index];
     154             :     }
     155             : 
     156        1304 :     return get_vlc2(w->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD);
     157             : }
     158             : 
     159             : #define extra_bits(eb)  (eb)        // 3 bits
     160             : #define extra_run       (0xFF << 8) // 1 bit
     161             : #define extra_level     (0x00 << 8) // 1 bit
     162             : #define run_offset(r)   ((r) << 16) // 6 bits
     163             : #define level_offset(l) ((l) << 24) // 5 bits
     164             : static const uint32_t ac_decode_table[] = {
     165             :     /* 46 */ extra_bits(3) | extra_run   | run_offset(16) | level_offset(0),
     166             :     /* 47 */ extra_bits(3) | extra_run   | run_offset(24) | level_offset(0),
     167             :     /* 48 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
     168             :     /* 49 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
     169             : 
     170             :     /* 50 */ extra_bits(5) | extra_run   | run_offset(32) | level_offset(0),
     171             :     /* 51 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
     172             : 
     173             :     /* 52 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
     174             :     /* 53 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(8),
     175             :     /* 54 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(12),
     176             :     /* 55 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(16),
     177             :     /* 56 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(24),
     178             : 
     179             :     /* 57 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
     180             :     /* 58 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
     181             : 
     182             :     /* 59 */ extra_bits(2) | extra_run   | run_offset(16) | level_offset(0),
     183             :     /* 60 */ extra_bits(2) | extra_run   | run_offset(20) | level_offset(0),
     184             :     /* 61 */ extra_bits(2) | extra_run   | run_offset(24) | level_offset(0),
     185             :     /* 62 */ extra_bits(2) | extra_run   | run_offset(28) | level_offset(0),
     186             :     /* 63 */ extra_bits(4) | extra_run   | run_offset(32) | level_offset(0),
     187             :     /* 64 */ extra_bits(4) | extra_run   | run_offset(48) | level_offset(0),
     188             : 
     189             :     /* 65 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
     190             :     /* 66 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
     191             :     /* 67 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
     192             : 
     193             :     /* 68 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
     194             :     /* 69 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(8),
     195             :     /* 70 */ extra_bits(4) | extra_level | run_offset(0)  | level_offset(16),
     196             : 
     197             :     /* 71 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
     198             :     /* 72 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
     199             : };
     200             : #undef extra_bits
     201             : #undef extra_run
     202             : #undef extra_level
     203             : #undef run_offset
     204             : #undef level_offset
     205             : 
     206        8932 : static void x8_get_ac_rlf(IntraX8Context *const w, const int mode,
     207             :                           int *const run, int *const level, int *const final)
     208             : {
     209             :     int i, e;
     210             : 
     211             : //    x8_select_ac_table(w, mode);
     212        8932 :     i = get_vlc2(w->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD);
     213             : 
     214        8932 :     if (i < 46) { // [0-45]
     215             :         int t, l;
     216        7635 :         if (i < 0) {
     217           0 :             *level =
     218           0 :             *final =      // prevent 'may be used uninitialized'
     219           0 :             *run   = 64;  // this would cause error exit in the ac loop
     220           0 :             return;
     221             :         }
     222             : 
     223             :         /*
     224             :          * i == 0-15  r = 0-15 l = 0; r = i & %01111
     225             :          * i == 16-19 r = 0-3  l = 1; r = i & %00011
     226             :          * i == 20-21 r = 0-1  l = 2; r = i & %00001
     227             :          * i == 22    r = 0    l = 3; r = i & %00000
     228             :          */
     229             : 
     230        7635 :         *final =
     231        7635 :         t      = i > 22;
     232        7635 :         i     -= 23 * t;
     233             : 
     234             :         /* l = lut_l[i / 2] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3 }[i >> 1];
     235             :          *     11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 */
     236        7635 :         l = (0xE50000 >> (i & 0x1E)) & 3; // 0x1E or ~1 or (i >> 1 << 1)
     237             : 
     238             :         /* t = lut_mask[l] = { 0x0f, 0x03, 0x01, 0x00 }[l];
     239             :          *     as i < 256 the higher bits do not matter */
     240        7635 :         t = 0x01030F >> (l << 3);
     241             : 
     242        7635 :         *run   = i & t;
     243        7635 :         *level = l;
     244        1297 :     } else if (i < 73) { // [46-72]
     245             :         uint32_t sm;
     246             :         uint32_t mask;
     247             : 
     248        1057 :         i -= 46;
     249        1057 :         sm = ac_decode_table[i];
     250             : 
     251        1057 :         e    = get_bits(w->gb, sm & 0xF);
     252        1057 :         sm >>= 8;                               // 3 bits
     253        1057 :         mask = sm & 0xff;
     254        1057 :         sm >>= 8;                               // 1 bit
     255             : 
     256        1057 :         *run   = (sm &  0xff) + (e &  mask);    // 6 bits
     257        1057 :         *level = (sm >>    8) + (e & ~mask);    // 5 bits
     258        1057 :         *final = i > (58 - 46);
     259         240 :     } else if (i < 75) { // [73-74]
     260             :         static const uint8_t crazy_mix_runlevel[32] = {
     261             :             0x22, 0x32, 0x33, 0x53, 0x23, 0x42, 0x43, 0x63,
     262             :             0x24, 0x52, 0x34, 0x73, 0x25, 0x62, 0x44, 0x83,
     263             :             0x26, 0x72, 0x35, 0x54, 0x27, 0x82, 0x45, 0x64,
     264             :             0x28, 0x92, 0x36, 0x74, 0x29, 0xa2, 0x46, 0x84,
     265             :         };
     266             : 
     267         234 :         *final = !(i & 1);
     268         234 :         e      = get_bits(w->gb, 5); // get the extra bits
     269         234 :         *run   = crazy_mix_runlevel[e] >> 4;
     270         234 :         *level = crazy_mix_runlevel[e] & 0x0F;
     271             :     } else {
     272           6 :         *level = get_bits(w->gb, 7 - 3 * (i & 1));
     273           6 :         *run   = get_bits(w->gb, 6);
     274           6 :         *final = get_bits1(w->gb);
     275             :     }
     276        8932 :     return;
     277             : }
     278             : 
     279             : /* static const uint8_t dc_extra_sbits[] = {
     280             :  *     0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
     281             :  * }; */
     282             : static const uint8_t dc_index_offset[] = {
     283             :     0, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
     284             : };
     285             : 
     286        5400 : static int x8_get_dc_rlf(IntraX8Context *const w, const int mode,
     287             :                          int *const level, int *const final)
     288             : {
     289             :     int i, e, c;
     290             : 
     291             :     av_assert2(mode < 3);
     292        5400 :     if (!w->j_dc_vlc[mode]) {
     293           9 :         int table_index = get_bits(w->gb, 3);
     294             :         // 4 modes, same table
     295           9 :         w->j_dc_vlc[mode] = &j_dc_vlc[w->quant < 13][table_index];
     296             :     }
     297             : 
     298        5400 :     i = get_vlc2(w->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD);
     299             : 
     300             :     /* (i >= 17) { i -= 17; final =1; } */
     301        5400 :     c      = i > 16;
     302        5400 :     *final = c;
     303        5400 :     i      -= 17 * c;
     304             : 
     305        5400 :     if (i <= 0) {
     306        1320 :         *level = 0;
     307        1320 :         return -i;
     308             :     }
     309        4080 :     c  = (i + 1) >> 1; // hackish way to calculate dc_extra_sbits[]
     310        4080 :     c -= c > 1;
     311             : 
     312        4080 :     e = get_bits(w->gb, c); // get the extra bits
     313        4080 :     i = dc_index_offset[i] + (e >> 1);
     314             : 
     315        4080 :     e      = -(e & 1);     // 0, 0xffffff
     316        4080 :     *level =  (i ^ e) - e; // (i ^ 0) - 0, (i ^ 0xff) - (-1)
     317        4080 :     return 0;
     318             : }
     319             : 
     320             : // end of huffman
     321             : 
     322        5400 : static int x8_setup_spatial_predictor(IntraX8Context *const w, const int chroma)
     323             : {
     324             :     int range;
     325             :     int sum;
     326             :     int quant;
     327             : 
     328       10800 :     w->dsp.setup_spatial_compensation(w->dest[chroma], w->scratchpad,
     329        5400 :                                       w->frame->linesize[chroma > 0],
     330             :                                       &range, &sum, w->edges);
     331        5400 :     if (chroma) {
     332        1800 :         w->orient = w->chroma_orient;
     333        1800 :         quant     = w->quant_dc_chroma;
     334             :     } else {
     335        3600 :         quant = w->quant;
     336             :     }
     337             : 
     338        5400 :     w->flat_dc = 0;
     339        5400 :     if (range < quant || range < 3) {
     340        3386 :         w->orient = 0;
     341             : 
     342             :         // yep you read right, a +-1 idct error may break decoding!
     343        3386 :         if (range < 3) {
     344        1365 :             w->flat_dc      = 1;
     345        1365 :             sum            += 9;
     346             :             // ((1 << 17) + 9) / (8 + 8 + 1 + 2) = 6899
     347        1365 :             w->predicted_dc = sum * 6899 >> 17;
     348             :         }
     349             :     }
     350        5400 :     if (chroma)
     351        1800 :         return 0;
     352             : 
     353             :     av_assert2(w->orient < 3);
     354        3600 :     if (range < 2 * w->quant) {
     355        2296 :         if ((w->edges & 3) == 0) {
     356        2102 :             if (w->orient == 1)
     357           6 :                 w->orient = 11;
     358        2102 :             if (w->orient == 2)
     359          16 :                 w->orient = 10;
     360             :         } else {
     361         194 :             w->orient = 0;
     362             :         }
     363        2296 :         w->raw_orient = 0;
     364             :     } else {
     365             :         static const uint8_t prediction_table[3][12] = {
     366             :             { 0, 8, 4, 10, 11, 2, 6, 9, 1, 3, 5, 7 },
     367             :             { 4, 0, 8, 11, 10, 3, 5, 2, 6, 9, 1, 7 },
     368             :             { 8, 0, 4, 10, 11, 1, 7, 2, 6, 9, 3, 5 },
     369             :         };
     370        1304 :         w->raw_orient = x8_get_orient_vlc(w);
     371        1304 :         if (w->raw_orient < 0)
     372           0 :             return -1;
     373             :         av_assert2(w->raw_orient < 12);
     374             :         av_assert2(w->orient < 3);
     375        1304 :         w->orient=prediction_table[w->orient][w->raw_orient];
     376             :     }
     377        3600 :     return 0;
     378             : }
     379             : 
     380        3600 : static void x8_update_predictions(IntraX8Context *const w, const int orient,
     381             :                                   const int est_run)
     382             : {
     383        3600 :     w->prediction_table[w->mb_x * 2 + (w->mb_y & 1)] = (est_run << 2) + 1 * (orient == 4) + 2 * (orient == 8);
     384             : /*
     385             :  * y = 2n + 0 -> // 0 2 4
     386             :  * y = 2n + 1 -> // 1 3 5
     387             :  */
     388        3600 : }
     389             : 
     390         900 : static void x8_get_prediction_chroma(IntraX8Context *const w)
     391             : {
     392         900 :     w->edges  = 1 * !(w->mb_x >> 1);
     393         900 :     w->edges |= 2 * !(w->mb_y >> 1);
     394         900 :     w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1)); // mb_x for chroma would always be odd
     395             : 
     396         900 :     w->raw_orient = 0;
     397             :     // lut_co[8] = {inv,4,8,8, inv,4,8,8} <- => {1,1,0,0;1,1,0,0} => 0xCC
     398         900 :     if (w->edges & 3) {
     399         102 :         w->chroma_orient = 4 << ((0xCC >> w->edges) & 1);
     400         102 :         return;
     401             :     }
     402             :     // block[x - 1][y | 1 - 1)]
     403         798 :     w->chroma_orient = (w->prediction_table[2 * w->mb_x - 2] & 0x03) << 2;
     404             : }
     405             : 
     406        3600 : static void x8_get_prediction(IntraX8Context *const w)
     407             : {
     408             :     int a, b, c, i;
     409             : 
     410        3600 :     w->edges  = 1 * !w->mb_x;
     411        3600 :     w->edges |= 2 * !w->mb_y;
     412        3600 :     w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1));
     413             : 
     414        3600 :     switch (w->edges & 3) {
     415        3393 :     case 0:
     416        3393 :         break;
     417          87 :     case 1:
     418             :         // take the one from the above block[0][y - 1]
     419          87 :         w->est_run = w->prediction_table[!(w->mb_y & 1)] >> 2;
     420          87 :         w->orient  = 1;
     421          87 :         return;
     422         117 :     case 2:
     423             :         // take the one from the previous block[x - 1][0]
     424         117 :         w->est_run = w->prediction_table[2 * w->mb_x - 2] >> 2;
     425         117 :         w->orient  = 2;
     426         117 :         return;
     427           3 :     case 3:
     428           3 :         w->est_run = 16;
     429           3 :         w->orient  = 0;
     430           3 :         return;
     431             :     }
     432             :     // no edge cases
     433        3393 :     b = w->prediction_table[2 * w->mb_x     + !(w->mb_y & 1)]; // block[x    ][y - 1]
     434        3393 :     a = w->prediction_table[2 * w->mb_x - 2 +  (w->mb_y & 1)]; // block[x - 1][y    ]
     435        3393 :     c = w->prediction_table[2 * w->mb_x - 2 + !(w->mb_y & 1)]; // block[x - 1][y - 1]
     436             : 
     437        3393 :     w->est_run = FFMIN(b, a);
     438             :     /* This condition has nothing to do with w->edges, even if it looks
     439             :      * similar it would trigger if e.g. x = 3; y = 2;
     440             :      * I guess somebody wrote something wrong and it became standard. */
     441        3393 :     if ((w->mb_x & w->mb_y) != 0)
     442        2565 :         w->est_run = FFMIN(c, w->est_run);
     443        3393 :     w->est_run >>= 2;
     444             : 
     445        3393 :     a &= 3;
     446        3393 :     b &= 3;
     447        3393 :     c &= 3;
     448             : 
     449        3393 :     i = (0xFFEAF4C4 >> (2 * b + 8 * a)) & 3;
     450        3393 :     if (i != 3)
     451        3373 :         w->orient = i;
     452             :     else
     453          20 :         w->orient = (0xFFEAD8 >> (2 * c + 8 * (w->quant > 12))) & 3;
     454             : /*
     455             :  * lut1[b][a] = {
     456             :  * ->{ 0, 1, 0, pad },
     457             :  *   { 0, 1, X, pad },
     458             :  *   { 2, 2, 2, pad }
     459             :  * }
     460             :  * pad 2  2  2;
     461             :  * pad X  1  0;
     462             :  * pad 0  1  0 <-
     463             :  * -> 11 10 '10 10 '11 11'01 00 '11 00'01 00 => 0xEAF4C4
     464             :  *
     465             :  * lut2[q>12][c] = {
     466             :  * ->{ 0, 2, 1, pad},
     467             :  *   { 2, 2, 2, pad}
     468             :  * }
     469             :  * pad 2  2  2;
     470             :  * pad 1  2  0 <-
     471             :  * -> 11 10'10 10 '11 01'10 00 => 0xEAD8
     472             :  */
     473             : }
     474             : 
     475        2761 : static void x8_ac_compensation(IntraX8Context *const w, const int direction,
     476             :                                const int dc_level)
     477             : {
     478             :     int t;
     479             : #define B(x,y)  w->block[0][w->idct_permutation[(x) + (y) * 8]]
     480             : #define T(x)  ((x) * dc_level + 0x8000) >> 16;
     481        2761 :     switch (direction) {
     482        1946 :     case 0:
     483        1946 :         t        = T(3811); // h
     484        1946 :         B(1, 0) -= t;
     485        1946 :         B(0, 1) -= t;
     486             : 
     487        1946 :         t        = T(487); // e
     488        1946 :         B(2, 0) -= t;
     489        1946 :         B(0, 2) -= t;
     490             : 
     491        1946 :         t        = T(506); // f
     492        1946 :         B(3, 0) -= t;
     493        1946 :         B(0, 3) -= t;
     494             : 
     495        1946 :         t        = T(135); // c
     496        1946 :         B(4, 0) -= t;
     497        1946 :         B(0, 4) -= t;
     498        1946 :         B(2, 1) += t;
     499        1946 :         B(1, 2) += t;
     500        1946 :         B(3, 1) += t;
     501        1946 :         B(1, 3) += t;
     502             : 
     503        1946 :         t        = T(173); // d
     504        1946 :         B(5, 0) -= t;
     505        1946 :         B(0, 5) -= t;
     506             : 
     507        1946 :         t        = T(61); // b
     508        1946 :         B(6, 0) -= t;
     509        1946 :         B(0, 6) -= t;
     510        1946 :         B(5, 1) += t;
     511        1946 :         B(1, 5) += t;
     512             : 
     513        1946 :         t        = T(42); // a
     514        1946 :         B(7, 0) -= t;
     515        1946 :         B(0, 7) -= t;
     516        1946 :         B(4, 1) += t;
     517        1946 :         B(1, 4) += t;
     518        1946 :         B(4, 4) += t;
     519             : 
     520        1946 :         t        = T(1084); // g
     521        1946 :         B(1, 1) += t;
     522             : 
     523        1946 :         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
     524        1946 :         break;
     525         312 :     case 1:
     526         312 :         B(0, 1) -= T(6269);
     527         312 :         B(0, 3) -= T(708);
     528         312 :         B(0, 5) -= T(172);
     529         312 :         B(0, 7) -= T(73);
     530             : 
     531         312 :         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
     532         312 :         break;
     533         503 :     case 2:
     534         503 :         B(1, 0) -= T(6269);
     535         503 :         B(3, 0) -= T(708);
     536         503 :         B(5, 0) -= T(172);
     537         503 :         B(7, 0) -= T(73);
     538             : 
     539         503 :         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7);
     540         503 :         break;
     541             :     }
     542             : #undef B
     543             : #undef T
     544        2761 : }
     545             : 
     546        1365 : static void dsp_x8_put_solidcolor(const uint8_t pix, uint8_t *dst,
     547             :                                   const ptrdiff_t linesize)
     548             : {
     549             :     int k;
     550       12285 :     for (k = 0; k < 8; k++) {
     551       10920 :         memset(dst, pix, 8);
     552       10920 :         dst += linesize;
     553             :     }
     554        1365 : }
     555             : 
     556             : static const int16_t quant_table[64] = {
     557             :     256, 256, 256, 256, 256, 256, 259, 262,
     558             :     265, 269, 272, 275, 278, 282, 285, 288,
     559             :     292, 295, 299, 303, 306, 310, 314, 317,
     560             :     321, 325, 329, 333, 337, 341, 345, 349,
     561             :     353, 358, 362, 366, 371, 375, 379, 384,
     562             :     389, 393, 398, 403, 408, 413, 417, 422,
     563             :     428, 433, 438, 443, 448, 454, 459, 465,
     564             :     470, 476, 482, 488, 493, 499, 505, 511,
     565             : };
     566             : 
     567        5400 : static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma)
     568             : {
     569             :     uint8_t *scantable;
     570             :     int final, run, level;
     571             :     int ac_mode, dc_mode, est_run, dc_level;
     572             :     int pos, n;
     573             :     int zeros_only;
     574             :     int use_quant_matrix;
     575             :     int sign;
     576             : 
     577             :     av_assert2(w->orient < 12);
     578        5400 :     w->bdsp.clear_block(w->block[0]);
     579             : 
     580        5400 :     if (chroma)
     581        1800 :         dc_mode = 2;
     582             :     else
     583        3600 :         dc_mode = !!w->est_run; // 0, 1
     584             : 
     585        5400 :     if (x8_get_dc_rlf(w, dc_mode, &dc_level, &final))
     586           0 :         return -1;
     587        5400 :     n          = 0;
     588        5400 :     zeros_only = 0;
     589        5400 :     if (!final) { // decode ac
     590        1693 :         use_quant_matrix = w->use_quant_matrix;
     591        1693 :         if (chroma) {
     592         368 :             ac_mode = 1;
     593         368 :             est_run = 64; // not used
     594             :         } else {
     595        1325 :             if (w->raw_orient < 3)
     596         905 :                 use_quant_matrix = 0;
     597             : 
     598        1325 :             if (w->raw_orient > 4) {
     599         124 :                 ac_mode = 0;
     600         124 :                 est_run = 64;
     601             :             } else {
     602        1201 :                 if (w->est_run > 1) {
     603         540 :                     ac_mode = 2;
     604         540 :                     est_run = w->est_run;
     605             :                 } else {
     606         661 :                     ac_mode = 3;
     607         661 :                     est_run = 64;
     608             :                 }
     609             :             }
     610             :         }
     611        1693 :         x8_select_ac_table(w, ac_mode);
     612             :         /* scantable_selector[12] = { 0, 2, 0, 1, 1, 1, 0, 2, 2, 0, 1, 2 }; <-
     613             :          * -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 => 0x928548 */
     614        1693 :         scantable = w->scantable[(0x928548 >> (2 * w->orient)) & 3].permutated;
     615        1693 :         pos       = 0;
     616             :         do {
     617        8932 :             n++;
     618        8932 :             if (n >= est_run) {
     619        2216 :                 ac_mode = 3;
     620        2216 :                 x8_select_ac_table(w, 3);
     621             :             }
     622             : 
     623        8932 :             x8_get_ac_rlf(w, ac_mode, &run, &level, &final);
     624             : 
     625        8932 :             pos += run + 1;
     626        8932 :             if (pos > 63) {
     627             :                 // this also handles vlc error in x8_get_ac_rlf
     628           0 :                 return -1;
     629             :             }
     630        8932 :             level  = (level + 1) * w->dquant;
     631        8932 :             level += w->qsum;
     632             : 
     633        8932 :             sign  = -get_bits1(w->gb);
     634        8932 :             level = (level ^ sign) - sign;
     635             : 
     636        8932 :             if (use_quant_matrix)
     637        4784 :                 level = (level * quant_table[pos]) >> 8;
     638             : 
     639        8932 :             w->block[0][scantable[pos]] = level;
     640        8932 :         } while (!final);
     641             : 
     642        1693 :         w->block_last_index[0] = pos;
     643             :     } else { // DC only
     644        3707 :         w->block_last_index[0] = 0;
     645        3707 :         if (w->flat_dc && ((unsigned) (dc_level + 1)) < 3) { // [-1; 1]
     646        1189 :             int32_t divide_quant = !chroma ? w->divide_quant_dc_luma
     647        1189 :                                            : w->divide_quant_dc_chroma;
     648        1189 :             int32_t dc_quant     = !chroma ? w->quant
     649        1189 :                                            : w->quant_dc_chroma;
     650             : 
     651             :             // original intent dc_level += predicted_dc/quant;
     652             :             // but it got lost somewhere in the rounding
     653        1189 :             dc_level += (w->predicted_dc * divide_quant + (1 << 12)) >> 13;
     654             : 
     655        1189 :             dsp_x8_put_solidcolor(av_clip_uint8((dc_level * dc_quant + 4) >> 3),
     656             :                                   w->dest[chroma],
     657        1189 :                                   w->frame->linesize[!!chroma]);
     658             : 
     659        1189 :             goto block_placed;
     660             :         }
     661        2518 :         zeros_only = dc_level == 0;
     662             :     }
     663        4211 :     if (!chroma)
     664        3071 :         w->block[0][0] = dc_level * w->quant;
     665             :     else
     666        1140 :         w->block[0][0] = dc_level * w->quant_dc_chroma;
     667             : 
     668             :     // there is !zero_only check in the original, but dc_level check is enough
     669        4211 :     if ((unsigned int) (dc_level + 1) >= 3 && (w->edges & 3) != 3) {
     670             :         int direction;
     671             :         /* ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 }; <-
     672             :          * -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 => 0x6A017C */
     673        2780 :         direction = (0x6A017C >> (w->orient * 2)) & 3;
     674        2780 :         if (direction != 3) {
     675             :             // modify block_last[]
     676        2761 :             x8_ac_compensation(w, direction, w->block[0][0]);
     677             :         }
     678             :     }
     679             : 
     680        4211 :     if (w->flat_dc) {
     681         176 :         dsp_x8_put_solidcolor(w->predicted_dc, w->dest[chroma],
     682         176 :                               w->frame->linesize[!!chroma]);
     683             :     } else {
     684        8070 :         w->dsp.spatial_compensation[w->orient](w->scratchpad,
     685             :                                                w->dest[chroma],
     686        4035 :                                                w->frame->linesize[!!chroma]);
     687             :     }
     688        4211 :     if (!zeros_only)
     689        7650 :         w->wdsp.idct_add(w->dest[chroma],
     690        3825 :                          w->frame->linesize[!!chroma],
     691        3825 :                          w->block[0]);
     692             : 
     693        5786 : block_placed:
     694        5400 :     if (!chroma)
     695        3600 :         x8_update_predictions(w, w->orient, n);
     696             : 
     697        5400 :     if (w->loopfilter) {
     698        5400 :         uint8_t *ptr = w->dest[chroma];
     699        5400 :         ptrdiff_t linesize = w->frame->linesize[!!chroma];
     700             : 
     701        5400 :         if (!((w->edges & 2) || (zeros_only && (w->orient | 4) == 4)))
     702        4836 :             w->dsp.h_loop_filter(ptr, linesize, w->quant);
     703             : 
     704        5400 :         if (!((w->edges & 1) || (zeros_only && (w->orient | 8) == 8)))
     705        4849 :             w->dsp.v_loop_filter(ptr, linesize, w->quant);
     706             :     }
     707        5400 :     return 0;
     708             : }
     709             : 
     710             : // FIXME maybe merge with ff_*
     711          90 : static void x8_init_block_index(IntraX8Context *w, AVFrame *frame)
     712             : {
     713             :     // not parent codec linesize as this would be wrong for field pics
     714             :     // not that IntraX8 has interlacing support ;)
     715          90 :     const ptrdiff_t linesize   = frame->linesize[0];
     716          90 :     const ptrdiff_t uvlinesize = frame->linesize[1];
     717             : 
     718          90 :     w->dest[0] = frame->data[0];
     719          90 :     w->dest[1] = frame->data[1];
     720          90 :     w->dest[2] = frame->data[2];
     721             : 
     722          90 :     w->dest[0] +=  w->mb_y       * linesize   << 3;
     723             :     // chroma blocks are on add rows
     724          90 :     w->dest[1] += (w->mb_y & ~1) * uvlinesize << 2;
     725          90 :     w->dest[2] += (w->mb_y & ~1) * uvlinesize << 2;
     726          90 : }
     727             : 
     728          48 : av_cold int ff_intrax8_common_init(AVCodecContext *avctx,
     729             :                                    IntraX8Context *w, IDCTDSPContext *idsp,
     730             :                                    int16_t (*block)[64],
     731             :                                    int block_last_index[12],
     732             :                                    int mb_width, int mb_height)
     733             : {
     734          48 :     int ret = x8_vlc_init();
     735          48 :     if (ret < 0)
     736           0 :         return ret;
     737             : 
     738          48 :     w->avctx = avctx;
     739          48 :     w->idsp = *idsp;
     740          48 :     w->mb_width  = mb_width;
     741          48 :     w->mb_height = mb_height;
     742          48 :     w->block = block;
     743          48 :     w->block_last_index = block_last_index;
     744             : 
     745             :     // two rows, 2 blocks per cannon mb
     746          48 :     w->prediction_table = av_mallocz(w->mb_width * 2 * 2);
     747          48 :     if (!w->prediction_table)
     748           0 :         return AVERROR(ENOMEM);
     749             : 
     750          48 :     ff_wmv2dsp_init(&w->wdsp);
     751             : 
     752          48 :     ff_init_scantable_permutation(w->idct_permutation,
     753          48 :                                   w->wdsp.idct_perm);
     754             : 
     755          48 :     ff_init_scantable(w->idct_permutation, &w->scantable[0],
     756             :                       ff_wmv1_scantable[0]);
     757          48 :     ff_init_scantable(w->idct_permutation, &w->scantable[1],
     758             :                       ff_wmv1_scantable[2]);
     759          48 :     ff_init_scantable(w->idct_permutation, &w->scantable[2],
     760             :                       ff_wmv1_scantable[3]);
     761             : 
     762          48 :     ff_intrax8dsp_init(&w->dsp);
     763          48 :     ff_blockdsp_init(&w->bdsp, avctx);
     764             : 
     765          48 :     return 0;
     766             : }
     767             : 
     768          58 : av_cold void ff_intrax8_common_end(IntraX8Context *w)
     769             : {
     770          58 :     av_freep(&w->prediction_table);
     771          58 : }
     772             : 
     773           3 : int ff_intrax8_decode_picture(IntraX8Context *w, Picture *pict,
     774             :                               GetBitContext *gb, int *mb_x, int *mb_y,
     775             :                               int dquant, int quant_offset,
     776             :                               int loopfilter, int lowdelay)
     777             : {
     778             :     int mb_xy;
     779             : 
     780           3 :     w->gb     = gb;
     781           3 :     w->dquant = dquant;
     782           3 :     w->quant  = dquant >> 1;
     783           3 :     w->qsum   = quant_offset;
     784           3 :     w->frame  = pict->f;
     785           3 :     w->loopfilter = loopfilter;
     786           3 :     w->use_quant_matrix = get_bits1(w->gb);
     787             : 
     788           3 :     w->mb_x = *mb_x;
     789           3 :     w->mb_y = *mb_y;
     790             : 
     791           3 :     w->divide_quant_dc_luma = ((1 << 16) + (w->quant >> 1)) / w->quant;
     792           3 :     if (w->quant < 5) {
     793           0 :         w->quant_dc_chroma        = w->quant;
     794           0 :         w->divide_quant_dc_chroma = w->divide_quant_dc_luma;
     795             :     } else {
     796           3 :         w->quant_dc_chroma        = w->quant + ((w->quant + 3) >> 3);
     797           3 :         w->divide_quant_dc_chroma = ((1 << 16) + (w->quant_dc_chroma >> 1)) / w->quant_dc_chroma;
     798             :     }
     799           3 :     x8_reset_vlc_tables(w);
     800             : 
     801          93 :     for (w->mb_y = 0; w->mb_y < w->mb_height * 2; w->mb_y++) {
     802          90 :         x8_init_block_index(w, w->frame);
     803          90 :         mb_xy = (w->mb_y >> 1) * (w->mb_width + 1);
     804        3690 :         for (w->mb_x = 0; w->mb_x < w->mb_width * 2; w->mb_x++) {
     805        3600 :             x8_get_prediction(w);
     806        3600 :             if (x8_setup_spatial_predictor(w, 0))
     807           0 :                 goto error;
     808        3600 :             if (x8_decode_intra_mb(w, 0))
     809           0 :                 goto error;
     810             : 
     811        3600 :             if (w->mb_x & w->mb_y & 1) {
     812         900 :                 x8_get_prediction_chroma(w);
     813             : 
     814             :                 /* when setting up chroma, no vlc is read,
     815             :                  * so no error condition can be reached */
     816         900 :                 x8_setup_spatial_predictor(w, 1);
     817         900 :                 if (x8_decode_intra_mb(w, 1))
     818           0 :                     goto error;
     819             : 
     820         900 :                 x8_setup_spatial_predictor(w, 2);
     821         900 :                 if (x8_decode_intra_mb(w, 2))
     822           0 :                     goto error;
     823             : 
     824         900 :                 w->dest[1] += 8;
     825         900 :                 w->dest[2] += 8;
     826             : 
     827         900 :                 pict->qscale_table[mb_xy] = w->quant;
     828         900 :                 mb_xy++;
     829             :             }
     830        3600 :             w->dest[0] += 8;
     831             :         }
     832          90 :         if (w->mb_y & 1)
     833          45 :             ff_draw_horiz_band(w->avctx, w->frame, w->frame,
     834          45 :                                (w->mb_y - 1) * 8, 16,
     835             :                                PICT_FRAME, 0, lowdelay);
     836             :     }
     837             : 
     838           3 : error:
     839           3 :     *mb_x = w->mb_x;
     840           3 :     *mb_y = w->mb_y;
     841             : 
     842           3 :     return 0;
     843             : }

Generated by: LCOV version 1.13