public int decode_cabac_p_mb_sub_type(H264Context h) { if (this.get_cabac(h.cabac_state, 21) != 0) return 0; /* 8x8 */ if (this.get_cabac(h.cabac_state, 22) == 0) return 1; /* 8x4 */ if (this.get_cabac(h.cabac_state, 23) != 0) return 2; /* 4x8 */ return 3; /* 4x4 */ }
/** * 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; }
public int decode_cabac_mb_ref(H264Context h, int list, int n) { int refa = h.ref_cache[list][H264Context.scan8[n] - 1]; int refb = h.ref_cache[list][H264Context.scan8[n] - 8]; int @ref = 0; int ctx = 0; if (h.slice_type_nos == H264Context.FF_B_TYPE) { if (refa > 0 && 0 == (h.direct_cache[H264Context.scan8[n] - 1] & (H264Context.MB_TYPE_DIRECT2 >> 1))) ctx++; if (refb > 0 && 0 == (h.direct_cache[H264Context.scan8[n] - 8] & (H264Context.MB_TYPE_DIRECT2 >> 1))) ctx += 2; } else { if (refa > 0) ctx++; if (refb > 0) ctx += 2; } while (this.get_cabac(h.cabac_state, 54 + ctx) != 0) { @ref++; ctx = (ctx >> 2) + 4; if (@ref >= 32 /*this.ref_list[list]*/) { return -1; } } return @ref; }
public int decode_cabac_mb_skip(H264Context h, int mb_x, int mb_y) { int mba_xy, mbb_xy; int ctx = 0; if (h.mb_aff_frame != 0) { //FIXME merge with the stuff in fill_caches? int mb_xy = mb_x + (mb_y & ~1) * h.s.mb_stride; mba_xy = mb_xy - 1; if ((mb_y & 1) != 0 && h.slice_table_base[h.slice_table_offset + mba_xy] == h.slice_num && h.mb_field_decoding_flag == ((h.s.current_picture.mb_type_base[h.s.current_picture.mb_type_offset + mba_xy] & H264Context.MB_TYPE_INTERLACED) != 0 ? 1 : 0)) mba_xy += h.s.mb_stride; if (h.mb_field_decoding_flag != 0) { mbb_xy = mb_xy - h.s.mb_stride; if (0 == (mb_y & 1) && h.slice_table_base[h.slice_table_offset + mbb_xy] == h.slice_num && (h.s.current_picture.mb_type_base[h.s.current_picture.mb_type_offset + mbb_xy] & H264Context.MB_TYPE_INTERLACED) != 0) mbb_xy -= h.s.mb_stride; } else mbb_xy = mb_x + (mb_y - 1) * h.s.mb_stride; } else { int mb_xy = h.mb_xy; mba_xy = mb_xy - 1; mbb_xy = mb_xy - (h.s.mb_stride << 0); } if (h.slice_table_base[h.slice_table_offset + mba_xy] == h.slice_num && ((h.s.current_picture.mb_type_base[h.s.current_picture.mb_type_offset + mba_xy] & H264Context.MB_TYPE_SKIP) == 0)) ctx++; if (h.slice_table_base[h.slice_table_offset + mbb_xy] == h.slice_num && ((h.s.current_picture.mb_type_base[h.s.current_picture.mb_type_offset + mbb_xy] & H264Context.MB_TYPE_SKIP) == 0)) ctx++; if (h.slice_type_nos == H264Context.FF_B_TYPE) ctx += 13; int ret = this.get_cabac_noinline(h.cabac_state, 11 + ctx); // DebugTool.printDebugString(" * decode_cabac_mb_skip return "+ret+"\n"); return ret; }
/** * Replicate H264 "master" context to thread contexts. */ public static void clone_slice(H264Context dst, H264Context src) { //memcpy(dst.block_offset, src.block_offset, sizeof(dst.block_offset)); Array.Copy(src.block_offset, 0, dst.block_offset, 0, dst.block_offset.Length); dst.s.current_picture_ptr = src.s.current_picture_ptr; dst.s.current_picture = src.s.current_picture; dst.s.linesize = src.s.linesize; dst.s.uvlinesize = src.s.uvlinesize; dst.s.first_field = src.s.first_field; dst.prev_poc_msb = src.prev_poc_msb; dst.prev_poc_lsb = src.prev_poc_lsb; dst.prev_frame_num_offset = src.prev_frame_num_offset; dst.prev_frame_num = src.prev_frame_num; dst.short_ref_count = src.short_ref_count; //memcpy(dst.short_ref, src.short_ref, sizeof(dst.short_ref)); //memcpy(dst.long_ref, src.long_ref, sizeof(dst.long_ref)); for (int i = 0; i < src.short_ref.Length; i++) src.short_ref[i].copyTo(dst.short_ref[i]); for (int i = 0; i < src.long_ref.Length; i++) src.long_ref[i].copyTo(dst.long_ref[i]); //memcpy(dst.default_ref_list, src.default_ref_list, sizeof(dst.default_ref_list)); //memcpy(dst.ref_list, src.ref_list, sizeof(dst.ref_list)); for (int i = 0; i < src.default_ref_list.Length; i++) for (int j = 0; j < src.default_ref_list[i].Length; j++) src.default_ref_list[i][j].copyTo(dst.default_ref_list[i][j]); for (int i = 0; i < src.ref_list.Length; i++) for (int j = 0; j < src.ref_list[i].Length; j++) src.ref_list[i][j].copyTo(dst.ref_list[i][j]); //memcpy(dst.dequant4_coeff, src.dequant4_coeff, sizeof(src.dequant4_coeff)); //memcpy(dst.dequant8_coeff, src.dequant8_coeff, sizeof(src.dequant8_coeff)); for (int i = 0; i < src.dequant4_coeff.Length; i++) for (int j = 0; j < src.dequant4_coeff[i].Length; j++) for (int k = 0; k < src.dequant4_coeff[i][j].Length; k++) dst.dequant4_coeff[i][j][k] = src.dequant4_coeff[i][j][k]; for (int i = 0; i < src.dequant8_coeff.Length; i++) for (int j = 0; j < src.dequant8_coeff[i].Length; j++) for (int k = 0; k < src.dequant8_coeff[i][j].Length; k++) dst.dequant8_coeff[i][j][k] = src.dequant8_coeff[i][j][k]; }
public static void dumpDebugFrameData(H264Context h, string msg, bool incrementCounter) { if (!DEBUG_MODE) return; try { if (incrementCounter) logCount++; Console.WriteLine("Dumping Decoder State(" + msg + "): " + logCount + ", Frame: " + h.frame_num); // Dump all data inside decoder Console.Write("ctx.non_zero_count_cache: "); for (int i = 0; i < h.non_zero_count_cache.Length; i++) { Console.Write("," + h.non_zero_count_cache[i]); } // for Console.WriteLine(); //for(int j=0;j<h.non_zero_count.Length;j++) { int j = h.mb_xy; if (h.non_zero_count != null) if (j >= 0 && j < h.non_zero_count.Length) { Console.Write("ctx.non_zero_count[" + j + "]: "); for (int i = 0; i < h.non_zero_count[j].Length; i++) { Console.Write("," + h.non_zero_count[j][i]); } // for i Console.WriteLine(); } // for j // Dump all data inside decoder Console.Write("edge_emu_buffer: "); for (int i = 0; i < (h.s.width + 64) * 2 * 21 && logCount == 9537; i++) { Console.Write("," + h.s.allocated_edge_emu_buffer[h.s.edge_emu_buffer_offset + i]); } // for Console.WriteLine(); Console.Write("ctx.mv_cache[0]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.mv_cache[0][i][0] + "," + h.mv_cache[0][i][1]); } // for Console.WriteLine(); Console.Write("ctx.mv_cache[1]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.mv_cache[1][i][0] + "," + h.mv_cache[1][i][1]); } // for Console.WriteLine(); Console.Write("ctx.mvd_cache[0]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.mvd_cache[0][i][0] + "," + h.mvd_cache[0][i][1]); } // for Console.WriteLine(); Console.Write("ctx.mvd_cache[1]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.mvd_cache[1][i][0] + "," + h.mvd_cache[1][i][1]); } // for Console.WriteLine(); if (h.mvd_table[0] != null) { Console.Write("ctx.mvd_table[0]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.mvd_table[0][i][0] + "," + h.mvd_table[0][i][1]); } // for Console.WriteLine(); Console.Write("ctx.mvd_table[1]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.mvd_table[1][i][0] + "," + h.mvd_table[1][i][1]); } // for Console.WriteLine(); } // if Console.Write("ctx.ref_cache[0]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.ref_cache[0][i] + "," + h.ref_cache[0][i]); } // for Console.WriteLine(); Console.Write("ctx.ref_cache[1]: "); for (int i = 0; i < 40; i++) { Console.Write("," + h.ref_cache[1][i] + "," + h.ref_cache[1][i]); } // for Console.WriteLine(); Console.Write("error_status_table: "); if (h.s.error_status_table != null) for (int i = 0; i </*h.s.error_status_table.Length*/32 && h.s.error_status_table.Length > 32; i++) { Console.Write("," + h.s.error_status_table[i]); } // for Console.WriteLine(); } catch (Exception e) { Console.WriteLine(e); } finally { } // try }
public int decode_cabac_mb_cbp_luma(H264Context h) { int cbp_b, cbp_a, ctx, cbp = 0; cbp_a = h.left_cbp; cbp_b = h.top_cbp; ctx = ((cbp_a & 0x02) == 0 ? 1 : 0) + 2 * ((cbp_b & 0x04) == 0 ? 1 : 0); cbp += this.get_cabac_noinline(h.cabac_state, 73 + ctx); ctx = ((cbp & 0x01) == 0 ? 1 : 0) + 2 * ((cbp_b & 0x08) == 0 ? 1 : 0); cbp += this.get_cabac_noinline(h.cabac_state, 73 + ctx) << 1; ctx = ((cbp_a & 0x08) == 0 ? 1 : 0) + 2 * ((cbp & 0x01) == 0 ? 1 : 0); cbp += this.get_cabac_noinline(h.cabac_state, 73 + ctx) << 2; ctx = ((cbp & 0x04) == 0 ? 1 : 0) + 2 * ((cbp & 0x02) == 0 ? 1 : 0); cbp += this.get_cabac_noinline(h.cabac_state, 73 + ctx) << 3; return cbp; }
public int avcodec_open(H264Decoder codec) { int ret = -1; /* If there is a user-supplied mutex locking routine, call it. */ /* if (ff_lockmgr_cb) { if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) return -1; } */ /* entangled_thread_counter++; if(entangled_thread_counter != 1){ av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n"); goto end; } */ //if(this.codec!=null || codec == null) // return ret; this.priv_data = new H264Context(); //priv_data.av_opt_set_defaults(); if (this.coded_width != 0 && this.coded_height != 0) this.avcodec_set_dimensions(this.coded_width, this.coded_height); else if (this.width != 0 && this.height != 0) this.avcodec_set_dimensions(this.width, this.height); if ((this.coded_width != 0 || this.coded_height != 0 || this.width != 0 || this.height != 0) && (av_image_check_size(this.coded_width, this.coded_height, 0, this) < 0 || av_image_check_size(this.width, this.height, 0, this) < 0)) { //av_log(avctx, AV_LOG_WARNING, "ignoring invalid width/height values\n"); this.avcodec_set_dimensions(0, 0); } /* if the decoder init function was already called previously, free the already allocated subtitle_header before overwriting it */ //?????????????????????? //if (codec.decode!=0) // av_freep(&this.subtitle_header); //#define SANE_NB_CHANNELS 128U //if (this.channels > 128) { // ret = -1; // return ret; // } this.codec = codec; //if ((this.codec_type == AVMEDIA_TYPE_UNKNOWN || this.codec_type == codec.type) && // this.codec_id == CODEC_ID_NONE) { // this.codec_type = codec.type; this.codec_id = codec.id; //} //if (this.codec_id != codec.id || (this.codec_type != codec.type // && this.codec_type != AVMEDIA_TYPE_ATTACHMENT)) { //av_log(avctx, AV_LOG_ERROR, "codec type or id mismatches\n"); // return ret; //} this.frame_number = 0; if (this.codec.max_lowres < this.lowres) { //av_log(avctx, AV_LOG_ERROR, "The maximum value for lowres supported by the decoder is %d\n", // this.codec.max_lowres); return ret; } ret = this.codec.init(this); if (ret < 0) { return ret; } // this ret = 0; return ret; }
public int decode_cabac_intra_mb_type(H264Context h, int ctx_base, int intra_slice) { int state_offset = ctx_base; int mb_type; if (intra_slice != 0) { int ctx = 0; if ((h.left_type[0] & (H264Context.MB_TYPE_INTRA16x16 | H264Context.MB_TYPE_INTRA_PCM)) != 0) ctx++; if ((h.top_type & (H264Context.MB_TYPE_INTRA16x16 | H264Context.MB_TYPE_INTRA_PCM)) != 0) ctx++; if (this.get_cabac_noinline(h.cabac_state, state_offset + ctx) == 0) return 0; /* I4x4 */ state_offset += 2; } else { if (this.get_cabac_noinline(h.cabac_state, state_offset) == 0) return 0; /* I4x4 */ } if (this.get_cabac_terminate() != 0) return 25; /* PCM */ mb_type = 1; /* I16x16 */ mb_type += 12 * this.get_cabac_noinline(h.cabac_state, state_offset + 1); /* cbp_luma != 0 */ if (this.get_cabac_noinline(h.cabac_state, state_offset + 2) != 0) /* cbp_chroma */ mb_type += 4 + 4 * this.get_cabac_noinline(h.cabac_state, state_offset + 2 + intra_slice); mb_type += 2 * this.get_cabac_noinline(h.cabac_state, state_offset + 3 + intra_slice); mb_type += 1 * this.get_cabac_noinline(h.cabac_state, state_offset + 3 + 2 * intra_slice); return mb_type; }
public int decode_cabac_mb_cbp_chroma(H264Context h) { int ctx; int cbp_a, cbp_b; cbp_a = (h.left_cbp >> 4) & 0x03; cbp_b = (h.top_cbp >> 4) & 0x03; ctx = 0; if (cbp_a > 0) ctx++; if (cbp_b > 0) ctx += 2; if (this.get_cabac_noinline(h.cabac_state, 77 + ctx) == 0) return 0; ctx = 4; if (cbp_a == 2) ctx++; if (cbp_b == 2) ctx += 2; return 1 + this.get_cabac_noinline(h.cabac_state, 77 + ctx); }
////////////////////////////////////////////////////// // H264 Specific CABAC Decoding Functions (2nd level) public int decode_cabac_field_decoding_flag(H264Context h) { int mbb_xy = (int)(h.mb_xy - 2L * h.s.mb_stride); int ctx = 0; ctx += (h.mb_field_decoding_flag & (/*!!*/h.s.mb_x)); //for FMO:(s.current_picture.mb_type[mba_xy]>>7)&(this.slice_table_base[this.slice_table_offset + mba_xy] == this.slice_num); ctx += (int)((h.s.current_picture.mb_type_base[h.s.current_picture.mb_type_offset + mbb_xy] >> 7) & (h.slice_table_base[h.slice_table_offset + mbb_xy] == h.slice_num ? 1 : 0)); return this.get_cabac_noinline(h.cabac_state, 70 + ctx);// &(this.cabac_state+70)[ctx] ); }
public int decode_cabac_b_mb_sub_type(H264Context h) { int type; if (0 == this.get_cabac(h.cabac_state, 36)) return 0; /* B_Direct_8x8 */ if (0 == this.get_cabac(h.cabac_state, 37)) return 1 + this.get_cabac(h.cabac_state, 39); /* B_L0_8x8, B_L1_8x8 */ type = 3; if (0 != this.get_cabac(h.cabac_state, 38)) { if (0 != this.get_cabac(h.cabac_state, 39)) return 11 + this.get_cabac(h.cabac_state, 39); /* B_L1_4x4, B_Bi_4x4 */ type += 4; } type += 2 * this.get_cabac(h.cabac_state, 39); type += this.get_cabac(h.cabac_state, 39); return type; }
// CABAC Decoder Functions public void ff_h264_init_cabac_states(H264Context h) { var tab = (h.slice_type_nos == H264Context.FF_I_TYPE) ? cabac_context_init_I : cabac_context_init_PB[h.cabac_init_idc] ; /* calculate pre-state */ for (int i = 0; i < 460; i++) { int pre = 2 * (((tab[i][0] * h.s.qscale) >> 4) + tab[i][1]) - 127; pre ^= pre >> 31; if (pre > 124) pre = 124 + (pre & 1); h.cabac_state[i] = pre; } }
/** * gets the predicted number of non-zero coefficients. * @param n block index */ /*inline*/ public static int pred_non_zero_count(H264Context h, int n) { int index8 = H264Context.scan8[n]; int left = h.non_zero_count_cache[index8 - 1]; int top = h.non_zero_count_cache[index8 - 8]; int i = left + top; if (i < 64) i = (i + 1) >> 1; //tprintf(h.s.avctx, "pred_nnz L%X T%X n%d s%d P%X\n", left, top, n, scan8[n], i&31); return i & 31; }
public int decode_cabac_mb_chroma_pre_mode(H264Context h) { int mba_xy = h.left_mb_xy[0]; int mbb_xy = h.top_mb_xy; int ctx = 0; /* No need to test for IS_INTRA4x4 and IS_INTRA16x16, as we set chroma_pred_mode_table to 0 */ if (h.left_type[0] != 0 && h.chroma_pred_mode_table[mba_xy] != 0) ctx++; if (h.top_type != 0 && h.chroma_pred_mode_table[mbb_xy] != 0) ctx++; if (this.get_cabac_noinline(h.cabac_state, 64 + ctx) == 0) return 0; if (this.get_cabac_noinline(h.cabac_state, 64 + 3) == 0) return 1; if (this.get_cabac_noinline(h.cabac_state, 64 + 3) == 0) return 2; else return 3; }
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; }
public int decode_cabac_mb_intra4x4_pred_mode(H264Context h, int pred_mode) { int mode = 0; if (this.get_cabac(h.cabac_state, 68) != 0) return pred_mode; mode += 1 * this.get_cabac(h.cabac_state, 69); mode += 2 * this.get_cabac(h.cabac_state, 69); mode += 4 * this.get_cabac(h.cabac_state, 69); return mode + ((mode >= pred_mode) ? 1 : 0); }
public int avcodec_close() { if (this.codec != null) this.codec.close(this); avcodec_default_free_buffers(); this.coded_frame = null; this.priv_data = null; this.codec = null; return 0; }
public int decode_cabac_mb_mvd(H264Context h, int ctxbase, int amvd, int[] mvda) { int mvd; // DebugTool.printDebugString(" - decode_cabac_mb_mvd: ctxbase="+ctxbase+", amvd="+amvd+", state_offset="+(ctxbase+((amvd-3)>>(INT_BIT-1))+((amvd-33)>>(INT_BIT-1))+2)+"\n"); // DebugTool.printDebugString(" - INT_BIT="+INT_BIT+", ((amvd-3)>>(INT_BIT-1))="+((amvd-3)>>(INT_BIT-1))+", ((amvd-33)>>(INT_BIT-1))="+((amvd-33)>>(INT_BIT-1))+"\n"); if (0 == this.get_cabac(h.cabac_state, ctxbase + ((amvd - 3) >> (INT_BIT - 1)) + ((amvd - 33) >> (INT_BIT - 1)) + 2)) { mvda[0] = 0; return 0; } mvd = 1; ctxbase += 3; while (mvd < 9 && this.get_cabac(h.cabac_state, ctxbase) != 0) { if (mvd < 4) ctxbase++; mvd++; } if (mvd >= 9) { int k = 3; while (this.get_cabac_bypass() != 0) { mvd += 1 << k; k++; if (k > 24) { //Console.WriteLine("overflow in decode_cabac_mb_mvd"); return int.MinValue; } } while (k-- != 0) { mvd += this.get_cabac_bypass() << k; } mvda[0] = mvd < 70 ? mvd : 70; } else mvda[0] = mvd; return this.get_cabac_bypass_sign(-mvd); }
/** * decodes a slice header. * This will also call MPV_common_init() and frame_start() as needed. * * @param h h264context * @param h0 h264 master context (differs from 'h' when doing sliced based parallel decoding) * * @return 0 if okay, <0 if an error occurred, 1 if decoding must not be multithreaded */ public static int decode_slice_header(H264Context h, H264Context h0) { MpegEncContext s = h.s; MpegEncContext s0 = h0.s; /*unsigned */ int first_mb_in_slice; /*unsigned */ int pps_id; int num_ref_idx_active_override_flag; /*unsigned */ int slice_type, tmp, i, j; int default_ref_list_done = 0; int last_pic_structure; s.dropable = (h.nal_ref_idc == 0) ? 1 : 0; s.me.qpel_put = DSPContext.put_h264_qpel_pixels_tab; s.me.qpel_avg = DSPContext.avg_h264_qpel_pixels_tab; first_mb_in_slice = s.gb.get_ue_golomb("first_mb_in_slice"); if (first_mb_in_slice == 0) { //FIXME better field boundary detection if ((h0.current_slice != 0) && (s.picture_structure != Constants.PICT_FRAME)) { h.field_end(); } // if h0.current_slice = 0; if (0 == s0.first_field) s.current_picture_ptr = null; } slice_type = s.gb.get_ue_golomb_31("slice_type"); if (slice_type > 9) { // DebugTool.printDebugString(" --- decode_slide_header error case 0\n"); //av_log(h.s.avctx, AV_LOG_ERROR, "slice type too large (%d) at %d %d\n", h.slice_type, s.mb_x, s.mb_y); return -60; } if (slice_type > 4) { slice_type -= 5; h.slice_type_fixed = 1; } else h.slice_type_fixed = 0; slice_type = H264Data.golomb_to_pict_type[slice_type]; /* if(slice_type == H264Context.FF_I_TYPE) { //Console.WriteLine("Decoding I-Slice."); } else if(slice_type == H264Context.FF_P_TYPE) { //Console.WriteLine("Decoding P-Slice."); } else if(slice_type == H264Context.FF_B_TYPE) { //Console.WriteLine("Decoding B-Slice."); } else if(slice_type == H264Context.FF_S_TYPE) { //Console.WriteLine("Decoding S-Slice."); } else if(slice_type == H264Context.FF_SI_TYPE) { //Console.WriteLine("Decoding SI-Slice."); } else if(slice_type == H264Context.FF_SP_TYPE) { //Console.WriteLine("Decoding SP-Slice."); } else if(slice_type == H264Context.FF_BI_TYPE) { //Console.WriteLine("Decoding BI-Slice."); } // if */ if (slice_type == FF_I_TYPE || (h0.current_slice != 0 && slice_type == h0.last_slice_type)) { default_ref_list_done = 1; } h.slice_type = slice_type; h.slice_type_nos = slice_type & 3; s.pict_type = h.slice_type; // to make a few old functions happy, it's wrong though pps_id = s.gb.get_ue_golomb("pps_id"); if (pps_id >= MAX_PPS_COUNT) { //av_log(h.s.avctx, AV_LOG_ERROR, "pps_id out of range\n"); // DebugTool.printDebugString(" --- decode_slide_header error case 1\n"); return -61; } if (null == h0.pps_buffers[pps_id]) { //av_log(h.s.avctx, AV_LOG_ERROR, "non-existing PPS %u referenced\n", pps_id); // DebugTool.printDebugString(" --- decode_slide_header error case 2\n"); return -62; } h0.pps_buffers[pps_id].copyTo(h.pps); if (null == h0.sps_buffers[(int)h.pps.sps_id]) { //av_log(h.s.avctx, AV_LOG_ERROR, "non-existing SPS %u referenced\n", h.pps.sps_id); // DebugTool.printDebugString(" --- decode_slide_header error case 3\n"); return -63; } h0.sps_buffers[(int)h.pps.sps_id].copyTo(h.sps); s.profile = h.sps.profile_idc; s.level = h.sps.level_idc; s.refs = h.sps.ref_frame_count; if (h == h0 && h.dequant_coeff_pps != pps_id) { h.dequant_coeff_pps = pps_id; h.init_dequant_tables(); } s.mb_width = h.sps.mb_width; s.mb_height = h.sps.mb_height * (2 - h.sps.frame_mbs_only_flag); h.b_stride = s.mb_width * 4; s.width = (int)(16 * s.mb_width - 2 * Math.Min(h.sps.crop_right, 7)); if (h.sps.frame_mbs_only_flag != 0) s.height = (int)(16 * s.mb_height - 2 * Math.Min(h.sps.crop_bottom, 7)); else s.height = (int)(16 * s.mb_height - 4 * Math.Min(h.sps.crop_bottom, 7)); if (s.context_initialized != 0 && ( /*s.width != s.avctx.width || s.height != s.avctx.height ||*/ av_cmp_q(h.sps.sar, s.sample_aspect_ratio) != 0)) { if (h != h0) { // DebugTool.printDebugString(" --- decode_slide_header error case 4\n"); return -64; // width / height changed during parallelized decoding } h.free_tables(); s.flush_dpb(); s.MPV_common_end(); } if (0 == s.context_initialized) { if (h != h0) { // DebugTool.printDebugString(" --- decode_slide_header error case 5\n"); return -65; // we cant (re-)initialize context during parallel decoding } s.avcodec_set_dimensions(s.width, s.height); s.sample_aspect_ratio = h.sps.sar; //av_assert0(s.avctx.sample_aspect_ratio.den); if (0 != h.sps.video_signal_type_present_flag) { s.color_range = ((h.sps.full_range != 0) ? MpegEncContext.AVCOL_RANGE_JPEG : MpegEncContext.AVCOL_RANGE_MPEG); if (h.sps.colour_description_present_flag != 0) { s.color_primaries = h.sps.color_primaries; s.color_trc = h.sps.color_trc; s.colorspace = h.sps.colorspace; } } if (h.sps.timing_info_present_flag != 0) { long den = h.sps.time_scale; if (h.x264_build < 44) den *= 2; int[] param = new int[] { s.time_base.num, s.time_base.den, }; av_reduce(param, h.sps.num_units_in_tick, den, 1 << 30); s.time_base.num = param[0]; s.time_base.den = param[1]; } s.pix_fmt = MpegEncContext.get_format( s.codec.pix_fmts != null ? s.codec.pix_fmts : s.color_range == MpegEncContext.AVCOL_RANGE_JPEG ? hwaccel_pixfmt_list_h264_jpeg_420 : MpegEncContext.ff_hwaccel_pixfmt_list_420); s.hwaccel = 0; // No H/W Accel!! // ff_find_hwaccel(s.avctx.codec.id, s.avctx.pix_fmt); if (s.MPV_common_init() < 0) { // DebugTool.printDebugString(" --- decode_slide_header error case 6\n"); return -66; } s.first_field = 0; h.prev_interlaced_frame = 1; h.init_scan_tables(); h.ff_h264_alloc_tables(); /*// We use single thread decoder for(i = 1; i < 1; i++) { H264Context c; c = h.thread_context[i] = new H264Context(); memcpy(c, h.s.thread_context[i], sizeof(MpegEncContext)); memset(&c->s + 1, 0, sizeof(H264Context) - sizeof(MpegEncContext)); c.h264dsp = h.h264dsp; c.sps = h.sps; c.pps = h.pps; c.init_scan_tables(); clone_tables(c, h, i); } */ for (i = 0; i < s.thread_count; i++) if (h.thread_context[i].context_init() < 0) { // DebugTool.printDebugString(" --- decode_slide_header error case 7\n"); return -67; } } h.frame_num = (int)s.gb.get_bits(h.sps.log2_max_frame_num, "frame_num"); h.mb_mbaff = 0; h.mb_aff_frame = 0; last_pic_structure = s0.picture_structure; if (h.sps.frame_mbs_only_flag != 0) { s.picture_structure = Constants.PICT_FRAME; } else { if (s.gb.get_bits1("field_pic_flag") != 0) { //field_pic_flag s.picture_structure = (int)(Constants.PICT_TOP_FIELD + s.gb.get_bits1("bottom_field_flag")); //bottom_field_flag } else { s.picture_structure = Constants.PICT_FRAME; h.mb_aff_frame = h.sps.mb_aff; } } h.mb_field_decoding_flag = ((s.picture_structure) != Constants.PICT_FRAME ? 1 : 0); if (h0.current_slice == 0) { while (h.frame_num != h.prev_frame_num && h.frame_num != ((h.prev_frame_num + 1) % (1 << h.sps.log2_max_frame_num))) { AVFrame prev = ((h.short_ref_count != 0) ? h.short_ref[0] : null); //av_log(h.s.avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n", h.frame_num, h.prev_frame_num); if (h.ff_h264_frame_start() < 0) { // DebugTool.printDebugString(" --- decode_slide_header error case 8\n"); return -68; } h.prev_frame_num++; h.prev_frame_num %= 1 << h.sps.log2_max_frame_num; s.current_picture_ptr.frame_num = h.prev_frame_num; h.ff_generate_sliding_window_mmcos(); h.ff_h264_execute_ref_pic_marking(h.mmco, h.mmco_index); /* Error concealment: if a ref is missing, copy the previous ref in its place. * FIXME: avoiding a memcpy would be nice, but ref handling makes many assumptions * about there being no actual duplicates. * FIXME: this doesn't copy padding for out-of-frame motion vectors. Given we're * concealing a lost frame, this probably isn't noticable by comparison, but it should * be fixed. */ if (h.short_ref_count != 0) { if (prev != null) { ImageUtils.av_image_copy(h.short_ref[0].data_base, h.short_ref[0].data_offset, h.short_ref[0].linesize, /*( uint8_t**)*/prev.data_base, prev.data_offset, prev.linesize, s.pix_fmt, s.mb_width * 16, s.mb_height * 16); h.short_ref[0].poc = prev.poc + 2; } h.short_ref[0].frame_num = h.prev_frame_num; } } /* See if we have a decoded first field looking for a pair... */ if (s0.first_field != 0) { ////assert(s0.current_picture_ptr); ////assert(s0.current_picture_ptr->data[0]); ////assert(s0.current_picture_ptr->reference != DELAYED_PIC_REF); /* figure out if we have a complementary field pair */ if (!(s.picture_structure != Constants.PICT_FRAME) || s.picture_structure == last_pic_structure) { /* * Previous field is unmatched. Don't display it, but let it * remain for reference if marked as such. */ s0.current_picture_ptr = null; s0.first_field = ((s.picture_structure != Constants.PICT_FRAME) ? 1 : 0); } else { if (h.nal_ref_idc != 0 && s0.current_picture_ptr.reference != 0 && s0.current_picture_ptr.frame_num != h.frame_num) { /* * This and previous field were reference, but had * different frame_nums. Consider this field first in * pair. Throw away previous field except for reference * purposes. */ s0.first_field = 1; s0.current_picture_ptr = null; } else { /* Second field in complementary pair */ s0.first_field = 0; } } } else { /* Frame or first field in a potentially complementary pair */ ////assert(!s0.current_picture_ptr); s0.first_field = ((s.picture_structure != Constants.PICT_FRAME) ? 1 : 0); } if ((0 == ((s.picture_structure != Constants.PICT_FRAME) ? 1 : 0) || 0 != s0.first_field) && h.ff_h264_frame_start() < 0) { s0.first_field = 0; // DebugTool.printDebugString(" --- decode_slide_header error case 9\n"); return -69; } } if (h != h0) clone_slice(h, h0); s.current_picture_ptr.frame_num = h.frame_num; //FIXME frame_num cleanup ////assert(s.mb_num == s.mb_width * s.mb_height); if (first_mb_in_slice << ((h.mb_aff_frame != 0 || (s.picture_structure != Constants.PICT_FRAME)) ? 1 : 0) >= s.mb_num || first_mb_in_slice >= s.mb_num) { //av_log(h.s.avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n"); // DebugTool.printDebugString(" --- decode_slide_header error case 10\n"); return -70; } s.resync_mb_x = s.mb_x = first_mb_in_slice % s.mb_width; s.resync_mb_y = s.mb_y = (first_mb_in_slice / s.mb_width) << ((h.mb_aff_frame != 0 || (s.picture_structure != Constants.PICT_FRAME)) ? 1 : 0); if (s.picture_structure == Constants.PICT_BOTTOM_FIELD) s.resync_mb_y = s.mb_y = s.mb_y + 1; //assert(s.mb_y < s.mb_height); if (s.picture_structure == Constants.PICT_FRAME) { h.curr_pic_num = h.frame_num; h.max_pic_num = 1 << h.sps.log2_max_frame_num; } else { h.curr_pic_num = 2 * h.frame_num + 1; h.max_pic_num = 1 << (h.sps.log2_max_frame_num + 1); } if (h.nal_unit_type == NAL_IDR_SLICE) { s.gb.get_ue_golomb("idr_pic_id"); /* idr_pic_id */ } if (h.sps.poc_type == 0) { h.poc_lsb = (int)s.gb.get_bits(h.sps.log2_max_poc_lsb, "poc_lsb"); if (h.pps.pic_order_present == 1 && s.picture_structure == Constants.PICT_FRAME) { h.delta_poc_bottom = s.gb.get_se_golomb("delta_poc_bottom"); } } if (h.sps.poc_type == 1 && 0 == h.sps.delta_pic_order_always_zero_flag) { h.delta_poc[0] = s.gb.get_se_golomb("delta_poc[0]"); if (h.pps.pic_order_present == 1 && s.picture_structure == Constants.PICT_FRAME) h.delta_poc[1] = s.gb.get_se_golomb("delta_poc[1]"); } h.init_poc(); if (h.pps.redundant_pic_cnt_present != 0) { h.redundant_pic_count = s.gb.get_ue_golomb("redundant_pic_count"); } //set defaults, might be overridden a few lines later h.ref_count[0] = h.pps.ref_count[0]; h.ref_count[1] = h.pps.ref_count[1]; if (h.slice_type_nos != FF_I_TYPE) { if (h.slice_type_nos == FF_B_TYPE) { h.direct_spatial_mv_pred = (int)s.gb.get_bits1("direct_spatial_mv_pred"); } num_ref_idx_active_override_flag = (int)s.gb.get_bits1("num_ref_idx_active_override_flag"); if (num_ref_idx_active_override_flag != 0) { h.ref_count[0] = s.gb.get_ue_golomb("ref_count[0]") + 1; if (h.slice_type_nos == FF_B_TYPE) h.ref_count[1] = s.gb.get_ue_golomb("ref_count[1]") + 1; if (h.ref_count[0] - 1 > 32 - 1 || h.ref_count[1] - 1 > 32 - 1) { //av_log(h.s.avctx, AV_LOG_ERROR, "reference overflow\n"); h.ref_count[0] = h.ref_count[1] = 1; // DebugTool.printDebugString(" --- decode_slide_header error case 11\n"); return -71; } } if (h.slice_type_nos == FF_B_TYPE) h.list_count = 2; else h.list_count = 1; } else h.list_count = 0; if (0 == default_ref_list_done) { h.ff_h264_fill_default_ref_list(); } if (h.slice_type_nos != FF_I_TYPE && h.ff_h264_decode_ref_pic_list_reordering() < 0) { // DebugTool.printDebugString(" --- decode_slide_header error case 12\n"); return -72; } if (h.slice_type_nos != FF_I_TYPE) { s.last_picture_ptr = h.ref_list[0][0]; MpegEncContext.ff_copy_picture(s.last_picture, s.last_picture_ptr); } if (h.slice_type_nos == FF_B_TYPE) { s.next_picture_ptr = h.ref_list[1][0]; MpegEncContext.ff_copy_picture(s.next_picture, s.next_picture_ptr); } if ((h.pps.weighted_pred != 0 && h.slice_type_nos == FF_P_TYPE) || (h.pps.weighted_bipred_idc == 1 && h.slice_type_nos == FF_B_TYPE)) h.pred_weight_table(); else if (h.pps.weighted_bipred_idc == 2 && h.slice_type_nos == FF_B_TYPE) { h.implicit_weight_table(-1); } else { h.use_weight = 0; for (i = 0; i < 2; i++) { h.luma_weight_flag[i] = 0; h.chroma_weight_flag[i] = 0; } } if (h.nal_ref_idc != 0) h0.ff_h264_decode_ref_pic_marking(s.gb); if (h.mb_aff_frame != 0) { h.ff_h264_fill_mbaff_ref_list(); if (h.pps.weighted_bipred_idc == 2 && h.slice_type_nos == FF_B_TYPE) { h.implicit_weight_table(0); h.implicit_weight_table(1); } } if (h.slice_type_nos == FF_B_TYPE && 0 == h.direct_spatial_mv_pred) h.ff_h264_direct_dist_scale_factor(); h.ff_h264_direct_ref_list_init(); if (h.slice_type_nos != FF_I_TYPE && h.pps.cabac != 0) { tmp = s.gb.get_ue_golomb_31("cabac_init_idc"); if (tmp > 2) { //av_log(s.avctx, AV_LOG_ERROR, "cabac_init_idc overflow\n"); // DebugTool.printDebugString(" --- decode_slide_header error case 13\n"); return -73; } h.cabac_init_idc = tmp; } h.last_qscale_diff = 0; tmp = h.pps.init_qp + s.gb.get_se_golomb("init_qp"); if (tmp > 51) { //av_log(s.avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); // DebugTool.printDebugString(" --- decode_slide_header error case 14\n"); return -74; } s.qscale = tmp; h.chroma_qp[0] = h.pps.chroma_qp_table[0][s.qscale]; h.chroma_qp[1] = h.pps.chroma_qp_table[1][s.qscale]; //FIXME qscale / qp ... stuff if (h.slice_type == FF_SP_TYPE) { s.gb.get_bits1("sp_for_switch_flag"); /* sp_for_switch_flag */ } if (h.slice_type == FF_SP_TYPE || h.slice_type == FF_SI_TYPE) { s.gb.get_se_golomb("slice_qs_delta"); /* slice_qs_delta */ } h.deblocking_filter = 1; h.slice_alpha_c0_offset = 52; h.slice_beta_offset = 52; if (0 != h.pps.deblocking_filter_parameters_present) { tmp = s.gb.get_ue_golomb_31("deblocking_filter_idc"); if (tmp > 2) { // DebugTool.printDebugString(" --- decode_slide_header error case 15\n"); //av_log(s.avctx, AV_LOG_ERROR, "deblocking_filter_idc %u out of range\n", tmp); return -75; } h.deblocking_filter = tmp; if (h.deblocking_filter < 2) h.deblocking_filter ^= 1; // 1<->0 if (0 != h.deblocking_filter) { h.slice_alpha_c0_offset += s.gb.get_se_golomb("slice_alpha_c0_offset") << 1; h.slice_beta_offset += s.gb.get_se_golomb("slice_beta_offset") << 1; if (h.slice_alpha_c0_offset > 104 || h.slice_beta_offset > 104) { // DebugTool.printDebugString(" --- decode_slide_header error case 16\n"); //av_log(s.avctx, AV_LOG_ERROR, "deblocking filter parameters %d %d out of range\n", h.slice_alpha_c0_offset, h.slice_beta_offset); return -76; } } } if (s.skip_loop_filter >= MpegEncContext.AVDISCARD_ALL || (s.skip_loop_filter >= MpegEncContext.AVDISCARD_NONKEY && h.slice_type_nos != FF_I_TYPE) || (s.skip_loop_filter >= MpegEncContext.AVDISCARD_BIDIR && h.slice_type_nos == FF_B_TYPE) || (s.skip_loop_filter >= MpegEncContext.AVDISCARD_NONREF && h.nal_ref_idc == 0)) h.deblocking_filter = 0; if (h.deblocking_filter == 1 && h0.max_contexts > 1) { if ((s.flags2 & MpegEncContext.CODEC_FLAG2_FAST) != 0) { /* Cheat slightly for speed: Do not bother to deblock across slices. */ h.deblocking_filter = 2; } else { h0.max_contexts = 1; if (0 == h0.single_decode_warning) { //av_log(s.avctx, AV_LOG_INFO, "Cannot parallelize deblocking type 1, decoding such frames in sequential order\n"); h0.single_decode_warning = 1; } if (h != h0) { // DebugTool.printDebugString(" --- decode_slide_header error case 17\n"); return 1; // deblocking switched inside frame } } } h.qp_thresh = 15 + 52 - Math.Min(h.slice_alpha_c0_offset, h.slice_beta_offset) - Math.Max(Math.Max(0, h.pps.chroma_qp_index_offset[0]), h.pps.chroma_qp_index_offset[1]); /* #if 0 //FMO if( h.pps.num_slice_groups > 1 && h.pps.mb_slice_group_map_type >= 3 && h.pps.mb_slice_group_map_type <= 5) slice_group_change_cycle= s.gb.get_bits( ?); #endif */ h0.last_slice_type = slice_type; h.slice_num = ++h0.current_slice; if (h.slice_num >= MAX_SLICES) { //av_log(s.avctx, AV_LOG_ERROR, "Too many slices, increase MAX_SLICES and recompile\n"); } for (j = 0; j < 2; j++) { int[] id_list = new int[16]; int[] ref2frm = h.ref2frm[h.slice_num & (MAX_SLICES - 1)][j]; for (i = 0; i < 16; i++) { id_list[i] = 60; if (h.ref_list[j][i].data_base[0] != null) { int k; //uint8_t *base= h.ref_list[j][i].base[0]; byte[] @base = h.ref_list[j][i].@base[0]; for (k = 0; k < h.short_ref_count; k++) if (h.short_ref[k].@base[0] == @base) { id_list[i] = k; break; } for (k = 0; k < h.long_ref_count; k++) if (h.long_ref[k] != null && h.long_ref[k].@base[0] == @base) { id_list[i] = h.short_ref_count + k; break; } } } ref2frm[0] = ref2frm[1] = -1; for (i = 0; i < 16; i++) ref2frm[i + 2] = 4 * id_list[i] + (h.ref_list[j][i].reference & 3); ref2frm[18 + 0] = ref2frm[18 + 1] = -1; for (i = 16; i < 48; i++) ref2frm[i + 4] = 4 * id_list[(i - 16) >> 1] + (h.ref_list[j][i].reference & 3); } h.emu_edge_width = ((s.flags & MpegEncContext.CODEC_FLAG_EMU_EDGE) != 0 ? 0 : 16); h.emu_edge_height = (0 != h.mb_aff_frame || (s.picture_structure != Constants.PICT_FRAME)) ? 0 : h.emu_edge_width; /* No debug if((s.debug&FF_DEBUG_PICT_INFO)!=0){ av_log(h.s.avctx, AV_LOG_DEBUG, "slice:%d %s mb:%d %c%s%s pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", h.slice_num, (s.picture_structure==PICT_FRAME ? "F" : s.picture_structure==PICT_TOP_FIELD ? "T" : "B"), first_mb_in_slice, av_get_pict_type_char(h.slice_type), h.slice_type_fixed ? " fix" : "", h.nal_unit_type == NAL_IDR_SLICE ? " IDR" : "", pps_id, h.frame_num, s.current_picture_ptr->field_poc[0], s.current_picture_ptr->field_poc[1], h.ref_count[0], h.ref_count[1], s.qscale, h.deblocking_filter, h.slice_alpha_c0_offset/2-26, h.slice_beta_offset/2-26, h.use_weight, h.use_weight==1 && h.use_weight_chroma ? "c" : "", h.slice_type == FF_B_TYPE ? (h.direct_spatial_mv_pred ? "SPAT" : "TEMP") : "" ); } */ // DebugTool.printDebugString(" --- decode_slide_header OK\n"); return 0; }
public static void dumpDebugFrameData(H264Context h, string msg) { if (!DEBUG_MODE) return; dumpDebugFrameData(h, msg, true); }