ff_h264_check_intra_pred_mode() public method

public ff_h264_check_intra_pred_mode ( int mode ) : int
mode int
return int
Example #1
0
        public int ff_h264_decode_mb_cavlc(H264Context h)
        {
            MpegEncContext s = h.s;
            int mb_xy;
            int partition_count;
            int mb_type, cbp;
            int dct8x8_allowed = h.pps.transform_8x8_mode;

            // DebugTool.dumpDebugFrameData(h, "BEFORE-ff_h264_decode_mb_cavlc");

            mb_xy = h.mb_xy = s.mb_x + s.mb_y * s.mb_stride;

            //tprintf(s.avctx, "pic:%d mb:%d/%d\n", h.frame_num, s.mb_x, s.mb_y);
            cbp = 0; /* avoid warning. FIXME: find a solution without slowing
                        down the code */
            if (h.slice_type_nos != H264Context.FF_I_TYPE)
            {
                if (s.mb_skip_run == -1)
                    s.mb_skip_run = s.gb.get_ue_golomb("mb_skip_run");

                if (0 != s.mb_skip_run--)
                {
                    if (h.mb_aff_frame != 0 && (s.mb_y & 1) == 0)
                    {
                        if (s.mb_skip_run == 0)
                            h.mb_mbaff = h.mb_field_decoding_flag = (int)s.gb.get_bits1("mb_mbaff");
                    }
                    h.decode_mb_skip();
                    return 0;
                }
            }
            if (h.mb_aff_frame != 0)
            {
                if ((s.mb_y & 1) == 0)
                    h.mb_mbaff = h.mb_field_decoding_flag = (int)s.gb.get_bits1("mb_field_decoding_flag");
            }

            h.prev_mb_skipped = 0;

            mb_type = s.gb.get_ue_golomb("mb_type");
            if (h.slice_type_nos == H264Context.FF_B_TYPE)
            {
                if (mb_type < 23)
                {
                    partition_count = H264Data.b_mb_type_info[mb_type].partition_count;
                    mb_type = H264Data.b_mb_type_info[mb_type].type;
                }
                else
                {
                    mb_type -= 23;
                    //	            goto decode_intra_mb;
                    //	        	decode_intra_mb:
                    if (mb_type > 25)
                    {
                        //av_log(h.s.avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_pict_type_char(h.slice_type), s.mb_x, s.mb_y);
                        return -1;
                    }
                    partition_count = 0;
                    cbp = H264Data.i_mb_type_info[mb_type].cbp;
                    h.intra16x16_pred_mode = H264Data.i_mb_type_info[mb_type].pred_mode;
                    mb_type = H264Data.i_mb_type_info[mb_type].type;
                }
            }
            else if (h.slice_type_nos == H264Context.FF_P_TYPE)
            {
                if (mb_type < 5)
                {
                    partition_count = H264Data.p_mb_type_info[mb_type].partition_count;
                    mb_type = H264Data.p_mb_type_info[mb_type].type;
                }
                else
                {
                    mb_type -= 5;
                    //	            goto decode_intra_mb;
                    //	        	decode_intra_mb:
                    if (mb_type > 25)
                    {
                        //av_log(h.s.avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_pict_type_char(h.slice_type), s.mb_x, s.mb_y);
                        return -1;
                    }
                    partition_count = 0;
                    cbp = H264Data.i_mb_type_info[mb_type].cbp;
                    h.intra16x16_pred_mode = H264Data.i_mb_type_info[mb_type].pred_mode;
                    mb_type = H264Data.i_mb_type_info[mb_type].type;
                }
            }
            else
            {
                //assert(h.slice_type_nos == H264Context.FF_I_TYPE);
                if (h.slice_type == H264Context.FF_SI_TYPE && mb_type != 0)
                    mb_type--;
                //decode_intra_mb:
                if (mb_type > 25)
                {
                    //av_log(h.s.avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_pict_type_char(h.slice_type), s.mb_x, s.mb_y);
                    return -1;
                }
                partition_count = 0;
                cbp = H264Data.i_mb_type_info[mb_type].cbp;
                h.intra16x16_pred_mode = H264Data.i_mb_type_info[mb_type].pred_mode;
                mb_type = H264Data.i_mb_type_info[mb_type].type;
            }

            if (h.mb_field_decoding_flag != 0)
                mb_type |= H264Context.MB_TYPE_INTERLACED;

            h.slice_table_base[h.slice_table_offset + mb_xy] = h.slice_num;

            if (0 != (mb_type & H264Context.MB_TYPE_INTRA_PCM))
            {
                int x;

                // We assume these blocks are very rare so we do not optimize it.
                s.gb.align_get_bits();

                // The pixels are stored in the same order as levels in h.mb array.
                for (x = 0; x < ((h.sps.chroma_format_idc != 0) ? 384 : 256); x += 2)
                {
                    // Combine 2 byte to get a short.
                    //((uint8_t*)h.mb)[x]= (int)s.gb.get_bits(8);
                    int val = (int)s.gb.get_bits(8, "val");
                    val = val | (((int)s.gb.get_bits(8, "val")) << 8);
                    h.mb[x / 2] = (short)val;
                }

                // In deblocking, the quantizer is 0
                s.current_picture.qscale_table[mb_xy] = 0;
                // All coeffs are present
                //memset(h.non_zero_count[mb_xy], 16, 32);
                Arrays.Fill(h.non_zero_count[mb_xy], 0, 32, 16);

                s.current_picture.mb_type_base[s.current_picture.mb_type_offset + mb_xy] = mb_type;
                return 0;
            }

            if (h.mb_mbaff != 0)
            {
                h.ref_count[0] <<= 1;
                h.ref_count[1] <<= 1;
            }

            h.fill_decode_neighbors(mb_type);
            h.fill_decode_caches(mb_type);

            //mb_pred
            if (0 != (mb_type & 7))
            {
                int pred_mode;
                //	            init_top_left_availability(h);
                if (0 != (mb_type & H264Context.MB_TYPE_INTRA4x4))
                {
                    int i;
                    int di = 1;
                    if (dct8x8_allowed != 0 && s.gb.get_bits1("MB_TYPE_8x8DCT?") != 0)
                    {
                        mb_type |= H264Context.MB_TYPE_8x8DCT;
                        di = 4;
                    }

                    //	                fill_intra4x4_pred_table(h);
                    for (i = 0; i < 16; i += di)
                    {
                        int mode = h.pred_intra_mode(i);

                        if (0 == s.gb.get_bits1("rem_mode"))
                        {
                            int rem_mode = (int)s.gb.get_bits(3, "rem_mode");
                            mode = rem_mode + ((rem_mode >= mode) ? 1 : 0);
                        }

                        if (di == 4)
                            Rectangle.fill_rectangle_sign(h.intra4x4_pred_mode_cache, H264Context.scan8[i], 2, 2, 8, mode, 1);
                        else
                            h.intra4x4_pred_mode_cache[H264Context.scan8[i]] = mode;
                    }
                    h.ff_h264_write_back_intra_pred_mode();
                    if (h.ff_h264_check_intra4x4_pred_mode() < 0)
                        return -1;
                }
                else
                {
                    h.intra16x16_pred_mode = h.ff_h264_check_intra_pred_mode(h.intra16x16_pred_mode);
                    if (h.intra16x16_pred_mode < 0)
                        return -1;
                }
                if (h.sps.chroma_format_idc != 0)
                {
                    pred_mode = h.ff_h264_check_intra_pred_mode(s.gb.get_ue_golomb_31("pred_mode"));
                    if (pred_mode < 0)
                        return -1;
                    h.chroma_pred_mode = pred_mode;
                }
            }
            else if (partition_count == 4)
            {
                int i, j;
                int[] sub_partition_count = new int[4];
                int list;
                int[][] @ref = Arrays.Create<int>(2, 4);

                if (h.slice_type_nos == H264Context.FF_B_TYPE)
                {
                    for (i = 0; i < 4; i++)
                    {
                        h.sub_mb_type[i] = s.gb.get_ue_golomb_31("sub_mb_type");
                        if (h.sub_mb_type[i] >= 13)
                        {
                            //av_log(h.s.avctx, AV_LOG_ERROR, "B sub_mb_type %u out of range at %d %d\n", h.sub_mb_type[i], s.mb_x, s.mb_y);
                            return -1;
                        }
                        sub_partition_count[i] = H264Data.b_sub_mb_type_info[h.sub_mb_type[i]].partition_count;
                        h.sub_mb_type[i] = H264Data.b_sub_mb_type_info[h.sub_mb_type[i]].type;
                    }
                    if (0 != ((h.sub_mb_type[0] | h.sub_mb_type[1] | h.sub_mb_type[2] | h.sub_mb_type[3]) & H264Context.MB_TYPE_DIRECT2))
                    {
                        mb_type = h.ff_h264_pred_direct_motion(mb_type);
                        h.ref_cache[0][H264Context.scan8[4]] =
                        h.ref_cache[1][H264Context.scan8[4]] =
                        h.ref_cache[0][H264Context.scan8[12]] =
                        h.ref_cache[1][H264Context.scan8[12]] = H264Context.PART_NOT_AVAILABLE;
                    }
                }
                else
                {
                    //assert(h.slice_type_nos == H264Context.FF_P_TYPE); //FIXME SP correct ?
                    for (i = 0; i < 4; i++)
                    {
                        h.sub_mb_type[i] = s.gb.get_ue_golomb_31("sub_mb_type");
                        if (h.sub_mb_type[i] >= 4)
                        {
                            //av_log(h.s.avctx, AV_LOG_ERROR, "P sub_mb_type %u out of range at %d %d\n", h.sub_mb_type[i], s.mb_x, s.mb_y);
                            return -1;
                        }
                        sub_partition_count[i] = H264Data.p_sub_mb_type_info[h.sub_mb_type[i]].partition_count;
                        h.sub_mb_type[i] = H264Data.p_sub_mb_type_info[h.sub_mb_type[i]].type;
                    }
                }

                for (list = 0; list < h.list_count; list++)
                {
                    int ref_count = ((mb_type & H264Context.MB_TYPE_REF0) != 0) ? 1 : (int)h.ref_count[list];
                    for (i = 0; i < 4; i++)
                    {
                        if (0 != (h.sub_mb_type[i] & H264Context.MB_TYPE_DIRECT2)) continue;
                        if (0 != ((h.sub_mb_type[i]) & (H264Context.MB_TYPE_P0L0 << ((0) + 2 * (list)))))
                        {
                            int tmp;
                            if (ref_count == 1)
                            {
                                tmp = 0;
                            }
                            else if (ref_count == 2)
                            {
                                tmp = (int)s.gb.get_bits1("ref_count?") ^ 1;
                            }
                            else
                            {
                                tmp = s.gb.get_ue_golomb_31("ref_count?");
                                if (tmp >= ref_count)
                                {
                                    //av_log(h.s.avctx, AV_LOG_ERROR, "ref %u overflow\n", tmp);
                                    return -1;
                                }
                            }
                            @ref[list][i] = tmp;
                        }
                        else
                        {
                            //FIXME
                            @ref[list][i] = -1;
                        }
                    }
                }

                if (dct8x8_allowed != 0)
                    dct8x8_allowed = h.get_dct8x8_allowed();

                for (list = 0; list < h.list_count; list++)
                {
                    for (i = 0; i < 4; i++)
                    {
                        if (0 != (h.sub_mb_type[i] & H264Context.MB_TYPE_DIRECT2))
                        {
                            h.ref_cache[list][H264Context.scan8[4 * i]] = h.ref_cache[list][H264Context.scan8[4 * i] + 1];
                            continue;
                        }
                        h.ref_cache[list][H264Context.scan8[4 * i]] = h.ref_cache[list][H264Context.scan8[4 * i] + 1] =
                        h.ref_cache[list][H264Context.scan8[4 * i] + 8] = h.ref_cache[list][H264Context.scan8[4 * i] + 9] = @ref[list][i];

                        if (((h.sub_mb_type[i]) & (H264Context.MB_TYPE_P0L0 << ((0) + 2 * (list)))) != 0)
                        {//IS_DIR(h.sub_mb_type[i], 0, list)){
                            int sub_mb_type = h.sub_mb_type[i];
                            int block_width = ((sub_mb_type & (H264Context.MB_TYPE_16x16 | H264Context.MB_TYPE_16x8)) != 0 ? 2 : 1);
                            for (j = 0; j < sub_partition_count[i]; j++)
                            {
                                int mx, my;
                                int index = 4 * i + block_width * j;
                                //int16_t (* mv_cache)[2]= &h.mv_cache[list][ H264Context.scan8[index] ];
                                int[][] mv_cache_base = h.mv_cache[list];
                                int my_cache_offset = H264Context.scan8[index];
                                int[] mxmy = new int[2];
                                h.pred_motion(index, block_width, list, h.ref_cache[list][H264Context.scan8[index]], mxmy);
                                mx = mxmy[0];
                                my = mxmy[1];
                                mx += s.gb.get_se_golomb("mx?");
                                my += s.gb.get_se_golomb("my?");
                                //tprintf(s.avctx, "final mv:%d %d\n", mx, my);

                                if (0 != (sub_mb_type & H264Context.MB_TYPE_16x16))
                                {
                                    mv_cache_base[my_cache_offset + 1][0] =
                                    mv_cache_base[my_cache_offset + 8][0] = mv_cache_base[my_cache_offset + 9][0] = mx;
                                    mv_cache_base[my_cache_offset + 1][1] =
                                    mv_cache_base[my_cache_offset + 8][1] = mv_cache_base[my_cache_offset + 9][1] = my;
                                }
                                else if (0 != (sub_mb_type & H264Context.MB_TYPE_16x8))
                                {
                                    mv_cache_base[my_cache_offset + 1][0] = mx;
                                    mv_cache_base[my_cache_offset + 1][1] = my;
                                }
                                else if (0 != (sub_mb_type & H264Context.MB_TYPE_8x16))
                                {
                                    mv_cache_base[my_cache_offset + 8][0] = mx;
                                    mv_cache_base[my_cache_offset + 8][1] = my;
                                }
                                mv_cache_base[my_cache_offset + 0][0] = mx;
                                mv_cache_base[my_cache_offset + 0][1] = my;
                            }
                        }
                        else
                        {
                            /*
                            uint32_t *p= (uint32_t *)&h.mv_cache[list][ scan8[4*i] ][0];
                            p[0] = p[1]=
                            p[8] = p[9]= 0;
                            */
                            h.mv_cache[list][H264Context.scan8[4 * i] + 0][0] = (short)0;
                            h.mv_cache[list][H264Context.scan8[4 * i] + 1][0] = (short)0;
                            h.mv_cache[list][H264Context.scan8[4 * i] + 8][0] = (short)0;
                            h.mv_cache[list][H264Context.scan8[4 * i] + 9][0] = (short)0;
                            h.mv_cache[list][H264Context.scan8[4 * i] + 0][1] = (short)0;
                            h.mv_cache[list][H264Context.scan8[4 * i] + 1][1] = (short)0;
                            h.mv_cache[list][H264Context.scan8[4 * i] + 8][1] = (short)0;
                            h.mv_cache[list][H264Context.scan8[4 * i] + 9][1] = (short)0;
                        }
                    }
                }
            }
            else if (0 != (mb_type & H264Context.MB_TYPE_DIRECT2))
            {
                mb_type = h.ff_h264_pred_direct_motion(mb_type);
                dct8x8_allowed &= h.sps.direct_8x8_inference_flag;
            }
            else
            {
                int list, mx = 0, my = 0, i;
                //FIXME we should set ref_idx_l? to 0 if we use that later ...
                if (0 != (mb_type & H264Context.MB_TYPE_16x16))
                {
                    for (list = 0; list < h.list_count; list++)
                    {
                        int val;
                        if (((mb_type) & (H264Context.MB_TYPE_P0L0 << ((0) + 2 * (list)))) != 0)
                        {
                            if (h.ref_count[list] == 1)
                            {
                                val = 0;
                            }
                            else if (h.ref_count[list] == 2)
                            {
                                val = (int)(s.gb.get_bits1("ref_count?") ^ 1);
                            }
                            else
                            {
                                val = s.gb.get_ue_golomb_31("ref_count?");
                                if (val >= h.ref_count[list])
                                {
                                    //av_log(h.s.avctx, AV_LOG_ERROR, "ref %u overflow\n", val);
                                    return -1;
                                }
                            }
                            Rectangle.fill_rectangle_sign(h.ref_cache[list], H264Context.scan8[0], 4, 4, 8, val, 1);
                        }
                    }
                    for (list = 0; list < h.list_count; list++)
                    {
                        if (((mb_type) & (H264Context.MB_TYPE_P0L0 << ((0) + 2 * (list)))) != 0)
                        {
                            int[] mxmy = new int[] { mx, my };
                            h.pred_motion(0, 4, list, h.ref_cache[list][H264Context.scan8[0]], mxmy);
                            mx = mxmy[0];
                            my = mxmy[1];
                            mx += s.gb.get_se_golomb("mx?");
                            my += s.gb.get_se_golomb("my?");
                            //int val = h.pack16to32(mx,my);

                            // DebugTool.printDebugString("    ****(1) mx="+mx+", my="+my+", val="+val+"\n");
                            //tprintf(s.avctx, "final mv:%d %d\n", mx, my);

                            Rectangle.fill_rectangle_mv_cache(h.mv_cache[list], H264Context.scan8[0], 4, 4, 8, H264Context.pack16to32(mx, my), 4);
                        }
                    }
                }
                else if (0 != (mb_type & H264Context.MB_TYPE_16x8))
                {
                    for (list = 0; list < h.list_count; list++)
                    {
                        for (i = 0; i < 2; i++)
                        {
                            int val;
                            if (((mb_type) & (H264Context.MB_TYPE_P0L0 << ((i) + 2 * (list)))) != 0)
                            {
                                if (h.ref_count[list] == 1)
                                {
                                    val = 0;
                                }
                                else if (h.ref_count[list] == 2)
                                {
                                    val = (int)(s.gb.get_bits1("ref_count?") ^ 1);
                                }
                                else
                                {
                                    val = s.gb.get_ue_golomb_31("ref_count?");
                                    if (val >= h.ref_count[list])
                                    {
                                        //av_log(h.s.avctx, AV_LOG_ERROR, "ref %u overflow\n", val);
                                        return -1;
                                    }
                                }
                            }
                            else
                            {
                                //!!?????????????????????? Need unsigneded??
                                val = H264Context.LIST_NOT_USED;
                            } // if
                            Rectangle.fill_rectangle_sign(h.ref_cache[list], H264Context.scan8[0] + 16 * i, 4, 2, 8, val, 1);
                        }
                    }
                    for (list = 0; list < h.list_count; list++)
                    {
                        for (i = 0; i < 2; i++)
                        {
                            int val;
                            if (((mb_type) & (H264Context.MB_TYPE_P0L0 << ((i) + 2 * (list)))) != 0)
                            {
                                int[] mxmy = new int[] { mx, my };
                                h.pred_16x8_motion(8 * i, list, h.ref_cache[list][H264Context.scan8[0] + 16 * i], mxmy);
                                mx = mxmy[0];
                                my = mxmy[1];
                                mx += s.gb.get_se_golomb("mx?");
                                my += s.gb.get_se_golomb("my?");
                                //tprintf(s.avctx, "final mv:%d %d\n", mx, my);

                                val = H264Context.pack16to32(mx, my);

                                // DebugTool.printDebugString("    ****(2) mx="+mx+", my="+my+", val="+val+"\n");

                            }
                            else
                                val = 0;
                            Rectangle.fill_rectangle_mv_cache(h.mv_cache[list], H264Context.scan8[0] + 16 * i, 4, 2, 8, val, 4);
                        }
                    }
                }
                else
                {
                    ////assert(IS_8X16(mb_type));
                    for (list = 0; list < h.list_count; list++)
                    {
                        for (i = 0; i < 2; i++)
                        {
                            int val;
                            if (((mb_type) & (H264Context.MB_TYPE_P0L0 << ((i) + 2 * (list)))) != 0)
                            { //FIXME optimize
                                if (h.ref_count[list] == 1)
                                {
                                    val = 0;
                                }
                                else if (h.ref_count[list] == 2)
                                {
                                    val = (int)(s.gb.get_bits1("ref-count?") ^ 1);
                                }
                                else
                                {
                                    val = s.gb.get_ue_golomb_31("ref-count?");
                                    if (val >= h.ref_count[list])
                                    {
                                        //av_log(h.s.avctx, AV_LOG_ERROR, "ref %u overflow\n", val);
                                        return -1;
                                    }
                                }
                            }
                            else
                            {
                                // !!?????????? Need Unsigned
                                val = H264Context.LIST_NOT_USED;
                            } // if

                            Rectangle.fill_rectangle_sign(h.ref_cache[list], H264Context.scan8[0] + 2 * i, 2, 4, 8, val, 1);
                        }
                    }
                    for (list = 0; list < h.list_count; list++)
                    {
                        for (i = 0; i < 2; i++)
                        {
                            int val;
                            if (((mb_type) & (H264Context.MB_TYPE_P0L0 << ((i) + 2 * (list)))) != 0)
                            {
                                int[] mxmy = new int[] { mx, my };
                                h.pred_8x16_motion(i * 4, list, h.ref_cache[list][H264Context.scan8[0] + 2 * i], mxmy);
                                mx = mxmy[0];
                                my = mxmy[1];
                                mx += s.gb.get_se_golomb("mx?");
                                my += s.gb.get_se_golomb("my?");
                                //tprintf(s.avctx, "final mv:%d %d\n", mx, my);

                                val = H264Context.pack16to32(mx, my);

                                // DebugTool.printDebugString("    ****(3) mx="+mx+", my="+my+", val="+val+"\n");

                            }
                            else
                                val = 0;
                            Rectangle.fill_rectangle_mv_cache(h.mv_cache[list], H264Context.scan8[0] + 2 * i, 2, 4, 8, val, 4);
                        }
                    }
                }
            }

            if (0 != (mb_type & (H264Context.MB_TYPE_16x16 | H264Context.MB_TYPE_16x8 | H264Context.MB_TYPE_8x16 | H264Context.MB_TYPE_8x8)))
                h.write_back_motion(mb_type);

            if (0 == (mb_type & H264Context.MB_TYPE_INTRA16x16))
            {
                cbp = s.gb.get_ue_golomb("cbp");
                if (cbp > 47)
                {
                    //av_log(h.s.avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, s.mb_x, s.mb_y);
                    return -1;
                }

                if (h.sps.chroma_format_idc != 0)
                {
                    if (0 != (mb_type & H264Context.MB_TYPE_INTRA4x4)) cbp = H264Data.golomb_to_intra4x4_cbp[cbp];
                    else cbp = H264Data.golomb_to_inter_cbp[cbp];
                }
                else
                {
                    if (0 != (mb_type & H264Context.MB_TYPE_INTRA4x4)) cbp = golomb_to_intra4x4_cbp_gray[cbp];
                    else cbp = golomb_to_inter_cbp_gray[cbp];
                }
            }

            if (dct8x8_allowed != 0 && (cbp & 15) != 0 && 0 == (mb_type & 7))
            {
                mb_type |= (int)(H264Context.MB_TYPE_8x8DCT * s.gb.get_bits1("mb_type"));
            }
            h.cbp =
            h.cbp_table[mb_xy] = cbp;
            s.current_picture.mb_type_base[s.current_picture.mb_type_offset + mb_xy] = mb_type;

            if (cbp != 0 || 0 != (mb_type & H264Context.MB_TYPE_INTRA16x16))
            {
                int i8x8, i4x4, chroma_idx;
                int dquant;
                GetBitContext gb = (((mb_type & 7) != 0) ? h.intra_gb_ptr : h.inter_gb_ptr);
                //uint8_t *scan, *scan8x8;
                byte[] scan;
                byte[] scan8x8;

                if (0 != (mb_type & H264Context.MB_TYPE_INTERLACED))
                {
                    scan8x8 = (s.qscale != 0 ? h.field_scan8x8_cavlc : h.field_scan8x8_cavlc_q0);
                    scan = (s.qscale != 0 ? h.field_scan : h.field_scan_q0);
                }
                else
                {
                    scan8x8 = (s.qscale != 0 ? h.zigzag_scan8x8_cavlc : h.zigzag_scan8x8_cavlc_q0);
                    scan = (s.qscale != 0 ? h.zigzag_scan : h.zigzag_scan_q0);
                }

                dquant = s.gb.get_se_golomb("dquant");

                s.qscale += dquant;

                if ((/*(unsigned)*/s.qscale) > 51)
                {
                    if (s.qscale < 0) s.qscale += 52;
                    else s.qscale -= 52;
                    if ((/*(unsigned)*/s.qscale) > 51)
                    {
                        //av_log(h.s.avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, s.mb_x, s.mb_y);
                        return -1;
                    }
                }

                h.chroma_qp[0] = h.pps.chroma_qp_table[0][s.qscale];
                h.chroma_qp[1] = h.pps.chroma_qp_table[1][s.qscale];
                if (0 != (mb_type & H264Context.MB_TYPE_INTRA16x16))
                {
                    // Fill 16 uint16_t with 0
                    Arrays.Fill(h.mb_luma_dc, 0, 16, (short)0);
                    //AV_ZERO128(h.mb_luma_dc+0);
                    //AV_ZERO128(h.mb_luma_dc+8);
                    if (decode_residual(h, h.intra_gb_ptr, h.mb_luma_dc, 0, H264Context.LUMA_DC_BLOCK_INDEX, scan, 0, h.dequant4_coeff[0][s.qscale], 0, 16) < 0)
                    {
                        return -1; //FIXME continue if partitioned and other return -1 too
                    }

                    //assert((cbp&15) == 0 || (cbp&15) == 15);

                    if ((cbp & 15) != 0)
                    {
                        /////////////////////////////////

                        for (i8x8 = 0; i8x8 < 4; i8x8++)
                        {
                            for (i4x4 = 0; i4x4 < 4; i4x4++)
                            {
                                int index = i4x4 + 4 * i8x8;
                                if (decode_residual(h, h.intra_gb_ptr, h.mb, 16 * index, index, scan, 1, h.dequant4_coeff[0][s.qscale], 0, 15) < 0)
                                {
                                    return -1;
                                }

                            }
                        }

                    }
                    else
                    {
                        Rectangle.fill_rectangle_unsign(h.non_zero_count_cache, H264Context.scan8[0], 4, 4, 8, 0, 1);
                    }
                }
                else
                {
                    for (i8x8 = 0; i8x8 < 4; i8x8++)
                    {
                        if ((cbp & (1 << i8x8)) != 0)
                        {
                            if (0 != (mb_type & H264Context.MB_TYPE_8x8DCT))
                            {
                                short[] buf_base = h.mb;
                                int buf_offset = 64 * i8x8;
                                for (i4x4 = 0; i4x4 < 4; i4x4++)
                                {
                                    if (decode_residual(h, gb, buf_base, buf_offset, i4x4 + 4 * i8x8, scan8x8, 16 * i4x4,
                                                        h.dequant8_coeff[(0 != (mb_type & 7)) ? 0 : 1][s.qscale], 0, 16) < 0)
                                        return -1;
                                }
                                int[] nnz_base = h.non_zero_count_cache;
                                int nnz_offset = H264Context.scan8[4 * i8x8];
                                nnz_base[nnz_offset + 0] += nnz_base[nnz_offset + 1] + nnz_base[nnz_offset + 8] + nnz_base[nnz_offset + 9];
                            }
                            else
                            {
                                for (i4x4 = 0; i4x4 < 4; i4x4++)
                                {
                                    int index = i4x4 + 4 * i8x8;

                                    if (decode_residual(h, gb, h.mb, 16 * index, index, scan, 0, h.dequant4_coeff[(mb_type & 7) != 0 ? 0 : 3][s.qscale], 0, 16) < 0)
                                    {
                                        return -1;
                                    }
                                }
                            }
                        }
                        else
                        {
                            int[] nnz_base = h.non_zero_count_cache;
                            int nnz_offset = H264Context.scan8[4 * i8x8];
                            nnz_base[nnz_offset + 0] = nnz_base[nnz_offset + 1] = nnz_base[nnz_offset + 8] = nnz_base[nnz_offset + 9] = 0;
                        }
                    }
                }

                if ((cbp & 0x030) != 0)
                {
                    // Fill 2x4 uint_16t with 0
                    Arrays.Fill(h.mb_chroma_dc[0], (short)0);
                    Arrays.Fill(h.mb_chroma_dc[1], (short)0);
                    //AV_ZERO128(h.mb_chroma_dc);
                    for (chroma_idx = 0; chroma_idx < 2; chroma_idx++)
                    {
                        if (decode_residual(h, gb, h.mb_chroma_dc[chroma_idx], 0, H264Context.CHROMA_DC_BLOCK_INDEX + chroma_idx, H264Data.chroma_dc_scan, 0, null, 0, 4) < 0)
                        {

                            // DebugTool.printDebugString("----Error type 16\n");

                            return -1;
                        }
                    }
                }

                if ((cbp & 0x020) != 0)
                {
                    for (chroma_idx = 0; chroma_idx < 2; chroma_idx++)
                    {
                        long[] qmul = h.dequant4_coeff[chroma_idx + 1 + (((mb_type & 7) != 0) ? 0 : 3)][h.chroma_qp[chroma_idx]];
                        for (i4x4 = 0; i4x4 < 4; i4x4++)
                        {
                            int index = 16 + 4 * chroma_idx + i4x4;
                            if (decode_residual(h, gb, h.mb, 16 * index, index, scan, 1, qmul, 0, 15) < 0)
                            {
                                return -1;
                            }
                        }
                    }
                }
                else
                {
                    int[] nnz = h.non_zero_count_cache;
                    nnz[H264Context.scan8[16] + 0] = nnz[H264Context.scan8[16] + 1] = nnz[H264Context.scan8[16] + 8] = nnz[H264Context.scan8[16] + 9] =
                    nnz[H264Context.scan8[20] + 0] = nnz[H264Context.scan8[20] + 1] = nnz[H264Context.scan8[20] + 8] = nnz[H264Context.scan8[20] + 9] = 0;
                }
            }
            else
            {
                int[] nnz = h.non_zero_count_cache;
                Rectangle.fill_rectangle_unsign(nnz, H264Context.scan8[0], 4, 4, 8, 0, 1);
                nnz[H264Context.scan8[16] + 0] = nnz[H264Context.scan8[16] + 1] = nnz[H264Context.scan8[16] + 8] = nnz[H264Context.scan8[16] + 9] =
                nnz[H264Context.scan8[20] + 0] = nnz[H264Context.scan8[20] + 1] = nnz[H264Context.scan8[20] + 8] = nnz[H264Context.scan8[20] + 9] = 0;
            }
            s.current_picture.qscale_table[mb_xy] = s.qscale;
            h.write_back_non_zero_count();

            if (h.mb_mbaff != 0)
            {
                h.ref_count[0] >>= 1;
                h.ref_count[1] >>= 1;
            }

            // DebugTool.dumpDebugFrameData(h, "AFTER-ff_h264_decode_mb_cavlc");

            return 0;
        }