// Implement row loopfiltering for each thread. static void loop_filter_rows_mt(const YV12_BUFFER_CONFIG *const frame_buffer, VP9_COMMON *const cm, MACROBLOCKD *const xd, int start, int stop, int y_only, VP9LfSync *const lf_sync, int num_lf_workers) { const int num_planes = y_only ? 1 : MAX_MB_PLANE; int r, c; // SB row and col const int sb_cols = mi_cols_aligned_to_sb(cm->mi_cols) >> MI_BLOCK_SIZE_LOG2; for (r = start; r < stop; r += num_lf_workers) { const int mi_row = r << MI_BLOCK_SIZE_LOG2; MODE_INFO **const mi = cm->mi_grid_visible + mi_row * cm->mi_stride; for (c = 0; c < sb_cols; ++c) { const int mi_col = c << MI_BLOCK_SIZE_LOG2; LOOP_FILTER_MASK lfm; int plane; sync_read(lf_sync, r, c); vp9_setup_dst_planes(xd, frame_buffer, mi_row, mi_col); vp9_setup_mask(cm, mi_row, mi_col, mi + mi_col, cm->mi_stride, &lfm); for (plane = 0; plane < num_planes; ++plane) { vp9_filter_block_plane(cm, &xd->plane[plane], mi_row, &lfm); } sync_write(lf_sync, r, c, sb_cols); } } }
// Implement row loopfiltering for each thread. static INLINE void thread_loop_filter_rows(const YV12_BUFFER_CONFIG *const frame_buffer, VP9_COMMON *const cm, struct macroblockd_plane planes[MAX_MB_PLANE], int start, int stop, int y_only, VP9LfSync *const lf_sync) { const int num_planes = y_only ? 1 : MAX_MB_PLANE; const int sb_cols = mi_cols_aligned_to_sb(cm->mi_cols) >> MI_BLOCK_SIZE_LOG2; int mi_row, mi_col; enum lf_path path; if (y_only) path = LF_PATH_444; else if (planes[1].subsampling_y == 1 && planes[1].subsampling_x == 1) path = LF_PATH_420; else if (planes[1].subsampling_y == 0 && planes[1].subsampling_x == 0) path = LF_PATH_444; else path = LF_PATH_SLOW; for (mi_row = start; mi_row < stop; mi_row += lf_sync->num_workers * MI_BLOCK_SIZE) { MODE_INFO **const mi = cm->mi_grid_visible + mi_row * cm->mi_stride; for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) { const int r = mi_row >> MI_BLOCK_SIZE_LOG2; const int c = mi_col >> MI_BLOCK_SIZE_LOG2; LOOP_FILTER_MASK lfm; int plane; sync_read(lf_sync, r, c); vp9_setup_dst_planes(planes, frame_buffer, mi_row, mi_col); // TODO(JBB): Make setup_mask work for non 420. vp9_setup_mask(cm, mi_row, mi_col, mi + mi_col, cm->mi_stride, &lfm); vp9_filter_block_plane_ss00(cm, &planes[0], mi_row, &lfm); for (plane = 1; plane < num_planes; ++plane) { switch (path) { case LF_PATH_420: vp9_filter_block_plane_ss11(cm, &planes[plane], mi_row, &lfm); break; case LF_PATH_444: vp9_filter_block_plane_ss00(cm, &planes[plane], mi_row, &lfm); break; case LF_PATH_SLOW: vp9_filter_block_plane_non420(cm, &planes[plane], mi + mi_col, mi_row, mi_col); break; } } sync_write(lf_sync, r, c, sb_cols); } } }
// Row-based multi-threaded loopfilter hook static int loop_filter_row_worker(thread_context *const thread_ctxt, void *unused) { VP9_COMP *const cpi = thread_ctxt->cpi; VP9_COMMON *const cm = &cpi->common; MACROBLOCKD *const xd = &cpi->mb.e_mbd; const YV12_BUFFER_CONFIG *const frame_buffer = cm->frame_to_show; struct macroblockd_plane planes[MAX_MB_PLANE]; const int num_planes = thread_ctxt->y_only ? 1 : MAX_MB_PLANE; int mi_row, mi_col; (void)unused; vp9_copy(planes, xd->plane); for (mi_row = thread_ctxt->mi_row_start; mi_row < thread_ctxt->mi_row_end; mi_row += thread_ctxt->mi_row_step) { const int sb_row = mi_row >> MI_BLOCK_SIZE_LOG2; MODE_INFO **const mi = cm->mi_grid_visible + mi_row * cm->mi_stride; for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) { const int sb_col = mi_col >> MI_BLOCK_SIZE_LOG2; LOOP_FILTER_MASK lfm; int plane; vp9_enc_sync_read(cpi, sb_row, sb_col); vp9_setup_dst_planes(planes, frame_buffer, mi_row, mi_col); vp9_setup_mask(cm, mi_row, mi_col, mi + mi_col, cm->mi_stride, &lfm); for (plane = 0; plane < num_planes; ++plane) { vp9_filter_block_plane(cm, &planes[plane], mi_row, &lfm); } vp9_enc_sync_write(cpi, sb_row); } } return 1; }