HEVC解码相关代码
2018-01-11 16:12
183 查看
ff_hevc_decoder
hevc_decode_frame–>decode_nal_units–>decode_nal_unit–>hls_slice_data–>hls_decode_entry–>hls_coding_quadtree(CTU)–>hls_coding_unit(解码CU)
hls_coding_unit–>hls_prediction_unit(解码PU)–>hevc_luma_mv_mvp_mode(得到pu的mvp)–>ff_hevc_hls_mvd_coding(得到pu的mvd)–>abs_mvd_greater0_flag_decode
hls_coding_unit–>hls_transform_tree(以当前CU为TU的根节点,判断是否划分)–>hls_transform_unit(解码PU)–>ff_hevc_hls_residual_coding
//未完
参考http://blog.csdn.net/leixiaohua1020/article/details/46412897
hevc_decode_frame–>decode_nal_units–>decode_nal_unit–>hls_slice_data–>hls_decode_entry–>hls_coding_quadtree(CTU)–>hls_coding_unit(解码CU)
hls_coding_unit–>hls_prediction_unit(解码PU)–>hevc_luma_mv_mvp_mode(得到pu的mvp)–>ff_hevc_hls_mvd_coding(得到pu的mvd)–>abs_mvd_greater0_flag_decode
hls_coding_unit–>hls_transform_tree(以当前CU为TU的根节点,判断是否划分)–>hls_transform_unit(解码PU)–>ff_hevc_hls_residual_coding
static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, AVPacket *avpkt) {//输入AVPacket *avpkt,输出为data;当有输出帧时got_output=1。 //解码时,解码帧放在AVFrame *output_frame中 int ret; int new_extradata_size; uint8_t *new_extradata; HEVCContext *s = avctx->priv_data; if (!avpkt->size) { ret = ff_hevc_output_frame(s, data, 1); if (ret < 0) return ret; *got_output = ret; return 0; } new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &new_extradata_size); if (new_extradata && new_extradata_size > 0) { ret = hevc_decode_extradata(s, new_extradata, new_extradata_size, 0); if (ret < 0) return ret; } s->ref = NULL; ret = decode_nal_units(s, avpkt->data, avpkt->size);//解码NAL,对每个nal会调用decode_nal_unit if (ret < 0) return ret; if (avctx->hwaccel) { if (s->ref && (ret = avctx->hwaccel->end_frame(avctx)) < 0) { av_log(avctx, AV_LOG_ERROR, "hardware accelerator failed to decode picture\n"); ff_hevc_unref_frame(s, s->ref, ~0); return ret; } } else { /* verify the SEI checksum */ if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded && s->is_md5) { ret = verify_md5(s, s->ref->frame); if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) { ff_hevc_unref_frame(s, s->ref, ~0); return ret; } } } s->is_md5 = 0; if (s->is_decoded) {//解码完一帧后is_decoded=1 av_log(avctx, AV_LOG_DEBUG, "Decoded frame with POC %d.\n", s->poc); s->is_decoded = 0; } if (s->output_frame->buf[0]) {//s->output_frame存放的是解码重构图像 av_frame_move_ref(data, s->output_frame); *got_output = 1; } return avpkt->size; }
static int hls_coding_quadtree(HEVCContext *s, int x0, int y0, int log2_cb_size, int cb_depth) {//(x0,y0)是当前cu的地址,log2_cb_size为当前cu的大小,cb_depth为当前cu的深度(64*64时为0) HEVCLocalContext *lc = s->HEVClc; const int cb_size = 1 << log2_cb_size; int ret; int split_cu; lc->ct_depth = cb_depth; if (x0 + cb_size <= s->ps.sps->width && y0 + cb_size <= s->ps.sps->height && log2_cb_size > s->ps.sps->log2_min_cb_size) { split_cu = ff_hevc_split_coding_unit_flag_decode(s, cb_depth, x0, y0); } else { split_cu = (log2_cb_size > s->ps.sps->log2_min_cb_size); } if (s->ps.pps->cu_qp_delta_enabled_flag && log2_cb_size >= s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth) { lc->tu.is_cu_qp_delta_coded = 0; lc->tu.cu_qp_delta = 0; } if (s->sh.cu_chroma_qp_offset_enabled_flag && log2_cb_size >= s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_chroma_qp_offset_depth) { lc->tu.is_cu_chroma_qp_offset_coded = 0; } if (split_cu) {//划分为子块,分别处理4个子块 int qp_block_mask = (1<<(s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth)) - 1; const int cb_size_split = cb_size >> 1; const int x1 = x0 + cb_size_split; const int y1 = y0 + cb_size_split; int more_data = 0; more_data = hls_coding_quadtree(s, x0, y0, log2_cb_size - 1, cb_depth + 1);//递归 if (more_data < 0) return more_data; if (more_data && x1 < s->ps.sps->width) { more_data = hls_coding_quadtree(s, x1, y0, log2_cb_size - 1, cb_depth + 1); if (more_data < 0) return more_data; } if (more_data && y1 < s->ps.sps->height) { more_data = hls_coding_quadtree(s, x0, y1, log2_cb_size - 1, cb_depth + 1); if (more_data < 0) return more_data; } if (more_data && x1 < s->ps.sps->width && y1 < s->ps.sps->height) { more_data = hls_coding_quadtree(s, x1, y1, log2_cb_size - 1, cb_depth + 1); if (more_data < 0) return more_data; } if(((x0 + (1<<log2_cb_size)) & qp_block_mask) == 0 && ((y0 + (1<<log2_cb_size)) & qp_block_mask) == 0) lc->qPy_pred = lc->qp_y; if (more_data) return ((x1 + cb_size_split) < s->ps.sps->width || (y1 + cb_size_split) < s->ps.sps->height); else return 0; } else {//不划分,解码当前块 ret = hls_coding_unit(s, x0, y0, log2_cb_size);//x0和y0分别为当前块的起始地址 if (ret < 0) return ret; if ((!((x0 + cb_size) % (1 << (s->ps.sps->log2_ctb_size))) || (x0 + cb_size >= s->ps.sps->width)) && (!((y0 + cb_size) % (1 << (s->ps.sps->log2_ctb_size))) || (y0 + cb_size >= s->ps.sps->height))) { int end_of_slice_flag = ff_hevc_end_of_slice_flag_decode(s); return !end_of_slice_flag; } else { return 1; } } return 0; }
static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) {//(x0,y0)是当前cu的地址,log2_cb_size为当前cu的大小 int cb_size = 1 << log2_cb_size;//当前块的大小 HEVCLocalContext *lc = s->HEVClc; int log2_min_cb_size = s->ps.sps->log2_min_cb_size;//值为4 。。编码器指定,可能为3,可能为4 int length = cb_size >> log2_min_cb_size;//可以将最小划分块看成1,则为横向有多少个最小划分块。 int min_cb_width = s->ps.sps->min_cb_width;//120 为图像宽/最小划分块 1920/16=120 int x_cb = x0 >> log2_min_cb_size; int y_cb = y0 >> log2_min_cb_size;//(x_cb,y_cb)是基于最小划分块的地址,比如(x0,y0)=(32,0),最小划分块为16*16,则(x_cb,y_cb)=(2,0) int idx = log2_cb_size - 2; int qp_block_mask = (1<<(s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth)) - 1; int x, y, ret; lc->cu.x = x0; lc->cu.y = y0; lc->cu.pred_mode = MODE_INTRA; lc->cu.part_mode = PART_2Nx2N; lc->cu.intra_split_flag = 0; SAMPLE_CTB(s->skip_flag, x_cb, y_cb) = 0; for (x = 0; x < 4; x++) lc->pu.intra_pred_mode[x] = 1; if (s->ps.pps->transquant_bypass_enable_flag) { lc->cu.cu_transquant_bypass_flag = ff_hevc_cu_transquant_bypass_flag_decode(s); if (lc->cu.cu_transquant_bypass_flag) set_deblocking_bypass(s, x0, y0, log2_cb_size); } else lc->cu.cu_transquant_bypass_flag = 0; if (s->sh.slice_type != HEVC_SLICE_I) { uint8_t skip_flag = ff_hevc_skip_flag_decode(s, x0, y0, x_cb, y_cb);//解析出skip_flag x = y_cb * min_cb_width + x_cb; for (y = 0; y < length; y++) { memset(&s->skip_flag[x], skip_flag, length); x += min_cb_width; } lc->cu.pred_mode = skip_flag ? MODE_SKIP : MODE_INTER; } else { x = y_cb * min_cb_width + x_cb; for (y = 0; y < length; y++) { memset(&s->skip_flag[x], 0, length); x += min_cb_width; } } if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) {//skip模式,是merge中的一种,不需要传输残差和mv信息 //av_log(NULL, AV_LOG_INFO, "XXXXXXXXXXXXXXXXskip_flag\n"); hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); if (!s->sh.disable_deblocking_filter_flag) ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); } else {//av_log(NULL, AV_LOG_INFO, "XXXXXXXXXXXXXXXX2\n"); int pcm_flag = 0; if (s->sh.slice_type != HEVC_SLICE_I) lc->cu.pred_mode = ff_hevc_pred_mode_decode(s); if (lc->cu.pred_mode != MODE_INTRA || log2_cb_size == s->ps.sps->log2_min_cb_size) { lc->cu.part_mode = ff_hevc_part_mode_decode(s, log2_cb_size);//cu的预测模式,帧间或帧内 lc->cu.intra_split_flag = lc->cu.part_mode == PART_NxN && lc->cu.pred_mode == MODE_INTRA;//pu的划分 } if (lc->cu.pred_mode == MODE_INTRA) {//intra cu if (lc->cu.part_mode == PART_2Nx2N && s->ps.sps->pcm_enabled_flag && log2_cb_size >= s->ps.sps->pcm.log2_min_pcm_cb_size && log2_cb_size <= s->ps.sps->pcm.log2_max_pcm_cb_size) { pcm_flag = ff_hevc_pcm_flag_decode(s); } if (pcm_flag) {//PCM模式 intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); ret = hls_pcm_sample(s, x0, y0, log2_cb_size); if (s->ps.sps->pcm.loop_filter_disable_flag) set_deblocking_bypass(s, x0, y0, log2_cb_size); if (ret < 0) return ret; } else { intra_prediction_unit(s, x0, y0, log2_cb_size);//帧内预测CU得到预测值 } } else {//inter cu intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); switch (lc->cu.part_mode) { case PART_2Nx2N: hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx);//帧间预测CU得到预测值 break; case PART_2NxN: hls_prediction_unit(s, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0, idx); hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1, idx); break; case PART_Nx2N: hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0, idx - 1); hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1, idx - 1); break; case PART_2NxnU: hls_prediction_unit(s, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0, idx); hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1, idx); break; case PART_2NxnD: hls_prediction_unit(s, x0, y0, cb_size, cb_size * 3 / 4, log2_cb_size, 0, idx); hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size / 4, log2_cb_size, 1, idx); break; case PART_nLx2N: hls_prediction_unit(s, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0, idx - 2); hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1, idx - 2); break; case PART_nRx2N: hls_prediction_unit(s, x0, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0, idx - 2); hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size / 4, cb_size, log2_cb_size, 1, idx - 2); break; case PART_NxN: hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0, idx - 1); hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1, idx - 1); hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2, idx - 1); hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3, idx - 1); break; } } if (!pcm_flag) { int rqt_root_cbf = 1; if (lc->cu.pred_mode != MODE_INTRA && !(lc->cu.part_mode == PART_2Nx2N && lc->pu.merge_flag)) { rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s); } if (rqt_root_cbf) { const static int cbf[2] = { 0 }; lc->cu.max_trafo_depth = lc->cu.pred_mode == MODE_INTRA ? s->ps.sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag : s->ps.sps->max_transform_hierarchy_depth_inter; ret = hls_transform_tree(s, x0, y0, x0, y0, x0, y0, log2_cb_size, log2_cb_size, 0, 0, cbf, cbf);//处理TU if (ret < 0) return ret; } else { if (!s->sh.disable_deblocking_filter_flag) ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); } } } if (s->ps.pps->cu_qp_delta_enabled_flag && lc->tu.is_cu_qp_delta_coded == 0) ff_hevc_set_qPy(s, x0, y0, log2_cb_size); x = y_cb * min_cb_width + x_cb; for (y = 0; y < length; y++) { memset(&s->qp_y_tab[x], lc->qp_y, length); x += min_cb_width; } //av_log(NULL, AV_LOG_INFO,"###########qp_y_tab=%d %d %d\n",s->qp_y_tab[x],s->qp_y_tab[x+1],s->qp_y_tab[x+1]); if(((x0 + (1<<log2_cb_size)) & qp_block_mask) == 0 && ((y0 + (1<<log2_cb_size)) & qp_block_mask) == 0) { lc->qPy_pred = lc->qp_y; } set_ct_depth(s, x0, y0, log2_cb_size, lc->ct_depth); return 0; }
static int hls_transform_tree(HEVCContext *s, int x0, int y0, int xBase, int yBase, int cb_xBase, int cb_yBase, int log2_cb_size, int log2_trafo_size, int trafo_depth, int blk_idx, const int *base_cbf_cb, const int *base_cbf_cr) {//log2_cb_size为cu的大小;log2_trafo_size为tu的大小(log后)。。 (x0,y0)为tu起始像素地址;(xBase,yase)为cu起始像素地址 //blk_idx为块的索引(若划分为四个子块,则为0~3) HEVCLocalContext *lc = s->HEVClc; uint8_t split_transform_flag; int cbf_cb[2]; int cbf_cr[2]; int ret; cbf_cb[0] = base_cbf_cb[0]; cbf_cb[1] = base_cbf_cb[1]; cbf_cr[0] = base_cbf_cr[0]; cbf_cr[1] = base_cbf_cr[1]; if (lc->cu.intra_split_flag) { if (trafo_depth == 1) { lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[blk_idx]; if (s->ps.sps->chroma_format_idc == 3) { lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[blk_idx]; lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[blk_idx]; } else { lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; } } } else { lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[0]; lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; } if (log2_trafo_size <= s->ps.sps->log2_max_trafo_size && log2_trafo_size > s->ps.sps->log2_min_tb_size && trafo_depth < lc->cu.max_trafo_depth && !(lc->cu.intra_split_flag && trafo_depth == 0)) { split_transform_flag = ff_hevc_split_transform_flag_decode(s, log2_trafo_size); } else { int inter_split = s->ps.sps->max_transform_hierarchy_depth_inter == 0 && lc->cu.pred_mode == MODE_INTER && lc->cu.part_mode != PART_2Nx2N && trafo_depth == 0; split_transform_flag = log2_trafo_size > s->ps.sps->log2_max_trafo_size || (lc->cu.intra_split_flag && trafo_depth == 0) || inter_split;//是否划分 } if (s->ps.sps->chroma_format_idc && (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3)) { if (trafo_depth == 0 || cbf_cb[0]) { cbf_cb[0] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); if (s->ps.sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { cbf_cb[1] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); } } if (trafo_depth == 0 || cbf_cr[0]) { cbf_cr[0] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); if (s->ps.sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { cbf_cr[1] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); } } } if (split_transform_flag) {//划分,递归调用 const int trafo_size_split = 1 << (log2_trafo_size - 1); const int x1 = x0 + trafo_size_split; const int y1 = y0 + trafo_size_split; #define SUBDIVIDE(x, y, idx) \ do { \ ret = hls_transform_tree(s, x, y, x0, y0, cb_xBase, cb_yBase, log2_cb_size, \ log2_trafo_size - 1, trafo_depth + 1, idx, \ cbf_cb, cbf_cr); \ if (ret < 0) \ return ret; \ } while (0) SUBDIVIDE(x0, y0, 0);//blk_idx在变,划分四个子块,每个块递归处理 SUBDIVIDE(x1, y0, 1); SUBDIVIDE(x0, y1, 2); SUBDIVIDE(x1, y1, 3); #undef SUBDIVIDE } else {//处理当前tu int min_tu_size = 1 << s->ps.sps->log2_min_tb_size; int log2_min_tu_size = s->ps.sps->log2_min_tb_size; int min_tu_width = s->ps.sps->min_tb_width; int cbf_luma = 1; if (lc->cu.pred_mode == MODE_INTRA || trafo_depth != 0 || cbf_cb[0] || cbf_cr[0] || (s->ps.sps->chroma_format_idc == 2 && (cbf_cb[1] || cbf_cr[1]))) { cbf_luma = ff_hevc_cbf_luma_decode(s, trafo_depth); } //av_log(NULL, AV_LOG_INFO, "$$$$$$$$$$$tu=%d %d\n",log2_trafo_size , s->ps.sps->log2_max_trafo_size); ret = hls_transform_unit(s, x0, y0, xBase, yBase, cb_xBase, cb_yBase, log2_cb_size, log2_trafo_size, blk_idx, cbf_luma, cbf_cb, cbf_cr);//处理TU-反量化DCT反变换 if (ret < 0) return ret; // TODO: store cbf_luma somewhere else if (cbf_luma) { int i, j; for (i = 0; i < (1 << log2_trafo_size); i += min_tu_size) for (j = 0; j < (1 << log2_trafo_size); j += min_tu_size) { int x_tu = (x0 + j) >> log2_min_tu_size; int y_tu = (y0 + i) >> log2_min_tu_size; s->cbf_luma[y_tu * min_tu_width + x_tu] = 1; } } if (!s->sh.disable_deblocking_filter_flag) { ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_trafo_size); if (s->ps.pps->transquant_bypass_enable_flag && lc->cu.cu_transquant_bypass_flag) set_deblocking_bypass(s, x0, y0, log2_trafo_size); } } return 0; }
static int hls_transform_unit(HEVCContext *s, int x0, int y0, int xBase, int yBase, int cb_xBase, int cb_yBase, int log2_cb_size, int log2_trafo_size, int blk_idx, int cbf_luma, int *cbf_cb, int *cbf_cr) {//(x0,y0)为tu起始像素地址;(xBase,yase)为cu起始像素地址 //blk_idx为当前块在上一层的索引(0,1,2,3) HEVCLocalContext *lc = s->HEVClc; const int log2_trafo_size_c = log2_trafo_size - s->ps.sps->hshift[1]; int i; if (lc->cu.pred_mode == MODE_INTRA) { int trafo_size = 1 << log2_trafo_size; ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0); } if (cbf_luma || cbf_cb[0] || cbf_cr[0] || (s->ps.sps->chroma_format_idc == 2 && (cbf_cb[1] || cbf_cr[1]))) { int scan_idx = SCAN_DIAG; int scan_idx_c = SCAN_DIAG; int cbf_chroma = cbf_cb[0] || cbf_cr[0] || (s->ps.sps->chroma_format_idc == 2 && (cbf_cb[1] || cbf_cr[1])); if (s->ps.pps->cu_qp_delta_enabled_flag && !lc->tu.is_cu_qp_delta_coded) { lc->tu.cu_qp_delta = ff_hevc_cu_qp_delta_abs(s);//得到tu的亮度qp_delta if (lc->tu.cu_qp_delta != 0) if (ff_hevc_cu_qp_delta_sign_flag(s) == 1) lc->tu.cu_qp_delta = -lc->tu.cu_qp_delta; lc->tu.is_cu_qp_delta_coded = 1; if (lc->tu.cu_qp_delta < -(26 + s->ps.sps->qp_bd_offset / 2) || lc->tu.cu_qp_delta > (25 + s->ps.sps->qp_bd_offset / 2)) { av_log(s->avctx, AV_LOG_ERROR, "The cu_qp_delta %d is outside the valid range " "[%d, %d].\n", lc->tu.cu_qp_delta, -(26 + s->ps.sps->qp_bd_offset / 2), (25 + s->ps.sps->qp_bd_offset / 2)); return AVERROR_INVALIDDATA; } ff_hevc_set_qPy(s, cb_xBase, cb_yBase, log2_cb_size);//得到tu的亮度qp,存放在s->HEVClc->qp_y中 } if (s->sh.cu_chroma_qp_offset_enabled_flag && cbf_chroma && !lc->cu.cu_transquant_bypass_flag && !lc->tu.is_cu_chroma_qp_offset_coded) { int cu_chroma_qp_offset_flag = ff_hevc_cu_chroma_qp_offset_flag(s); if (cu_chroma_qp_offset_flag) { int cu_chroma_qp_offset_idx = 0; if (s->ps.pps->chroma_qp_offset_list_len_minus1 > 0) { cu_chroma_qp_offset_idx = ff_hevc_cu_chroma_qp_offset_idx(s); av_log(s->avctx, AV_LOG_ERROR, "cu_chroma_qp_offset_idx not yet tested.\n"); } lc->tu.cu_qp_offset_cb = s->ps.pps->cb_qp_offset_list[cu_chroma_qp_offset_idx];//得到tu的色度qp_offset lc->tu.cu_qp_offset_cr = s->ps.pps->cr_qp_offset_list[cu_chroma_qp_offset_idx]; } else { lc->tu.cu_qp_offset_cb = 0; lc->tu.cu_qp_offset_cr = 0; } lc->tu.is_cu_chroma_qp_offset_coded = 1; } if (lc->cu.pred_mode == MODE_INTRA && log2_trafo_size < 4) { if (lc->tu.intra_pred_mode >= 6 && lc->tu.intra_pred_mode <= 14) { scan_idx = SCAN_VERT; } else if (lc->tu.intra_pred_mode >= 22 && lc->tu.intra_pred_mode <= 30) { scan_idx = SCAN_HORIZ; } if (lc->tu.intra_pred_mode_c >= 6 && lc->tu.intra_pred_mode_c <= 14) { scan_idx_c = SCAN_VERT; } else if (lc->tu.intra_pred_mode_c >= 22 && lc->tu.intra_pred_mode_c <= 30) { scan_idx_c = SCAN_HORIZ; } } lc->tu.cross_pf = 0; //av_log(NULL, AV_LOG_INFO, "%d",s->ps.sps->chroma_format_idc);//1 //av_log(NULL, AV_LOG_INFO, "%d",cbf_cb[0]); if (cbf_luma) ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size, scan_idx, 0);//读取残差数据,进行反量化,DCT反变换 if (s->ps.sps->chroma_format_idc && (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3)) { //av_log(NULL, AV_LOG_INFO, "@@@@@@@@@@@@@@@@@@0\n"); int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]); int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]); lc->tu.cross_pf = (s->ps.pps->cross_component_prediction_enabled_flag && cbf_luma && (lc->cu.pred_mode == MODE_INTER || (lc->tu.chroma_mode_c == 4))); if (lc->tu.cross_pf) { hls_cross_component_pred(s, 0); } for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { if (lc->cu.pred_mode == MODE_INTRA) { ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1); } if (cbf_cb[i]) ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), log2_trafo_size_c, scan_idx_c, 1); else if (lc->tu.cross_pf) { ptrdiff_t stride = s->frame->linesize[1]; int hshift = s->ps.sps->hshift[1]; int vshift = s->ps.sps->vshift[1]; int16_t *coeffs_y = (int16_t*)lc->edge_emu_buffer; int16_t *coeffs = (int16_t*)lc->edge_emu_buffer2; int size = 1 << log2_trafo_size_c; uint8_t *dst = &s->frame->data[1][(y0 >> vshift) * stride + ((x0 >> hshift) << s->ps.sps->pixel_shift)]; for (i = 0; i < (size * size); i++) { coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); } s->hevcdsp.add_residual[log2_trafo_size_c-2](dst, coeffs, stride);//叠加残差数据 } } if (lc->tu.cross_pf) { hls_cross_component_pred(s, 1); } for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { if (lc->cu.pred_mode == MODE_INTRA) { ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2); } if (cbf_cr[i]) ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), log2_trafo_size_c, scan_idx_c, 2); else if (lc->tu.cross_pf) { ptrdiff_t stride = s->frame->linesize[2]; int hshift = s->ps.sps->hshift[2]; int vshift = s->ps.sps->vshift[2]; int16_t *coeffs_y = (int16_t*)lc->edge_emu_buffer; int16_t *coeffs = (int16_t*)lc->edge_emu_buffer2; int size = 1 << log2_trafo_size_c; uint8_t *dst = &s->frame->data[2][(y0 >> vshift) * stride + ((x0 >> hshift) << s->ps.sps->pixel_shift)]; for (i = 0; i < (size * size); i++) { coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); } s->hevcdsp.add_residual[log2_trafo_size_c-2](dst, coeffs, stride); } } } else if (s->ps.sps->chroma_format_idc && blk_idx == 3) { //此时log2_trafo_size=2且blk_idx == 3,即当前块亮度大小为4*4,上一层的8*8块只有一个4*4的cb块,所以色度必须在最后一个子块(即blk_idx == 3)处理 //av_log(NULL, AV_LOG_INFO, "@@@@@@@@@@@@@@@@@@1\n"); int trafo_size_h = 1 << (log2_trafo_size + 1); int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]); for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { if (lc->cu.pred_mode == MODE_INTRA) { ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1); } if (cbf_cb[i]) ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), log2_trafo_size, scan_idx_c, 1); } for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { if (lc->cu.pred_mode == MODE_INTRA) { ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2); } if (cbf_cr[i]) ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), log2_trafo_size, scan_idx_c, 2); } } } else if (s->ps.sps->chroma_format_idc && lc->cu.pred_mode == MODE_INTRA) { //av_log(NULL, AV_LOG_INFO, "@@@@@@@@@@@@@@@@@@2\n"); if (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3) { int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]); int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]); ff_hevc_set_neighbour_available(s, x0, y0, trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 1); s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 2); if (s->ps.sps->chroma_format_idc == 2) { ff_hevc_set_neighbour_available(s, x0, y0 + (1 << log2_trafo_size_c), trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 1); s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 2); } } else if (blk_idx == 3) { int trafo_size_h = 1 << (log2_trafo_size + 1); int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]); ff_hevc_set_neighbour_available(s, xBase, yBase, trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1); s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2); if (s->ps.sps->chroma_format_idc == 2) { ff_hevc_set_neighbour_available(s, xBase, yBase + (1 << (log2_trafo_size)), trafo_size_h, trafo_size_v); s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 1); s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 2); } } } return 0; }
//未完
参考http://blog.csdn.net/leixiaohua1020/article/details/46412897
相关文章推荐
- HEVC代码追踪(十五):解码之decompressSlice
- HEVC代码追踪(十五):解码之decompressSlice
- HEVC加权预测(Weight Prediction)原理兼解码代码
- HEVC代码学习33:量化相关代码学习
- HEVC代码追踪(十二):解码之int main
- HEVC代码追踪(十二):解码之int main
- HEVC代码追踪(十三):解码之decode
- HEVC熵解码代码分析—代码解码流程(2)
- HEVC代码追踪(十三):解码之decode
- HEVC代码追踪(十四):解码之xDecodeSlice
- HEVC代码追踪(十四):解码之xDecodeSlice
- js 日期比较相关天数代码
- Arcgis Engine矢量裁剪栅格,调用Mask工具相关代码
- 软件工程相关资料。代码大全,人月神话.。。
- Java——I/O相关练习代码
- Spark Streaming 中使用kafka低级api+zookeeper 保存 offset 并重用 以及 相关代码整合
- 关于数据集的相关代码
- 嵌入式Linux启动相关代码分析
- [置顶] HEVC代码学习0:HM使用+码流分析教程
- HEVC代码追踪(八。一):estIntraPredQT