OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 20 matching lines...) Expand all Loading... |
31 // Controls how long a block will need to wait to be refreshed again. | 31 // Controls how long a block will need to wait to be refreshed again. |
32 int time_for_refresh; | 32 int time_for_refresh; |
33 // Actual number of (8x8) blocks that were applied delta-q (segment 1). | 33 // Actual number of (8x8) blocks that were applied delta-q (segment 1). |
34 int num_seg_blocks; | 34 int num_seg_blocks; |
35 // Actual encoding bits for segment 1. | 35 // Actual encoding bits for segment 1. |
36 int actual_seg_bits; | 36 int actual_seg_bits; |
37 // RD mult. parameters for segment 1. | 37 // RD mult. parameters for segment 1. |
38 int rdmult; | 38 int rdmult; |
39 // Cyclic refresh map. | 39 // Cyclic refresh map. |
40 signed char *map; | 40 signed char *map; |
41 // Projected rate and distortion for the current superblock. | |
42 int64_t projected_rate_sb; | |
43 int64_t projected_dist_sb; | |
44 // Thresholds applied to projected rate/distortion of the superblock. | 41 // Thresholds applied to projected rate/distortion of the superblock. |
45 int64_t thresh_rate_sb; | 42 int64_t thresh_rate_sb; |
46 int64_t thresh_dist_sb; | 43 int64_t thresh_dist_sb; |
47 }; | 44 }; |
48 | 45 |
49 CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) { | 46 CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) { |
50 CYCLIC_REFRESH *const cr = vpx_calloc(1, sizeof(*cr)); | 47 CYCLIC_REFRESH *const cr = vpx_calloc(1, sizeof(*cr)); |
51 if (cr == NULL) | 48 if (cr == NULL) |
52 return NULL; | 49 return NULL; |
53 | 50 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 else | 82 else |
86 return 1; | 83 return 1; |
87 } | 84 } |
88 | 85 |
89 // Check if this coding block, of size bsize, should be considered for refresh | 86 // Check if this coding block, of size bsize, should be considered for refresh |
90 // (lower-qp coding). Decision can be based on various factors, such as | 87 // (lower-qp coding). Decision can be based on various factors, such as |
91 // size of the coding block (i.e., below min_block size rejected), coding | 88 // size of the coding block (i.e., below min_block size rejected), coding |
92 // mode, and rate/distortion. | 89 // mode, and rate/distortion. |
93 static int candidate_refresh_aq(const CYCLIC_REFRESH *cr, | 90 static int candidate_refresh_aq(const CYCLIC_REFRESH *cr, |
94 const MB_MODE_INFO *mbmi, | 91 const MB_MODE_INFO *mbmi, |
95 BLOCK_SIZE bsize, int use_rd) { | 92 BLOCK_SIZE bsize, int use_rd, |
| 93 int64_t rate_sb) { |
96 if (use_rd) { | 94 if (use_rd) { |
| 95 MV mv = mbmi->mv[0].as_mv; |
97 // If projected rate is below the thresh_rate (well below target, | 96 // If projected rate is below the thresh_rate (well below target, |
98 // so undershoot expected), accept it for lower-qp coding. | 97 // so undershoot expected), accept it for lower-qp coding. |
99 if (cr->projected_rate_sb < cr->thresh_rate_sb) | 98 if (rate_sb < cr->thresh_rate_sb) |
100 return 1; | 99 return 1; |
101 // Otherwise, reject the block for lower-qp coding if any of the following: | 100 // Otherwise, reject the block for lower-qp coding if any of the following: |
102 // 1) prediction block size is below min_block_size | 101 // 1) mode uses large mv |
103 // 2) mode is non-zero mv and projected distortion is above thresh_dist | 102 // 2) mode is an intra-mode (we may want to allow some of this under |
104 // 3) mode is an intra-mode (we may want to allow some of this under | |
105 // another thresh_dist) | 103 // another thresh_dist) |
106 else if (bsize < cr->min_block_size || | 104 else if (mv.row > 32 || mv.row < -32 || |
107 (mbmi->mv[0].as_int != 0 && | 105 mv.col > 32 || mv.col < -32 || !is_inter_block(mbmi)) |
108 cr->projected_dist_sb > cr->thresh_dist_sb) || | |
109 !is_inter_block(mbmi)) | |
110 return 0; | 106 return 0; |
111 else | 107 else |
112 return 1; | 108 return 1; |
113 } else { | 109 } else { |
114 // Rate/distortion not used for update. | 110 // Rate/distortion not used for update. |
115 if (bsize < cr->min_block_size || | 111 if (bsize < cr->min_block_size || |
116 mbmi->mv[0].as_int != 0 || | 112 mbmi->mv[0].as_int != 0 || |
117 !is_inter_block(mbmi)) | 113 !is_inter_block(mbmi)) |
118 return 0; | 114 return 0; |
119 else | 115 else |
120 return 1; | 116 return 1; |
121 } | 117 } |
122 } | 118 } |
123 | 119 |
124 // Prior to coding a given prediction block, of size bsize at (mi_row, mi_col), | 120 // Prior to coding a given prediction block, of size bsize at (mi_row, mi_col), |
125 // check if we should reset the segment_id, and update the cyclic_refresh map | 121 // check if we should reset the segment_id, and update the cyclic_refresh map |
126 // and segmentation map. | 122 // and segmentation map. |
127 void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, | 123 void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, |
128 MB_MODE_INFO *const mbmi, | 124 MB_MODE_INFO *const mbmi, |
129 int mi_row, int mi_col, | 125 int mi_row, int mi_col, |
130 BLOCK_SIZE bsize, int use_rd) { | 126 BLOCK_SIZE bsize, int use_rd, |
| 127 int64_t rate_sb) { |
131 const VP9_COMMON *const cm = &cpi->common; | 128 const VP9_COMMON *const cm = &cpi->common; |
132 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; | 129 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; |
133 const int bw = num_8x8_blocks_wide_lookup[bsize]; | 130 const int bw = num_8x8_blocks_wide_lookup[bsize]; |
134 const int bh = num_8x8_blocks_high_lookup[bsize]; | 131 const int bh = num_8x8_blocks_high_lookup[bsize]; |
135 const int xmis = MIN(cm->mi_cols - mi_col, bw); | 132 const int xmis = MIN(cm->mi_cols - mi_col, bw); |
136 const int ymis = MIN(cm->mi_rows - mi_row, bh); | 133 const int ymis = MIN(cm->mi_rows - mi_row, bh); |
137 const int block_index = mi_row * cm->mi_cols + mi_col; | 134 const int block_index = mi_row * cm->mi_cols + mi_col; |
138 const int refresh_this_block = cpi->mb.in_static_area || | 135 const int refresh_this_block = candidate_refresh_aq(cr, mbmi, bsize, use_rd, |
139 candidate_refresh_aq(cr, mbmi, bsize, use_rd); | 136 rate_sb); |
140 // Default is to not update the refresh map. | 137 // Default is to not update the refresh map. |
141 int new_map_value = cr->map[block_index]; | 138 int new_map_value = cr->map[block_index]; |
142 int x = 0; int y = 0; | 139 int x = 0; int y = 0; |
143 | 140 |
144 // Check if we should reset the segment_id for this block. | 141 // Check if we should reset the segment_id for this block. |
145 if (mbmi->segment_id > 0 && !refresh_this_block) | 142 if (mbmi->segment_id > 0 && !refresh_this_block) |
146 mbmi->segment_id = 0; | 143 mbmi->segment_id = 0; |
147 | 144 |
148 // Update the cyclic refresh map, to be used for setting segmentation map | 145 // Update the cyclic refresh map, to be used for setting segmentation map |
149 // for the next frame. If the block will be refreshed this frame, mark it | 146 // for the next frame. If the block will be refreshed this frame, mark it |
150 // as clean. The magnitude of the -ve influences how long before we consider | 147 // as clean. The magnitude of the -ve influences how long before we consider |
151 // it for refresh again. | 148 // it for refresh again. |
152 if (mbmi->segment_id == 1) { | 149 if (mbmi->segment_id == 1) { |
153 new_map_value = -cr->time_for_refresh; | 150 new_map_value = -cr->time_for_refresh; |
154 } else if (refresh_this_block) { | 151 } else if (refresh_this_block) { |
155 // Else if it is accepted as candidate for refresh, and has not already | 152 // Else if it is accepted as candidate for refresh, and has not already |
156 // been refreshed (marked as 1) then mark it as a candidate for cleanup | 153 // been refreshed (marked as 1) then mark it as a candidate for cleanup |
157 // for future time (marked as 0), otherwise don't update it. | 154 // for future time (marked as 0), otherwise don't update it. |
158 if (cr->map[block_index] == 1) | 155 if (cr->map[block_index] == 1) |
159 new_map_value = 0; | 156 new_map_value = 0; |
160 } else { | 157 } else { |
161 // Leave it marked as block that is not candidate for refresh. | 158 // Leave it marked as block that is not candidate for refresh. |
162 new_map_value = 1; | 159 new_map_value = 1; |
163 } | 160 } |
| 161 |
164 // Update entries in the cyclic refresh map with new_map_value, and | 162 // Update entries in the cyclic refresh map with new_map_value, and |
165 // copy mbmi->segment_id into global segmentation map. | 163 // copy mbmi->segment_id into global segmentation map. |
166 for (y = 0; y < ymis; y++) | 164 for (y = 0; y < ymis; y++) |
167 for (x = 0; x < xmis; x++) { | 165 for (x = 0; x < xmis; x++) { |
168 cr->map[block_index + y * cm->mi_cols + x] = new_map_value; | 166 cr->map[block_index + y * cm->mi_cols + x] = new_map_value; |
169 cpi->segmentation_map[block_index + y * cm->mi_cols + x] = | 167 cpi->segmentation_map[block_index + y * cm->mi_cols + x] = |
170 mbmi->segment_id; | 168 mbmi->segment_id; |
171 } | 169 } |
172 // Keep track of actual number (in units of 8x8) of blocks in segment 1 used | 170 // Keep track of actual number (in units of 8x8) of blocks in segment 1 used |
173 // for encoding this frame. | 171 // for encoding this frame. |
174 if (mbmi->segment_id) | 172 if (mbmi->segment_id) |
175 cr->num_seg_blocks += xmis * ymis; | 173 cr->num_seg_blocks += xmis * ymis; |
176 } | 174 } |
177 | 175 |
178 // Setup cyclic background refresh: set delta q and segmentation map. | 176 // Setup cyclic background refresh: set delta q and segmentation map. |
179 void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { | 177 void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { |
180 VP9_COMMON *const cm = &cpi->common; | 178 VP9_COMMON *const cm = &cpi->common; |
181 const RATE_CONTROL *const rc = &cpi->rc; | 179 const RATE_CONTROL *const rc = &cpi->rc; |
182 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; | 180 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; |
183 struct segmentation *const seg = &cm->seg; | 181 struct segmentation *const seg = &cm->seg; |
184 unsigned char *const seg_map = cpi->segmentation_map; | 182 unsigned char *const seg_map = cpi->segmentation_map; |
185 const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc); | 183 const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc); |
186 // Don't apply refresh on key frame or enhancement layer frames. | 184 // Don't apply refresh on key frame or enhancement layer frames. |
187 if (!apply_cyclic_refresh || | 185 if (!apply_cyclic_refresh || |
188 (cm->frame_type == KEY_FRAME) || | 186 (cm->frame_type == KEY_FRAME) || |
189 (cpi->svc.temporal_layer_id > 0)) { | 187 (cpi->svc.temporal_layer_id > 0) || |
| 188 (cpi->svc.spatial_layer_id > 0)) { |
190 // Set segmentation map to 0 and disable. | 189 // Set segmentation map to 0 and disable. |
191 vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols); | 190 vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols); |
192 vp9_disable_segmentation(&cm->seg); | 191 vp9_disable_segmentation(&cm->seg); |
193 if (cm->frame_type == KEY_FRAME) | 192 if (cm->frame_type == KEY_FRAME) |
194 cr->sb_index = 0; | 193 cr->sb_index = 0; |
195 return; | 194 return; |
196 } else { | 195 } else { |
197 int qindex_delta = 0; | 196 int qindex_delta = 0; |
198 int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame; | 197 int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame; |
199 int xmis, ymis, x, y, qindex2; | 198 int xmis, ymis, x, y, qindex2; |
200 | 199 |
201 // Rate target ratio to set q delta. | 200 // Rate target ratio to set q delta. |
202 const float rate_ratio_qdelta = 2.0; | 201 const float rate_ratio_qdelta = 2.0; |
203 const double q = vp9_convert_qindex_to_q(cm->base_qindex, cm->bit_depth); | 202 const double q = vp9_convert_qindex_to_q(cm->base_qindex, cm->bit_depth); |
204 vp9_clear_system_state(); | 203 vp9_clear_system_state(); |
205 // Some of these parameters may be set via codec-control function later. | 204 // Some of these parameters may be set via codec-control function later. |
206 cr->max_sbs_perframe = 10; | 205 cr->max_sbs_perframe = 10; |
207 cr->max_qdelta_perc = 50; | 206 cr->max_qdelta_perc = 50; |
208 cr->min_block_size = BLOCK_8X8; | 207 cr->min_block_size = BLOCK_8X8; |
209 cr->time_for_refresh = 1; | 208 cr->time_for_refresh = 1; |
210 // Set rate threshold to some fraction of target (and scaled by 256). | 209 // Set rate threshold to some fraction of target (and scaled by 256). |
211 cr->thresh_rate_sb = (rc->sb64_target_rate * 256) >> 2; | 210 cr->thresh_rate_sb = (rc->sb64_target_rate * 256) >> 2; |
212 // Distortion threshold, quadratic in Q, scale factor to be adjusted. | 211 // Distortion threshold, quadratic in Q, scale factor to be adjusted. |
213 cr->thresh_dist_sb = 8 * (int)(q * q); | 212 cr->thresh_dist_sb = 8 * (int)(q * q); |
214 if (cpi->sf.use_nonrd_pick_mode) { | 213 if (cpi->sf.use_nonrd_pick_mode) { |
215 // May want to be more conservative with thresholds in non-rd mode for now | 214 // May want to be more conservative with thresholds in non-rd mode for now |
216 // as rate/distortion are derived from model based on prediction residual. | 215 // as rate/distortion are derived from model based on prediction residual. |
217 cr->thresh_rate_sb = (rc->sb64_target_rate * 256) >> 3; | 216 cr->thresh_rate_sb = (rc->sb64_target_rate * 256); |
218 cr->thresh_dist_sb = 4 * (int)(q * q); | 217 cr->thresh_dist_sb = 16 * (int)(q * q); |
219 } | 218 } |
220 | 219 |
221 cr->num_seg_blocks = 0; | 220 cr->num_seg_blocks = 0; |
222 // Set up segmentation. | 221 // Set up segmentation. |
223 // Clear down the segment map. | 222 // Clear down the segment map. |
224 vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols); | 223 vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols); |
225 vp9_enable_segmentation(&cm->seg); | 224 vp9_enable_segmentation(&cm->seg); |
226 vp9_clearall_segfeatures(seg); | 225 vp9_clearall_segfeatures(seg); |
227 // Select delta coding method. | 226 // Select delta coding method. |
228 seg->abs_delta = SEGMENT_DELTADATA; | 227 seg->abs_delta = SEGMENT_DELTADATA; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 if (i == sbs_in_frame) { | 305 if (i == sbs_in_frame) { |
307 i = 0; | 306 i = 0; |
308 } | 307 } |
309 if (sum_map >= xmis * ymis /2) | 308 if (sum_map >= xmis * ymis /2) |
310 block_count--; | 309 block_count--; |
311 } while (block_count && i != cr->sb_index); | 310 } while (block_count && i != cr->sb_index); |
312 cr->sb_index = i; | 311 cr->sb_index = i; |
313 } | 312 } |
314 } | 313 } |
315 | 314 |
316 void vp9_cyclic_refresh_set_rate_and_dist_sb(CYCLIC_REFRESH *cr, | |
317 int64_t rate_sb, int64_t dist_sb) { | |
318 cr->projected_rate_sb = rate_sb; | |
319 cr->projected_dist_sb = dist_sb; | |
320 } | |
321 | |
322 int vp9_cyclic_refresh_get_rdmult(const CYCLIC_REFRESH *cr) { | 315 int vp9_cyclic_refresh_get_rdmult(const CYCLIC_REFRESH *cr) { |
323 return cr->rdmult; | 316 return cr->rdmult; |
324 } | 317 } |
OLD | NEW |