ref: 38a4412e1bcce41cb443fac05e94b580152d8c09
parent: 746154d905e021bb6a6b2c16cc37ad2cc08fd67d
author: James Zern <[email protected]>
date: Fri Jul 19 10:40:34 EDT 2013
vp9: apply loopfilter inline if possible excludes tiled content currently Change-Id: I44155253e8d6771e5e039d663be5f21cc9d0355d
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -71,8 +71,8 @@
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 @@
}
}
-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);
}
--- a/vp9/common/vp9_loopfilter.h
+++ b/vp9/common/vp9_loopfilter.h
@@ -48,8 +48,20 @@
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_
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -603,6 +603,10 @@
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
@@ -609,9 +613,25 @@
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);
+ }
}
static void setup_tile_info(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
@@ -929,6 +949,8 @@
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;
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -346,7 +346,7 @@
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);
}
--- a/vp9/decoder/vp9_onyxd_int.h
+++ b/vp9/decoder/vp9_onyxd_int.h
@@ -38,6 +38,8 @@
int initial_width;
int initial_height;
+
+ int do_loopfilter_inline; // apply loopfilter to available rows immediately
} VP9D_COMP;
#endif // VP9_DECODER_VP9_TREEREADER_H_