1 /*
2 * Copyright (c) 2019, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12 #ifndef AOM_AV1_ENCODER_PARTITION_STRATEGY_H_
13 #define AOM_AV1_ENCODER_PARTITION_STRATEGY_H_
14
15 #include "av1/encoder/encodeframe.h"
16 #include "av1/encoder/encodemb.h"
17 #include "av1/encoder/encoder.h"
18
19 #define FEATURE_SIZE_SMS_PRUNE_PART 25
20 #define FEATURE_SIZE_SMS_TERM_NONE 28
21 #define FEATURE_SIZE_FP_SMS_TERM_NONE 20
22 #define FEATURE_SIZE_MAX_MIN_PART_PRED 13
23 #define MAX_NUM_CLASSES_MAX_MIN_PART_PRED 4
24
25 // Performs a simple_motion_search with a single reference frame and extract
26 // the variance of residues. Then use the features to determine whether we want
27 // to go straight to splitting without trying PARTITION_NONE
28 void av1_simple_motion_search_based_split(
29 AV1_COMP *const cpi, MACROBLOCK *x, int mi_row, int mi_col,
30 BLOCK_SIZE bsize, int *partition_none_allowed, int *partition_horz_allowed,
31 int *partition_vert_allowed, int *do_rectangular_split,
32 int *do_square_split);
33
34 // Performs a simple_motion_search with two reference frames and extract
35 // the variance of residues. Then use the features to determine whether we want
36 // to prune some partitions.
37 void av1_simple_motion_search_prune_part(
38 AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
39 int mi_col, BLOCK_SIZE bsize, int *partition_none_allowed,
40 int *partition_horz_allowed, int *partition_vert_allowed,
41 int *do_square_split, int *do_rectangular_split, int *prune_horz,
42 int *prune_vert, float *features, int *valid);
43
44 // Early terminates PARTITION_NONE using simple_motion_search features and the
45 // rate, distortion, and rdcost of PARTITION_NONE. This is only called when:
46 // - The frame is a show frame
47 // - The frame is not intra only
48 // - The current bsize is > BLOCK_8X8
49 // - blk_row + blk_height/2 < total_rows and blk_col + blk_width/2 < total_cols
50 void av1_simple_motion_search_early_term_none(
51 AV1_COMP *const cpi, MACROBLOCK *x, PC_TREE *pc_tree, int mi_row,
52 int mi_col, BLOCK_SIZE bsize, const RD_STATS *none_rdc,
53 int *early_terminate, float *simple_motion_features,
54 int *simple_motion_features_are_valid);
55
56 // Early terminates after PARTITION_NONE in firstpass of two pass partition
57 // search.
58 void av1_firstpass_simple_motion_search_early_term(AV1_COMP *const cpi,
59 MACROBLOCK *x,
60 PC_TREE *pc_tree, int mi_row,
61 int mi_col, BLOCK_SIZE bsize,
62 const RD_STATS *none_rdc,
63 int *do_square_split);
64
65 // Get the features for selecting the max and min partition size. Currently this
66 // performs simple_motion_search on 16X16 subblocks of the currnet superblock,
67 // and then extract the statistics of sse and motion vectors as features.
68 void av1_get_max_min_partition_features(AV1_COMP *const cpi, MACROBLOCK *x,
69 int mi_row, int mi_col,
70 float *features);
71
72 // Predict the maximum BLOCK_SIZE to be used to encoder the current superblock.
73 BLOCK_SIZE av1_predict_max_partition(AV1_COMP *const cpi, MACROBLOCK *const x,
74 const float *features);
75
76 // A simplified version of set_offsets meant to be used for
77 // simple_motion_search.
set_offsets_for_motion_search(const AV1_COMP * const cpi,MACROBLOCK * const x,int mi_row,int mi_col,BLOCK_SIZE bsize)78 static INLINE void set_offsets_for_motion_search(const AV1_COMP *const cpi,
79 MACROBLOCK *const x,
80 int mi_row, int mi_col,
81 BLOCK_SIZE bsize) {
82 const AV1_COMMON *const cm = &cpi->common;
83 const int num_planes = av1_num_planes(cm);
84 MACROBLOCKD *const xd = &x->e_mbd;
85 const int mi_width = mi_size_wide[bsize];
86 const int mi_height = mi_size_high[bsize];
87
88 set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
89
90 // Set up destination pointers.
91 av1_setup_dst_planes(xd->plane, bsize, &cm->cur_frame->buf, mi_row, mi_col, 0,
92 num_planes);
93
94 // Set up limit values for MV components.
95 // Mv beyond the range do not produce new/different prediction block.
96 x->mv_limits.row_min =
97 -(((mi_row + mi_height) * MI_SIZE) + AOM_INTERP_EXTEND);
98 x->mv_limits.col_min = -(((mi_col + mi_width) * MI_SIZE) + AOM_INTERP_EXTEND);
99 x->mv_limits.row_max = (cm->mi_rows - mi_row) * MI_SIZE + AOM_INTERP_EXTEND;
100 x->mv_limits.col_max = (cm->mi_cols - mi_col) * MI_SIZE + AOM_INTERP_EXTEND;
101
102 set_plane_n4(xd, mi_width, mi_height, num_planes);
103
104 // Set up distance of MB to edge of frame in 1/8th pel units.
105 assert(!(mi_col & (mi_width - 1)) && !(mi_row & (mi_height - 1)));
106 xd->mb_to_top_edge = -((mi_row * MI_SIZE) * 8);
107 xd->mb_to_bottom_edge = ((cm->mi_rows - mi_height - mi_row) * MI_SIZE) * 8;
108 xd->mb_to_left_edge = -((mi_col * MI_SIZE) * 8);
109 xd->mb_to_right_edge = ((cm->mi_cols - mi_width - mi_col) * MI_SIZE) * 8;
110
111 // Set up source buffers.
112 av1_setup_src_planes(x, cpi->source, mi_row, mi_col, num_planes, bsize);
113
114 // R/D setup.
115 x->rdmult = cpi->rd.RDMULT;
116 }
117
init_simple_motion_search_mvs(PC_TREE * pc_tree)118 static INLINE void init_simple_motion_search_mvs(PC_TREE *pc_tree) {
119 for (int idx = 0; idx < REF_FRAMES; idx++) {
120 pc_tree->mv_ref_fulls[idx].row = 0;
121 pc_tree->mv_ref_fulls[idx].col = 0;
122 }
123 if (pc_tree->block_size >= BLOCK_8X8) {
124 init_simple_motion_search_mvs(pc_tree->split[0]);
125 init_simple_motion_search_mvs(pc_tree->split[1]);
126 init_simple_motion_search_mvs(pc_tree->split[2]);
127 init_simple_motion_search_mvs(pc_tree->split[3]);
128 }
129 }
130
is_full_sb(AV1_COMMON * const cm,int mi_row,int mi_col,BLOCK_SIZE sb_size)131 static INLINE int is_full_sb(AV1_COMMON *const cm, int mi_row, int mi_col,
132 BLOCK_SIZE sb_size) {
133 const int sb_mi_wide = mi_size_wide[sb_size];
134 const int sb_mi_high = mi_size_high[sb_size];
135
136 return (mi_row + sb_mi_high) <= cm->mi_rows &&
137 (mi_col + sb_mi_wide) <= cm->mi_cols;
138 }
139
use_auto_max_partition(AV1_COMP * const cpi,BLOCK_SIZE sb_size,int mi_row,int mi_col)140 static INLINE int use_auto_max_partition(AV1_COMP *const cpi,
141 BLOCK_SIZE sb_size, int mi_row,
142 int mi_col) {
143 AV1_COMMON *const cm = &cpi->common;
144
145 return !frame_is_intra_only(cm) &&
146 cpi->sf.auto_max_partition_based_on_simple_motion != NOT_IN_USE &&
147 sb_size == BLOCK_128X128 && is_full_sb(cm, mi_row, mi_col, sb_size) &&
148 cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index] !=
149 OVERLAY_UPDATE &&
150 cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index] !=
151 INTNL_OVERLAY_UPDATE;
152 }
153
154 #endif // AOM_AV1_ENCODER_PARTITION_STRATEGY_H_
155