From 38a4412e1bcce41cb443fac05e94b580152d8c09 Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 19 Jul 2013 14:40:34 -0700 Subject: [PATCH] vp9: apply loopfilter inline if possible excludes tiled content currently Change-Id: I44155253e8d6771e5e039d663be5f21cc9d0355d --- vp9/common/vp9_loopfilter.c | 24 +++++++++++++++--------- vp9/common/vp9_loopfilter.h | 12 ++++++++++++ vp9/decoder/vp9_decodframe.c | 24 +++++++++++++++++++++++- vp9/decoder/vp9_onyxd_if.c | 2 +- vp9/decoder/vp9_onyxd_int.h | 2 ++ 5 files changed, 53 insertions(+), 11 deletions(-) diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c index c62f07f..d8be876 100644 --- a/vp9/common/vp9_loopfilter.c +++ b/vp9/common/vp9_loopfilter.c @@ -71,8 +71,8 @@ void vp9_loop_filter_init(VP9_COMMON *cm, struct loopfilter *lf) { vpx_memset(lfi->hev_thr[i], i, SIMD_WIDTH); } -static void loop_filter_frame_init(VP9_COMMON *const cm, MACROBLOCKD *const xd, - int default_filt_lvl) { +void vp9_loop_filter_frame_init(VP9_COMMON *const cm, MACROBLOCKD *const xd, + int default_filt_lvl) { int seg; // n_shift is the a multiplier for lf_deltas // the multiplier is 1 for when filter_lvl is between 0 and 31; @@ -349,24 +349,30 @@ static void filter_block_plane(VP9_COMMON *const cm, } } -void vp9_loop_filter_frame(VP9_COMMON *cm, MACROBLOCKD *xd, - int frame_filter_level, int y_only) { +void vp9_loop_filter_rows(const YV12_BUFFER_CONFIG *frame_buffer, + VP9_COMMON *cm, MACROBLOCKD *xd, + int start, int stop, int y_only) { const int num_planes = y_only ? 1 : MAX_MB_PLANE; int mi_row, mi_col; - // Initialize the loop filter for this frame. - loop_filter_frame_init(cm, xd, frame_filter_level); - - for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MI_BLOCK_SIZE) { + for (mi_row = start; mi_row < stop; mi_row += MI_BLOCK_SIZE) { MODE_INFO* const mi = cm->mi + mi_row * cm->mode_info_stride; for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) { int plane; - setup_dst_planes(xd, cm->frame_to_show, mi_row, mi_col); + setup_dst_planes(xd, frame_buffer, mi_row, mi_col); for (plane = 0; plane < num_planes; ++plane) { filter_block_plane(cm, &xd->plane[plane], mi + mi_col, mi_row, mi_col); } } } } + +void vp9_loop_filter_frame(VP9_COMMON *cm, MACROBLOCKD *xd, + int frame_filter_level, int y_only) { + if (!frame_filter_level) return; + vp9_loop_filter_frame_init(cm, xd, frame_filter_level); + vp9_loop_filter_rows(cm->frame_to_show, cm, xd, + 0, cm->mi_rows, y_only); +} diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h index cbe52c2..fddf2ce 100644 --- a/vp9/common/vp9_loopfilter.h +++ b/vp9/common/vp9_loopfilter.h @@ -48,8 +48,20 @@ struct macroblockd; void vp9_loop_filter_init(struct VP9Common *cm, struct loopfilter *lf); +// Update the loop filter for the current frame. +// This should be called before vp9_loop_filter_rows(), vp9_loop_filter_frame() +// calls this function directly. +void vp9_loop_filter_frame_init(struct VP9Common *const cm, + struct macroblockd *const xd, + int default_filt_lvl); + void vp9_loop_filter_frame(struct VP9Common *cm, struct macroblockd *mbd, int filter_level, int y_only); + +// Apply the loop filter to [start, stop) macro block rows in frame_buffer. +void vp9_loop_filter_rows(const YV12_BUFFER_CONFIG *frame_buffer, + struct VP9Common *cm, struct macroblockd *xd, + int start, int stop, int y_only); #endif // VP9_COMMON_VP9_LOOPFILTER_H_ diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 3d11a22..61c14b8 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -603,14 +603,34 @@ static void decode_tile(VP9D_COMP *pbi, vp9_reader *r) { VP9_COMMON *const pc = &pbi->common; int mi_row, mi_col; + if (pbi->do_loopfilter_inline) { + vp9_loop_filter_frame_init(pc, &pbi->mb, pbi->mb.lf.filter_level); + } + for (mi_row = pc->cur_tile_mi_row_start; mi_row < pc->cur_tile_mi_row_end; mi_row += MI_BLOCK_SIZE) { // For a SB there are 2 left contexts, each pertaining to a MB row within vpx_memset(&pc->left_context, 0, sizeof(pc->left_context)); vpx_memset(pc->left_seg_context, 0, sizeof(pc->left_seg_context)); for (mi_col = pc->cur_tile_mi_col_start; mi_col < pc->cur_tile_mi_col_end; - mi_col += MI_BLOCK_SIZE) + mi_col += MI_BLOCK_SIZE) { decode_modes_sb(pbi, mi_row, mi_col, r, BLOCK_SIZE_SB64X64); + } + + if (pbi->do_loopfilter_inline) { + YV12_BUFFER_CONFIG *const fb = + &pbi->common.yv12_fb[pbi->common.new_fb_idx]; + // delay the loopfilter by 1 macroblock row. + const int lf_start = mi_row - MI_BLOCK_SIZE; + if (lf_start < 0) continue; + vp9_loop_filter_rows(fb, pc, &pbi->mb, lf_start, mi_row, 0); + } + } + + if (pbi->do_loopfilter_inline) { + YV12_BUFFER_CONFIG *const fb = &pbi->common.yv12_fb[pbi->common.new_fb_idx]; + vp9_loop_filter_rows(fb, pc, &pbi->mb, + mi_row - MI_BLOCK_SIZE, pc->mi_rows, 0); } } @@ -929,6 +949,8 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { data += vp9_rb_bytes_read(&rb); xd->corrupted = 0; new_fb->corrupted = 0; + pbi->do_loopfilter_inline = + (pc->log2_tile_rows | pc->log2_tile_cols) == 0 && pbi->mb.lf.filter_level; if (!pbi->decoded_key_frame && !keyframe) return -1; diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c index 095485c..cb72920 100644 --- a/vp9/decoder/vp9_onyxd_if.c +++ b/vp9/decoder/vp9_onyxd_if.c @@ -346,7 +346,7 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, cm->current_video_frame + 1000); #endif - if (pbi->mb.lf.filter_level) { + if (!pbi->do_loopfilter_inline) { /* Apply the loop filter if appropriate. */ vp9_loop_filter_frame(cm, &pbi->mb, pbi->mb.lf.filter_level, 0); } diff --git a/vp9/decoder/vp9_onyxd_int.h b/vp9/decoder/vp9_onyxd_int.h index 0d85d44..4760066 100644 --- a/vp9/decoder/vp9_onyxd_int.h +++ b/vp9/decoder/vp9_onyxd_int.h @@ -38,6 +38,8 @@ typedef struct VP9Decompressor { int initial_width; int initial_height; + + int do_loopfilter_inline; // apply loopfilter to available rows immediately } VP9D_COMP; #endif // VP9_DECODER_VP9_TREEREADER_H_ -- 2.7.4