libavcodec/intrax8.c
9abc7e0f
 /*
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 /**
ba87f080
  * @file
c238beb5
  * @brief IntraX8 (J-Frame) subdecoder, used by WMV2 and VC-1
9abc7e0f
  */
 
aee675a3
 #include "libavutil/avassert.h"
9abc7e0f
 #include "avcodec.h"
9106a698
 #include "get_bits.h"
e3fcb143
 #include "idctdsp.h"
9abc7e0f
 #include "msmpeg4data.h"
 #include "intrax8huf.h"
 #include "intrax8.h"
15616eb0
 #include "intrax8dsp.h"
c2084ffc
 #include "mpegutils.h"
9abc7e0f
 
2ade1cda
 #define MAX_TABLE_DEPTH(table_bits, max_bits) \
     ((max_bits + table_bits - 1) / table_bits)
9abc7e0f
 
 #define DC_VLC_BITS 9
 #define AC_VLC_BITS 9
 #define OR_VLC_BITS 7
 
 #define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS)
 #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS)
 #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS)
 
2ade1cda
 static VLC j_ac_vlc[2][2][8];  // [quant < 13], [intra / inter], [select]
 static VLC j_dc_vlc[2][8];     // [quant], [select]
 static VLC j_orient_vlc[2][4]; // [quant], [select]
9abc7e0f
 
0372e73f
 static av_cold int x8_vlc_init(void)
2ade1cda
 {
9abc7e0f
     int i;
2f9bbdd2
     int offset = 0;
     int sizeidx = 0;
2ade1cda
     static const uint16_t sizes[8 * 4 + 8 * 2 + 2 + 4] = {
2f9bbdd2
         576, 548, 582, 618, 546, 616, 560, 642,
         584, 582, 704, 664, 512, 544, 656, 640,
         512, 648, 582, 566, 532, 614, 596, 648,
         586, 552, 584, 590, 544, 578, 584, 624,
 
         528, 528, 526, 528, 536, 528, 526, 544,
         544, 512, 512, 528, 528, 544, 512, 544,
 
2ade1cda
         128, 128, 128, 128, 128, 128,
     };
2f9bbdd2
 
     static VLC_TYPE table[28150][2];
9abc7e0f
 
2ade1cda
 // set ac tables
 #define init_ac_vlc(dst, src)                                                 \
     do {                                                                      \
         dst.table           = &table[offset];                                 \
         dst.table_allocated = sizes[sizeidx];                                 \
         offset             += sizes[sizeidx++];                               \
         init_vlc(&dst, AC_VLC_BITS, 77, &src[1], 4, 2, &src[0], 4, 2,         \
                  INIT_VLC_USE_NEW_STATIC);                                    \
75056254
     } while(0)
2ade1cda
 
     for (i = 0; i < 8; i++) {
         init_ac_vlc(j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0]);
         init_ac_vlc(j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0]);
         init_ac_vlc(j_ac_vlc[1][0][i], x8_ac0_lowquant_table[i][0]);
         init_ac_vlc(j_ac_vlc[1][1][i], x8_ac1_lowquant_table[i][0]);
9abc7e0f
     }
 #undef init_ac_vlc
 
2ade1cda
 // set dc tables
 #define init_dc_vlc(dst, src)                                                 \
     do {                                                                      \
         dst.table           = &table[offset];                                 \
         dst.table_allocated = sizes[sizeidx];                                 \
         offset             += sizes[sizeidx++];                               \
         init_vlc(&dst, DC_VLC_BITS, 34, &src[1], 4, 2, &src[0], 4, 2,         \
                  INIT_VLC_USE_NEW_STATIC);                                    \
75056254
     } while(0)
2ade1cda
 
     for (i = 0; i < 8; i++) {
         init_dc_vlc(j_dc_vlc[0][i], x8_dc_highquant_table[i][0]);
         init_dc_vlc(j_dc_vlc[1][i], x8_dc_lowquant_table[i][0]);
9abc7e0f
     }
 #undef init_dc_vlc
 
2ade1cda
 // set orient tables
 #define init_or_vlc(dst, src)                                                 \
     do {                                                                      \
         dst.table           = &table[offset];                                 \
         dst.table_allocated = sizes[sizeidx];                                 \
         offset             += sizes[sizeidx++];                               \
         init_vlc(&dst, OR_VLC_BITS, 12, &src[1], 4, 2, &src[0], 4, 2,         \
                  INIT_VLC_USE_NEW_STATIC);                                    \
75056254
     } while(0)
2ade1cda
 
     for (i = 0; i < 2; i++)
         init_or_vlc(j_orient_vlc[0][i], x8_orient_highquant_table[i][0]);
     for (i = 0; i < 4; i++)
         init_or_vlc(j_orient_vlc[1][i], x8_orient_lowquant_table[i][0]);
 #undef init_or_vlc
 
0372e73f
     if (offset != sizeof(table) / sizeof(VLC_TYPE) / 2) {
db8e8c97
         av_log(NULL, AV_LOG_ERROR, "table size %"SIZE_SPECIFIER" does not match needed %i\n",
6f5ff559
                sizeof(table) / sizeof(VLC_TYPE) / 2, offset);
0372e73f
         return AVERROR_INVALIDDATA;
     }
 
     return 0;
9abc7e0f
 }
 
2ade1cda
 static void x8_reset_vlc_tables(IntraX8Context *w)
 {
     memset(w->j_dc_vlc, 0, sizeof(w->j_dc_vlc));
     memset(w->j_ac_vlc, 0, sizeof(w->j_ac_vlc));
     w->j_orient_vlc = NULL;
9abc7e0f
 }
 
2ade1cda
 static inline void x8_select_ac_table(IntraX8Context *const w, int mode)
 {
9abc7e0f
     int table_index;
 
ba5bcf96
     av_assert2(mode < 4);
9abc7e0f
 
2ade1cda
     if (w->j_ac_vlc[mode])
         return;
 
8072345e
     table_index       = get_bits(w->gb, 3);
2ade1cda
     // 2 modes use same tables
     w->j_ac_vlc[mode] = &j_ac_vlc[w->quant < 13][mode >> 1][table_index];
aee675a3
     av_assert2(w->j_ac_vlc[mode]);
9abc7e0f
 }
 
2ade1cda
 static inline int x8_get_orient_vlc(IntraX8Context *w)
 {
     if (!w->j_orient_vlc) {
8072345e
         int table_index = get_bits(w->gb, 1 + (w->quant < 13));
2ade1cda
         w->j_orient_vlc = &j_orient_vlc[w->quant < 13][table_index];
9abc7e0f
     }
 
8072345e
     return get_vlc2(w->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD);
9abc7e0f
 }
 
42244ce0
 #define extra_bits(eb)  (eb)        // 3 bits
 #define extra_run       (0xFF << 8) // 1 bit
 #define extra_level     (0x00 << 8) // 1 bit
 #define run_offset(r)   ((r) << 16) // 6 bits
 #define level_offset(l) ((l) << 24) // 5 bits
2ade1cda
 static const uint32_t ac_decode_table[] = {
     /* 46 */ extra_bits(3) | extra_run   | run_offset(16) | level_offset(0),
     /* 47 */ extra_bits(3) | extra_run   | run_offset(24) | level_offset(0),
     /* 48 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
     /* 49 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
 
     /* 50 */ extra_bits(5) | extra_run   | run_offset(32) | level_offset(0),
     /* 51 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
 
     /* 52 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
     /* 53 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(8),
     /* 54 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(12),
     /* 55 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(16),
     /* 56 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(24),
 
     /* 57 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
     /* 58 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
 
     /* 59 */ extra_bits(2) | extra_run   | run_offset(16) | level_offset(0),
     /* 60 */ extra_bits(2) | extra_run   | run_offset(20) | level_offset(0),
     /* 61 */ extra_bits(2) | extra_run   | run_offset(24) | level_offset(0),
     /* 62 */ extra_bits(2) | extra_run   | run_offset(28) | level_offset(0),
     /* 63 */ extra_bits(4) | extra_run   | run_offset(32) | level_offset(0),
     /* 64 */ extra_bits(4) | extra_run   | run_offset(48) | level_offset(0),
 
     /* 65 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
     /* 66 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
     /* 67 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
 
     /* 68 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
     /* 69 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(8),
     /* 70 */ extra_bits(4) | extra_level | run_offset(0)  | level_offset(16),
 
     /* 71 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
     /* 72 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
9abc7e0f
 };
 #undef extra_bits
 #undef extra_run
 #undef extra_level
 #undef run_offset
 #undef level_offset
 
2ade1cda
 static void x8_get_ac_rlf(IntraX8Context *const w, const int mode,
                           int *const run, int *const level, int *const final)
 {
     int i, e;
9abc7e0f
 
2ade1cda
 //    x8_select_ac_table(w, mode);
8072345e
     i = get_vlc2(w->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD);
9abc7e0f
 
2ade1cda
     if (i < 46) { // [0-45]
         int t, l;
         if (i < 0) {
6ebd06a9
             *level =
41ed7ab4
             *final =      // prevent 'may be used uninitialized'
6ebd06a9
             *run   = 64;  // this would cause error exit in the ac loop
9abc7e0f
             return;
         }
 
2ade1cda
         /*
          * i == 0-15  r = 0-15 l = 0; r = i & %01111
          * i == 16-19 r = 0-3  l = 1; r = i & %00011
          * i == 20-21 r = 0-1  l = 2; r = i & %00001
          * i == 22    r = 0    l = 3; r = i & %00000
          */
 
6ebd06a9
         *final =
         t      = i > 22;
         i     -= 23 * t;
2ade1cda
 
         /* l = lut_l[i / 2] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3 }[i >> 1];
          *     11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 */
6ebd06a9
         l = (0xE50000 >> (i & 0x1E)) & 3; // 0x1E or ~1 or (i >> 1 << 1)
2ade1cda
 
         /* t = lut_mask[l] = { 0x0f, 0x03, 0x01, 0x00 }[l];
          *     as i < 256 the higher bits do not matter */
6ebd06a9
         t = 0x01030F >> (l << 3);
2ade1cda
 
6ebd06a9
         *run   = i & t;
         *level = l;
2ade1cda
     } else if (i < 73) { // [46-72]
9abc7e0f
         uint32_t sm;
         uint32_t mask;
 
2ade1cda
         i -= 46;
         sm = ac_decode_table[i];
 
8072345e
         e    = get_bits(w->gb, sm & 0xF);
41ed7ab4
         sm >>= 8;                               // 3 bits
2ade1cda
         mask = sm & 0xff;
41ed7ab4
         sm >>= 8;                               // 1 bit
2ade1cda
 
41ed7ab4
         *run   = (sm &  0xff) + (e &  mask);    // 6 bits
         *level = (sm >>    8) + (e & ~mask);    // 5 bits
6ebd06a9
         *final = i > (58 - 46);
2ade1cda
     } else if (i < 75) { // [73-74]
         static const uint8_t crazy_mix_runlevel[32] = {
             0x22, 0x32, 0x33, 0x53, 0x23, 0x42, 0x43, 0x63,
             0x24, 0x52, 0x34, 0x73, 0x25, 0x62, 0x44, 0x83,
             0x26, 0x72, 0x35, 0x54, 0x27, 0x82, 0x45, 0x64,
             0x28, 0x92, 0x36, 0x74, 0x29, 0xa2, 0x46, 0x84,
         };
 
6ebd06a9
         *final = !(i & 1);
         e      = get_bits(w->gb, 5); // get the extra bits
         *run   = crazy_mix_runlevel[e] >> 4;
         *level = crazy_mix_runlevel[e] & 0x0F;
2ade1cda
     } else {
6ebd06a9
         *level = get_bits(w->gb, 7 - 3 * (i & 1));
         *run   = get_bits(w->gb, 6);
         *final = get_bits1(w->gb);
9abc7e0f
     }
     return;
 }
 
2ade1cda
 /* static const uint8_t dc_extra_sbits[] = {
  *     0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
  * }; */
 static const uint8_t dc_index_offset[] = {
     0, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
 };
9abc7e0f
 
8dead2aa
 static int x8_get_dc_rlf(IntraX8Context *const w, const int mode,
                          int *const level, int *const final)
2ade1cda
 {
     int i, e, c;
 
ba5bcf96
     av_assert2(mode < 3);
2ade1cda
     if (!w->j_dc_vlc[mode]) {
8072345e
         int table_index = get_bits(w->gb, 3);
2ade1cda
         // 4 modes, same table
         w->j_dc_vlc[mode] = &j_dc_vlc[w->quant < 13][table_index];
9abc7e0f
     }
 
8072345e
     i = get_vlc2(w->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD);
9abc7e0f
 
2ade1cda
     /* (i >= 17) { i -= 17; final =1; } */
6ebd06a9
     c      = i > 16;
     *final = c;
     i      -= 17 * c;
9abc7e0f
 
2ade1cda
     if (i <= 0) {
6ebd06a9
         *level = 0;
9abc7e0f
         return -i;
     }
2ade1cda
     c  = (i + 1) >> 1; // hackish way to calculate dc_extra_sbits[]
     c -= c > 1;
9abc7e0f
 
8072345e
     e = get_bits(w->gb, c); // get the extra bits
2ade1cda
     i = dc_index_offset[i] + (e >> 1);
9abc7e0f
 
6ebd06a9
     e      = -(e & 1);     // 0, 0xffffff
     *level =  (i ^ e) - e; // (i ^ 0) - 0, (i ^ 0xff) - (-1)
9abc7e0f
     return 0;
 }
 
2ade1cda
 // end of huffman
 
 static int x8_setup_spatial_predictor(IntraX8Context *const w, const int chroma)
 {
9abc7e0f
     int range;
     int sum;
     int quant;
 
65f14128
     w->dsp.setup_spatial_compensation(w->dest[chroma], w->scratchpad,
eaeba6f2
                                       w->frame->linesize[chroma > 0],
15616eb0
                                       &range, &sum, w->edges);
2ade1cda
     if (chroma) {
         w->orient = w->chroma_orient;
         quant     = w->quant_dc_chroma;
     } else {
         quant = w->quant;
9abc7e0f
     }
 
2ade1cda
     w->flat_dc = 0;
     if (range < quant || range < 3) {
         w->orient = 0;
 
         // yep you read right, a +-1 idct error may break decoding!
         if (range < 3) {
             w->flat_dc      = 1;
             sum            += 9;
             // ((1 << 17) + 9) / (8 + 8 + 1 + 2) = 6899
6ebd06a9
             w->predicted_dc = sum * 6899 >> 17;
9abc7e0f
         }
     }
2ade1cda
     if (chroma)
9abc7e0f
         return 0;
 
aee675a3
     av_assert2(w->orient < 3);
2ade1cda
     if (range < 2 * w->quant) {
         if ((w->edges & 3) == 0) {
             if (w->orient == 1)
                 w->orient = 11;
             if (w->orient == 2)
                 w->orient = 10;
         } else {
             w->orient = 0;
9abc7e0f
         }
2ade1cda
         w->raw_orient = 0;
     } else {
         static const uint8_t prediction_table[3][12] = {
             { 0, 8, 4, 10, 11, 2, 6, 9, 1, 3, 5, 7 },
             { 4, 0, 8, 11, 10, 3, 5, 2, 6, 9, 1, 7 },
             { 8, 0, 4, 10, 11, 1, 7, 2, 6, 9, 3, 5 },
9abc7e0f
         };
2ade1cda
         w->raw_orient = x8_get_orient_vlc(w);
         if (w->raw_orient < 0)
             return -1;
ba5bcf96
         av_assert2(w->raw_orient < 12);
         av_assert2(w->orient < 3);
9abc7e0f
         w->orient=prediction_table[w->orient][w->raw_orient];
     }
     return 0;
 }
 
2ade1cda
 static void x8_update_predictions(IntraX8Context *const w, const int orient,
                                   const int est_run)
 {
b1268e0f
     w->prediction_table[w->mb_x * 2 + (w->mb_y & 1)] = (est_run << 2) + 1 * (orient == 4) + 2 * (orient == 8);
9abc7e0f
 /*
2ade1cda
  * y = 2n + 0 -> // 0 2 4
  * y = 2n + 1 -> // 1 3 5
  */
9abc7e0f
 }
 
2ade1cda
 static void x8_get_prediction_chroma(IntraX8Context *const w)
 {
6ebd06a9
     w->edges  = 1 * !(w->mb_x >> 1);
     w->edges |= 2 * !(w->mb_y >> 1);
b1268e0f
     w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1)); // mb_x for chroma would always be odd
2ade1cda
 
     w->raw_orient = 0;
     // lut_co[8] = {inv,4,8,8, inv,4,8,8} <- => {1,1,0,0;1,1,0,0} => 0xCC
     if (w->edges & 3) {
         w->chroma_orient = 4 << ((0xCC >> w->edges) & 1);
9abc7e0f
         return;
     }
2ade1cda
     // block[x - 1][y | 1 - 1)]
b1268e0f
     w->chroma_orient = (w->prediction_table[2 * w->mb_x - 2] & 0x03) << 2;
9abc7e0f
 }
 
2ade1cda
 static void x8_get_prediction(IntraX8Context *const w)
 {
     int a, b, c, i;
 
6ebd06a9
     w->edges  = 1 * !w->mb_x;
     w->edges |= 2 * !w->mb_y;
b1268e0f
     w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1));
2ade1cda
 
     switch (w->edges & 3) {
     case 0:
         break;
     case 1:
         // take the one from the above block[0][y - 1]
b1268e0f
         w->est_run = w->prediction_table[!(w->mb_y & 1)] >> 2;
2ade1cda
         w->orient  = 1;
         return;
     case 2:
         // take the one from the previous block[x - 1][0]
b1268e0f
         w->est_run = w->prediction_table[2 * w->mb_x - 2] >> 2;
2ade1cda
         w->orient  = 2;
         return;
     case 3:
         w->est_run = 16;
         w->orient  = 0;
         return;
9abc7e0f
     }
2ade1cda
     // no edge cases
b1268e0f
     b = w->prediction_table[2 * w->mb_x     + !(w->mb_y & 1)]; // block[x    ][y - 1]
     a = w->prediction_table[2 * w->mb_x - 2 +  (w->mb_y & 1)]; // block[x - 1][y    ]
     c = w->prediction_table[2 * w->mb_x - 2 + !(w->mb_y & 1)]; // block[x - 1][y - 1]
9abc7e0f
 
2ade1cda
     w->est_run = FFMIN(b, a);
c238beb5
     /* This condition has nothing to do with w->edges, even if it looks
2ade1cda
      * similar it would trigger if e.g. x = 3; y = 2;
      * I guess somebody wrote something wrong and it became standard. */
b1268e0f
     if ((w->mb_x & w->mb_y) != 0)
2ade1cda
         w->est_run = FFMIN(c, w->est_run);
     w->est_run >>= 2;
 
     a &= 3;
     b &= 3;
     c &= 3;
 
     i = (0xFFEAF4C4 >> (2 * b + 8 * a)) & 3;
     if (i != 3)
         w->orient = i;
     else
         w->orient = (0xFFEAD8 >> (2 * c + 8 * (w->quant > 12))) & 3;
9abc7e0f
 /*
2ade1cda
  * lut1[b][a] = {
  * ->{ 0, 1, 0, pad },
  *   { 0, 1, X, pad },
  *   { 2, 2, 2, pad }
  * }
  * pad 2  2  2;
  * pad X  1  0;
  * pad 0  1  0 <-
  * -> 11 10 '10 10 '11 11'01 00 '11 00'01 00 => 0xEAF4C4
  *
  * lut2[q>12][c] = {
  * ->{ 0, 2, 1, pad},
  *   { 2, 2, 2, pad}
  * }
  * pad 2  2  2;
  * pad 1  2  0 <-
  * -> 11 10'10 10 '11 01'10 00 => 0xEAD8
  */
9abc7e0f
 }
 
8dead2aa
 static void x8_ac_compensation(IntraX8Context *const w, const int direction,
                                const int dc_level)
2ade1cda
 {
9abc7e0f
     int t;
f110c624
 #define B(x,y)  w->block[0][w->idct_permutation[(x) + (y) * 8]]
9abc7e0f
 #define T(x)  ((x) * dc_level + 0x8000) >> 16;
2ade1cda
     switch (direction) {
9abc7e0f
     case 0:
2ade1cda
         t        = T(3811); // h
         B(1, 0) -= t;
         B(0, 1) -= t;
 
         t        = T(487); // e
         B(2, 0) -= t;
         B(0, 2) -= t;
 
         t        = T(506); // f
         B(3, 0) -= t;
         B(0, 3) -= t;
 
         t        = T(135); // c
         B(4, 0) -= t;
         B(0, 4) -= t;
         B(2, 1) += t;
         B(1, 2) += t;
         B(3, 1) += t;
         B(1, 3) += t;
 
         t        = T(173); // d
         B(5, 0) -= t;
         B(0, 5) -= t;
 
         t        = T(61); // b
         B(6, 0) -= t;
         B(0, 6) -= t;
         B(5, 1) += t;
         B(1, 5) += t;
 
         t        = T(42); // a
         B(7, 0) -= t;
         B(0, 7) -= t;
         B(4, 1) += t;
         B(1, 4) += t;
         B(4, 4) += t;
 
         t        = T(1084); // g
         B(1, 1) += t;
 
9fa888c0
         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
9abc7e0f
         break;
     case 1:
2ade1cda
         B(0, 1) -= T(6269);
         B(0, 3) -= T(708);
         B(0, 5) -= T(172);
         B(0, 7) -= T(73);
9abc7e0f
 
9fa888c0
         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
9abc7e0f
         break;
     case 2:
2ade1cda
         B(1, 0) -= T(6269);
         B(3, 0) -= T(708);
         B(5, 0) -= T(172);
         B(7, 0) -= T(73);
9abc7e0f
 
9fa888c0
         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7);
9abc7e0f
         break;
     }
 #undef B
 #undef T
 }
 
8dead2aa
 static void dsp_x8_put_solidcolor(const uint8_t pix, uint8_t *dst,
                                   const int linesize)
2ade1cda
 {
9abc7e0f
     int k;
2ade1cda
     for (k = 0; k < 8; k++) {
         memset(dst, pix, 8);
         dst += linesize;
9abc7e0f
     }
 }
 
 static const int16_t quant_table[64] = {
2ade1cda
     256, 256, 256, 256, 256, 256, 259, 262,
     265, 269, 272, 275, 278, 282, 285, 288,
     292, 295, 299, 303, 306, 310, 314, 317,
     321, 325, 329, 333, 337, 341, 345, 349,
     353, 358, 362, 366, 371, 375, 379, 384,
     389, 393, 398, 403, 408, 413, 417, 422,
     428, 433, 438, 443, 448, 454, 459, 465,
     470, 476, 482, 488, 493, 499, 505, 511,
9abc7e0f
 };
 
2ade1cda
 static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma)
 {
     uint8_t *scantable;
     int final, run, level;
     int ac_mode, dc_mode, est_run, dc_level;
     int pos, n;
9abc7e0f
     int zeros_only;
     int use_quant_matrix;
     int sign;
 
ba5bcf96
     av_assert2(w->orient < 12);
9fa888c0
     w->bdsp.clear_block(w->block[0]);
9abc7e0f
 
2ade1cda
     if (chroma)
         dc_mode = 2;
     else
         dc_mode = !!w->est_run; // 0, 1
 
     if (x8_get_dc_rlf(w, dc_mode, &dc_level, &final))
         return -1;
     n          = 0;
     zeros_only = 0;
     if (!final) { // decode ac
         use_quant_matrix = w->use_quant_matrix;
         if (chroma) {
9abc7e0f
             ac_mode = 1;
2ade1cda
             est_run = 64; // not used
         } else {
             if (w->raw_orient < 3)
9abc7e0f
                 use_quant_matrix = 0;
2ade1cda
 
             if (w->raw_orient > 4) {
9abc7e0f
                 ac_mode = 0;
                 est_run = 64;
2ade1cda
             } else {
                 if (w->est_run > 1) {
9abc7e0f
                     ac_mode = 2;
2ade1cda
                     est_run = w->est_run;
                 } else {
9abc7e0f
                     ac_mode = 3;
                     est_run = 64;
                 }
             }
         }
2ade1cda
         x8_select_ac_table(w, ac_mode);
         /* scantable_selector[12] = { 0, 2, 0, 1, 1, 1, 0, 2, 2, 0, 1, 2 }; <-
          * -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 => 0x928548 */
         scantable = w->scantable[(0x928548 >> (2 * w->orient)) & 3].permutated;
         pos       = 0;
9abc7e0f
         do {
             n++;
2ade1cda
             if (n >= est_run) {
                 ac_mode = 3;
                 x8_select_ac_table(w, 3);
9abc7e0f
             }
 
2ade1cda
             x8_get_ac_rlf(w, ac_mode, &run, &level, &final);
9abc7e0f
 
2ade1cda
             pos += run + 1;
             if (pos > 63) {
                 // this also handles vlc error in x8_get_ac_rlf
9abc7e0f
                 return -1;
             }
2ade1cda
             level  = (level + 1) * w->dquant;
             level += w->qsum;
9abc7e0f
 
8072345e
             sign  = -get_bits1(w->gb);
9abc7e0f
             level = (level ^ sign) - sign;
 
2ade1cda
             if (use_quant_matrix)
                 level = (level * quant_table[pos]) >> 8;
9abc7e0f
 
9fa888c0
             w->block[0][scantable[pos]] = level;
2ade1cda
         } while (!final);
9abc7e0f
 
9fa888c0
         w->block_last_index[0] = pos;
2ade1cda
     } else { // DC only
9fa888c0
         w->block_last_index[0] = 0;
2ade1cda
         if (w->flat_dc && ((unsigned) (dc_level + 1)) < 3) { // [-1; 1]
             int32_t divide_quant = !chroma ? w->divide_quant_dc_luma
                                            : w->divide_quant_dc_chroma;
             int32_t dc_quant     = !chroma ? w->quant
                                            : w->quant_dc_chroma;
9abc7e0f
 
2ade1cda
             // original intent dc_level += predicted_dc/quant;
             // but it got lost somewhere in the rounding
             dc_level += (w->predicted_dc * divide_quant + (1 << 12)) >> 13;
 
             dsp_x8_put_solidcolor(av_clip_uint8((dc_level * dc_quant + 4) >> 3),
922b7e6d
                                   w->dest[chroma],
eaeba6f2
                                   w->frame->linesize[!!chroma]);
9abc7e0f
 
             goto block_placed;
         }
6ebd06a9
         zeros_only = dc_level == 0;
9abc7e0f
     }
2ade1cda
     if (!chroma)
9fa888c0
         w->block[0][0] = dc_level * w->quant;
2ade1cda
     else
9fa888c0
         w->block[0][0] = dc_level * w->quant_dc_chroma;
9abc7e0f
 
2ade1cda
     // there is !zero_only check in the original, but dc_level check is enough
     if ((unsigned int) (dc_level + 1) >= 3 && (w->edges & 3) != 3) {
9abc7e0f
         int direction;
2ade1cda
         /* ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 }; <-
          * -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 => 0x6A017C */
         direction = (0x6A017C >> (w->orient * 2)) & 3;
         if (direction != 3) {
             // modify block_last[]
9fa888c0
             x8_ac_compensation(w, direction, w->block[0][0]);
9abc7e0f
         }
     }
 
2ade1cda
     if (w->flat_dc) {
922b7e6d
         dsp_x8_put_solidcolor(w->predicted_dc, w->dest[chroma],
eaeba6f2
                               w->frame->linesize[!!chroma]);
2ade1cda
     } else {
65f14128
         w->dsp.spatial_compensation[w->orient](w->scratchpad,
922b7e6d
                                                w->dest[chroma],
eaeba6f2
                                                w->frame->linesize[!!chroma]);
9abc7e0f
     }
2ade1cda
     if (!zeros_only)
1a9ffc59
         w->wdsp.idct_add(w->dest[chroma],
eaeba6f2
                          w->frame->linesize[!!chroma],
9fa888c0
                          w->block[0]);
9abc7e0f
 
 block_placed:
2ade1cda
     if (!chroma)
         x8_update_predictions(w, w->orient, n);
9abc7e0f
 
57739332
     if (w->loopfilter) {
922b7e6d
         uint8_t *ptr = w->dest[chroma];
eaeba6f2
         int linesize = w->frame->linesize[!!chroma];
9abc7e0f
 
2ade1cda
         if (!((w->edges & 2) || (zeros_only && (w->orient | 4) == 4)))
15616eb0
             w->dsp.h_loop_filter(ptr, linesize, w->quant);
2ade1cda
 
         if (!((w->edges & 1) || (zeros_only && (w->orient | 8) == 8)))
15616eb0
             w->dsp.v_loop_filter(ptr, linesize, w->quant);
9abc7e0f
     }
     return 0;
 }
 
2ade1cda
 // FIXME maybe merge with ff_*
b1268e0f
 static void x8_init_block_index(IntraX8Context *w, AVFrame *frame)
2ade1cda
 {
65127450
     // not parent codec linesize as this would be wrong for field pics
2ade1cda
     // not that IntraX8 has interlacing support ;)
65127450
     const int linesize   = frame->linesize[0];
     const int uvlinesize = frame->linesize[1];
9abc7e0f
 
65127450
     w->dest[0] = frame->data[0];
     w->dest[1] = frame->data[1];
     w->dest[2] = frame->data[2];
9abc7e0f
 
6ebd06a9
     w->dest[0] +=  w->mb_y       * linesize   << 3;
2ade1cda
     // chroma blocks are on add rows
6ebd06a9
     w->dest[1] += (w->mb_y & ~1) * uvlinesize << 2;
     w->dest[2] += (w->mb_y & ~1) * uvlinesize << 2;
9abc7e0f
 }
 
1eaae7ab
 av_cold int ff_intrax8_common_init(AVCodecContext *avctx,
                                    IntraX8Context *w, IDCTDSPContext *idsp,
9fa888c0
                                    int16_t (*block)[64],
                                    int block_last_index[12],
ca8c7591
                                    int mb_width, int mb_height)
2ade1cda
 {
0372e73f
     int ret = x8_vlc_init();
     if (ret < 0)
         return ret;
 
1eaae7ab
     w->avctx = avctx;
68127e1b
     w->idsp = *idsp;
d0540fd0
     w->mb_width  = mb_width;
     w->mb_height = mb_height;
9fa888c0
     w->block = block;
     w->block_last_index = block_last_index;
9abc7e0f
 
2ade1cda
     // two rows, 2 blocks per cannon mb
d0540fd0
     w->prediction_table = av_mallocz(w->mb_width * 2 * 2);
0372e73f
     if (!w->prediction_table)
         return AVERROR(ENOMEM);
9abc7e0f
 
9a0aa8d0
     ff_wmv2dsp_init(&w->wdsp);
ba5bcf96
 
9a0aa8d0
     ff_init_scantable_permutation(w->idct_permutation,
                                   w->wdsp.idct_perm);
 
ba5bcf96
     ff_init_scantable(w->idct_permutation, &w->scantable[0],
2ade1cda
                       ff_wmv1_scantable[0]);
ba5bcf96
     ff_init_scantable(w->idct_permutation, &w->scantable[1],
2ade1cda
                       ff_wmv1_scantable[2]);
ba5bcf96
     ff_init_scantable(w->idct_permutation, &w->scantable[2],
2ade1cda
                       ff_wmv1_scantable[3]);
15616eb0
 
     ff_intrax8dsp_init(&w->dsp);
15932389
     ff_blockdsp_init(&w->bdsp, avctx);
0372e73f
 
     return 0;
9abc7e0f
 }
 
2ade1cda
 av_cold void ff_intrax8_common_end(IntraX8Context *w)
e2fdba65
 {
     av_freep(&w->prediction_table);
 }
 
eaeba6f2
 int ff_intrax8_decode_picture(IntraX8Context *const w, Picture *pict,
b1268e0f
                               GetBitContext *gb, int *mb_x, int *mb_y,
c2084ffc
                               int dquant, int quant_offset,
                               int loopfilter, int lowdelay)
2ade1cda
 {
9abc7e0f
     int mb_xy;
 
8072345e
     w->gb     = gb;
9abc7e0f
     w->dquant = dquant;
     w->quant  = dquant >> 1;
     w->qsum   = quant_offset;
eaeba6f2
     w->frame  = pict->f;
57739332
     w->loopfilter = loopfilter;
8072345e
     w->use_quant_matrix = get_bits1(w->gb);
9abc7e0f
 
b1268e0f
     w->mb_x = *mb_x;
     w->mb_y = *mb_y;
 
2ade1cda
     w->divide_quant_dc_luma = ((1 << 16) + (w->quant >> 1)) / w->quant;
     if (w->quant < 5) {
         w->quant_dc_chroma        = w->quant;
9abc7e0f
         w->divide_quant_dc_chroma = w->divide_quant_dc_luma;
2ade1cda
     } else {
         w->quant_dc_chroma        = w->quant + ((w->quant + 3) >> 3);
         w->divide_quant_dc_chroma = ((1 << 16) + (w->quant_dc_chroma >> 1)) / w->quant_dc_chroma;
9abc7e0f
     }
     x8_reset_vlc_tables(w);
 
b1268e0f
     for (w->mb_y = 0; w->mb_y < w->mb_height * 2; w->mb_y++) {
         x8_init_block_index(w, w->frame);
         mb_xy = (w->mb_y >> 1) * (w->mb_width + 1);
         for (w->mb_x = 0; w->mb_x < w->mb_width * 2; w->mb_x++) {
9abc7e0f
             x8_get_prediction(w);
2ade1cda
             if (x8_setup_spatial_predictor(w, 0))
                 goto error;
             if (x8_decode_intra_mb(w, 0))
                 goto error;
9abc7e0f
 
b1268e0f
             if (w->mb_x & w->mb_y & 1) {
9abc7e0f
                 x8_get_prediction_chroma(w);
 
2ade1cda
                 /* when setting up chroma, no vlc is read,
                  * so no error condition can be reached */
                 x8_setup_spatial_predictor(w, 1);
                 if (x8_decode_intra_mb(w, 1))
                     goto error;
9abc7e0f
 
2ade1cda
                 x8_setup_spatial_predictor(w, 2);
                 if (x8_decode_intra_mb(w, 2))
                     goto error;
9abc7e0f
 
922b7e6d
                 w->dest[1] += 8;
                 w->dest[2] += 8;
9abc7e0f
 
eaeba6f2
                 pict->qscale_table[mb_xy] = w->quant;
9abc7e0f
                 mb_xy++;
             }
922b7e6d
             w->dest[0] += 8;
9abc7e0f
         }
b1268e0f
         if (w->mb_y & 1)
c2084ffc
             ff_draw_horiz_band(w->avctx, w->frame, w->frame,
                                (w->mb_y - 1) * 8, 16,
                                PICT_FRAME, 0, lowdelay);
9abc7e0f
     }
 
 error:
b1268e0f
     *mb_x = w->mb_x;
     *mb_y = w->mb_y;
 
9abc7e0f
     return 0;
 }