您的位置:首页 > 编程语言

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

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: