static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma)

{

    MpegEncContext *const s = w->s;



    uint8_t *scantable;

    int final, run, level;

    int ac_mode, dc_mode, est_run, dc_level;

    int pos, n;

    int zeros_only;

    int use_quant_matrix;

    int sign;



    assert(w->orient < 12);

    s->bdsp.clear_block(s->block[0]);



    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) {

            ac_mode = 1;

            est_run = 64; // not used

        } else {

            if (w->raw_orient < 3)

                use_quant_matrix = 0;



            if (w->raw_orient > 4) {

                ac_mode = 0;

                est_run = 64;

            } else {

                if (w->est_run > 1) {

                    ac_mode = 2;

                    est_run = w->est_run;

                } else {

                    ac_mode = 3;

                    est_run = 64;

                }

            }

        }

        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;

        do {

            n++;

            if (n >= est_run) {

                ac_mode = 3;

                x8_select_ac_table(w, 3);

            }



            x8_get_ac_rlf(w, ac_mode, &run, &level, &final);



            pos += run + 1;

            if (pos > 63) {

                // this also handles vlc error in x8_get_ac_rlf

                return -1;

            }

            level  = (level + 1) * w->dquant;

            level += w->qsum;



            sign  = -get_bits1(&s->gb);

            level = (level ^ sign) - sign;



            if (use_quant_matrix)

                level = (level * quant_table[pos]) >> 8;



            s->block[0][scantable[pos]] = level;

        } while (!final);



        s->block_last_index[0] = pos;

    } else { // DC only

        s->block_last_index[0] = 0;

        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;



            // 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),

                                  w->dest[chroma],

                                  s->current_picture.f->linesize[!!chroma]);



            goto block_placed;

        }

        zeros_only = (dc_level == 0);

    }

    if (!chroma)

        s->block[0][0] = dc_level * w->quant;

    else

        s->block[0][0] = dc_level * w->quant_dc_chroma;



    // 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) {

        int direction;

        /* 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[]

            x8_ac_compensation(w, direction, s->block[0][0]);

        }

    }



    if (w->flat_dc) {

        dsp_x8_put_solidcolor(w->predicted_dc, w->dest[chroma],

                              s->current_picture.f->linesize[!!chroma]);

    } else {

        w->dsp.spatial_compensation[w->orient](s->sc.edge_emu_buffer,

                                               w->dest[chroma],

                                               s->current_picture.f->linesize[!!chroma]);

    }

    if (!zeros_only)

        w->idsp.idct_add(w->dest[chroma],

                         s->current_picture.f->linesize[!!chroma],

                         s->block[0]);



block_placed:

    if (!chroma)

        x8_update_predictions(w, w->orient, n);



    if (s->loop_filter) {

        uint8_t *ptr = w->dest[chroma];

        int linesize = s->current_picture.f->linesize[!!chroma];



        if (!((w->edges & 2) || (zeros_only && (w->orient | 4) == 4)))

            w->dsp.h_loop_filter(ptr, linesize, w->quant);



        if (!((w->edges & 1) || (zeros_only && (w->orient | 8) == 8)))

            w->dsp.v_loop_filter(ptr, linesize, w->quant);

    }

    return 0;

}
