| 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 |