void vp10_dering_frame(YV12_BUFFER_CONFIG *frame, VP10_COMMON *cm, MACROBLOCKD *xd, int global_level) { int r, c; int sbr, sbc; int nhsb, nvsb; od_dering_in *src[3]; unsigned char *bskip; int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = {{0}}; int stride; int bsize[3]; int dec[3]; int pli; int coeff_shift = VPXMAX(cm->bit_depth - 8, 0); nvsb = (cm->mi_rows + MI_BLOCK_SIZE - 1)/MI_BLOCK_SIZE; nhsb = (cm->mi_cols + MI_BLOCK_SIZE - 1)/MI_BLOCK_SIZE; bskip = vpx_malloc(sizeof(*bskip)*cm->mi_rows*cm->mi_cols); vp10_setup_dst_planes(xd->plane, frame, 0, 0); for (pli = 0; pli < 3; pli++) { dec[pli] = xd->plane[pli].subsampling_x; bsize[pli] = 8 >> dec[pli]; } stride = bsize[0]*cm->mi_cols; for (pli = 0; pli < 3; pli++) { src[pli] = vpx_malloc(sizeof(*src)*cm->mi_rows*cm->mi_cols*64); for (r = 0; r < bsize[pli]*cm->mi_rows; ++r) { for (c = 0; c < bsize[pli]*cm->mi_cols; ++c) { #if CONFIG_VPX_HIGHBITDEPTH if (cm->use_highbitdepth) { src[pli][r * stride + c] = CONVERT_TO_SHORTPTR(xd->plane[pli].dst.buf) [r * xd->plane[pli].dst.stride + c]; } else { #endif src[pli][r * stride + c] = xd->plane[pli].dst.buf[r * xd->plane[pli].dst.stride + c]; #if CONFIG_VPX_HIGHBITDEPTH } #endif } } } for (r = 0; r < cm->mi_rows; ++r) { for (c = 0; c < cm->mi_cols; ++c) { const MB_MODE_INFO *mbmi = &cm->mi_grid_visible[r * cm->mi_stride + c]->mbmi; bskip[r * cm->mi_cols + c] = mbmi->skip; } } for (sbr = 0; sbr < nvsb; sbr++) { for (sbc = 0; sbc < nhsb; sbc++) { int level; int nhb, nvb; nhb = VPXMIN(MI_BLOCK_SIZE, cm->mi_cols - MI_BLOCK_SIZE*sbc); nvb = VPXMIN(MI_BLOCK_SIZE, cm->mi_rows - MI_BLOCK_SIZE*sbr); for (pli = 0; pli < 3; pli++) { int16_t dst[MI_BLOCK_SIZE*MI_BLOCK_SIZE*8*8]; int threshold; #if DERING_REFINEMENT level = compute_level_from_index( global_level, cm->mi_grid_visible[MI_BLOCK_SIZE*sbr*cm->mi_stride + MI_BLOCK_SIZE*sbc]->mbmi.dering_gain); #else level = global_level; #endif /* FIXME: This is a temporary hack that uses more conservative deringing for chroma. */ if (pli) level = (level*5 + 4) >> 3; if (sb_all_skip(cm, sbr*MI_BLOCK_SIZE, sbc*MI_BLOCK_SIZE)) level = 0; threshold = level << coeff_shift; od_dering( &OD_DERING_VTBL_C, dst, MI_BLOCK_SIZE*bsize[pli], &src[pli][sbr*stride*bsize[pli]*MI_BLOCK_SIZE + sbc*bsize[pli]*MI_BLOCK_SIZE], stride, nhb, nvb, sbc, sbr, nhsb, nvsb, dec[pli], dir, pli, &bskip[MI_BLOCK_SIZE*sbr*cm->mi_cols + MI_BLOCK_SIZE*sbc], cm->mi_cols, threshold, OD_DERING_NO_CHECK_OVERLAP, coeff_shift); for (r = 0; r < bsize[pli]*nvb; ++r) { for (c = 0; c < bsize[pli]*nhb; ++c) { #if CONFIG_VPX_HIGHBITDEPTH if (cm->use_highbitdepth) { CONVERT_TO_SHORTPTR(xd->plane[pli].dst.buf) [xd->plane[pli].dst.stride*(bsize[pli]*MI_BLOCK_SIZE*sbr + r) + sbc*bsize[pli]*MI_BLOCK_SIZE + c] = dst[r * MI_BLOCK_SIZE * bsize[pli] + c]; } else { #endif xd->plane[pli].dst.buf[xd->plane[pli].dst.stride* (bsize[pli]*MI_BLOCK_SIZE*sbr + r) + sbc*bsize[pli]*MI_BLOCK_SIZE + c] = dst[r * MI_BLOCK_SIZE * bsize[pli] + c]; #if CONFIG_VPX_HIGHBITDEPTH } #endif } } } } } for (pli = 0; pli < 3; pli++) { vpx_free(src[pli]); } vpx_free(bskip); }
void av1_dering_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm, MACROBLOCKD *xd, int global_level) { int r, c; int sbr, sbc; int nhsb, nvsb; int16_t src[OD_DERING_INBUF_SIZE]; int16_t *linebuf[3]; int16_t colbuf[3][OD_BSIZE_MAX + 2 * OD_FILT_VBORDER][OD_FILT_HBORDER]; dering_list dlist[MAX_MIB_SIZE * MAX_MIB_SIZE]; unsigned char *row_dering, *prev_row_dering, *curr_row_dering; int dering_count; int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = { { 0 } }; int stride; int bsize[3]; int dec[3]; int pli; int dering_left; int coeff_shift = AOMMAX(cm->bit_depth - 8, 0); int nplanes; if (xd->plane[1].subsampling_x == xd->plane[1].subsampling_y && xd->plane[2].subsampling_x == xd->plane[2].subsampling_y) nplanes = 3; else nplanes = 1; nvsb = (cm->mi_rows + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE; nhsb = (cm->mi_cols + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE; av1_setup_dst_planes(xd->plane, frame, 0, 0); row_dering = aom_malloc(sizeof(*row_dering) * nhsb * 2); memset(row_dering, 1, sizeof(*row_dering) * (nhsb + 2) * 2); prev_row_dering = row_dering + 1; curr_row_dering = prev_row_dering + nhsb + 2; for (pli = 0; pli < nplanes; pli++) { dec[pli] = xd->plane[pli].subsampling_x; bsize[pli] = OD_DERING_SIZE_LOG2 - dec[pli]; } stride = (cm->mi_cols << bsize[0]) + 2 * OD_FILT_HBORDER; for (pli = 0; pli < nplanes; pli++) { linebuf[pli] = aom_malloc(sizeof(*linebuf) * OD_FILT_VBORDER * stride); } for (sbr = 0; sbr < nvsb; sbr++) { for (pli = 0; pli < nplanes; pli++) { for (r = 0; r < (MAX_MIB_SIZE << bsize[pli]) + 2 * OD_FILT_VBORDER; r++) { for (c = 0; c < OD_FILT_HBORDER; c++) { colbuf[pli][r][c] = OD_DERING_VERY_LARGE; } } } dering_left = 1; for (sbc = 0; sbc < nhsb; sbc++) { int level; int nhb, nvb; int cstart = 0; if (!dering_left) cstart = -OD_FILT_HBORDER; nhb = AOMMIN(MAX_MIB_SIZE, cm->mi_cols - MAX_MIB_SIZE * sbc); nvb = AOMMIN(MAX_MIB_SIZE, cm->mi_rows - MAX_MIB_SIZE * sbr); level = compute_level_from_index( global_level, cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride + MAX_MIB_SIZE * sbc] ->mbmi.dering_gain); curr_row_dering[sbc] = 0; if (level == 0 || (dering_count = sb_compute_dering_list( cm, sbr * MAX_MIB_SIZE, sbc * MAX_MIB_SIZE, dlist)) == 0) { dering_left = 0; continue; } curr_row_dering[sbc] = 1; for (pli = 0; pli < nplanes; pli++) { int16_t dst[OD_BSIZE_MAX * OD_BSIZE_MAX]; int threshold; int coffset; int rend, cend; if (sbc == nhsb - 1) cend = (nhb << bsize[pli]); else cend = (nhb << bsize[pli]) + OD_FILT_HBORDER; if (sbr == nvsb - 1) rend = (nvb << bsize[pli]); else rend = (nvb << bsize[pli]) + OD_FILT_VBORDER; coffset = sbc * MAX_MIB_SIZE << bsize[pli]; if (sbc == nhsb - 1) { /* On the last superblock column, fill in the right border with OD_DERING_VERY_LARGE to avoid filtering with the outside. */ for (r = 0; r < rend + OD_FILT_VBORDER; r++) { for (c = cend; c < (nhb << bsize[pli]) + OD_FILT_HBORDER; ++c) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (sbr == nvsb - 1) { /* On the last superblock row, fill in the bottom border with OD_DERING_VERY_LARGE to avoid filtering with the outside. */ for (r = rend; r < rend + OD_FILT_VBORDER; r++) { for (c = 0; c < (nhb << bsize[pli]) + 2 * OD_FILT_HBORDER; c++) { src[(r + OD_FILT_VBORDER) * OD_FILT_BSTRIDE + c] = OD_DERING_VERY_LARGE; } } } /* Copy in the pixels we need from the current superblock for deringing.*/ copy_sb8_16( cm, &src[OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER + cstart], OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr, coffset + cstart, xd->plane[pli].dst.stride, rend, cend - cstart); if (!prev_row_dering[sbc]) { copy_sb8_16(cm, &src[OD_FILT_HBORDER], OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr - OD_FILT_VBORDER, coffset, xd->plane[pli].dst.stride, OD_FILT_VBORDER, nhb << bsize[pli]); } else if (sbr > 0) { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = 0; c < nhb << bsize[pli]; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = linebuf[pli][r * stride + coffset + c]; } } } else { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = 0; c < nhb << bsize[pli]; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (!prev_row_dering[sbc - 1]) { copy_sb8_16(cm, src, OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr - OD_FILT_VBORDER, coffset - OD_FILT_HBORDER, xd->plane[pli].dst.stride, OD_FILT_VBORDER, OD_FILT_HBORDER); } else if (sbr > 0 && sbc > 0) { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = -OD_FILT_HBORDER; c < 0; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = linebuf[pli][r * stride + coffset + c]; } } } else { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = -OD_FILT_HBORDER; c < 0; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (!prev_row_dering[sbc + 1]) { copy_sb8_16(cm, &src[OD_FILT_HBORDER + (nhb << bsize[pli])], OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr - OD_FILT_VBORDER, coffset + (nhb << bsize[pli]), xd->plane[pli].dst.stride, OD_FILT_VBORDER, OD_FILT_HBORDER); } else if (sbr > 0 && sbc < nhsb - 1) { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = nhb << bsize[pli]; c < (nhb << bsize[pli]) + OD_FILT_HBORDER; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = linebuf[pli][r * stride + coffset + c]; } } } else { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = nhb << bsize[pli]; c < (nhb << bsize[pli]) + OD_FILT_HBORDER; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (dering_left) { /* If we deringed the superblock on the left then we need to copy in saved pixels. */ for (r = 0; r < rend + OD_FILT_VBORDER; r++) { for (c = 0; c < OD_FILT_HBORDER; c++) { src[r * OD_FILT_BSTRIDE + c] = colbuf[pli][r][c]; } } } for (r = 0; r < rend + OD_FILT_VBORDER; r++) { for (c = 0; c < OD_FILT_HBORDER; c++) { /* Saving pixels in case we need to dering the superblock on the right. */ colbuf[pli][r][c] = src[r * OD_FILT_BSTRIDE + c + (nhb << bsize[pli])]; } } copy_sb8_16(cm, &linebuf[pli][coffset], stride, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * (sbr + 1) - OD_FILT_VBORDER, coffset, xd->plane[pli].dst.stride, OD_FILT_VBORDER, (nhb << bsize[pli])); /* FIXME: This is a temporary hack that uses more conservative deringing for chroma. */ if (pli) threshold = (level * 5 + 4) >> 3 << coeff_shift; else threshold = level << coeff_shift; if (threshold == 0) continue; od_dering( dst, &src[OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER], dec[pli], dir, pli, dlist, dering_count, threshold, coeff_shift); #if CONFIG_AOM_HIGHBITDEPTH if (cm->use_highbitdepth) { copy_dering_16bit_to_16bit( (int16_t *)&CONVERT_TO_SHORTPTR( xd->plane[pli] .dst.buf)[xd->plane[pli].dst.stride * (MAX_MIB_SIZE * sbr << bsize[pli]) + (sbc * MAX_MIB_SIZE << bsize[pli])], xd->plane[pli].dst.stride, dst, dlist, dering_count, 3 - dec[pli]); } else { #endif copy_dering_16bit_to_8bit( &xd->plane[pli].dst.buf[xd->plane[pli].dst.stride * (MAX_MIB_SIZE * sbr << bsize[pli]) + (sbc * MAX_MIB_SIZE << bsize[pli])], xd->plane[pli].dst.stride, dst, dlist, dering_count, bsize[pli]); #if CONFIG_AOM_HIGHBITDEPTH } #endif } dering_left = 1; } { unsigned char *tmp; tmp = prev_row_dering; prev_row_dering = curr_row_dering; curr_row_dering = tmp; } }