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 29 matching lines...) Expand all Loading... |
40 signed char *map; | 40 signed char *map; |
41 // Thresholds applied to the projected rate/distortion of the coding block, | 41 // Thresholds applied to the projected rate/distortion of the coding block, |
42 // when deciding whether block should be refreshed. | 42 // when deciding whether block should be refreshed. |
43 int64_t thresh_rate_sb; | 43 int64_t thresh_rate_sb; |
44 int64_t thresh_dist_sb; | 44 int64_t thresh_dist_sb; |
45 // Threshold applied to the motion vector (in units of 1/8 pel) of the | 45 // Threshold applied to the motion vector (in units of 1/8 pel) of the |
46 // coding block, when deciding whether block should be refreshed. | 46 // coding block, when deciding whether block should be refreshed. |
47 int16_t motion_thresh; | 47 int16_t motion_thresh; |
48 // Rate target ratio to set q delta. | 48 // Rate target ratio to set q delta. |
49 double rate_ratio_qdelta; | 49 double rate_ratio_qdelta; |
| 50 double low_content_avg; |
50 }; | 51 }; |
51 | 52 |
52 CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) { | 53 CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) { |
53 CYCLIC_REFRESH *const cr = vpx_calloc(1, sizeof(*cr)); | 54 CYCLIC_REFRESH *const cr = vpx_calloc(1, sizeof(*cr)); |
54 if (cr == NULL) | 55 if (cr == NULL) |
55 return NULL; | 56 return NULL; |
56 | 57 |
57 cr->map = vpx_calloc(mi_rows * mi_cols, sizeof(*cr->map)); | 58 cr->map = vpx_calloc(mi_rows * mi_cols, sizeof(*cr->map)); |
58 if (cr->map == NULL) { | 59 if (cr->map == NULL) { |
59 vpx_free(cr); | 60 vpx_free(cr); |
60 return NULL; | 61 return NULL; |
61 } | 62 } |
62 | 63 |
63 return cr; | 64 return cr; |
64 } | 65 } |
65 | 66 |
66 void vp9_cyclic_refresh_free(CYCLIC_REFRESH *cr) { | 67 void vp9_cyclic_refresh_free(CYCLIC_REFRESH *cr) { |
67 vpx_free(cr->map); | 68 vpx_free(cr->map); |
68 vpx_free(cr); | 69 vpx_free(cr); |
69 } | 70 } |
70 | 71 |
71 // Check if we should turn off cyclic refresh based on bitrate condition. | 72 // Check if we should turn off cyclic refresh based on bitrate condition. |
72 static int apply_cyclic_refresh_bitrate(const VP9_COMMON *cm, | 73 static int apply_cyclic_refresh_bitrate(const VP9_COMMON *cm, |
73 const RATE_CONTROL *rc) { | 74 const RATE_CONTROL *rc) { |
74 // Turn off cyclic refresh if bits available per frame is not sufficiently | 75 // Turn off cyclic refresh if bits available per frame is not sufficiently |
75 // larger than bit cost of segmentation. Segment map bit cost should scale | 76 // larger than bit cost of segmentation. Segment map bit cost should scale |
76 // with number of seg blocks, so compare available bits to number of blocks. | 77 // with number of seg blocks, so compare available bits to number of blocks. |
77 // Average bits available per frame = avg_frame_bandwidth | 78 // Average bits available per frame = avg_frame_bandwidth |
78 // Number of (8x8) blocks in frame = mi_rows * mi_cols; | 79 // Number of (8x8) blocks in frame = mi_rows * mi_cols; |
79 const float factor = 0.5; | 80 const float factor = 0.25; |
80 const int number_blocks = cm->mi_rows * cm->mi_cols; | 81 const int number_blocks = cm->mi_rows * cm->mi_cols; |
81 // The condition below corresponds to turning off at target bitrates: | 82 // The condition below corresponds to turning off at target bitrates: |
82 // ~24kbps for CIF, 72kbps for VGA (at 30fps). | 83 // (at 30fps), ~12kbps for CIF, 36kbps for VGA, 100kps for HD/720p. |
83 // Also turn off at very small frame sizes, to avoid too large fraction of | 84 // Also turn off at very small frame sizes, to avoid too large fraction of |
84 // superblocks to be refreshed per frame. Threshold below is less than QCIF. | 85 // superblocks to be refreshed per frame. Threshold below is less than QCIF. |
85 if (rc->avg_frame_bandwidth < factor * number_blocks || | 86 if (rc->avg_frame_bandwidth < factor * number_blocks || |
86 number_blocks / 64 < 5) | 87 number_blocks / 64 < 5) |
87 return 0; | 88 return 0; |
88 else | 89 else |
89 return 1; | 90 return 1; |
90 } | 91 } |
91 | 92 |
92 // Check if this coding block, of size bsize, should be considered for refresh | 93 // Check if this coding block, of size bsize, should be considered for refresh |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 const int ymis = MIN(cm->mi_rows - mi_row, bh); | 207 const int ymis = MIN(cm->mi_rows - mi_row, bh); |
207 const int block_index = mi_row * cm->mi_cols + mi_col; | 208 const int block_index = mi_row * cm->mi_cols + mi_col; |
208 const int refresh_this_block = candidate_refresh_aq(cr, mbmi, rate, dist, | 209 const int refresh_this_block = candidate_refresh_aq(cr, mbmi, rate, dist, |
209 bsize); | 210 bsize); |
210 // Default is to not update the refresh map. | 211 // Default is to not update the refresh map. |
211 int new_map_value = cr->map[block_index]; | 212 int new_map_value = cr->map[block_index]; |
212 int x = 0; int y = 0; | 213 int x = 0; int y = 0; |
213 | 214 |
214 // If this block is labeled for refresh, check if we should reset the | 215 // If this block is labeled for refresh, check if we should reset the |
215 // segment_id. | 216 // segment_id. |
216 if (mbmi->segment_id != CR_SEGMENT_ID_BASE) | 217 if (cyclic_refresh_segment_id_boosted(mbmi->segment_id)) |
217 mbmi->segment_id = refresh_this_block; | 218 mbmi->segment_id = refresh_this_block; |
218 | 219 |
219 // Update the cyclic refresh map, to be used for setting segmentation map | 220 // Update the cyclic refresh map, to be used for setting segmentation map |
220 // for the next frame. If the block will be refreshed this frame, mark it | 221 // for the next frame. If the block will be refreshed this frame, mark it |
221 // as clean. The magnitude of the -ve influences how long before we consider | 222 // as clean. The magnitude of the -ve influences how long before we consider |
222 // it for refresh again. | 223 // it for refresh again. |
223 if (mbmi->segment_id != CR_SEGMENT_ID_BASE) { | 224 if (cyclic_refresh_segment_id_boosted(mbmi->segment_id)) { |
224 new_map_value = -cr->time_for_refresh; | 225 new_map_value = -cr->time_for_refresh; |
225 } else if (refresh_this_block) { | 226 } else if (refresh_this_block) { |
226 // Else if it is accepted as candidate for refresh, and has not already | 227 // Else if it is accepted as candidate for refresh, and has not already |
227 // been refreshed (marked as 1) then mark it as a candidate for cleanup | 228 // been refreshed (marked as 1) then mark it as a candidate for cleanup |
228 // for future time (marked as 0), otherwise don't update it. | 229 // for future time (marked as 0), otherwise don't update it. |
229 if (cr->map[block_index] == 1) | 230 if (cr->map[block_index] == 1) |
230 new_map_value = 0; | 231 new_map_value = 0; |
231 } else { | 232 } else { |
232 // Leave it marked as block that is not candidate for refresh. | 233 // Leave it marked as block that is not candidate for refresh. |
233 new_map_value = 1; | 234 new_map_value = 1; |
234 } | 235 } |
235 | 236 |
236 // Update entries in the cyclic refresh map with new_map_value, and | 237 // Update entries in the cyclic refresh map with new_map_value, and |
237 // copy mbmi->segment_id into global segmentation map. | 238 // copy mbmi->segment_id into global segmentation map. |
238 for (y = 0; y < ymis; y++) | 239 for (y = 0; y < ymis; y++) |
239 for (x = 0; x < xmis; x++) { | 240 for (x = 0; x < xmis; x++) { |
240 cr->map[block_index + y * cm->mi_cols + x] = new_map_value; | 241 cr->map[block_index + y * cm->mi_cols + x] = new_map_value; |
241 cpi->segmentation_map[block_index + y * cm->mi_cols + x] = | 242 cpi->segmentation_map[block_index + y * cm->mi_cols + x] = |
242 mbmi->segment_id; | 243 mbmi->segment_id; |
243 } | 244 } |
244 } | 245 } |
245 | 246 |
246 // Update the actual number of blocks that were applied the segment delta q. | 247 // Update the actual number of blocks that were applied the segment delta q. |
247 void vp9_cyclic_refresh_update_actual_count(struct VP9_COMP *const cpi) { | 248 void vp9_cyclic_refresh_postencode(VP9_COMP *const cpi) { |
248 VP9_COMMON *const cm = &cpi->common; | 249 VP9_COMMON *const cm = &cpi->common; |
249 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; | 250 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; |
250 unsigned char *const seg_map = cpi->segmentation_map; | 251 unsigned char *const seg_map = cpi->segmentation_map; |
251 int mi_row, mi_col; | 252 int mi_row, mi_col; |
252 cr->actual_num_seg_blocks = 0; | 253 cr->actual_num_seg_blocks = 0; |
253 for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) | 254 for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) |
254 for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) { | 255 for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) { |
255 if (seg_map[mi_row * cm->mi_cols + mi_col] != CR_SEGMENT_ID_BASE) | 256 if (cyclic_refresh_segment_id_boosted( |
256 cr->actual_num_seg_blocks++; | 257 seg_map[mi_row * cm->mi_cols + mi_col])) |
| 258 cr->actual_num_seg_blocks++; |
| 259 } |
| 260 } |
| 261 |
| 262 // Set golden frame update interval, for non-svc 1 pass CBR mode. |
| 263 void vp9_cyclic_refresh_set_golden_update(VP9_COMP *const cpi) { |
| 264 RATE_CONTROL *const rc = &cpi->rc; |
| 265 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; |
| 266 // Set minimum gf_interval for GF update to a multiple (== 2) of refresh |
| 267 // period. Depending on past encoding stats, GF flag may be reset and update |
| 268 // may not occur until next baseline_gf_interval. |
| 269 if (cr->percent_refresh > 0) |
| 270 rc->baseline_gf_interval = 2 * (100 / cr->percent_refresh); |
| 271 else |
| 272 rc->baseline_gf_interval = 20; |
| 273 } |
| 274 |
| 275 // Update some encoding stats (from the just encoded frame), and if the golden |
| 276 // reference is to be updated check if we should NOT update the golden ref. |
| 277 void vp9_cyclic_refresh_check_golden_update(VP9_COMP *const cpi) { |
| 278 VP9_COMMON *const cm = &cpi->common; |
| 279 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; |
| 280 int mi_row, mi_col; |
| 281 double fraction_low = 0.0; |
| 282 int low_content_frame = 0; |
| 283 for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) |
| 284 for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) { |
| 285 if (cr->map[mi_row * cm->mi_cols + mi_col] < 1) |
| 286 low_content_frame++; |
| 287 } |
| 288 fraction_low = |
| 289 (double)low_content_frame / (cm->mi_rows * cm->mi_cols); |
| 290 // Update average. |
| 291 cr->low_content_avg = (fraction_low + 3 * cr->low_content_avg) / 4; |
| 292 if (cpi->refresh_golden_frame == 1) { |
| 293 // Don't update golden reference if the amount of low_content for the |
| 294 // current encoded frame is small, or if the recursive average of the |
| 295 // low_content over the update interval window falls below threshold. |
| 296 if (fraction_low < 0.8 || cr->low_content_avg < 0.7) |
| 297 cpi->refresh_golden_frame = 0; |
| 298 // Reset for next internal. |
| 299 cr->low_content_avg = fraction_low; |
257 } | 300 } |
258 } | 301 } |
259 | 302 |
260 // Update the segmentation map, and related quantities: cyclic refresh map, | 303 // Update the segmentation map, and related quantities: cyclic refresh map, |
261 // refresh sb_index, and target number of blocks to be refreshed. | 304 // refresh sb_index, and target number of blocks to be refreshed. |
262 // The map is set to either 0/CR_SEGMENT_ID_BASE (no refresh) or to | 305 // The map is set to either 0/CR_SEGMENT_ID_BASE (no refresh) or to |
263 // 1/CR_SEGMENT_ID_BOOST1 (refresh) for each superblock. | 306 // 1/CR_SEGMENT_ID_BOOST1 (refresh) for each superblock. |
264 // Blocks labeled as BOOST1 may later get set to BOOST2 (during the | 307 // Blocks labeled as BOOST1 may later get set to BOOST2 (during the |
265 // encoding of the superblock). | 308 // encoding of the superblock). |
266 void vp9_cyclic_refresh_update_map(VP9_COMP *const cpi) { | 309 void vp9_cyclic_refresh_update_map(VP9_COMP *const cpi) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 cr->rate_ratio_qdelta = 2.0; | 383 cr->rate_ratio_qdelta = 2.0; |
341 } | 384 } |
342 | 385 |
343 // Setup cyclic background refresh: set delta q and segmentation map. | 386 // Setup cyclic background refresh: set delta q and segmentation map. |
344 void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { | 387 void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { |
345 VP9_COMMON *const cm = &cpi->common; | 388 VP9_COMMON *const cm = &cpi->common; |
346 const RATE_CONTROL *const rc = &cpi->rc; | 389 const RATE_CONTROL *const rc = &cpi->rc; |
347 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; | 390 CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; |
348 struct segmentation *const seg = &cm->seg; | 391 struct segmentation *const seg = &cm->seg; |
349 const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc); | 392 const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc); |
| 393 if (cm->current_video_frame == 0) |
| 394 cr->low_content_avg = 0.0; |
350 // Don't apply refresh on key frame or enhancement layer frames. | 395 // Don't apply refresh on key frame or enhancement layer frames. |
351 if (!apply_cyclic_refresh || | 396 if (!apply_cyclic_refresh || |
352 (cm->frame_type == KEY_FRAME) || | 397 (cm->frame_type == KEY_FRAME) || |
353 (cpi->svc.temporal_layer_id > 0) || | 398 (cpi->svc.temporal_layer_id > 0) || |
354 (cpi->svc.spatial_layer_id > 0)) { | 399 (cpi->svc.spatial_layer_id > 0)) { |
355 // Set segmentation map to 0 and disable. | 400 // Set segmentation map to 0 and disable. |
356 unsigned char *const seg_map = cpi->segmentation_map; | 401 unsigned char *const seg_map = cpi->segmentation_map; |
357 vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols); | 402 vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols); |
358 vp9_disable_segmentation(&cm->seg); | 403 vp9_disable_segmentation(&cm->seg); |
359 if (cm->frame_type == KEY_FRAME) | 404 if (cm->frame_type == KEY_FRAME) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 vp9_set_segdata(seg, CR_SEGMENT_ID_BOOST2, SEG_LVL_ALT_Q, qindex_delta); | 456 vp9_set_segdata(seg, CR_SEGMENT_ID_BOOST2, SEG_LVL_ALT_Q, qindex_delta); |
412 | 457 |
413 // Update the segmentation and refresh map. | 458 // Update the segmentation and refresh map. |
414 vp9_cyclic_refresh_update_map(cpi); | 459 vp9_cyclic_refresh_update_map(cpi); |
415 } | 460 } |
416 } | 461 } |
417 | 462 |
418 int vp9_cyclic_refresh_get_rdmult(const CYCLIC_REFRESH *cr) { | 463 int vp9_cyclic_refresh_get_rdmult(const CYCLIC_REFRESH *cr) { |
419 return cr->rdmult; | 464 return cr->rdmult; |
420 } | 465 } |
OLD | NEW |