vp9: apply loopfilter inline if possible
authorJames Zern <jzern@google.com>
Fri, 19 Jul 2013 21:40:34 +0000 (14:40 -0700)
committerJames Zern <jzern@google.com>
Mon, 22 Jul 2013 22:52:10 +0000 (15:52 -0700)
excludes tiled content currently

Change-Id: I44155253e8d6771e5e039d663be5f21cc9d0355d

vp9/common/vp9_loopfilter.c
vp9/common/vp9_loopfilter.h
vp9/decoder/vp9_decodframe.c
vp9/decoder/vp9_onyxd_if.c
vp9/decoder/vp9_onyxd_int.h

index c62f07f..d8be876 100644 (file)
@@ -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);
+}
index cbe52c2..fddf2ce 100644 (file)
@@ -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_
index 3d11a22..61c14b8 100644 (file)
@@ -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;
index 095485c..cb72920 100644 (file)
@@ -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);
     }
index 0d85d44..4760066 100644 (file)
@@ -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_