homerHEVC代码阅读(38)——熵编码(2)主要流程的函数

来源:互联网 发布:java 异常体系 编辑:程序博客网 时间:2024/05/16 10:07

一、HomerHEVC的熵编码和环路滤波被包含在函数hmr_deblock_sao_pad_sync_ctu中


二、熵编码的入口函数是wfpp_encode_ctu,下面是它的流程:

    1、统计比特流

    2、调用ee_encode_sao,对SAO的相关信息进行熵编码

    3、调用ee_encode_ctu,对CTU的信息和数据进行熵编码

    4、如果有必要就复制熵编码的上下文模型,ee_copy_entropy_model

    5、如果有必要就调用ee_end_slice结束对一个slice熵编码


熵编码入口函数:

void wfpp_encode_ctu(henc_thread_t* et, ctu_info_t *ctu){int gcnt = 0;int bits_allocated;int ctu_num = ctu->ctu_number;int ctu_x = ctu_num%et->pict_width_in_ctu;int ctu_y = ctu_num / et->pict_width_in_ctu;int ee_index = (ctu_y) % et->enc_engine->wfpp_num_threads;picture_t *currpict = &et->enc_engine->current_pict;slice_t *currslice = &currpict->slice;bits_allocated = hmr_bitstream_bitcount(et->ee->bs);if (currslice->sps->sample_adaptive_offset_enabled_flag)ee_encode_sao(et, et->ee, currslice, ctu);ee_encode_ctu(et, et->ee, currslice, ctu, gcnt);PRINTF_CTU_ENCODE("ee_encode_ctu, ctu_num:%d\r\n", ctu_num);et->num_bits += hmr_bitstream_bitcount(et->ee->bs) - bits_allocated;if (ctu_x == 1 && ctu_y + 1 != et->pict_height_in_ctu){if (et->wfpp_enable)ee_copy_entropy_model(et->ee->contexts, et->enc_engine->ee_list[(2 * ee_index + 1) % et->enc_engine->num_ee]->contexts);PRINTF_CTU_ENCODE("ee_copy, ctu_num:%d, ee_index_dst:%d\r\n", ctu_num, (2 * ee_index + 1) % et->enc_engine->num_ee);}if ((et->wfpp_enable && ctu_x + 1 == et->pict_width_in_ctu) || (!et->wfpp_enable) && (ctu_x + 1 == et->pict_total_ctu)){ee_end_slice(et->ee, currslice, ctu);PRINTF_CTU_ENCODE("ee_end_slice, ctu_num:%d\r\n", ctu_num);}et->num_encoded_ctus++;}


对SAO的相关信息进行熵编码:

void ee_encode_sao(henc_thread_t* et, enc_env_t* ee, slice_t *currslice, ctu_info_t* ctu){int ctu_idx = ctu->ctu_number;int pic_width_in_ctu = et->pict_width_in_ctu;if (currslice->sao_luma_flag || currslice->sao_chroma_flag){sao_blk_param_t* sao_blk_param = &ctu->coded_params;int left_merge_avail = FALSE;int above_merge_avail= FALSE;int rx = (ctu_idx%pic_width_in_ctu);int ry = (ctu_idx/pic_width_in_ctu);if(rx > 0){left_merge_avail = TRUE;}if(ry > 0){above_merge_avail = TRUE;}code_sao_blk_param(ee, sao_blk_param, et->enc_engine->slice_enabled, left_merge_avail, above_merge_avail, FALSE);}}

对CTU的信息和数据进行熵编码:

void ee_encode_ctu(henc_thread_t* et, enc_env_t* ee, slice_t *currslice, ctu_info_t* ctu, int gcnt){int curr_depth = 0;cu_partition_info_t*curr_partition_info;int depth_state[MAX_PARTITION_DEPTH] = { 0, 0, 0, 0, 0 };int pred_depth;curr_partition_info = ctu->partition_list;//encode parentcurr_depth = curr_partition_info->depth;memset(depth_state, 0, sizeof(depth_state));et->write_qp_flag = TRUE;//coding_quadtreewhile (curr_depth != 0 || depth_state[curr_depth] != 1){if (et->enc_engine->num_encoded_frames == 1 && ctu->ctu_number == 24 && curr_partition_info->abs_index >= 32)// && ctu->ctu_number==1)// && curr_partition_info->abs_index>=32)// && curr_partition_info->abs_index>=192)// && curr_depth==2){int iiiiii = 0;}if (curr_partition_info->is_r_inside_frame && curr_partition_info->is_b_inside_frame){if (curr_partition_info->depth != (et->max_cu_depth - et->mincu_mintr_shift_diff))encode_split_flag(ee, ctu, curr_partition_info); // 对split标志进行熵编码}//implement qp modification in this loop - setQPSubCUs in HMif (curr_partition_info->depth == currslice->pps->diff_cu_qp_delta_depth && currslice->pps->cu_qp_delta_enabled_flag){et->curr_ref_qp = get_ref_qp(et, ctu, curr_partition_info);et->found_zero_cbf = FALSE;}pred_depth = ctu->pred_depth[curr_partition_info->abs_index];depth_state[curr_depth]++;if (curr_depth < pred_depth)//go down one level{if (depth_state[curr_depth] == 1 && curr_depth == currslice->pps->diff_cu_qp_delta_depth && currslice->pps->cu_qp_delta_enabled_flag)//if( (g_uiMaxCUWidth>>uiDepth) >= pcCU->getSlice()->getPPS()->getMinCuDQPSize() && pcCU->getSlice()->getPPS()->getUseDQP()){et->write_qp_flag = TRUE;}curr_depth++;curr_partition_info = curr_partition_info->children[depth_state[curr_depth]];}else //go up 1 level {if (curr_partition_info->is_r_inside_frame && curr_partition_info->is_b_inside_frame){if (currslice->pps->cu_qp_delta_enabled_flag && !et->found_zero_cbf){int tr_depth = curr_partition_info->depth - pred_depth;if (ctu->cbf[Y_COMP][curr_partition_info->abs_index] || ctu->cbf[U_COMP][curr_partition_info->abs_index] || ctu->cbf[V_COMP][curr_partition_info->abs_index]){et->found_zero_cbf = TRUE;if (depth_state[curr_depth]>1)et->write_qp_flag = TRUE;}else{//cbf==0 modify qp to reference qpmemset(&ctu->qp[curr_partition_info->abs_index], et->curr_ref_qp, curr_partition_info->num_part_in_cu);}}if (curr_partition_info->depth <= currslice->pps->diff_cu_qp_delta_depth && currslice->pps->cu_qp_delta_enabled_flag)// (g_uiMaxCUWidth>>uiDepth) == pcCU->getSlice()->getPPS()->getMinCuDQPSize() && pcCU->getSlice()->getPPS()->getUseDQP()){et->write_qp_flag = TRUE;}ee_encode_coding_unit(et, ee, ctu, curr_partition_info, gcnt); // 对于一个PU进行熵编码}while (depth_state[curr_depth] == 4){depth_state[curr_depth] = 0;curr_depth--;curr_partition_info = curr_partition_info->parent;}if (curr_partition_info->parent != NULL)curr_partition_info = curr_partition_info->parent->children[depth_state[curr_depth]];}}}

结束对slice的熵编码:

void ee_end_slice(enc_env_t* ee, slice_t *currslice, ctu_info_t* ctu){ee->ee_encode_bin_TRM( ee, 1);ee->ee_finish(ee);hmr_bitstream_rbsp_trailing_bits(ee->bs);}



0 0
原创粉丝点击