1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <limits.h>
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <math.h>
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_aq_cyclicrefresh.h"
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/common/vp9_seg_common.h"
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_ratectrl.h"
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_rdopt.h"
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/encoder/vp9_segmentation.h"
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan
22233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct CYCLIC_REFRESH {
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Percentage of super-blocks per frame that are targeted as candidates
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // for cyclic refresh.
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int max_sbs_perframe;
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Maximum q-delta as percentage of base q.
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int max_qdelta_perc;
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Block size below which we don't apply cyclic refresh.
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan  BLOCK_SIZE min_block_size;
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Superblock starting index for cycling through the frame.
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int sb_index;
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Controls how long a block will need to wait to be refreshed again.
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int time_for_refresh;
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Actual number of (8x8) blocks that were applied delta-q (segment 1).
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int num_seg_blocks;
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Actual encoding bits for segment 1.
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int actual_seg_bits;
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // RD mult. parameters for segment 1.
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int rdmult;
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Cyclic refresh map.
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan  signed char *map;
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Projected rate and distortion for the current superblock.
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t projected_rate_sb;
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t projected_dist_sb;
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Thresholds applied to projected rate/distortion of the superblock.
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t thresh_rate_sb;
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t thresh_dist_sb;
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan
50233d2500723e5594f3e7c70896ffeeef32b9c950ywanCYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) {
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan  CYCLIC_REFRESH *const cr = vpx_calloc(1, sizeof(*cr));
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cr == NULL)
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cr->map = vpx_calloc(mi_rows * mi_cols, sizeof(*cr->map));
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (cr->map == NULL) {
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_free(cr);
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NULL;
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return cr;
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan
64233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_cyclic_refresh_free(CYCLIC_REFRESH *cr) {
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_free(cr->map);
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_free(cr);
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Check if we should turn off cyclic refresh based on bitrate condition.
70233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int apply_cyclic_refresh_bitrate(const VP9_COMMON *cm,
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                        const RATE_CONTROL *rc) {
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Turn off cyclic refresh if bits available per frame is not sufficiently
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // larger than bit cost of segmentation. Segment map bit cost should scale
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // with number of seg blocks, so compare available bits to number of blocks.
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Average bits available per frame = av_per_frame_bandwidth
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Number of (8x8) blocks in frame = mi_rows * mi_cols;
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const float factor  = 0.5;
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int number_blocks = cm->mi_rows  * cm->mi_cols;
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // The condition below corresponds to turning off at target bitrates:
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // ~24kbps for CIF, 72kbps for VGA (at 30fps).
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Also turn off at very small frame sizes, to avoid too large fraction of
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // superblocks to be refreshed per frame. Threshold below is less than QCIF.
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (rc->av_per_frame_bandwidth < factor * number_blocks ||
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan      number_blocks / 64 < 5)
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Check if this coding block, of size bsize, should be considered for refresh
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan// (lower-qp coding). Decision can be based on various factors, such as
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan// size of the coding block (i.e., below min_block size rejected), coding
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan// mode, and rate/distortion.
94233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int candidate_refresh_aq(const CYCLIC_REFRESH *cr,
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                const MB_MODE_INFO *mbmi,
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                BLOCK_SIZE bsize, int use_rd) {
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (use_rd) {
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // If projected rate is below the thresh_rate (well below target,
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // so undershoot expected), accept it for lower-qp coding.
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cr->projected_rate_sb < cr->thresh_rate_sb)
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 1;
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Otherwise, reject the block for lower-qp coding if any of the following:
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // 1) prediction block size is below min_block_size
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // 2) mode is non-zero mv and projected distortion is above thresh_dist
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // 3) mode is an intra-mode (we may want to allow some of this under
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // another thresh_dist)
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else if (bsize < cr->min_block_size ||
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan             (mbmi->mv[0].as_int != 0 &&
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan              cr->projected_dist_sb > cr->thresh_dist_sb) ||
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan             !is_inter_block(mbmi))
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 1;
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Rate/distortion not used for update.
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (bsize < cr->min_block_size ||
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan        mbmi->mv[0].as_int != 0 ||
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan        !is_inter_block(mbmi))
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 1;
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Prior to coding a given prediction block, of size bsize at (mi_row, mi_col),
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan// check if we should reset the segment_id, and update the cyclic_refresh map
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan// and segmentation map.
128233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi,
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       MB_MODE_INFO *const mbmi,
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       int mi_row, int mi_col,
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                       BLOCK_SIZE bsize, int use_rd) {
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const VP9_COMMON *const cm = &cpi->common;
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int bw = num_8x8_blocks_wide_lookup[bsize];
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int bh = num_8x8_blocks_high_lookup[bsize];
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int xmis = MIN(cm->mi_cols - mi_col, bw);
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int ymis = MIN(cm->mi_rows - mi_row, bh);
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int block_index = mi_row * cm->mi_cols + mi_col;
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int refresh_this_block = candidate_refresh_aq(cr, mbmi, bsize, use_rd);
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Default is to not update the refresh map.
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int new_map_value = cr->map[block_index];
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int x = 0; int y = 0;
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Check if we should reset the segment_id for this block.
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mbmi->segment_id > 0 && !refresh_this_block)
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mbmi->segment_id = 0;
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Update the cyclic refresh map, to be used for setting segmentation map
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // for the next frame. If the block  will be refreshed this frame, mark it
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // as clean. The magnitude of the -ve influences how long before we consider
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // it for refresh again.
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mbmi->segment_id == 1) {
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_map_value = -cr->time_for_refresh;
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else if (refresh_this_block) {
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Else if it is accepted as candidate for refresh, and has not already
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // been refreshed (marked as 1) then mark it as a candidate for cleanup
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // for future time (marked as 0), otherwise don't update it.
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cr->map[block_index] == 1)
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan      new_map_value = 0;
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Leave it marked as block that is not candidate for refresh.
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan    new_map_value = 1;
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Update entries in the cyclic refresh map with new_map_value, and
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // copy mbmi->segment_id into global segmentation map.
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (y = 0; y < ymis; y++)
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (x = 0; x < xmis; x++) {
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cr->map[block_index + y * cm->mi_cols + x] = new_map_value;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cpi->segmentation_map[block_index + y * cm->mi_cols + x] =
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan          mbmi->segment_id;
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
172233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Keep track of actual number (in units of 8x8) of blocks in segment 1 used
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // for encoding this frame.
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (mbmi->segment_id)
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->num_seg_blocks += xmis * ymis;
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Setup cyclic background refresh: set delta q and segmentation map.
179233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_cyclic_refresh_setup(VP9_COMP *const cpi) {
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VP9_COMMON *const cm = &cpi->common;
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const RATE_CONTROL *const rc = &cpi->rc;
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan  CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct segmentation *const seg = &cm->seg;
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char *const seg_map = cpi->segmentation_map;
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int apply_cyclic_refresh  = apply_cyclic_refresh_bitrate(cm, rc);
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan  // Don't apply refresh on key frame or enhancement layer frames.
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!apply_cyclic_refresh ||
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (cm->frame_type == KEY_FRAME) ||
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan      (cpi->svc.temporal_layer_id > 0)) {
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Set segmentation map to 0 and disable.
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_disable_segmentation(&cm->seg);
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cm->frame_type == KEY_FRAME)
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cr->sb_index = 0;
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int qindex_delta = 0;
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame;
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int xmis, ymis, x, y, qindex2;
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Rate target ratio to set q delta.
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const float rate_ratio_qdelta = 2.0;
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_clear_system_state();
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Some of these parameters may be set via codec-control function later.
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->max_sbs_perframe = 10;
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->max_qdelta_perc = 50;
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->min_block_size = BLOCK_8X8;
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->time_for_refresh = 1;
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Set rate threshold to some fraction of target (and scaled by 256).
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->thresh_rate_sb = (rc->sb64_target_rate * 256) >> 2;
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Distortion threshold, quadratic in Q, scale factor to be adjusted.
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->thresh_dist_sb = 8 * (int)(vp9_convert_qindex_to_q(cm->base_qindex) *
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vp9_convert_qindex_to_q(cm->base_qindex));
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (cpi->sf.use_nonrd_pick_mode) {
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // May want to be more conservative with thresholds in non-rd mode for now
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // as rate/distortion are derived from model based on prediction residual.
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cr->thresh_rate_sb = (rc->sb64_target_rate * 256) >> 3;
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cr->thresh_dist_sb = 4 * (int)(vp9_convert_qindex_to_q(cm->base_qindex) *
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan          vp9_convert_qindex_to_q(cm->base_qindex));
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->num_seg_blocks = 0;
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Set up segmentation.
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Clear down the segment map.
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_enable_segmentation(&cm->seg);
227233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_clearall_segfeatures(seg);
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Select delta coding method.
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan    seg->abs_delta = SEGMENT_DELTADATA;
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Note: setting temporal_update has no effect, as the seg-map coding method
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // (temporal or spatial) is determined in vp9_choose_segmap_coding_method(),
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // based on the coding cost of each method. For error_resilient mode on the
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // last_frame_seg_map is set to 0, so if temporal coding is used, it is
235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // relative to 0 previous map.
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // seg->temporal_update = 0;
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Segment 0 "Q" feature is disabled so it defaults to the baseline Q.
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_disable_segfeature(seg, 0, SEG_LVL_ALT_Q);
240233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Use segment 1 for in-frame Q adjustment.
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_enable_segfeature(seg, 1, SEG_LVL_ALT_Q);
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Set the q delta for segment 1.
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan    qindex_delta = vp9_compute_qdelta_by_rate(cpi,
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              cm->base_qindex,
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                              rate_ratio_qdelta);
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // TODO(marpan): Incorporate the actual-vs-target rate over/undershoot from
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // previous encoded frame.
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (-qindex_delta > cr->max_qdelta_perc * cm->base_qindex / 100)
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan      qindex_delta = -cr->max_qdelta_perc * cm->base_qindex / 100;
251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Compute rd-mult for segment 1.
253233d2500723e5594f3e7c70896ffeeef32b9c950ywan    qindex2 = clamp(cm->base_qindex + cm->y_dc_delta_q + qindex_delta, 0, MAXQ);
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->rdmult = vp9_compute_rd_mult(cpi, qindex2);
255233d2500723e5594f3e7c70896ffeeef32b9c950ywan
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vp9_set_segdata(seg, 1, SEG_LVL_ALT_Q, qindex_delta);
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan
258233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sb_cols = (cm->mi_cols + MI_BLOCK_SIZE - 1) / MI_BLOCK_SIZE;
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sb_rows = (cm->mi_rows + MI_BLOCK_SIZE - 1) / MI_BLOCK_SIZE;
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sbs_in_frame = sb_cols * sb_rows;
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Number of target superblocks to get the q delta (segment 1).
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan    block_count = cr->max_sbs_perframe * sbs_in_frame / 100;
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // Set the segmentation map: cycle through the superblocks, starting at
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // cr->mb_index, and stopping when either block_count blocks have been found
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan    // to be refreshed, or we have passed through whole frame.
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(cr->sb_index < sbs_in_frame);
267233d2500723e5594f3e7c70896ffeeef32b9c950ywan    i = cr->sb_index;
268233d2500723e5594f3e7c70896ffeeef32b9c950ywan    do {
269233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int sum_map = 0;
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Get the mi_row/mi_col corresponding to superblock index i.
271233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int sb_row_index = (i / sb_cols);
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int sb_col_index = i - sb_row_index * sb_cols;
273233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int mi_row = sb_row_index * MI_BLOCK_SIZE;
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan      int mi_col = sb_col_index * MI_BLOCK_SIZE;
275233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(mi_row >= 0 && mi_row < cm->mi_rows);
276233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(mi_col >= 0 && mi_col < cm->mi_cols);
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan      bl_index = mi_row * cm->mi_cols + mi_col;
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Loop through all 8x8 blocks in superblock and update map.
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan      xmis = MIN(cm->mi_cols - mi_col,
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 num_8x8_blocks_wide_lookup[BLOCK_64X64]);
281233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ymis = MIN(cm->mi_rows - mi_row,
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan                 num_8x8_blocks_high_lookup[BLOCK_64X64]);
283233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (y = 0; y < ymis; y++) {
284233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (x = 0; x < xmis; x++) {
285233d2500723e5594f3e7c70896ffeeef32b9c950ywan          const int bl_index2 = bl_index + y * cm->mi_cols + x;
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // If the block is as a candidate for clean up then mark it
287233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // for possible boost/refresh (segment 1). The segment id may get
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan          // reset to 0 later if block gets coded anything other than ZEROMV.
289233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (cr->map[bl_index2] == 0) {
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan            seg_map[bl_index2] = 1;
291233d2500723e5594f3e7c70896ffeeef32b9c950ywan            sum_map++;
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan          } else if (cr->map[bl_index2] < 0) {
293233d2500723e5594f3e7c70896ffeeef32b9c950ywan            cr->map[bl_index2]++;
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
296233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // Enforce constant segment over superblock.
298233d2500723e5594f3e7c70896ffeeef32b9c950ywan      // If segment is partial over superblock, reset to either all 1 or 0.
299233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (sum_map > 0 && sum_map < xmis * ymis) {
300233d2500723e5594f3e7c70896ffeeef32b9c950ywan        const int new_value = (sum_map >= xmis * ymis / 2);
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan        for (y = 0; y < ymis; y++)
302233d2500723e5594f3e7c70896ffeeef32b9c950ywan          for (x = 0; x < xmis; x++)
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan            seg_map[bl_index + y * cm->mi_cols + x] = new_value;
304233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan      i++;
306233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (i == sbs_in_frame) {
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan        i = 0;
308233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (sum_map >= xmis * ymis /2)
310233d2500723e5594f3e7c70896ffeeef32b9c950ywan        block_count--;
311233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } while (block_count && i != cr->sb_index);
312233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cr->sb_index = i;
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
314233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan
316233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp9_cyclic_refresh_set_rate_and_dist_sb(CYCLIC_REFRESH *cr,
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                             int64_t rate_sb, int64_t dist_sb) {
318233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cr->projected_rate_sb = rate_sb;
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cr->projected_dist_sb = dist_sb;
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan
322233d2500723e5594f3e7c70896ffeeef32b9c950ywanint vp9_cyclic_refresh_get_rdmult(const CYCLIC_REFRESH *cr) {
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return cr->rdmult;
324233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
325