1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #include <limits.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
13*fb1b10abSAndroid Build Coastguard Worker
14*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/system_state.h"
16*fb1b10abSAndroid Build Coastguard Worker
17*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_aq_cyclicrefresh.h"
18*fb1b10abSAndroid Build Coastguard Worker
19*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_seg_common.h"
20*fb1b10abSAndroid Build Coastguard Worker
21*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_ratectrl.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_segmentation.h"
23*fb1b10abSAndroid Build Coastguard Worker
24*fb1b10abSAndroid Build Coastguard Worker static const uint8_t VP9_VAR_OFFS[64] = {
25*fb1b10abSAndroid Build Coastguard Worker 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
26*fb1b10abSAndroid Build Coastguard Worker 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
27*fb1b10abSAndroid Build Coastguard Worker 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
28*fb1b10abSAndroid Build Coastguard Worker 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
29*fb1b10abSAndroid Build Coastguard Worker 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
30*fb1b10abSAndroid Build Coastguard Worker };
31*fb1b10abSAndroid Build Coastguard Worker
vp9_cyclic_refresh_alloc(int mi_rows,int mi_cols)32*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) {
33*fb1b10abSAndroid Build Coastguard Worker size_t last_coded_q_map_size;
34*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = vpx_calloc(1, sizeof(*cr));
35*fb1b10abSAndroid Build Coastguard Worker if (cr == NULL) return NULL;
36*fb1b10abSAndroid Build Coastguard Worker
37*fb1b10abSAndroid Build Coastguard Worker cr->map = vpx_calloc(mi_rows * mi_cols, sizeof(*cr->map));
38*fb1b10abSAndroid Build Coastguard Worker if (cr->map == NULL) {
39*fb1b10abSAndroid Build Coastguard Worker vp9_cyclic_refresh_free(cr);
40*fb1b10abSAndroid Build Coastguard Worker return NULL;
41*fb1b10abSAndroid Build Coastguard Worker }
42*fb1b10abSAndroid Build Coastguard Worker last_coded_q_map_size = mi_rows * mi_cols * sizeof(*cr->last_coded_q_map);
43*fb1b10abSAndroid Build Coastguard Worker cr->last_coded_q_map = vpx_malloc(last_coded_q_map_size);
44*fb1b10abSAndroid Build Coastguard Worker if (cr->last_coded_q_map == NULL) {
45*fb1b10abSAndroid Build Coastguard Worker vp9_cyclic_refresh_free(cr);
46*fb1b10abSAndroid Build Coastguard Worker return NULL;
47*fb1b10abSAndroid Build Coastguard Worker }
48*fb1b10abSAndroid Build Coastguard Worker assert(MAXQ <= 255);
49*fb1b10abSAndroid Build Coastguard Worker memset(cr->last_coded_q_map, MAXQ, last_coded_q_map_size);
50*fb1b10abSAndroid Build Coastguard Worker cr->counter_encode_maxq_scene_change = 0;
51*fb1b10abSAndroid Build Coastguard Worker cr->content_mode = 1;
52*fb1b10abSAndroid Build Coastguard Worker return cr;
53*fb1b10abSAndroid Build Coastguard Worker }
54*fb1b10abSAndroid Build Coastguard Worker
vp9_cyclic_refresh_free(CYCLIC_REFRESH * cr)55*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_free(CYCLIC_REFRESH *cr) {
56*fb1b10abSAndroid Build Coastguard Worker if (cr != NULL) {
57*fb1b10abSAndroid Build Coastguard Worker vpx_free(cr->map);
58*fb1b10abSAndroid Build Coastguard Worker vpx_free(cr->last_coded_q_map);
59*fb1b10abSAndroid Build Coastguard Worker vpx_free(cr);
60*fb1b10abSAndroid Build Coastguard Worker }
61*fb1b10abSAndroid Build Coastguard Worker }
62*fb1b10abSAndroid Build Coastguard Worker
63*fb1b10abSAndroid Build Coastguard Worker // Check if this coding block, of size bsize, should be considered for refresh
64*fb1b10abSAndroid Build Coastguard Worker // (lower-qp coding). Decision can be based on various factors, such as
65*fb1b10abSAndroid Build Coastguard Worker // size of the coding block (i.e., below min_block size rejected), coding
66*fb1b10abSAndroid Build Coastguard Worker // mode, and rate/distortion.
candidate_refresh_aq(const CYCLIC_REFRESH * cr,const MODE_INFO * mi,int64_t rate,int64_t dist,int bsize)67*fb1b10abSAndroid Build Coastguard Worker static int candidate_refresh_aq(const CYCLIC_REFRESH *cr, const MODE_INFO *mi,
68*fb1b10abSAndroid Build Coastguard Worker int64_t rate, int64_t dist, int bsize) {
69*fb1b10abSAndroid Build Coastguard Worker MV mv = mi->mv[0].as_mv;
70*fb1b10abSAndroid Build Coastguard Worker // Reject the block for lower-qp coding if projected distortion
71*fb1b10abSAndroid Build Coastguard Worker // is above the threshold, and any of the following is true:
72*fb1b10abSAndroid Build Coastguard Worker // 1) mode uses large mv
73*fb1b10abSAndroid Build Coastguard Worker // 2) mode is an intra-mode
74*fb1b10abSAndroid Build Coastguard Worker // Otherwise accept for refresh.
75*fb1b10abSAndroid Build Coastguard Worker if (dist > cr->thresh_dist_sb &&
76*fb1b10abSAndroid Build Coastguard Worker (mv.row > cr->motion_thresh || mv.row < -cr->motion_thresh ||
77*fb1b10abSAndroid Build Coastguard Worker mv.col > cr->motion_thresh || mv.col < -cr->motion_thresh ||
78*fb1b10abSAndroid Build Coastguard Worker !is_inter_block(mi)))
79*fb1b10abSAndroid Build Coastguard Worker return CR_SEGMENT_ID_BASE;
80*fb1b10abSAndroid Build Coastguard Worker else if (bsize >= BLOCK_16X16 && rate < cr->thresh_rate_sb &&
81*fb1b10abSAndroid Build Coastguard Worker is_inter_block(mi) && mi->mv[0].as_int == 0 &&
82*fb1b10abSAndroid Build Coastguard Worker cr->rate_boost_fac > 10)
83*fb1b10abSAndroid Build Coastguard Worker // More aggressive delta-q for bigger blocks with zero motion.
84*fb1b10abSAndroid Build Coastguard Worker return CR_SEGMENT_ID_BOOST2;
85*fb1b10abSAndroid Build Coastguard Worker else
86*fb1b10abSAndroid Build Coastguard Worker return CR_SEGMENT_ID_BOOST1;
87*fb1b10abSAndroid Build Coastguard Worker }
88*fb1b10abSAndroid Build Coastguard Worker
89*fb1b10abSAndroid Build Coastguard Worker // Compute delta-q for the segment.
compute_deltaq(const VP9_COMP * cpi,int q,double rate_factor)90*fb1b10abSAndroid Build Coastguard Worker static int compute_deltaq(const VP9_COMP *cpi, int q, double rate_factor) {
91*fb1b10abSAndroid Build Coastguard Worker const CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
92*fb1b10abSAndroid Build Coastguard Worker const RATE_CONTROL *const rc = &cpi->rc;
93*fb1b10abSAndroid Build Coastguard Worker int deltaq = vp9_compute_qdelta_by_rate(rc, cpi->common.frame_type, q,
94*fb1b10abSAndroid Build Coastguard Worker rate_factor, cpi->common.bit_depth);
95*fb1b10abSAndroid Build Coastguard Worker if ((-deltaq) > cr->max_qdelta_perc * q / 100) {
96*fb1b10abSAndroid Build Coastguard Worker deltaq = -cr->max_qdelta_perc * q / 100;
97*fb1b10abSAndroid Build Coastguard Worker }
98*fb1b10abSAndroid Build Coastguard Worker return deltaq;
99*fb1b10abSAndroid Build Coastguard Worker }
100*fb1b10abSAndroid Build Coastguard Worker
101*fb1b10abSAndroid Build Coastguard Worker // For the just encoded frame, estimate the bits, incorporating the delta-q
102*fb1b10abSAndroid Build Coastguard Worker // from non-base segment. For now ignore effect of multiple segments
103*fb1b10abSAndroid Build Coastguard Worker // (with different delta-q). Note this function is called in the postencode
104*fb1b10abSAndroid Build Coastguard Worker // (called from rc_update_rate_correction_factors()).
vp9_cyclic_refresh_estimate_bits_at_q(const VP9_COMP * cpi,double correction_factor)105*fb1b10abSAndroid Build Coastguard Worker int vp9_cyclic_refresh_estimate_bits_at_q(const VP9_COMP *cpi,
106*fb1b10abSAndroid Build Coastguard Worker double correction_factor) {
107*fb1b10abSAndroid Build Coastguard Worker const VP9_COMMON *const cm = &cpi->common;
108*fb1b10abSAndroid Build Coastguard Worker const CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
109*fb1b10abSAndroid Build Coastguard Worker int estimated_bits;
110*fb1b10abSAndroid Build Coastguard Worker int mbs = cm->MBs;
111*fb1b10abSAndroid Build Coastguard Worker int num8x8bl = mbs << 2;
112*fb1b10abSAndroid Build Coastguard Worker // Weight for non-base segments: use actual number of blocks refreshed in
113*fb1b10abSAndroid Build Coastguard Worker // previous/just encoded frame. Note number of blocks here is in 8x8 units.
114*fb1b10abSAndroid Build Coastguard Worker double weight_segment1 = (double)cr->actual_num_seg1_blocks / num8x8bl;
115*fb1b10abSAndroid Build Coastguard Worker double weight_segment2 = (double)cr->actual_num_seg2_blocks / num8x8bl;
116*fb1b10abSAndroid Build Coastguard Worker // Take segment weighted average for estimated bits.
117*fb1b10abSAndroid Build Coastguard Worker estimated_bits = (int)round(
118*fb1b10abSAndroid Build Coastguard Worker (1.0 - weight_segment1 - weight_segment2) *
119*fb1b10abSAndroid Build Coastguard Worker vp9_estimate_bits_at_q(cm->frame_type, cm->base_qindex, mbs,
120*fb1b10abSAndroid Build Coastguard Worker correction_factor, cm->bit_depth) +
121*fb1b10abSAndroid Build Coastguard Worker weight_segment1 *
122*fb1b10abSAndroid Build Coastguard Worker vp9_estimate_bits_at_q(cm->frame_type,
123*fb1b10abSAndroid Build Coastguard Worker cm->base_qindex + cr->qindex_delta[1], mbs,
124*fb1b10abSAndroid Build Coastguard Worker correction_factor, cm->bit_depth) +
125*fb1b10abSAndroid Build Coastguard Worker weight_segment2 *
126*fb1b10abSAndroid Build Coastguard Worker vp9_estimate_bits_at_q(cm->frame_type,
127*fb1b10abSAndroid Build Coastguard Worker cm->base_qindex + cr->qindex_delta[2], mbs,
128*fb1b10abSAndroid Build Coastguard Worker correction_factor, cm->bit_depth));
129*fb1b10abSAndroid Build Coastguard Worker return estimated_bits;
130*fb1b10abSAndroid Build Coastguard Worker }
131*fb1b10abSAndroid Build Coastguard Worker
132*fb1b10abSAndroid Build Coastguard Worker // Prior to encoding the frame, estimate the bits per mb, for a given q = i and
133*fb1b10abSAndroid Build Coastguard Worker // a corresponding delta-q (for segment 1). This function is called in the
134*fb1b10abSAndroid Build Coastguard Worker // rc_regulate_q() to set the base qp index.
135*fb1b10abSAndroid Build Coastguard Worker // Note: the segment map is set to either 0/CR_SEGMENT_ID_BASE (no refresh) or
136*fb1b10abSAndroid Build Coastguard Worker // to 1/CR_SEGMENT_ID_BOOST1 (refresh) for each superblock, prior to encoding.
vp9_cyclic_refresh_rc_bits_per_mb(const VP9_COMP * cpi,int i,double correction_factor)137*fb1b10abSAndroid Build Coastguard Worker int vp9_cyclic_refresh_rc_bits_per_mb(const VP9_COMP *cpi, int i,
138*fb1b10abSAndroid Build Coastguard Worker double correction_factor) {
139*fb1b10abSAndroid Build Coastguard Worker const VP9_COMMON *const cm = &cpi->common;
140*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
141*fb1b10abSAndroid Build Coastguard Worker int bits_per_mb;
142*fb1b10abSAndroid Build Coastguard Worker int deltaq = 0;
143*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.speed < 8)
144*fb1b10abSAndroid Build Coastguard Worker deltaq = compute_deltaq(cpi, i, cr->rate_ratio_qdelta);
145*fb1b10abSAndroid Build Coastguard Worker else
146*fb1b10abSAndroid Build Coastguard Worker deltaq = -(cr->max_qdelta_perc * i) / 200;
147*fb1b10abSAndroid Build Coastguard Worker // Take segment weighted average for bits per mb.
148*fb1b10abSAndroid Build Coastguard Worker bits_per_mb =
149*fb1b10abSAndroid Build Coastguard Worker (int)round((1.0 - cr->weight_segment) *
150*fb1b10abSAndroid Build Coastguard Worker vp9_rc_bits_per_mb(cm->frame_type, i, correction_factor,
151*fb1b10abSAndroid Build Coastguard Worker cm->bit_depth) +
152*fb1b10abSAndroid Build Coastguard Worker cr->weight_segment *
153*fb1b10abSAndroid Build Coastguard Worker vp9_rc_bits_per_mb(cm->frame_type, i + deltaq,
154*fb1b10abSAndroid Build Coastguard Worker correction_factor, cm->bit_depth));
155*fb1b10abSAndroid Build Coastguard Worker return bits_per_mb;
156*fb1b10abSAndroid Build Coastguard Worker }
157*fb1b10abSAndroid Build Coastguard Worker
158*fb1b10abSAndroid Build Coastguard Worker // Prior to coding a given prediction block, of size bsize at (mi_row, mi_col),
159*fb1b10abSAndroid Build Coastguard Worker // check if we should reset the segment_id, and update the cyclic_refresh map
160*fb1b10abSAndroid Build Coastguard Worker // and segmentation map.
vp9_cyclic_refresh_update_segment(VP9_COMP * const cpi,MODE_INFO * const mi,int mi_row,int mi_col,BLOCK_SIZE bsize,int64_t rate,int64_t dist,int skip,struct macroblock_plane * const p)161*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, MODE_INFO *const mi,
162*fb1b10abSAndroid Build Coastguard Worker int mi_row, int mi_col, BLOCK_SIZE bsize,
163*fb1b10abSAndroid Build Coastguard Worker int64_t rate, int64_t dist, int skip,
164*fb1b10abSAndroid Build Coastguard Worker struct macroblock_plane *const p) {
165*fb1b10abSAndroid Build Coastguard Worker const VP9_COMMON *const cm = &cpi->common;
166*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
167*fb1b10abSAndroid Build Coastguard Worker const int bw = num_8x8_blocks_wide_lookup[bsize];
168*fb1b10abSAndroid Build Coastguard Worker const int bh = num_8x8_blocks_high_lookup[bsize];
169*fb1b10abSAndroid Build Coastguard Worker const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
170*fb1b10abSAndroid Build Coastguard Worker const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
171*fb1b10abSAndroid Build Coastguard Worker const int block_index = mi_row * cm->mi_cols + mi_col;
172*fb1b10abSAndroid Build Coastguard Worker int refresh_this_block = candidate_refresh_aq(cr, mi, rate, dist, bsize);
173*fb1b10abSAndroid Build Coastguard Worker // Default is to not update the refresh map.
174*fb1b10abSAndroid Build Coastguard Worker int new_map_value = cr->map[block_index];
175*fb1b10abSAndroid Build Coastguard Worker int x = 0;
176*fb1b10abSAndroid Build Coastguard Worker int y = 0;
177*fb1b10abSAndroid Build Coastguard Worker
178*fb1b10abSAndroid Build Coastguard Worker int is_skin = 0;
179*fb1b10abSAndroid Build Coastguard Worker if (refresh_this_block == 0 && bsize <= BLOCK_16X16 &&
180*fb1b10abSAndroid Build Coastguard Worker cpi->use_skin_detection) {
181*fb1b10abSAndroid Build Coastguard Worker is_skin =
182*fb1b10abSAndroid Build Coastguard Worker vp9_compute_skin_block(p[0].src.buf, p[1].src.buf, p[2].src.buf,
183*fb1b10abSAndroid Build Coastguard Worker p[0].src.stride, p[1].src.stride, bsize, 0, 0);
184*fb1b10abSAndroid Build Coastguard Worker if (is_skin) refresh_this_block = 1;
185*fb1b10abSAndroid Build Coastguard Worker }
186*fb1b10abSAndroid Build Coastguard Worker
187*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.rc_mode == VPX_VBR && mi->ref_frame[0] == GOLDEN_FRAME)
188*fb1b10abSAndroid Build Coastguard Worker refresh_this_block = 0;
189*fb1b10abSAndroid Build Coastguard Worker
190*fb1b10abSAndroid Build Coastguard Worker // If this block is labeled for refresh, check if we should reset the
191*fb1b10abSAndroid Build Coastguard Worker // segment_id.
192*fb1b10abSAndroid Build Coastguard Worker if (cpi->sf.use_nonrd_pick_mode &&
193*fb1b10abSAndroid Build Coastguard Worker cyclic_refresh_segment_id_boosted(mi->segment_id)) {
194*fb1b10abSAndroid Build Coastguard Worker mi->segment_id = refresh_this_block;
195*fb1b10abSAndroid Build Coastguard Worker // Reset segment_id if it will be skipped.
196*fb1b10abSAndroid Build Coastguard Worker if (skip) mi->segment_id = CR_SEGMENT_ID_BASE;
197*fb1b10abSAndroid Build Coastguard Worker }
198*fb1b10abSAndroid Build Coastguard Worker
199*fb1b10abSAndroid Build Coastguard Worker // Update the cyclic refresh map, to be used for setting segmentation map
200*fb1b10abSAndroid Build Coastguard Worker // for the next frame. If the block will be refreshed this frame, mark it
201*fb1b10abSAndroid Build Coastguard Worker // as clean. The magnitude of the -ve influences how long before we consider
202*fb1b10abSAndroid Build Coastguard Worker // it for refresh again.
203*fb1b10abSAndroid Build Coastguard Worker if (cyclic_refresh_segment_id_boosted(mi->segment_id)) {
204*fb1b10abSAndroid Build Coastguard Worker new_map_value = -cr->time_for_refresh;
205*fb1b10abSAndroid Build Coastguard Worker } else if (refresh_this_block) {
206*fb1b10abSAndroid Build Coastguard Worker // Else if it is accepted as candidate for refresh, and has not already
207*fb1b10abSAndroid Build Coastguard Worker // been refreshed (marked as 1) then mark it as a candidate for cleanup
208*fb1b10abSAndroid Build Coastguard Worker // for future time (marked as 0), otherwise don't update it.
209*fb1b10abSAndroid Build Coastguard Worker if (cr->map[block_index] == 1) new_map_value = 0;
210*fb1b10abSAndroid Build Coastguard Worker } else {
211*fb1b10abSAndroid Build Coastguard Worker // Leave it marked as block that is not candidate for refresh.
212*fb1b10abSAndroid Build Coastguard Worker new_map_value = 1;
213*fb1b10abSAndroid Build Coastguard Worker }
214*fb1b10abSAndroid Build Coastguard Worker
215*fb1b10abSAndroid Build Coastguard Worker // Update entries in the cyclic refresh map with new_map_value, and
216*fb1b10abSAndroid Build Coastguard Worker // copy mbmi->segment_id into global segmentation map.
217*fb1b10abSAndroid Build Coastguard Worker for (y = 0; y < ymis; y++)
218*fb1b10abSAndroid Build Coastguard Worker for (x = 0; x < xmis; x++) {
219*fb1b10abSAndroid Build Coastguard Worker int map_offset = block_index + y * cm->mi_cols + x;
220*fb1b10abSAndroid Build Coastguard Worker cr->map[map_offset] = new_map_value;
221*fb1b10abSAndroid Build Coastguard Worker cpi->segmentation_map[map_offset] = mi->segment_id;
222*fb1b10abSAndroid Build Coastguard Worker }
223*fb1b10abSAndroid Build Coastguard Worker }
224*fb1b10abSAndroid Build Coastguard Worker
vp9_cyclic_refresh_update_sb_postencode(VP9_COMP * const cpi,const MODE_INFO * const mi,int mi_row,int mi_col,BLOCK_SIZE bsize)225*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_update_sb_postencode(VP9_COMP *const cpi,
226*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const mi,
227*fb1b10abSAndroid Build Coastguard Worker int mi_row, int mi_col,
228*fb1b10abSAndroid Build Coastguard Worker BLOCK_SIZE bsize) {
229*fb1b10abSAndroid Build Coastguard Worker const VP9_COMMON *const cm = &cpi->common;
230*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
231*fb1b10abSAndroid Build Coastguard Worker const int bw = num_8x8_blocks_wide_lookup[bsize];
232*fb1b10abSAndroid Build Coastguard Worker const int bh = num_8x8_blocks_high_lookup[bsize];
233*fb1b10abSAndroid Build Coastguard Worker const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
234*fb1b10abSAndroid Build Coastguard Worker const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
235*fb1b10abSAndroid Build Coastguard Worker const int block_index = mi_row * cm->mi_cols + mi_col;
236*fb1b10abSAndroid Build Coastguard Worker int x, y;
237*fb1b10abSAndroid Build Coastguard Worker for (y = 0; y < ymis; y++)
238*fb1b10abSAndroid Build Coastguard Worker for (x = 0; x < xmis; x++) {
239*fb1b10abSAndroid Build Coastguard Worker int map_offset = block_index + y * cm->mi_cols + x;
240*fb1b10abSAndroid Build Coastguard Worker // Inter skip blocks were clearly not coded at the current qindex, so
241*fb1b10abSAndroid Build Coastguard Worker // don't update the map for them. For cases where motion is non-zero or
242*fb1b10abSAndroid Build Coastguard Worker // the reference frame isn't the previous frame, the previous value in
243*fb1b10abSAndroid Build Coastguard Worker // the map for this spatial location is not entirely correct.
244*fb1b10abSAndroid Build Coastguard Worker if ((!is_inter_block(mi) || !mi->skip) &&
245*fb1b10abSAndroid Build Coastguard Worker mi->segment_id <= CR_SEGMENT_ID_BOOST2) {
246*fb1b10abSAndroid Build Coastguard Worker cr->last_coded_q_map[map_offset] =
247*fb1b10abSAndroid Build Coastguard Worker clamp(cm->base_qindex + cr->qindex_delta[mi->segment_id], 0, MAXQ);
248*fb1b10abSAndroid Build Coastguard Worker } else if (is_inter_block(mi) && mi->skip &&
249*fb1b10abSAndroid Build Coastguard Worker mi->segment_id <= CR_SEGMENT_ID_BOOST2) {
250*fb1b10abSAndroid Build Coastguard Worker cr->last_coded_q_map[map_offset] = VPXMIN(
251*fb1b10abSAndroid Build Coastguard Worker clamp(cm->base_qindex + cr->qindex_delta[mi->segment_id], 0, MAXQ),
252*fb1b10abSAndroid Build Coastguard Worker cr->last_coded_q_map[map_offset]);
253*fb1b10abSAndroid Build Coastguard Worker }
254*fb1b10abSAndroid Build Coastguard Worker }
255*fb1b10abSAndroid Build Coastguard Worker }
256*fb1b10abSAndroid Build Coastguard Worker
257*fb1b10abSAndroid Build Coastguard Worker // From the just encoded frame: update the actual number of blocks that were
258*fb1b10abSAndroid Build Coastguard Worker // applied the segment delta q, and the amount of low motion in the frame.
259*fb1b10abSAndroid Build Coastguard Worker // Also check conditions for forcing golden update, or preventing golden
260*fb1b10abSAndroid Build Coastguard Worker // update if the period is up.
vp9_cyclic_refresh_postencode(VP9_COMP * const cpi)261*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_postencode(VP9_COMP *const cpi) {
262*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *const cm = &cpi->common;
263*fb1b10abSAndroid Build Coastguard Worker MODE_INFO **mi = cm->mi_grid_visible;
264*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
265*fb1b10abSAndroid Build Coastguard Worker RATE_CONTROL *const rc = &cpi->rc;
266*fb1b10abSAndroid Build Coastguard Worker unsigned char *const seg_map = cpi->segmentation_map;
267*fb1b10abSAndroid Build Coastguard Worker double fraction_low = 0.0;
268*fb1b10abSAndroid Build Coastguard Worker int force_gf_refresh = 0;
269*fb1b10abSAndroid Build Coastguard Worker int low_content_frame = 0;
270*fb1b10abSAndroid Build Coastguard Worker int mi_row, mi_col;
271*fb1b10abSAndroid Build Coastguard Worker cr->actual_num_seg1_blocks = 0;
272*fb1b10abSAndroid Build Coastguard Worker cr->actual_num_seg2_blocks = 0;
273*fb1b10abSAndroid Build Coastguard Worker for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) {
274*fb1b10abSAndroid Build Coastguard Worker for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) {
275*fb1b10abSAndroid Build Coastguard Worker MV mv = mi[0]->mv[0].as_mv;
276*fb1b10abSAndroid Build Coastguard Worker int map_index = mi_row * cm->mi_cols + mi_col;
277*fb1b10abSAndroid Build Coastguard Worker if (cyclic_refresh_segment_id(seg_map[map_index]) == CR_SEGMENT_ID_BOOST1)
278*fb1b10abSAndroid Build Coastguard Worker cr->actual_num_seg1_blocks++;
279*fb1b10abSAndroid Build Coastguard Worker else if (cyclic_refresh_segment_id(seg_map[map_index]) ==
280*fb1b10abSAndroid Build Coastguard Worker CR_SEGMENT_ID_BOOST2)
281*fb1b10abSAndroid Build Coastguard Worker cr->actual_num_seg2_blocks++;
282*fb1b10abSAndroid Build Coastguard Worker // Accumulate low_content_frame.
283*fb1b10abSAndroid Build Coastguard Worker if (is_inter_block(mi[0]) && abs(mv.row) < 16 && abs(mv.col) < 16)
284*fb1b10abSAndroid Build Coastguard Worker low_content_frame++;
285*fb1b10abSAndroid Build Coastguard Worker mi++;
286*fb1b10abSAndroid Build Coastguard Worker }
287*fb1b10abSAndroid Build Coastguard Worker mi += 8;
288*fb1b10abSAndroid Build Coastguard Worker }
289*fb1b10abSAndroid Build Coastguard Worker // Check for golden frame update: only for non-SVC and non-golden boost.
290*fb1b10abSAndroid Build Coastguard Worker if (!cpi->use_svc && cpi->ext_refresh_frame_flags_pending == 0 &&
291*fb1b10abSAndroid Build Coastguard Worker !cpi->oxcf.gf_cbr_boost_pct) {
292*fb1b10abSAndroid Build Coastguard Worker // Force this frame as a golden update frame if this frame changes the
293*fb1b10abSAndroid Build Coastguard Worker // resolution (resize_pending != 0).
294*fb1b10abSAndroid Build Coastguard Worker if (cpi->resize_pending != 0) {
295*fb1b10abSAndroid Build Coastguard Worker vp9_cyclic_refresh_set_golden_update(cpi);
296*fb1b10abSAndroid Build Coastguard Worker rc->frames_till_gf_update_due = rc->baseline_gf_interval;
297*fb1b10abSAndroid Build Coastguard Worker if (rc->frames_till_gf_update_due > rc->frames_to_key)
298*fb1b10abSAndroid Build Coastguard Worker rc->frames_till_gf_update_due = rc->frames_to_key;
299*fb1b10abSAndroid Build Coastguard Worker cpi->refresh_golden_frame = 1;
300*fb1b10abSAndroid Build Coastguard Worker force_gf_refresh = 1;
301*fb1b10abSAndroid Build Coastguard Worker }
302*fb1b10abSAndroid Build Coastguard Worker // Update average of low content/motion in the frame.
303*fb1b10abSAndroid Build Coastguard Worker fraction_low = (double)low_content_frame / (cm->mi_rows * cm->mi_cols);
304*fb1b10abSAndroid Build Coastguard Worker cr->low_content_avg = (fraction_low + 3 * cr->low_content_avg) / 4;
305*fb1b10abSAndroid Build Coastguard Worker if (!force_gf_refresh && cpi->refresh_golden_frame == 1 &&
306*fb1b10abSAndroid Build Coastguard Worker rc->frames_since_key > rc->frames_since_golden + 1) {
307*fb1b10abSAndroid Build Coastguard Worker // Don't update golden reference if the amount of low_content for the
308*fb1b10abSAndroid Build Coastguard Worker // current encoded frame is small, or if the recursive average of the
309*fb1b10abSAndroid Build Coastguard Worker // low_content over the update interval window falls below threshold.
310*fb1b10abSAndroid Build Coastguard Worker if (fraction_low < 0.65 || cr->low_content_avg < 0.6) {
311*fb1b10abSAndroid Build Coastguard Worker cpi->refresh_golden_frame = 0;
312*fb1b10abSAndroid Build Coastguard Worker }
313*fb1b10abSAndroid Build Coastguard Worker // Reset for next internal.
314*fb1b10abSAndroid Build Coastguard Worker cr->low_content_avg = fraction_low;
315*fb1b10abSAndroid Build Coastguard Worker }
316*fb1b10abSAndroid Build Coastguard Worker }
317*fb1b10abSAndroid Build Coastguard Worker }
318*fb1b10abSAndroid Build Coastguard Worker
319*fb1b10abSAndroid Build Coastguard Worker // Set golden frame update interval, for non-svc 1 pass CBR mode.
vp9_cyclic_refresh_set_golden_update(VP9_COMP * const cpi)320*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_set_golden_update(VP9_COMP *const cpi) {
321*fb1b10abSAndroid Build Coastguard Worker RATE_CONTROL *const rc = &cpi->rc;
322*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
323*fb1b10abSAndroid Build Coastguard Worker // Set minimum gf_interval for GF update to a multiple of the refresh period,
324*fb1b10abSAndroid Build Coastguard Worker // with some max limit. Depending on past encoding stats, GF flag may be
325*fb1b10abSAndroid Build Coastguard Worker // reset and update may not occur until next baseline_gf_interval.
326*fb1b10abSAndroid Build Coastguard Worker if (cr->percent_refresh > 0)
327*fb1b10abSAndroid Build Coastguard Worker rc->baseline_gf_interval = VPXMIN(4 * (100 / cr->percent_refresh), 40);
328*fb1b10abSAndroid Build Coastguard Worker else
329*fb1b10abSAndroid Build Coastguard Worker rc->baseline_gf_interval = 40;
330*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.rc_mode == VPX_VBR) rc->baseline_gf_interval = 20;
331*fb1b10abSAndroid Build Coastguard Worker if (rc->avg_frame_low_motion < 50 && rc->frames_since_key > 40 &&
332*fb1b10abSAndroid Build Coastguard Worker cr->content_mode)
333*fb1b10abSAndroid Build Coastguard Worker rc->baseline_gf_interval = 10;
334*fb1b10abSAndroid Build Coastguard Worker }
335*fb1b10abSAndroid Build Coastguard Worker
is_superblock_flat_static(VP9_COMP * const cpi,int sb_row_index,int sb_col_index)336*fb1b10abSAndroid Build Coastguard Worker static int is_superblock_flat_static(VP9_COMP *const cpi, int sb_row_index,
337*fb1b10abSAndroid Build Coastguard Worker int sb_col_index) {
338*fb1b10abSAndroid Build Coastguard Worker unsigned int source_variance;
339*fb1b10abSAndroid Build Coastguard Worker const uint8_t *src_y = cpi->Source->y_buffer;
340*fb1b10abSAndroid Build Coastguard Worker const int ystride = cpi->Source->y_stride;
341*fb1b10abSAndroid Build Coastguard Worker unsigned int sse;
342*fb1b10abSAndroid Build Coastguard Worker const BLOCK_SIZE bsize = BLOCK_64X64;
343*fb1b10abSAndroid Build Coastguard Worker src_y += (sb_row_index << 6) * ystride + (sb_col_index << 6);
344*fb1b10abSAndroid Build Coastguard Worker source_variance =
345*fb1b10abSAndroid Build Coastguard Worker cpi->fn_ptr[bsize].vf(src_y, ystride, VP9_VAR_OFFS, 0, &sse);
346*fb1b10abSAndroid Build Coastguard Worker if (source_variance == 0) {
347*fb1b10abSAndroid Build Coastguard Worker uint64_t block_sad;
348*fb1b10abSAndroid Build Coastguard Worker const uint8_t *last_src_y = cpi->Last_Source->y_buffer;
349*fb1b10abSAndroid Build Coastguard Worker const int last_ystride = cpi->Last_Source->y_stride;
350*fb1b10abSAndroid Build Coastguard Worker last_src_y += (sb_row_index << 6) * ystride + (sb_col_index << 6);
351*fb1b10abSAndroid Build Coastguard Worker block_sad =
352*fb1b10abSAndroid Build Coastguard Worker cpi->fn_ptr[bsize].sdf(src_y, ystride, last_src_y, last_ystride);
353*fb1b10abSAndroid Build Coastguard Worker if (block_sad == 0) return 1;
354*fb1b10abSAndroid Build Coastguard Worker }
355*fb1b10abSAndroid Build Coastguard Worker return 0;
356*fb1b10abSAndroid Build Coastguard Worker }
357*fb1b10abSAndroid Build Coastguard Worker
358*fb1b10abSAndroid Build Coastguard Worker // Update the segmentation map, and related quantities: cyclic refresh map,
359*fb1b10abSAndroid Build Coastguard Worker // refresh sb_index, and target number of blocks to be refreshed.
360*fb1b10abSAndroid Build Coastguard Worker // The map is set to either 0/CR_SEGMENT_ID_BASE (no refresh) or to
361*fb1b10abSAndroid Build Coastguard Worker // 1/CR_SEGMENT_ID_BOOST1 (refresh) for each superblock.
362*fb1b10abSAndroid Build Coastguard Worker // Blocks labeled as BOOST1 may later get set to BOOST2 (during the
363*fb1b10abSAndroid Build Coastguard Worker // encoding of the superblock).
cyclic_refresh_update_map(VP9_COMP * const cpi)364*fb1b10abSAndroid Build Coastguard Worker static void cyclic_refresh_update_map(VP9_COMP *const cpi) {
365*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *const cm = &cpi->common;
366*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
367*fb1b10abSAndroid Build Coastguard Worker unsigned char *const seg_map = cpi->segmentation_map;
368*fb1b10abSAndroid Build Coastguard Worker int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame;
369*fb1b10abSAndroid Build Coastguard Worker int xmis, ymis, x, y;
370*fb1b10abSAndroid Build Coastguard Worker int consec_zero_mv_thresh = 0;
371*fb1b10abSAndroid Build Coastguard Worker int qindex_thresh = 0;
372*fb1b10abSAndroid Build Coastguard Worker int count_sel = 0;
373*fb1b10abSAndroid Build Coastguard Worker int count_tot = 0;
374*fb1b10abSAndroid Build Coastguard Worker memset(seg_map, CR_SEGMENT_ID_BASE, cm->mi_rows * cm->mi_cols);
375*fb1b10abSAndroid Build Coastguard Worker sb_cols = (cm->mi_cols + MI_BLOCK_SIZE - 1) / MI_BLOCK_SIZE;
376*fb1b10abSAndroid Build Coastguard Worker sb_rows = (cm->mi_rows + MI_BLOCK_SIZE - 1) / MI_BLOCK_SIZE;
377*fb1b10abSAndroid Build Coastguard Worker sbs_in_frame = sb_cols * sb_rows;
378*fb1b10abSAndroid Build Coastguard Worker // Number of target blocks to get the q delta (segment 1).
379*fb1b10abSAndroid Build Coastguard Worker block_count = cr->percent_refresh * cm->mi_rows * cm->mi_cols / 100;
380*fb1b10abSAndroid Build Coastguard Worker // Set the segmentation map: cycle through the superblocks, starting at
381*fb1b10abSAndroid Build Coastguard Worker // cr->mb_index, and stopping when either block_count blocks have been found
382*fb1b10abSAndroid Build Coastguard Worker // to be refreshed, or we have passed through whole frame.
383*fb1b10abSAndroid Build Coastguard Worker assert(cr->sb_index < sbs_in_frame);
384*fb1b10abSAndroid Build Coastguard Worker i = cr->sb_index;
385*fb1b10abSAndroid Build Coastguard Worker cr->target_num_seg_blocks = 0;
386*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.content != VP9E_CONTENT_SCREEN) {
387*fb1b10abSAndroid Build Coastguard Worker consec_zero_mv_thresh = 100;
388*fb1b10abSAndroid Build Coastguard Worker }
389*fb1b10abSAndroid Build Coastguard Worker qindex_thresh =
390*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.content == VP9E_CONTENT_SCREEN
391*fb1b10abSAndroid Build Coastguard Worker ? vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST2, cm->base_qindex)
392*fb1b10abSAndroid Build Coastguard Worker : vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST1, cm->base_qindex);
393*fb1b10abSAndroid Build Coastguard Worker // More aggressive settings for noisy content.
394*fb1b10abSAndroid Build Coastguard Worker if (cpi->noise_estimate.enabled && cpi->noise_estimate.level >= kMedium &&
395*fb1b10abSAndroid Build Coastguard Worker cr->content_mode) {
396*fb1b10abSAndroid Build Coastguard Worker consec_zero_mv_thresh = 60;
397*fb1b10abSAndroid Build Coastguard Worker qindex_thresh =
398*fb1b10abSAndroid Build Coastguard Worker VPXMAX(vp9_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST1, cm->base_qindex),
399*fb1b10abSAndroid Build Coastguard Worker cm->base_qindex);
400*fb1b10abSAndroid Build Coastguard Worker }
401*fb1b10abSAndroid Build Coastguard Worker do {
402*fb1b10abSAndroid Build Coastguard Worker int sum_map = 0;
403*fb1b10abSAndroid Build Coastguard Worker int consec_zero_mv_thresh_block = consec_zero_mv_thresh;
404*fb1b10abSAndroid Build Coastguard Worker // Get the mi_row/mi_col corresponding to superblock index i.
405*fb1b10abSAndroid Build Coastguard Worker int sb_row_index = (i / sb_cols);
406*fb1b10abSAndroid Build Coastguard Worker int sb_col_index = i - sb_row_index * sb_cols;
407*fb1b10abSAndroid Build Coastguard Worker int mi_row = sb_row_index * MI_BLOCK_SIZE;
408*fb1b10abSAndroid Build Coastguard Worker int mi_col = sb_col_index * MI_BLOCK_SIZE;
409*fb1b10abSAndroid Build Coastguard Worker int flat_static_blocks = 0;
410*fb1b10abSAndroid Build Coastguard Worker int compute_content = 1;
411*fb1b10abSAndroid Build Coastguard Worker assert(mi_row >= 0 && mi_row < cm->mi_rows);
412*fb1b10abSAndroid Build Coastguard Worker assert(mi_col >= 0 && mi_col < cm->mi_cols);
413*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
414*fb1b10abSAndroid Build Coastguard Worker if (cpi->common.use_highbitdepth) compute_content = 0;
415*fb1b10abSAndroid Build Coastguard Worker #endif
416*fb1b10abSAndroid Build Coastguard Worker if (cr->content_mode == 0 || cpi->Last_Source == NULL ||
417*fb1b10abSAndroid Build Coastguard Worker cpi->Last_Source->y_width != cpi->Source->y_width ||
418*fb1b10abSAndroid Build Coastguard Worker cpi->Last_Source->y_height != cpi->Source->y_height)
419*fb1b10abSAndroid Build Coastguard Worker compute_content = 0;
420*fb1b10abSAndroid Build Coastguard Worker bl_index = mi_row * cm->mi_cols + mi_col;
421*fb1b10abSAndroid Build Coastguard Worker // Loop through all 8x8 blocks in superblock and update map.
422*fb1b10abSAndroid Build Coastguard Worker xmis =
423*fb1b10abSAndroid Build Coastguard Worker VPXMIN(cm->mi_cols - mi_col, num_8x8_blocks_wide_lookup[BLOCK_64X64]);
424*fb1b10abSAndroid Build Coastguard Worker ymis =
425*fb1b10abSAndroid Build Coastguard Worker VPXMIN(cm->mi_rows - mi_row, num_8x8_blocks_high_lookup[BLOCK_64X64]);
426*fb1b10abSAndroid Build Coastguard Worker if (cpi->noise_estimate.enabled && cpi->noise_estimate.level >= kMedium &&
427*fb1b10abSAndroid Build Coastguard Worker (xmis <= 2 || ymis <= 2))
428*fb1b10abSAndroid Build Coastguard Worker consec_zero_mv_thresh_block = 4;
429*fb1b10abSAndroid Build Coastguard Worker for (y = 0; y < ymis; y++) {
430*fb1b10abSAndroid Build Coastguard Worker for (x = 0; x < xmis; x++) {
431*fb1b10abSAndroid Build Coastguard Worker const int bl_index2 = bl_index + y * cm->mi_cols + x;
432*fb1b10abSAndroid Build Coastguard Worker // If the block is as a candidate for clean up then mark it
433*fb1b10abSAndroid Build Coastguard Worker // for possible boost/refresh (segment 1). The segment id may get
434*fb1b10abSAndroid Build Coastguard Worker // reset to 0 later depending on the coding mode.
435*fb1b10abSAndroid Build Coastguard Worker if (cr->map[bl_index2] == 0) {
436*fb1b10abSAndroid Build Coastguard Worker count_tot++;
437*fb1b10abSAndroid Build Coastguard Worker if (cr->content_mode == 0 ||
438*fb1b10abSAndroid Build Coastguard Worker cr->last_coded_q_map[bl_index2] > qindex_thresh ||
439*fb1b10abSAndroid Build Coastguard Worker cpi->consec_zero_mv[bl_index2] < consec_zero_mv_thresh_block) {
440*fb1b10abSAndroid Build Coastguard Worker sum_map++;
441*fb1b10abSAndroid Build Coastguard Worker count_sel++;
442*fb1b10abSAndroid Build Coastguard Worker }
443*fb1b10abSAndroid Build Coastguard Worker } else if (cr->map[bl_index2] < 0) {
444*fb1b10abSAndroid Build Coastguard Worker cr->map[bl_index2]++;
445*fb1b10abSAndroid Build Coastguard Worker }
446*fb1b10abSAndroid Build Coastguard Worker }
447*fb1b10abSAndroid Build Coastguard Worker }
448*fb1b10abSAndroid Build Coastguard Worker // Enforce constant segment over superblock.
449*fb1b10abSAndroid Build Coastguard Worker // If segment is at least half of superblock, set to 1.
450*fb1b10abSAndroid Build Coastguard Worker if (sum_map >= xmis * ymis / 2) {
451*fb1b10abSAndroid Build Coastguard Worker // This superblock is a candidate for refresh:
452*fb1b10abSAndroid Build Coastguard Worker // compute spatial variance and exclude blocks that are spatially flat
453*fb1b10abSAndroid Build Coastguard Worker // and stationary. Note: this is currently only done for screne content
454*fb1b10abSAndroid Build Coastguard Worker // mode.
455*fb1b10abSAndroid Build Coastguard Worker if (compute_content && cr->skip_flat_static_blocks)
456*fb1b10abSAndroid Build Coastguard Worker flat_static_blocks =
457*fb1b10abSAndroid Build Coastguard Worker is_superblock_flat_static(cpi, sb_row_index, sb_col_index);
458*fb1b10abSAndroid Build Coastguard Worker if (!flat_static_blocks) {
459*fb1b10abSAndroid Build Coastguard Worker // Label this superblock as segment 1.
460*fb1b10abSAndroid Build Coastguard Worker for (y = 0; y < ymis; y++)
461*fb1b10abSAndroid Build Coastguard Worker for (x = 0; x < xmis; x++) {
462*fb1b10abSAndroid Build Coastguard Worker seg_map[bl_index + y * cm->mi_cols + x] = CR_SEGMENT_ID_BOOST1;
463*fb1b10abSAndroid Build Coastguard Worker }
464*fb1b10abSAndroid Build Coastguard Worker cr->target_num_seg_blocks += xmis * ymis;
465*fb1b10abSAndroid Build Coastguard Worker }
466*fb1b10abSAndroid Build Coastguard Worker }
467*fb1b10abSAndroid Build Coastguard Worker i++;
468*fb1b10abSAndroid Build Coastguard Worker if (i == sbs_in_frame) {
469*fb1b10abSAndroid Build Coastguard Worker i = 0;
470*fb1b10abSAndroid Build Coastguard Worker }
471*fb1b10abSAndroid Build Coastguard Worker } while (cr->target_num_seg_blocks < block_count && i != cr->sb_index);
472*fb1b10abSAndroid Build Coastguard Worker cr->sb_index = i;
473*fb1b10abSAndroid Build Coastguard Worker cr->reduce_refresh = 0;
474*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.content != VP9E_CONTENT_SCREEN)
475*fb1b10abSAndroid Build Coastguard Worker if (count_sel < (3 * count_tot) >> 2) cr->reduce_refresh = 1;
476*fb1b10abSAndroid Build Coastguard Worker }
477*fb1b10abSAndroid Build Coastguard Worker
478*fb1b10abSAndroid Build Coastguard Worker // Set cyclic refresh parameters.
vp9_cyclic_refresh_update_parameters(VP9_COMP * const cpi)479*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
480*fb1b10abSAndroid Build Coastguard Worker const RATE_CONTROL *const rc = &cpi->rc;
481*fb1b10abSAndroid Build Coastguard Worker const VP9_COMMON *const cm = &cpi->common;
482*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
483*fb1b10abSAndroid Build Coastguard Worker int num8x8bl = cm->MBs << 2;
484*fb1b10abSAndroid Build Coastguard Worker int target_refresh = 0;
485*fb1b10abSAndroid Build Coastguard Worker double weight_segment_target = 0;
486*fb1b10abSAndroid Build Coastguard Worker double weight_segment = 0;
487*fb1b10abSAndroid Build Coastguard Worker int thresh_low_motion = 20;
488*fb1b10abSAndroid Build Coastguard Worker int qp_thresh = VPXMIN((cpi->oxcf.content == VP9E_CONTENT_SCREEN) ? 35 : 20,
489*fb1b10abSAndroid Build Coastguard Worker rc->best_quality << 1);
490*fb1b10abSAndroid Build Coastguard Worker int qp_max_thresh = 117 * MAXQ >> 7;
491*fb1b10abSAndroid Build Coastguard Worker cr->apply_cyclic_refresh = 1;
492*fb1b10abSAndroid Build Coastguard Worker if (frame_is_intra_only(cm) || cpi->svc.temporal_layer_id > 0 ||
493*fb1b10abSAndroid Build Coastguard Worker is_lossless_requested(&cpi->oxcf) ||
494*fb1b10abSAndroid Build Coastguard Worker rc->avg_frame_qindex[INTER_FRAME] < qp_thresh ||
495*fb1b10abSAndroid Build Coastguard Worker (cpi->use_svc &&
496*fb1b10abSAndroid Build Coastguard Worker cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) ||
497*fb1b10abSAndroid Build Coastguard Worker (!cpi->use_svc && cr->content_mode &&
498*fb1b10abSAndroid Build Coastguard Worker rc->avg_frame_low_motion < thresh_low_motion &&
499*fb1b10abSAndroid Build Coastguard Worker rc->frames_since_key > 40) ||
500*fb1b10abSAndroid Build Coastguard Worker (!cpi->use_svc && rc->avg_frame_qindex[INTER_FRAME] > qp_max_thresh &&
501*fb1b10abSAndroid Build Coastguard Worker rc->frames_since_key > 20) ||
502*fb1b10abSAndroid Build Coastguard Worker (cpi->roi.enabled && cpi->roi.skip[BACKGROUND_SEG_SKIP_ID] &&
503*fb1b10abSAndroid Build Coastguard Worker rc->frames_since_key > FRAMES_NO_SKIPPING_AFTER_KEY)) {
504*fb1b10abSAndroid Build Coastguard Worker cr->apply_cyclic_refresh = 0;
505*fb1b10abSAndroid Build Coastguard Worker return;
506*fb1b10abSAndroid Build Coastguard Worker }
507*fb1b10abSAndroid Build Coastguard Worker cr->percent_refresh = 10;
508*fb1b10abSAndroid Build Coastguard Worker if (cr->reduce_refresh) cr->percent_refresh = 5;
509*fb1b10abSAndroid Build Coastguard Worker cr->max_qdelta_perc = 60;
510*fb1b10abSAndroid Build Coastguard Worker cr->time_for_refresh = 0;
511*fb1b10abSAndroid Build Coastguard Worker cr->motion_thresh = 32;
512*fb1b10abSAndroid Build Coastguard Worker cr->rate_boost_fac = 15;
513*fb1b10abSAndroid Build Coastguard Worker // Use larger delta-qp (increase rate_ratio_qdelta) for first few (~4)
514*fb1b10abSAndroid Build Coastguard Worker // periods of the refresh cycle, after a key frame.
515*fb1b10abSAndroid Build Coastguard Worker // Account for larger interval on base layer for temporal layers.
516*fb1b10abSAndroid Build Coastguard Worker if (cr->percent_refresh > 0 &&
517*fb1b10abSAndroid Build Coastguard Worker rc->frames_since_key <
518*fb1b10abSAndroid Build Coastguard Worker (4 * cpi->svc.number_temporal_layers) * (100 / cr->percent_refresh)) {
519*fb1b10abSAndroid Build Coastguard Worker cr->rate_ratio_qdelta = 3.0;
520*fb1b10abSAndroid Build Coastguard Worker } else {
521*fb1b10abSAndroid Build Coastguard Worker cr->rate_ratio_qdelta = 2.0;
522*fb1b10abSAndroid Build Coastguard Worker if (cr->content_mode && cpi->noise_estimate.enabled &&
523*fb1b10abSAndroid Build Coastguard Worker cpi->noise_estimate.level >= kMedium) {
524*fb1b10abSAndroid Build Coastguard Worker // Reduce the delta-qp if the estimated source noise is above threshold.
525*fb1b10abSAndroid Build Coastguard Worker cr->rate_ratio_qdelta = 1.7;
526*fb1b10abSAndroid Build Coastguard Worker cr->rate_boost_fac = 13;
527*fb1b10abSAndroid Build Coastguard Worker }
528*fb1b10abSAndroid Build Coastguard Worker }
529*fb1b10abSAndroid Build Coastguard Worker // For screen-content: keep rate_ratio_qdelta to 2.0 (segment#1 boost) and
530*fb1b10abSAndroid Build Coastguard Worker // percent_refresh (refresh rate) to 10. But reduce rate boost for segment#2
531*fb1b10abSAndroid Build Coastguard Worker // (rate_boost_fac = 10 disables segment#2).
532*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.content == VP9E_CONTENT_SCREEN) {
533*fb1b10abSAndroid Build Coastguard Worker // Only enable feature of skipping flat_static blocks for top layer
534*fb1b10abSAndroid Build Coastguard Worker // under screen content mode.
535*fb1b10abSAndroid Build Coastguard Worker if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)
536*fb1b10abSAndroid Build Coastguard Worker cr->skip_flat_static_blocks = 1;
537*fb1b10abSAndroid Build Coastguard Worker cr->percent_refresh = (cr->skip_flat_static_blocks) ? 5 : 10;
538*fb1b10abSAndroid Build Coastguard Worker // Increase the amount of refresh on scene change that is encoded at max Q,
539*fb1b10abSAndroid Build Coastguard Worker // increase for a few cycles of the refresh period (~100 / percent_refresh).
540*fb1b10abSAndroid Build Coastguard Worker if (cr->content_mode && cr->counter_encode_maxq_scene_change < 30)
541*fb1b10abSAndroid Build Coastguard Worker cr->percent_refresh = (cr->skip_flat_static_blocks) ? 10 : 15;
542*fb1b10abSAndroid Build Coastguard Worker cr->rate_ratio_qdelta = 2.0;
543*fb1b10abSAndroid Build Coastguard Worker cr->rate_boost_fac = 10;
544*fb1b10abSAndroid Build Coastguard Worker }
545*fb1b10abSAndroid Build Coastguard Worker // Adjust some parameters for low resolutions.
546*fb1b10abSAndroid Build Coastguard Worker if (cm->width * cm->height <= 352 * 288) {
547*fb1b10abSAndroid Build Coastguard Worker if (rc->avg_frame_bandwidth < 3000) {
548*fb1b10abSAndroid Build Coastguard Worker cr->motion_thresh = 64;
549*fb1b10abSAndroid Build Coastguard Worker cr->rate_boost_fac = 13;
550*fb1b10abSAndroid Build Coastguard Worker } else {
551*fb1b10abSAndroid Build Coastguard Worker cr->max_qdelta_perc = 70;
552*fb1b10abSAndroid Build Coastguard Worker cr->rate_ratio_qdelta = VPXMAX(cr->rate_ratio_qdelta, 2.5);
553*fb1b10abSAndroid Build Coastguard Worker }
554*fb1b10abSAndroid Build Coastguard Worker }
555*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.rc_mode == VPX_VBR) {
556*fb1b10abSAndroid Build Coastguard Worker // To be adjusted for VBR mode, e.g., based on gf period and boost.
557*fb1b10abSAndroid Build Coastguard Worker // For now use smaller qp-delta (than CBR), no second boosted seg, and
558*fb1b10abSAndroid Build Coastguard Worker // turn-off (no refresh) on golden refresh (since it's already boosted).
559*fb1b10abSAndroid Build Coastguard Worker cr->percent_refresh = 10;
560*fb1b10abSAndroid Build Coastguard Worker cr->rate_ratio_qdelta = 1.5;
561*fb1b10abSAndroid Build Coastguard Worker cr->rate_boost_fac = 10;
562*fb1b10abSAndroid Build Coastguard Worker if (cpi->refresh_golden_frame == 1 && !cpi->use_svc) {
563*fb1b10abSAndroid Build Coastguard Worker cr->percent_refresh = 0;
564*fb1b10abSAndroid Build Coastguard Worker cr->rate_ratio_qdelta = 1.0;
565*fb1b10abSAndroid Build Coastguard Worker }
566*fb1b10abSAndroid Build Coastguard Worker }
567*fb1b10abSAndroid Build Coastguard Worker // Weight for segment prior to encoding: take the average of the target
568*fb1b10abSAndroid Build Coastguard Worker // number for the frame to be encoded and the actual from the previous frame.
569*fb1b10abSAndroid Build Coastguard Worker // Use the target if its less. To be used for setting the base qp for the
570*fb1b10abSAndroid Build Coastguard Worker // frame in vp9_rc_regulate_q.
571*fb1b10abSAndroid Build Coastguard Worker target_refresh = cr->percent_refresh * cm->mi_rows * cm->mi_cols / 100;
572*fb1b10abSAndroid Build Coastguard Worker weight_segment_target = (double)(target_refresh) / num8x8bl;
573*fb1b10abSAndroid Build Coastguard Worker weight_segment = (double)((target_refresh + cr->actual_num_seg1_blocks +
574*fb1b10abSAndroid Build Coastguard Worker cr->actual_num_seg2_blocks) >>
575*fb1b10abSAndroid Build Coastguard Worker 1) /
576*fb1b10abSAndroid Build Coastguard Worker num8x8bl;
577*fb1b10abSAndroid Build Coastguard Worker if (weight_segment_target < 7 * weight_segment / 8)
578*fb1b10abSAndroid Build Coastguard Worker weight_segment = weight_segment_target;
579*fb1b10abSAndroid Build Coastguard Worker // For screen-content: don't include target for the weight segment,
580*fb1b10abSAndroid Build Coastguard Worker // since for all flat areas the segment is reset, so its more accurate
581*fb1b10abSAndroid Build Coastguard Worker // to just use the previous actual number of seg blocks for the weight.
582*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.content == VP9E_CONTENT_SCREEN)
583*fb1b10abSAndroid Build Coastguard Worker weight_segment =
584*fb1b10abSAndroid Build Coastguard Worker (double)(cr->actual_num_seg1_blocks + cr->actual_num_seg2_blocks) /
585*fb1b10abSAndroid Build Coastguard Worker num8x8bl;
586*fb1b10abSAndroid Build Coastguard Worker cr->weight_segment = weight_segment;
587*fb1b10abSAndroid Build Coastguard Worker if (cr->content_mode == 0) {
588*fb1b10abSAndroid Build Coastguard Worker cr->actual_num_seg1_blocks =
589*fb1b10abSAndroid Build Coastguard Worker cr->percent_refresh * cm->mi_rows * cm->mi_cols / 100;
590*fb1b10abSAndroid Build Coastguard Worker cr->actual_num_seg2_blocks = 0;
591*fb1b10abSAndroid Build Coastguard Worker cr->weight_segment = (double)(cr->actual_num_seg1_blocks) / num8x8bl;
592*fb1b10abSAndroid Build Coastguard Worker }
593*fb1b10abSAndroid Build Coastguard Worker }
594*fb1b10abSAndroid Build Coastguard Worker
595*fb1b10abSAndroid Build Coastguard Worker // Setup cyclic background refresh: set delta q and segmentation map.
vp9_cyclic_refresh_setup(VP9_COMP * const cpi)596*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) {
597*fb1b10abSAndroid Build Coastguard Worker VP9_COMMON *const cm = &cpi->common;
598*fb1b10abSAndroid Build Coastguard Worker const RATE_CONTROL *const rc = &cpi->rc;
599*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
600*fb1b10abSAndroid Build Coastguard Worker struct segmentation *const seg = &cm->seg;
601*fb1b10abSAndroid Build Coastguard Worker int scene_change_detected =
602*fb1b10abSAndroid Build Coastguard Worker cpi->rc.high_source_sad ||
603*fb1b10abSAndroid Build Coastguard Worker (cpi->use_svc && cpi->svc.high_source_sad_superframe);
604*fb1b10abSAndroid Build Coastguard Worker if (cm->current_video_frame == 0) cr->low_content_avg = 0.0;
605*fb1b10abSAndroid Build Coastguard Worker // Reset if resoluton change has occurred.
606*fb1b10abSAndroid Build Coastguard Worker if (cpi->resize_pending != 0) vp9_cyclic_refresh_reset_resize(cpi);
607*fb1b10abSAndroid Build Coastguard Worker if (!cr->apply_cyclic_refresh || (cpi->force_update_segmentation) ||
608*fb1b10abSAndroid Build Coastguard Worker scene_change_detected) {
609*fb1b10abSAndroid Build Coastguard Worker // Set segmentation map to 0 and disable.
610*fb1b10abSAndroid Build Coastguard Worker unsigned char *const seg_map = cpi->segmentation_map;
611*fb1b10abSAndroid Build Coastguard Worker memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
612*fb1b10abSAndroid Build Coastguard Worker vp9_disable_segmentation(&cm->seg);
613*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type == KEY_FRAME || scene_change_detected) {
614*fb1b10abSAndroid Build Coastguard Worker memset(cr->last_coded_q_map, MAXQ,
615*fb1b10abSAndroid Build Coastguard Worker cm->mi_rows * cm->mi_cols * sizeof(*cr->last_coded_q_map));
616*fb1b10abSAndroid Build Coastguard Worker cr->sb_index = 0;
617*fb1b10abSAndroid Build Coastguard Worker cr->reduce_refresh = 0;
618*fb1b10abSAndroid Build Coastguard Worker cr->counter_encode_maxq_scene_change = 0;
619*fb1b10abSAndroid Build Coastguard Worker }
620*fb1b10abSAndroid Build Coastguard Worker return;
621*fb1b10abSAndroid Build Coastguard Worker } else {
622*fb1b10abSAndroid Build Coastguard Worker int qindex_delta = 0;
623*fb1b10abSAndroid Build Coastguard Worker int qindex2;
624*fb1b10abSAndroid Build Coastguard Worker const double q = vp9_convert_qindex_to_q(cm->base_qindex, cm->bit_depth);
625*fb1b10abSAndroid Build Coastguard Worker cr->counter_encode_maxq_scene_change++;
626*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
627*fb1b10abSAndroid Build Coastguard Worker // Set rate threshold to some multiple (set to 2 for now) of the target
628*fb1b10abSAndroid Build Coastguard Worker // rate (target is given by sb64_target_rate and scaled by 256).
629*fb1b10abSAndroid Build Coastguard Worker cr->thresh_rate_sb = ((int64_t)(rc->sb64_target_rate) << 8) << 2;
630*fb1b10abSAndroid Build Coastguard Worker // Distortion threshold, quadratic in Q, scale factor to be adjusted.
631*fb1b10abSAndroid Build Coastguard Worker // q will not exceed 457, so (q * q) is within 32bit; see:
632*fb1b10abSAndroid Build Coastguard Worker // vp9_convert_qindex_to_q(), vp9_ac_quant(), ac_qlookup*[].
633*fb1b10abSAndroid Build Coastguard Worker cr->thresh_dist_sb = ((int64_t)(q * q)) << 2;
634*fb1b10abSAndroid Build Coastguard Worker
635*fb1b10abSAndroid Build Coastguard Worker // Set up segmentation.
636*fb1b10abSAndroid Build Coastguard Worker // Clear down the segment map.
637*fb1b10abSAndroid Build Coastguard Worker vp9_enable_segmentation(&cm->seg);
638*fb1b10abSAndroid Build Coastguard Worker vp9_clearall_segfeatures(seg);
639*fb1b10abSAndroid Build Coastguard Worker // Select delta coding method.
640*fb1b10abSAndroid Build Coastguard Worker seg->abs_delta = SEGMENT_DELTADATA;
641*fb1b10abSAndroid Build Coastguard Worker
642*fb1b10abSAndroid Build Coastguard Worker // Note: setting temporal_update has no effect, as the seg-map coding method
643*fb1b10abSAndroid Build Coastguard Worker // (temporal or spatial) is determined in vp9_choose_segmap_coding_method(),
644*fb1b10abSAndroid Build Coastguard Worker // based on the coding cost of each method. For error_resilient mode on the
645*fb1b10abSAndroid Build Coastguard Worker // last_frame_seg_map is set to 0, so if temporal coding is used, it is
646*fb1b10abSAndroid Build Coastguard Worker // relative to 0 previous map.
647*fb1b10abSAndroid Build Coastguard Worker // seg->temporal_update = 0;
648*fb1b10abSAndroid Build Coastguard Worker
649*fb1b10abSAndroid Build Coastguard Worker // Segment BASE "Q" feature is disabled so it defaults to the baseline Q.
650*fb1b10abSAndroid Build Coastguard Worker vp9_disable_segfeature(seg, CR_SEGMENT_ID_BASE, SEG_LVL_ALT_Q);
651*fb1b10abSAndroid Build Coastguard Worker // Use segment BOOST1 for in-frame Q adjustment.
652*fb1b10abSAndroid Build Coastguard Worker vp9_enable_segfeature(seg, CR_SEGMENT_ID_BOOST1, SEG_LVL_ALT_Q);
653*fb1b10abSAndroid Build Coastguard Worker // Use segment BOOST2 for more aggressive in-frame Q adjustment.
654*fb1b10abSAndroid Build Coastguard Worker vp9_enable_segfeature(seg, CR_SEGMENT_ID_BOOST2, SEG_LVL_ALT_Q);
655*fb1b10abSAndroid Build Coastguard Worker
656*fb1b10abSAndroid Build Coastguard Worker // Set the q delta for segment BOOST1.
657*fb1b10abSAndroid Build Coastguard Worker qindex_delta = compute_deltaq(cpi, cm->base_qindex, cr->rate_ratio_qdelta);
658*fb1b10abSAndroid Build Coastguard Worker cr->qindex_delta[1] = qindex_delta;
659*fb1b10abSAndroid Build Coastguard Worker
660*fb1b10abSAndroid Build Coastguard Worker // Compute rd-mult for segment BOOST1.
661*fb1b10abSAndroid Build Coastguard Worker qindex2 = clamp(cm->base_qindex + cm->y_dc_delta_q + qindex_delta, 0, MAXQ);
662*fb1b10abSAndroid Build Coastguard Worker
663*fb1b10abSAndroid Build Coastguard Worker cr->rdmult = vp9_compute_rd_mult(cpi, qindex2);
664*fb1b10abSAndroid Build Coastguard Worker
665*fb1b10abSAndroid Build Coastguard Worker vp9_set_segdata(seg, CR_SEGMENT_ID_BOOST1, SEG_LVL_ALT_Q, qindex_delta);
666*fb1b10abSAndroid Build Coastguard Worker
667*fb1b10abSAndroid Build Coastguard Worker // Set a more aggressive (higher) q delta for segment BOOST2.
668*fb1b10abSAndroid Build Coastguard Worker qindex_delta = compute_deltaq(
669*fb1b10abSAndroid Build Coastguard Worker cpi, cm->base_qindex,
670*fb1b10abSAndroid Build Coastguard Worker VPXMIN(CR_MAX_RATE_TARGET_RATIO,
671*fb1b10abSAndroid Build Coastguard Worker 0.1 * cr->rate_boost_fac * cr->rate_ratio_qdelta));
672*fb1b10abSAndroid Build Coastguard Worker cr->qindex_delta[2] = qindex_delta;
673*fb1b10abSAndroid Build Coastguard Worker vp9_set_segdata(seg, CR_SEGMENT_ID_BOOST2, SEG_LVL_ALT_Q, qindex_delta);
674*fb1b10abSAndroid Build Coastguard Worker
675*fb1b10abSAndroid Build Coastguard Worker // Update the segmentation and refresh map.
676*fb1b10abSAndroid Build Coastguard Worker cyclic_refresh_update_map(cpi);
677*fb1b10abSAndroid Build Coastguard Worker }
678*fb1b10abSAndroid Build Coastguard Worker }
679*fb1b10abSAndroid Build Coastguard Worker
vp9_cyclic_refresh_get_rdmult(const CYCLIC_REFRESH * cr)680*fb1b10abSAndroid Build Coastguard Worker int vp9_cyclic_refresh_get_rdmult(const CYCLIC_REFRESH *cr) {
681*fb1b10abSAndroid Build Coastguard Worker return cr->rdmult;
682*fb1b10abSAndroid Build Coastguard Worker }
683*fb1b10abSAndroid Build Coastguard Worker
vp9_cyclic_refresh_reset_resize(VP9_COMP * const cpi)684*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_reset_resize(VP9_COMP *const cpi) {
685*fb1b10abSAndroid Build Coastguard Worker const VP9_COMMON *const cm = &cpi->common;
686*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
687*fb1b10abSAndroid Build Coastguard Worker memset(cr->map, 0, cm->mi_rows * cm->mi_cols);
688*fb1b10abSAndroid Build Coastguard Worker memset(cr->last_coded_q_map, MAXQ,
689*fb1b10abSAndroid Build Coastguard Worker cm->mi_rows * cm->mi_cols * sizeof(*cr->last_coded_q_map));
690*fb1b10abSAndroid Build Coastguard Worker cr->sb_index = 0;
691*fb1b10abSAndroid Build Coastguard Worker cpi->refresh_golden_frame = 1;
692*fb1b10abSAndroid Build Coastguard Worker cpi->refresh_alt_ref_frame = 1;
693*fb1b10abSAndroid Build Coastguard Worker cr->counter_encode_maxq_scene_change = 0;
694*fb1b10abSAndroid Build Coastguard Worker }
695*fb1b10abSAndroid Build Coastguard Worker
vp9_cyclic_refresh_limit_q(const VP9_COMP * cpi,int * q)696*fb1b10abSAndroid Build Coastguard Worker void vp9_cyclic_refresh_limit_q(const VP9_COMP *cpi, int *q) {
697*fb1b10abSAndroid Build Coastguard Worker CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
698*fb1b10abSAndroid Build Coastguard Worker // For now apply hard limit to frame-level decrease in q, if the cyclic
699*fb1b10abSAndroid Build Coastguard Worker // refresh is active (percent_refresh > 0).
700*fb1b10abSAndroid Build Coastguard Worker if (cr->percent_refresh > 0 && cpi->rc.q_1_frame - *q > 8) {
701*fb1b10abSAndroid Build Coastguard Worker *q = cpi->rc.q_1_frame - 8;
702*fb1b10abSAndroid Build Coastguard Worker }
703*fb1b10abSAndroid Build Coastguard Worker }
704