public int ff_h264_decode_ref_pic_marking(GetBitContext gb) { int i; this.mmco_index = 0; if (this.nal_unit_type == NAL_IDR_SLICE) { //FIXME fields s.broken_link = (int)gb.get_bits1("broken_link") - 1; if (gb.get_bits1("MMCO_LONG?") != 0) { this.mmco[0].opcode = MMCO.MMCO_LONG; this.mmco[0].long_arg = 0; this.mmco_index = 1; } } else { if (gb.get_bits1("adaptive_ref_pic_marking_mode_flag") != 0) { // adaptive_ref_pic_marking_mode_flag for (i = 0; i < MAX_MMCO_COUNT; i++) { /*MMCOOpcode*/ int opcode = gb.get_ue_golomb_31("MMCOOpcode"); this.mmco[i].opcode = opcode; if (opcode == MMCO.MMCO_SHORT2UNUSED || opcode == MMCO.MMCO_SHORT2LONG) { this.mmco[i].short_pic_num = (this.curr_pic_num - gb.get_ue_golomb("?") - 1) & (this.max_pic_num - 1); /* if(this.mmco[i].short_pic_num >= this.short_ref_count || this.short_ref[ this.mmco[i].short_pic_num ] == NULL){ av_log(s.avctx, AV_LOG_ERROR, "illegal short ref in memory management control operation %d\n", mmco); return -1; }*/ } if (opcode == MMCO.MMCO_SHORT2LONG || opcode == MMCO.MMCO_LONG2UNUSED || opcode == MMCO.MMCO_LONG || opcode == MMCO.MMCO_SET_MAX_LONG) { /*unsigned */ int long_arg = gb.get_ue_golomb_31("long_arg"); if (long_arg >= 32 || (long_arg >= 16 && !(opcode == MMCO.MMCO_LONG2UNUSED && (s.picture_structure != Constants.PICT_FRAME)))) { //av_log(this.s.avctx, AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode); return -58; } this.mmco[i].long_arg = long_arg; } if (opcode > /*(unsigned)*/MMCO.MMCO_LONG) { //av_log(this.s.avctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode); return -59; } if (opcode == MMCO.MMCO_END) break; } this.mmco_index = i; } else { this.ff_generate_sliding_window_mmcos(); } } return 0; }
/** * decodes a residual block. * @param n block index * @param scantable scantable * @param max_coeff number of coefficients in the block * @return <0 if an error occurred */ public static int decode_residual(H264Context h, GetBitContext gb, short[] block_base, int block_offset , int n, byte[] scantable_base, int scantable_offset, long[] qmul_base, int qmul_offset, int max_coeff) { // , int n, uint8_t *scantable, uint32_t *qmul, int max_coeff){ //MpegEncContext s = h.s; int[/*17*/] coeff_token_table_index = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; int[] level = new int[16]; int zeros_left, coeff_token, total_coeff, i, trailing_ones, run_before; //FIXME put trailing_onex into the context if (n >= H264Context.CHROMA_DC_BLOCK_INDEX) { coeff_token = gb.get_vlc2( chroma_dc_coeff_token_vlc.table_base, chroma_dc_coeff_token_vlc.table_offset, H264Context.CHROMA_DC_COEFF_TOKEN_VLC_BITS, 1, "coeff_token_CROMA_DC"); total_coeff = coeff_token >> 2; //Console.WriteLine("get_vlc2(CHROMA_DC_COEFF_TOKEN) => total_coeff = " + total_coeff ); } else { if (n == H264Context.LUMA_DC_BLOCK_INDEX) { total_coeff = pred_non_zero_count(h, 0); //Console.WriteLine("Prediected Non-Zero count = "+total_coeff); coeff_token = gb.get_vlc2( coeff_token_vlc[coeff_token_table_index[total_coeff]].table_base, coeff_token_vlc[coeff_token_table_index[total_coeff]].table_offset, H264Context.COEFF_TOKEN_VLC_BITS, 2, "coeff_token_LUMA_DC"); total_coeff = coeff_token >> 2; //Console.WriteLine("get_vlc2(LUMA_DC_COEFF_TOKEN) => total_coeff = " + total_coeff ); } else { total_coeff = pred_non_zero_count(h, n); // DebugTool.printDebugString("predicted non_zero_count("+n+") = "+total_coeff+"\n"); coeff_token = gb.get_vlc2( coeff_token_vlc[coeff_token_table_index[total_coeff]].table_base, coeff_token_vlc[coeff_token_table_index[total_coeff]].table_offset, H264Context.COEFF_TOKEN_VLC_BITS, 2, "coeff_token_LUMA(2)_DC"); total_coeff = coeff_token >> 2; // DebugTool.printDebugString("predicted non_zero_count-2 = "+total_coeff+"\n"); } } h.non_zero_count_cache[H264Context.scan8[n]] = total_coeff; //FIXME set last_non_zero? if (total_coeff == 0) return 0; if (total_coeff > /*(unsigned)*/max_coeff) { // av_log(h.s.avctx, AV_LOG_ERROR, "corrupted macroblock %d %d (total_coeff=%d)\n", s.mb_x, s.mb_y, total_coeff); // DebugTool.printDebugString(" -------- Error type 1.0\n"); return -1; } trailing_ones = coeff_token & 3; // tprintf(h.s.avctx, "trailing:%d, total:%d\n", trailing_ones, total_coeff); //assert(total_coeff<=16); // DebugTool.printDebugString(" - trailing_ones = "+trailing_ones+"\n"); i = (int)gb.show_bits(3); gb.skip_bits(trailing_ones); level[0] = 1 - ((i & 4) >> 1); level[1] = 1 - ((i & 2)); level[2] = 1 - ((i & 1) << 1); // DebugTool.printDebugString(" - i = "+i+"\n"); if (trailing_ones < total_coeff) { int mask, prefix; int suffix_length = ((total_coeff > 10) ? 1 : 0) & ((trailing_ones < 3) ? 1 : 0); int bitsi = (int)gb.show_bits(LEVEL_TAB_BITS); int level_code = cavlc_level_tab[suffix_length][bitsi][0]; // DebugTool.printDebugString(" - bitsi = "+bitsi+", level_code = "+level_code+", skip_bit = "+cavlc_level_tab[suffix_length][bitsi][1]+"\n"); gb.skip_bits(cavlc_level_tab[suffix_length][bitsi][1]); if (level_code >= 100) { prefix = level_code - 100; if (prefix == LEVEL_TAB_BITS) prefix += get_level_prefix(gb); // DebugTool.printDebugString(" - prefix = "+prefix+"\n"); //first coefficient has suffix_length equal to 0 or 1 if (prefix < 14) { //FIXME try to build a large unified VLC table for all this if (suffix_length != 0) level_code = (int)((prefix << 1) + gb.get_bits1("level_code")); //part else level_code = prefix; //part } else if (prefix == 14) { if (suffix_length != 0) level_code = (int)((prefix << 1) + gb.get_bits1("level_code")); //part else level_code = (int)(prefix + gb.get_bits(4, "level_code")); //part } else { // Nok: Prevent bug?? in ffmpeg that the decoder may overflow? level_code = 30 + (int)(gb.get_bits(prefix - 3, "level_code")); //part if (prefix >= 16) { if (prefix > 25 + 3) { // DebugTool.printDebugString(" -------- Error type 1.1\n"); //av_log(h.s.avctx, AV_LOG_ERROR, "Invalid level prefix\n"); return -1; } level_code += (1 << (prefix - 3)) - 4096; } } if (trailing_ones < 3) level_code += 2; // DebugTool.printDebugString(" - level_code(1) = "+level_code+"\n"); suffix_length = 2; mask = -(level_code & 1); level[trailing_ones] = (((2 + level_code) >> 1) ^ mask) - mask; } else { level_code += ((level_code >> 31) | 1) & -((trailing_ones < 3) ? 1 : 0); // DebugTool.printDebugString(" - level_code(2) = "+level_code+"\n"); // Fix: for difference between JAVA and C, we need to convert signed to unsigned when we compare // signed and unsigned number because, in C, such comparing will be done in common part. // In which, common part in C in unsigned, while java is signed. -= Nok =- suffix_length = 1 + (((0xffffffffL & (level_code + 3)) > 6) ? 1 : 0); level[trailing_ones] = level_code; } // DebugTool.printDebugString(" - suffix_length(1) = "+suffix_length+"\n"); //remaining coefficients have suffix_length > 0 for (i = trailing_ones + 1; i < total_coeff; i++) { int[/*7*/] suffix_limit = { 0, 3, 6, 12, 24, 48, int.MaxValue }; bitsi = (int)gb.show_bits(LEVEL_TAB_BITS); level_code = cavlc_level_tab[suffix_length][bitsi][0]; // DebugTool.printDebugString(" - cavlc_level_tab["+suffix_length+"]["+bitsi+"][0] = "+level_code+"\n"); gb.skip_bits(cavlc_level_tab[suffix_length][bitsi][1]); if (level_code >= 100) { prefix = level_code - 100; if (prefix == LEVEL_TAB_BITS) { prefix += get_level_prefix(gb); } if (prefix < 15) { level_code = (int)((prefix << suffix_length) + gb.get_bits(suffix_length, "level_code")); } else { level_code = (int)((15 << suffix_length) + gb.get_bits(prefix - 3, "level_code")); if (prefix >= 16) level_code += (1 << (prefix - 3)) - 4096; } mask = -(level_code & 1); level_code = (((2 + level_code) >> 1) ^ mask) - mask; } level[i] = level_code; // DebugTool.printDebugString(" - prefix(6) = "+level_code+"\n"); // Fix: for difference between JAVA and C, we need to convert signed to unsigned when we compare // signed and unsigned number because, in C, such comparing will be done in common part. // In which, common part in C in unsigned, while java is signed. -= Nok =- suffix_length += (((0xffffffffL & (suffix_limit[suffix_length] + level_code)) > (2L * suffix_limit[suffix_length])) ? 1 : 0); } // DebugTool.printDebugString(" - suffix_length(2) = "+suffix_length+"\n"); } if (total_coeff == max_coeff) zeros_left = 0; else { if (n >= H264Context.CHROMA_DC_BLOCK_INDEX) { zeros_left = gb.get_vlc2(chroma_dc_total_zeros_vlc[total_coeff - 1].table_base, chroma_dc_total_zeros_vlc[total_coeff - 1].table_offset, H264Context.CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 1, "coeff_token_CROMA_DC_TOTAL_ZERO"); // DebugTool.printDebugString("get_vlc2(CHROMA_DC_ZERO_LEFT) => zeros_left = " + zeros_left +"\n"); } else { zeros_left = gb.get_vlc2(total_zeros_vlc[total_coeff - 1].table_base, total_zeros_vlc[total_coeff - 1].table_offset, H264Context.TOTAL_ZEROS_VLC_BITS, 1, "coeff_token_TOTAL_ZEROS"); // DebugTool.printDebugString("get_vlc2(LUMA_DC_ZERO_LEFT) => zeros_left = " + zeros_left +"\n"); } // if } /* // DebugTool.printDebugString("scantable_offset(before) = {" +scantable_base[scantable_offset+0]+"," +scantable_base[scantable_offset+1]+"," +scantable_base[scantable_offset+2]+"," +scantable_base[scantable_offset+3]+"," +scantable_base[scantable_offset+4] +"}\n"); */ scantable_offset += zeros_left + total_coeff - 1; /* // DebugTool.printDebugString("scantable_offset(after) = {" +scantable_base[scantable_offset+0]+"," +scantable_base[scantable_offset+1]+"," +scantable_base[scantable_offset+2]+"," +scantable_base[scantable_offset+3]+"," +scantable_base[scantable_offset+4] +"}\n"); */ //!!????????????????????????????????? Magic about array resizing?? if (scantable_offset < 0) { byte[] new_scantable_base = new byte[scantable_base.Length + (-scantable_offset)]; Array.Copy(scantable_base, 0, new_scantable_base, -scantable_offset, scantable_base.Length); scantable_base = new_scantable_base; scantable_offset = 0; } if (n >= H264Context.LUMA_DC_BLOCK_INDEX) { // DebugTool.printDebugString("****RESE-CASE 1\n"); block_base[block_offset + scantable_base[scantable_offset]] = (short)level[0]; for (i = 1; i < total_coeff && zeros_left > 0; i++) { if (zeros_left < 7) { //????????????????????????????????????????/ // run_before= gb.get_vlc2((run_vlc-1)[zeros_left].table, H264Context.RUN_VLC_BITS, 1); run_before = gb.get_vlc2(run_vlc[zeros_left - 1].table_base, run_vlc[zeros_left - 1].table_offset, H264Context.RUN_VLC_BITS, 1, "RUN_VLC"); //Console.WriteLine("get_vlc2(LUMA_RUN_VLC) => run_before = " + run_before ); } else { run_before = gb.get_vlc2(run7_vlc.table_base, run7_vlc.table_offset, H264Context.RUN7_VLC_BITS, 2, "RUN7_VLC"); //Console.WriteLine("get_vlc2(LUMA_RUN_VLC7) => run_before = " + run_before ); } // if ////Console.WriteLine("run_before = "+run_before); zeros_left -= run_before; scantable_offset -= 1 + run_before; block_base[block_offset + scantable_base[scantable_offset]] = (short)level[i]; } for (; i < total_coeff; i++) { scantable_offset--; block_base[block_offset + scantable_base[scantable_offset]] = (short)level[i]; } } else { // DebugTool.printDebugString("****RESE-CASE 2\n"); block_base[block_offset + scantable_base[scantable_offset]] = (short)((level[0] * qmul_base[qmul_offset + scantable_base[scantable_offset]] + 32) >> 6); for (i = 1; i < total_coeff && zeros_left > 0; i++) { if (zeros_left < 7) { run_before = gb.get_vlc2(run_vlc[zeros_left - 1].table_base, run_vlc[zeros_left - 1].table_offset, H264Context.RUN_VLC_BITS, 1, "RUN_VLC"); //Console.WriteLine("get_vlc2(CHROMA_RUN_VLC) => run_before = " + run_before ); } else { run_before = gb.get_vlc2(run7_vlc.table_base, run7_vlc.table_offset, H264Context.RUN7_VLC_BITS, 2, "RUN7_VLC"); //Console.WriteLine("get_vlc2(CHROMA_RUN_VLC7) => run_before = " + run_before ); } // if ////Console.WriteLine("run_before = "+run_before); zeros_left -= run_before; scantable_offset -= (1 + run_before); block_base[block_offset + scantable_base[scantable_offset]] = (short)((level[i] * qmul_base[qmul_offset + scantable_base[scantable_offset]] + 32) >> 6); } for (; i < total_coeff; i++) { scantable_offset--; block_base[block_offset + scantable_base[scantable_offset]] = (short)((level[i] * qmul_base[qmul_offset + scantable_base[scantable_offset]] + 32) >> 6); } } if (zeros_left < 0) { //av_log(h.s.avctx, AV_LOG_ERROR, "negative number of zero coeffs at %d %d\n", s.mb_x, s.mb_y); // DebugTool.printDebugString(" -------- Error type 1.2\n"); return -1; } return 0; }