xref: /aosp_15_r20/external/libvpx/vp9/encoder/vp9_firstpass.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2010 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 #include <stdint.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
15*fb1b10abSAndroid Build Coastguard Worker 
16*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_scale_rtcd.h"
18*fb1b10abSAndroid Build Coastguard Worker 
19*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/system_state.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "vpx_scale/vpx_scale.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vpx_scale/yv12config.h"
25*fb1b10abSAndroid Build Coastguard Worker 
26*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_entropymv.h"
27*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_quant_common.h"
28*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconinter.h"  // vp9_setup_dst_planes()
29*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_aq_variance.h"
30*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_block.h"
31*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encodeframe.h"
32*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encodemb.h"
33*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encodemv.h"
34*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
35*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_ethread.h"
36*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_extend.h"
37*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_ext_ratectrl.h"
38*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_firstpass.h"
39*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_mcomp.h"
40*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_quantize.h"
41*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_ratectrl.h"
42*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_rd.h"
43*fb1b10abSAndroid Build Coastguard Worker #include "vpx/internal/vpx_codec_internal.h"
44*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_codec.h"
45*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_ext_ratectrl.h"
46*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/variance.h"
47*fb1b10abSAndroid Build Coastguard Worker 
48*fb1b10abSAndroid Build Coastguard Worker #define OUTPUT_FPF 0
49*fb1b10abSAndroid Build Coastguard Worker #define ARF_STATS_OUTPUT 0
50*fb1b10abSAndroid Build Coastguard Worker #define COMPLEXITY_STATS_OUTPUT 0
51*fb1b10abSAndroid Build Coastguard Worker 
52*fb1b10abSAndroid Build Coastguard Worker #define FIRST_PASS_Q 10.0
53*fb1b10abSAndroid Build Coastguard Worker #define NORMAL_BOOST 100
54*fb1b10abSAndroid Build Coastguard Worker #define MIN_ARF_GF_BOOST 250
55*fb1b10abSAndroid Build Coastguard Worker #define MIN_DECAY_FACTOR 0.01
56*fb1b10abSAndroid Build Coastguard Worker #define NEW_MV_MODE_PENALTY 32
57*fb1b10abSAndroid Build Coastguard Worker #define DARK_THRESH 64
58*fb1b10abSAndroid Build Coastguard Worker #define LOW_I_THRESH 24000
59*fb1b10abSAndroid Build Coastguard Worker 
60*fb1b10abSAndroid Build Coastguard Worker #define NCOUNT_INTRA_THRESH 8192
61*fb1b10abSAndroid Build Coastguard Worker #define NCOUNT_INTRA_FACTOR 3
62*fb1b10abSAndroid Build Coastguard Worker 
63*fb1b10abSAndroid Build Coastguard Worker #define INTRA_PART 0.005
64*fb1b10abSAndroid Build Coastguard Worker #define DEFAULT_DECAY_LIMIT 0.75
65*fb1b10abSAndroid Build Coastguard Worker #define LOW_SR_DIFF_TRHESH 0.1
66*fb1b10abSAndroid Build Coastguard Worker #define LOW_CODED_ERR_PER_MB 10.0
67*fb1b10abSAndroid Build Coastguard Worker #define NCOUNT_FRAME_II_THRESH 6.0
68*fb1b10abSAndroid Build Coastguard Worker #define BASELINE_ERR_PER_MB 12500.0
69*fb1b10abSAndroid Build Coastguard Worker #define GF_MAX_FRAME_BOOST 96.0
70*fb1b10abSAndroid Build Coastguard Worker 
71*fb1b10abSAndroid Build Coastguard Worker #ifdef AGGRESSIVE_VBR
72*fb1b10abSAndroid Build Coastguard Worker #define KF_MIN_FRAME_BOOST 40.0
73*fb1b10abSAndroid Build Coastguard Worker #define KF_MAX_FRAME_BOOST 80.0
74*fb1b10abSAndroid Build Coastguard Worker #define MAX_KF_TOT_BOOST 4800
75*fb1b10abSAndroid Build Coastguard Worker #else
76*fb1b10abSAndroid Build Coastguard Worker #define KF_MIN_FRAME_BOOST 40.0
77*fb1b10abSAndroid Build Coastguard Worker #define KF_MAX_FRAME_BOOST 96.0
78*fb1b10abSAndroid Build Coastguard Worker #define MAX_KF_TOT_BOOST 5400
79*fb1b10abSAndroid Build Coastguard Worker #endif
80*fb1b10abSAndroid Build Coastguard Worker 
81*fb1b10abSAndroid Build Coastguard Worker #define DEFAULT_ZM_FACTOR 0.5
82*fb1b10abSAndroid Build Coastguard Worker #define MINQ_ADJ_LIMIT 48
83*fb1b10abSAndroid Build Coastguard Worker #define MINQ_ADJ_LIMIT_CQ 20
84*fb1b10abSAndroid Build Coastguard Worker #define HIGH_UNDERSHOOT_RATIO 2
85*fb1b10abSAndroid Build Coastguard Worker #define AV_WQ_FACTOR 4.0
86*fb1b10abSAndroid Build Coastguard Worker 
87*fb1b10abSAndroid Build Coastguard Worker #define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x)-0.000001 : (x) + 0.000001)
88*fb1b10abSAndroid Build Coastguard Worker 
89*fb1b10abSAndroid Build Coastguard Worker #if ARF_STATS_OUTPUT
90*fb1b10abSAndroid Build Coastguard Worker unsigned int arf_count = 0;
91*fb1b10abSAndroid Build Coastguard Worker #endif
92*fb1b10abSAndroid Build Coastguard Worker 
93*fb1b10abSAndroid Build Coastguard Worker // Resets the first pass file to the given position using a relative seek from
94*fb1b10abSAndroid Build Coastguard Worker // the current position.
reset_fpf_position(TWO_PASS * p,const FIRSTPASS_STATS * position)95*fb1b10abSAndroid Build Coastguard Worker static void reset_fpf_position(TWO_PASS *p, const FIRSTPASS_STATS *position) {
96*fb1b10abSAndroid Build Coastguard Worker   p->stats_in = position;
97*fb1b10abSAndroid Build Coastguard Worker }
98*fb1b10abSAndroid Build Coastguard Worker 
99*fb1b10abSAndroid Build Coastguard Worker // Read frame stats at an offset from the current position.
read_frame_stats(const TWO_PASS * p,int offset)100*fb1b10abSAndroid Build Coastguard Worker static const FIRSTPASS_STATS *read_frame_stats(const TWO_PASS *p, int offset) {
101*fb1b10abSAndroid Build Coastguard Worker   if ((offset >= 0 && p->stats_in + offset >= p->stats_in_end) ||
102*fb1b10abSAndroid Build Coastguard Worker       (offset < 0 && p->stats_in + offset < p->stats_in_start)) {
103*fb1b10abSAndroid Build Coastguard Worker     return NULL;
104*fb1b10abSAndroid Build Coastguard Worker   }
105*fb1b10abSAndroid Build Coastguard Worker 
106*fb1b10abSAndroid Build Coastguard Worker   return &p->stats_in[offset];
107*fb1b10abSAndroid Build Coastguard Worker }
108*fb1b10abSAndroid Build Coastguard Worker 
input_stats(TWO_PASS * p,FIRSTPASS_STATS * fps)109*fb1b10abSAndroid Build Coastguard Worker static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) {
110*fb1b10abSAndroid Build Coastguard Worker   if (p->stats_in >= p->stats_in_end) return EOF;
111*fb1b10abSAndroid Build Coastguard Worker 
112*fb1b10abSAndroid Build Coastguard Worker   *fps = *p->stats_in;
113*fb1b10abSAndroid Build Coastguard Worker   ++p->stats_in;
114*fb1b10abSAndroid Build Coastguard Worker   return 1;
115*fb1b10abSAndroid Build Coastguard Worker }
116*fb1b10abSAndroid Build Coastguard Worker 
output_stats(FIRSTPASS_STATS * stats)117*fb1b10abSAndroid Build Coastguard Worker static void output_stats(FIRSTPASS_STATS *stats) {
118*fb1b10abSAndroid Build Coastguard Worker   (void)stats;
119*fb1b10abSAndroid Build Coastguard Worker // TEMP debug code
120*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_FPF
121*fb1b10abSAndroid Build Coastguard Worker   {
122*fb1b10abSAndroid Build Coastguard Worker     FILE *fpfile;
123*fb1b10abSAndroid Build Coastguard Worker     fpfile = fopen("firstpass.stt", "a");
124*fb1b10abSAndroid Build Coastguard Worker 
125*fb1b10abSAndroid Build Coastguard Worker     fprintf(fpfile,
126*fb1b10abSAndroid Build Coastguard Worker             "%12.0lf %12.4lf %12.2lf %12.2lf %12.2lf %12.0lf %12.4lf %12.4lf"
127*fb1b10abSAndroid Build Coastguard Worker             "%12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf"
128*fb1b10abSAndroid Build Coastguard Worker             "%12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.0lf %12.4lf %12.0lf"
129*fb1b10abSAndroid Build Coastguard Worker             "%12.4lf"
130*fb1b10abSAndroid Build Coastguard Worker             "\n",
131*fb1b10abSAndroid Build Coastguard Worker             stats->frame, stats->weight, stats->intra_error, stats->coded_error,
132*fb1b10abSAndroid Build Coastguard Worker             stats->sr_coded_error, stats->frame_noise_energy, stats->pcnt_inter,
133*fb1b10abSAndroid Build Coastguard Worker             stats->pcnt_motion, stats->pcnt_second_ref, stats->pcnt_neutral,
134*fb1b10abSAndroid Build Coastguard Worker             stats->pcnt_intra_low, stats->pcnt_intra_high,
135*fb1b10abSAndroid Build Coastguard Worker             stats->intra_skip_pct, stats->intra_smooth_pct,
136*fb1b10abSAndroid Build Coastguard Worker             stats->inactive_zone_rows, stats->inactive_zone_cols, stats->MVr,
137*fb1b10abSAndroid Build Coastguard Worker             stats->mvr_abs, stats->MVc, stats->mvc_abs, stats->MVrv,
138*fb1b10abSAndroid Build Coastguard Worker             stats->MVcv, stats->mv_in_out_count, stats->count, stats->duration);
139*fb1b10abSAndroid Build Coastguard Worker     fclose(fpfile);
140*fb1b10abSAndroid Build Coastguard Worker   }
141*fb1b10abSAndroid Build Coastguard Worker #endif
142*fb1b10abSAndroid Build Coastguard Worker }
143*fb1b10abSAndroid Build Coastguard Worker 
zero_stats(FIRSTPASS_STATS * section)144*fb1b10abSAndroid Build Coastguard Worker static void zero_stats(FIRSTPASS_STATS *section) {
145*fb1b10abSAndroid Build Coastguard Worker   section->frame = 0.0;
146*fb1b10abSAndroid Build Coastguard Worker   section->weight = 0.0;
147*fb1b10abSAndroid Build Coastguard Worker   section->intra_error = 0.0;
148*fb1b10abSAndroid Build Coastguard Worker   section->coded_error = 0.0;
149*fb1b10abSAndroid Build Coastguard Worker   section->sr_coded_error = 0.0;
150*fb1b10abSAndroid Build Coastguard Worker   section->frame_noise_energy = 0.0;
151*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_inter = 0.0;
152*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_motion = 0.0;
153*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_second_ref = 0.0;
154*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_neutral = 0.0;
155*fb1b10abSAndroid Build Coastguard Worker   section->intra_skip_pct = 0.0;
156*fb1b10abSAndroid Build Coastguard Worker   section->intra_smooth_pct = 0.0;
157*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_intra_low = 0.0;
158*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_intra_high = 0.0;
159*fb1b10abSAndroid Build Coastguard Worker   section->inactive_zone_rows = 0.0;
160*fb1b10abSAndroid Build Coastguard Worker   section->inactive_zone_cols = 0.0;
161*fb1b10abSAndroid Build Coastguard Worker   section->new_mv_count = 0.0;
162*fb1b10abSAndroid Build Coastguard Worker   section->MVr = 0.0;
163*fb1b10abSAndroid Build Coastguard Worker   section->mvr_abs = 0.0;
164*fb1b10abSAndroid Build Coastguard Worker   section->MVc = 0.0;
165*fb1b10abSAndroid Build Coastguard Worker   section->mvc_abs = 0.0;
166*fb1b10abSAndroid Build Coastguard Worker   section->MVrv = 0.0;
167*fb1b10abSAndroid Build Coastguard Worker   section->MVcv = 0.0;
168*fb1b10abSAndroid Build Coastguard Worker   section->mv_in_out_count = 0.0;
169*fb1b10abSAndroid Build Coastguard Worker   section->count = 0.0;
170*fb1b10abSAndroid Build Coastguard Worker   section->duration = 1.0;
171*fb1b10abSAndroid Build Coastguard Worker   section->spatial_layer_id = 0;
172*fb1b10abSAndroid Build Coastguard Worker }
173*fb1b10abSAndroid Build Coastguard Worker 
accumulate_stats(FIRSTPASS_STATS * section,const FIRSTPASS_STATS * frame)174*fb1b10abSAndroid Build Coastguard Worker static void accumulate_stats(FIRSTPASS_STATS *section,
175*fb1b10abSAndroid Build Coastguard Worker                              const FIRSTPASS_STATS *frame) {
176*fb1b10abSAndroid Build Coastguard Worker   section->frame += frame->frame;
177*fb1b10abSAndroid Build Coastguard Worker   section->weight += frame->weight;
178*fb1b10abSAndroid Build Coastguard Worker   section->spatial_layer_id = frame->spatial_layer_id;
179*fb1b10abSAndroid Build Coastguard Worker   section->intra_error += frame->intra_error;
180*fb1b10abSAndroid Build Coastguard Worker   section->coded_error += frame->coded_error;
181*fb1b10abSAndroid Build Coastguard Worker   section->sr_coded_error += frame->sr_coded_error;
182*fb1b10abSAndroid Build Coastguard Worker   section->frame_noise_energy += frame->frame_noise_energy;
183*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_inter += frame->pcnt_inter;
184*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_motion += frame->pcnt_motion;
185*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_second_ref += frame->pcnt_second_ref;
186*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_neutral += frame->pcnt_neutral;
187*fb1b10abSAndroid Build Coastguard Worker   section->intra_skip_pct += frame->intra_skip_pct;
188*fb1b10abSAndroid Build Coastguard Worker   section->intra_smooth_pct += frame->intra_smooth_pct;
189*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_intra_low += frame->pcnt_intra_low;
190*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_intra_high += frame->pcnt_intra_high;
191*fb1b10abSAndroid Build Coastguard Worker   section->inactive_zone_rows += frame->inactive_zone_rows;
192*fb1b10abSAndroid Build Coastguard Worker   section->inactive_zone_cols += frame->inactive_zone_cols;
193*fb1b10abSAndroid Build Coastguard Worker   section->new_mv_count += frame->new_mv_count;
194*fb1b10abSAndroid Build Coastguard Worker   section->MVr += frame->MVr;
195*fb1b10abSAndroid Build Coastguard Worker   section->mvr_abs += frame->mvr_abs;
196*fb1b10abSAndroid Build Coastguard Worker   section->MVc += frame->MVc;
197*fb1b10abSAndroid Build Coastguard Worker   section->mvc_abs += frame->mvc_abs;
198*fb1b10abSAndroid Build Coastguard Worker   section->MVrv += frame->MVrv;
199*fb1b10abSAndroid Build Coastguard Worker   section->MVcv += frame->MVcv;
200*fb1b10abSAndroid Build Coastguard Worker   section->mv_in_out_count += frame->mv_in_out_count;
201*fb1b10abSAndroid Build Coastguard Worker   section->count += frame->count;
202*fb1b10abSAndroid Build Coastguard Worker   section->duration += frame->duration;
203*fb1b10abSAndroid Build Coastguard Worker }
204*fb1b10abSAndroid Build Coastguard Worker 
subtract_stats(FIRSTPASS_STATS * section,const FIRSTPASS_STATS * frame)205*fb1b10abSAndroid Build Coastguard Worker static void subtract_stats(FIRSTPASS_STATS *section,
206*fb1b10abSAndroid Build Coastguard Worker                            const FIRSTPASS_STATS *frame) {
207*fb1b10abSAndroid Build Coastguard Worker   section->frame -= frame->frame;
208*fb1b10abSAndroid Build Coastguard Worker   section->weight -= frame->weight;
209*fb1b10abSAndroid Build Coastguard Worker   section->intra_error -= frame->intra_error;
210*fb1b10abSAndroid Build Coastguard Worker   section->coded_error -= frame->coded_error;
211*fb1b10abSAndroid Build Coastguard Worker   section->sr_coded_error -= frame->sr_coded_error;
212*fb1b10abSAndroid Build Coastguard Worker   section->frame_noise_energy -= frame->frame_noise_energy;
213*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_inter -= frame->pcnt_inter;
214*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_motion -= frame->pcnt_motion;
215*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_second_ref -= frame->pcnt_second_ref;
216*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_neutral -= frame->pcnt_neutral;
217*fb1b10abSAndroid Build Coastguard Worker   section->intra_skip_pct -= frame->intra_skip_pct;
218*fb1b10abSAndroid Build Coastguard Worker   section->intra_smooth_pct -= frame->intra_smooth_pct;
219*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_intra_low -= frame->pcnt_intra_low;
220*fb1b10abSAndroid Build Coastguard Worker   section->pcnt_intra_high -= frame->pcnt_intra_high;
221*fb1b10abSAndroid Build Coastguard Worker   section->inactive_zone_rows -= frame->inactive_zone_rows;
222*fb1b10abSAndroid Build Coastguard Worker   section->inactive_zone_cols -= frame->inactive_zone_cols;
223*fb1b10abSAndroid Build Coastguard Worker   section->new_mv_count -= frame->new_mv_count;
224*fb1b10abSAndroid Build Coastguard Worker   section->MVr -= frame->MVr;
225*fb1b10abSAndroid Build Coastguard Worker   section->mvr_abs -= frame->mvr_abs;
226*fb1b10abSAndroid Build Coastguard Worker   section->MVc -= frame->MVc;
227*fb1b10abSAndroid Build Coastguard Worker   section->mvc_abs -= frame->mvc_abs;
228*fb1b10abSAndroid Build Coastguard Worker   section->MVrv -= frame->MVrv;
229*fb1b10abSAndroid Build Coastguard Worker   section->MVcv -= frame->MVcv;
230*fb1b10abSAndroid Build Coastguard Worker   section->mv_in_out_count -= frame->mv_in_out_count;
231*fb1b10abSAndroid Build Coastguard Worker   section->count -= frame->count;
232*fb1b10abSAndroid Build Coastguard Worker   section->duration -= frame->duration;
233*fb1b10abSAndroid Build Coastguard Worker }
234*fb1b10abSAndroid Build Coastguard Worker 
235*fb1b10abSAndroid Build Coastguard Worker // Calculate an active area of the image that discounts formatting
236*fb1b10abSAndroid Build Coastguard Worker // bars and partially discounts other 0 energy areas.
237*fb1b10abSAndroid Build Coastguard Worker #define MIN_ACTIVE_AREA 0.5
238*fb1b10abSAndroid Build Coastguard Worker #define MAX_ACTIVE_AREA 1.0
calculate_active_area(const FRAME_INFO * frame_info,const FIRSTPASS_STATS * this_frame)239*fb1b10abSAndroid Build Coastguard Worker static double calculate_active_area(const FRAME_INFO *frame_info,
240*fb1b10abSAndroid Build Coastguard Worker                                     const FIRSTPASS_STATS *this_frame) {
241*fb1b10abSAndroid Build Coastguard Worker   double active_pct;
242*fb1b10abSAndroid Build Coastguard Worker 
243*fb1b10abSAndroid Build Coastguard Worker   active_pct =
244*fb1b10abSAndroid Build Coastguard Worker       1.0 -
245*fb1b10abSAndroid Build Coastguard Worker       ((this_frame->intra_skip_pct / 2) +
246*fb1b10abSAndroid Build Coastguard Worker        ((this_frame->inactive_zone_rows * 2) / (double)frame_info->mb_rows));
247*fb1b10abSAndroid Build Coastguard Worker   return fclamp(active_pct, MIN_ACTIVE_AREA, MAX_ACTIVE_AREA);
248*fb1b10abSAndroid Build Coastguard Worker }
249*fb1b10abSAndroid Build Coastguard Worker 
250*fb1b10abSAndroid Build Coastguard Worker // Get the average weighted error for the clip (or corpus)
get_distribution_av_err(VP9_COMP * cpi,TWO_PASS * const twopass)251*fb1b10abSAndroid Build Coastguard Worker static double get_distribution_av_err(VP9_COMP *cpi, TWO_PASS *const twopass) {
252*fb1b10abSAndroid Build Coastguard Worker   const double av_weight =
253*fb1b10abSAndroid Build Coastguard Worker       twopass->total_stats.weight / twopass->total_stats.count;
254*fb1b10abSAndroid Build Coastguard Worker 
255*fb1b10abSAndroid Build Coastguard Worker   if (cpi->oxcf.vbr_corpus_complexity)
256*fb1b10abSAndroid Build Coastguard Worker     return av_weight * twopass->mean_mod_score;
257*fb1b10abSAndroid Build Coastguard Worker   else
258*fb1b10abSAndroid Build Coastguard Worker     return (twopass->total_stats.coded_error * av_weight) /
259*fb1b10abSAndroid Build Coastguard Worker            twopass->total_stats.count;
260*fb1b10abSAndroid Build Coastguard Worker }
261*fb1b10abSAndroid Build Coastguard Worker 
262*fb1b10abSAndroid Build Coastguard Worker #define ACT_AREA_CORRECTION 0.5
263*fb1b10abSAndroid Build Coastguard Worker // Calculate a modified Error used in distributing bits between easier and
264*fb1b10abSAndroid Build Coastguard Worker // harder frames.
calculate_mod_frame_score(const VP9_COMP * cpi,const VP9EncoderConfig * oxcf,const FIRSTPASS_STATS * this_frame,const double av_err)265*fb1b10abSAndroid Build Coastguard Worker static double calculate_mod_frame_score(const VP9_COMP *cpi,
266*fb1b10abSAndroid Build Coastguard Worker                                         const VP9EncoderConfig *oxcf,
267*fb1b10abSAndroid Build Coastguard Worker                                         const FIRSTPASS_STATS *this_frame,
268*fb1b10abSAndroid Build Coastguard Worker                                         const double av_err) {
269*fb1b10abSAndroid Build Coastguard Worker   double modified_score =
270*fb1b10abSAndroid Build Coastguard Worker       av_err * pow(this_frame->coded_error * this_frame->weight /
271*fb1b10abSAndroid Build Coastguard Worker                        DOUBLE_DIVIDE_CHECK(av_err),
272*fb1b10abSAndroid Build Coastguard Worker                    oxcf->two_pass_vbrbias / 100.0);
273*fb1b10abSAndroid Build Coastguard Worker 
274*fb1b10abSAndroid Build Coastguard Worker   // Correction for active area. Frames with a reduced active area
275*fb1b10abSAndroid Build Coastguard Worker   // (eg due to formatting bars) have a higher error per mb for the
276*fb1b10abSAndroid Build Coastguard Worker   // remaining active MBs. The correction here assumes that coding
277*fb1b10abSAndroid Build Coastguard Worker   // 0.5N blocks of complexity 2X is a little easier than coding N
278*fb1b10abSAndroid Build Coastguard Worker   // blocks of complexity X.
279*fb1b10abSAndroid Build Coastguard Worker   modified_score *= pow(calculate_active_area(&cpi->frame_info, this_frame),
280*fb1b10abSAndroid Build Coastguard Worker                         ACT_AREA_CORRECTION);
281*fb1b10abSAndroid Build Coastguard Worker 
282*fb1b10abSAndroid Build Coastguard Worker   return modified_score;
283*fb1b10abSAndroid Build Coastguard Worker }
284*fb1b10abSAndroid Build Coastguard Worker 
calc_norm_frame_score(const VP9EncoderConfig * oxcf,const FRAME_INFO * frame_info,const FIRSTPASS_STATS * this_frame,double mean_mod_score,double av_err)285*fb1b10abSAndroid Build Coastguard Worker static double calc_norm_frame_score(const VP9EncoderConfig *oxcf,
286*fb1b10abSAndroid Build Coastguard Worker                                     const FRAME_INFO *frame_info,
287*fb1b10abSAndroid Build Coastguard Worker                                     const FIRSTPASS_STATS *this_frame,
288*fb1b10abSAndroid Build Coastguard Worker                                     double mean_mod_score, double av_err) {
289*fb1b10abSAndroid Build Coastguard Worker   double modified_score =
290*fb1b10abSAndroid Build Coastguard Worker       av_err * pow(this_frame->coded_error * this_frame->weight /
291*fb1b10abSAndroid Build Coastguard Worker                        DOUBLE_DIVIDE_CHECK(av_err),
292*fb1b10abSAndroid Build Coastguard Worker                    oxcf->two_pass_vbrbias / 100.0);
293*fb1b10abSAndroid Build Coastguard Worker 
294*fb1b10abSAndroid Build Coastguard Worker   const double min_score = (double)(oxcf->two_pass_vbrmin_section) / 100.0;
295*fb1b10abSAndroid Build Coastguard Worker   const double max_score = (double)(oxcf->two_pass_vbrmax_section) / 100.0;
296*fb1b10abSAndroid Build Coastguard Worker 
297*fb1b10abSAndroid Build Coastguard Worker   // Correction for active area. Frames with a reduced active area
298*fb1b10abSAndroid Build Coastguard Worker   // (eg due to formatting bars) have a higher error per mb for the
299*fb1b10abSAndroid Build Coastguard Worker   // remaining active MBs. The correction here assumes that coding
300*fb1b10abSAndroid Build Coastguard Worker   // 0.5N blocks of complexity 2X is a little easier than coding N
301*fb1b10abSAndroid Build Coastguard Worker   // blocks of complexity X.
302*fb1b10abSAndroid Build Coastguard Worker   modified_score *=
303*fb1b10abSAndroid Build Coastguard Worker       pow(calculate_active_area(frame_info, this_frame), ACT_AREA_CORRECTION);
304*fb1b10abSAndroid Build Coastguard Worker 
305*fb1b10abSAndroid Build Coastguard Worker   // Normalize to a midpoint score.
306*fb1b10abSAndroid Build Coastguard Worker   modified_score /= DOUBLE_DIVIDE_CHECK(mean_mod_score);
307*fb1b10abSAndroid Build Coastguard Worker   return fclamp(modified_score, min_score, max_score);
308*fb1b10abSAndroid Build Coastguard Worker }
309*fb1b10abSAndroid Build Coastguard Worker 
calculate_norm_frame_score(const VP9_COMP * cpi,const TWO_PASS * twopass,const VP9EncoderConfig * oxcf,const FIRSTPASS_STATS * this_frame,const double av_err)310*fb1b10abSAndroid Build Coastguard Worker static double calculate_norm_frame_score(const VP9_COMP *cpi,
311*fb1b10abSAndroid Build Coastguard Worker                                          const TWO_PASS *twopass,
312*fb1b10abSAndroid Build Coastguard Worker                                          const VP9EncoderConfig *oxcf,
313*fb1b10abSAndroid Build Coastguard Worker                                          const FIRSTPASS_STATS *this_frame,
314*fb1b10abSAndroid Build Coastguard Worker                                          const double av_err) {
315*fb1b10abSAndroid Build Coastguard Worker   return calc_norm_frame_score(oxcf, &cpi->frame_info, this_frame,
316*fb1b10abSAndroid Build Coastguard Worker                                twopass->mean_mod_score, av_err);
317*fb1b10abSAndroid Build Coastguard Worker }
318*fb1b10abSAndroid Build Coastguard Worker 
319*fb1b10abSAndroid Build Coastguard Worker // This function returns the maximum target rate per frame.
frame_max_bits(const RATE_CONTROL * rc,const VP9EncoderConfig * oxcf)320*fb1b10abSAndroid Build Coastguard Worker static int frame_max_bits(const RATE_CONTROL *rc,
321*fb1b10abSAndroid Build Coastguard Worker                           const VP9EncoderConfig *oxcf) {
322*fb1b10abSAndroid Build Coastguard Worker   int64_t max_bits = ((int64_t)rc->avg_frame_bandwidth *
323*fb1b10abSAndroid Build Coastguard Worker                       (int64_t)oxcf->two_pass_vbrmax_section) /
324*fb1b10abSAndroid Build Coastguard Worker                      100;
325*fb1b10abSAndroid Build Coastguard Worker   if (max_bits < 0)
326*fb1b10abSAndroid Build Coastguard Worker     max_bits = 0;
327*fb1b10abSAndroid Build Coastguard Worker   else if (max_bits > rc->max_frame_bandwidth)
328*fb1b10abSAndroid Build Coastguard Worker     max_bits = rc->max_frame_bandwidth;
329*fb1b10abSAndroid Build Coastguard Worker 
330*fb1b10abSAndroid Build Coastguard Worker   return (int)max_bits;
331*fb1b10abSAndroid Build Coastguard Worker }
332*fb1b10abSAndroid Build Coastguard Worker 
vp9_init_first_pass(VP9_COMP * cpi)333*fb1b10abSAndroid Build Coastguard Worker void vp9_init_first_pass(VP9_COMP *cpi) {
334*fb1b10abSAndroid Build Coastguard Worker   zero_stats(&cpi->twopass.total_stats);
335*fb1b10abSAndroid Build Coastguard Worker }
336*fb1b10abSAndroid Build Coastguard Worker 
vp9_end_first_pass(VP9_COMP * cpi)337*fb1b10abSAndroid Build Coastguard Worker void vp9_end_first_pass(VP9_COMP *cpi) {
338*fb1b10abSAndroid Build Coastguard Worker   output_stats(&cpi->twopass.total_stats);
339*fb1b10abSAndroid Build Coastguard Worker   cpi->twopass.first_pass_done = 1;
340*fb1b10abSAndroid Build Coastguard Worker   vpx_free(cpi->twopass.fp_mb_float_stats);
341*fb1b10abSAndroid Build Coastguard Worker   cpi->twopass.fp_mb_float_stats = NULL;
342*fb1b10abSAndroid Build Coastguard Worker }
343*fb1b10abSAndroid Build Coastguard Worker 
get_block_variance_fn(BLOCK_SIZE bsize)344*fb1b10abSAndroid Build Coastguard Worker static vpx_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
345*fb1b10abSAndroid Build Coastguard Worker   switch (bsize) {
346*fb1b10abSAndroid Build Coastguard Worker     case BLOCK_8X8: return vpx_mse8x8;
347*fb1b10abSAndroid Build Coastguard Worker     case BLOCK_16X8: return vpx_mse16x8;
348*fb1b10abSAndroid Build Coastguard Worker     case BLOCK_8X16: return vpx_mse8x16;
349*fb1b10abSAndroid Build Coastguard Worker     default: return vpx_mse16x16;
350*fb1b10abSAndroid Build Coastguard Worker   }
351*fb1b10abSAndroid Build Coastguard Worker }
352*fb1b10abSAndroid Build Coastguard Worker 
get_prediction_error(BLOCK_SIZE bsize,const struct buf_2d * src,const struct buf_2d * ref)353*fb1b10abSAndroid Build Coastguard Worker static unsigned int get_prediction_error(BLOCK_SIZE bsize,
354*fb1b10abSAndroid Build Coastguard Worker                                          const struct buf_2d *src,
355*fb1b10abSAndroid Build Coastguard Worker                                          const struct buf_2d *ref) {
356*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;
357*fb1b10abSAndroid Build Coastguard Worker   const vpx_variance_fn_t fn = get_block_variance_fn(bsize);
358*fb1b10abSAndroid Build Coastguard Worker   fn(src->buf, src->stride, ref->buf, ref->stride, &sse);
359*fb1b10abSAndroid Build Coastguard Worker   return sse;
360*fb1b10abSAndroid Build Coastguard Worker }
361*fb1b10abSAndroid Build Coastguard Worker 
362*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
highbd_get_block_variance_fn(BLOCK_SIZE bsize,int bd)363*fb1b10abSAndroid Build Coastguard Worker static vpx_variance_fn_t highbd_get_block_variance_fn(BLOCK_SIZE bsize,
364*fb1b10abSAndroid Build Coastguard Worker                                                       int bd) {
365*fb1b10abSAndroid Build Coastguard Worker   switch (bd) {
366*fb1b10abSAndroid Build Coastguard Worker     default:
367*fb1b10abSAndroid Build Coastguard Worker       switch (bsize) {
368*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_8X8: return vpx_highbd_8_mse8x8;
369*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_16X8: return vpx_highbd_8_mse16x8;
370*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_8X16: return vpx_highbd_8_mse8x16;
371*fb1b10abSAndroid Build Coastguard Worker         default: return vpx_highbd_8_mse16x16;
372*fb1b10abSAndroid Build Coastguard Worker       }
373*fb1b10abSAndroid Build Coastguard Worker     case 10:
374*fb1b10abSAndroid Build Coastguard Worker       switch (bsize) {
375*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_8X8: return vpx_highbd_10_mse8x8;
376*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_16X8: return vpx_highbd_10_mse16x8;
377*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_8X16: return vpx_highbd_10_mse8x16;
378*fb1b10abSAndroid Build Coastguard Worker         default: return vpx_highbd_10_mse16x16;
379*fb1b10abSAndroid Build Coastguard Worker       }
380*fb1b10abSAndroid Build Coastguard Worker     case 12:
381*fb1b10abSAndroid Build Coastguard Worker       switch (bsize) {
382*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_8X8: return vpx_highbd_12_mse8x8;
383*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_16X8: return vpx_highbd_12_mse16x8;
384*fb1b10abSAndroid Build Coastguard Worker         case BLOCK_8X16: return vpx_highbd_12_mse8x16;
385*fb1b10abSAndroid Build Coastguard Worker         default: return vpx_highbd_12_mse16x16;
386*fb1b10abSAndroid Build Coastguard Worker       }
387*fb1b10abSAndroid Build Coastguard Worker   }
388*fb1b10abSAndroid Build Coastguard Worker }
389*fb1b10abSAndroid Build Coastguard Worker 
highbd_get_prediction_error(BLOCK_SIZE bsize,const struct buf_2d * src,const struct buf_2d * ref,int bd)390*fb1b10abSAndroid Build Coastguard Worker static unsigned int highbd_get_prediction_error(BLOCK_SIZE bsize,
391*fb1b10abSAndroid Build Coastguard Worker                                                 const struct buf_2d *src,
392*fb1b10abSAndroid Build Coastguard Worker                                                 const struct buf_2d *ref,
393*fb1b10abSAndroid Build Coastguard Worker                                                 int bd) {
394*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;
395*fb1b10abSAndroid Build Coastguard Worker   const vpx_variance_fn_t fn = highbd_get_block_variance_fn(bsize, bd);
396*fb1b10abSAndroid Build Coastguard Worker   fn(src->buf, src->stride, ref->buf, ref->stride, &sse);
397*fb1b10abSAndroid Build Coastguard Worker   return sse;
398*fb1b10abSAndroid Build Coastguard Worker }
399*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
400*fb1b10abSAndroid Build Coastguard Worker 
401*fb1b10abSAndroid Build Coastguard Worker // Refine the motion search range according to the frame dimension
402*fb1b10abSAndroid Build Coastguard Worker // for first pass test.
get_search_range(const VP9_COMP * cpi)403*fb1b10abSAndroid Build Coastguard Worker static int get_search_range(const VP9_COMP *cpi) {
404*fb1b10abSAndroid Build Coastguard Worker   int sr = 0;
405*fb1b10abSAndroid Build Coastguard Worker   const int dim = VPXMIN(cpi->initial_width, cpi->initial_height);
406*fb1b10abSAndroid Build Coastguard Worker 
407*fb1b10abSAndroid Build Coastguard Worker   while ((dim << sr) < MAX_FULL_PEL_VAL) ++sr;
408*fb1b10abSAndroid Build Coastguard Worker   return sr;
409*fb1b10abSAndroid Build Coastguard Worker }
410*fb1b10abSAndroid Build Coastguard Worker 
411*fb1b10abSAndroid Build Coastguard Worker // Reduce limits to keep the motion search within MV_MAX of ref_mv. Not doing
412*fb1b10abSAndroid Build Coastguard Worker // this can be problematic for big videos (8K) and may cause assert failure
413*fb1b10abSAndroid Build Coastguard Worker // (or memory violation) in mv_cost. Limits are only modified if they would
414*fb1b10abSAndroid Build Coastguard Worker // be non-empty. Returns 1 if limits are non-empty.
intersect_limits_with_mv_max(MvLimits * mv_limits,const MV * ref_mv)415*fb1b10abSAndroid Build Coastguard Worker static int intersect_limits_with_mv_max(MvLimits *mv_limits, const MV *ref_mv) {
416*fb1b10abSAndroid Build Coastguard Worker   const int row_min =
417*fb1b10abSAndroid Build Coastguard Worker       VPXMAX(mv_limits->row_min, (ref_mv->row + 7 - MV_MAX) >> 3);
418*fb1b10abSAndroid Build Coastguard Worker   const int row_max =
419*fb1b10abSAndroid Build Coastguard Worker       VPXMIN(mv_limits->row_max, (ref_mv->row - 1 + MV_MAX) >> 3);
420*fb1b10abSAndroid Build Coastguard Worker   const int col_min =
421*fb1b10abSAndroid Build Coastguard Worker       VPXMAX(mv_limits->col_min, (ref_mv->col + 7 - MV_MAX) >> 3);
422*fb1b10abSAndroid Build Coastguard Worker   const int col_max =
423*fb1b10abSAndroid Build Coastguard Worker       VPXMIN(mv_limits->col_max, (ref_mv->col - 1 + MV_MAX) >> 3);
424*fb1b10abSAndroid Build Coastguard Worker   if (row_min > row_max || col_min > col_max) {
425*fb1b10abSAndroid Build Coastguard Worker     return 0;
426*fb1b10abSAndroid Build Coastguard Worker   }
427*fb1b10abSAndroid Build Coastguard Worker   mv_limits->row_min = row_min;
428*fb1b10abSAndroid Build Coastguard Worker   mv_limits->row_max = row_max;
429*fb1b10abSAndroid Build Coastguard Worker   mv_limits->col_min = col_min;
430*fb1b10abSAndroid Build Coastguard Worker   mv_limits->col_max = col_max;
431*fb1b10abSAndroid Build Coastguard Worker   return 1;
432*fb1b10abSAndroid Build Coastguard Worker }
433*fb1b10abSAndroid Build Coastguard Worker 
first_pass_motion_search(VP9_COMP * cpi,MACROBLOCK * x,const MV * ref_mv,MV * best_mv,int * best_motion_err)434*fb1b10abSAndroid Build Coastguard Worker static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
435*fb1b10abSAndroid Build Coastguard Worker                                      const MV *ref_mv, MV *best_mv,
436*fb1b10abSAndroid Build Coastguard Worker                                      int *best_motion_err) {
437*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
438*fb1b10abSAndroid Build Coastguard Worker   MV tmp_mv = { 0, 0 };
439*fb1b10abSAndroid Build Coastguard Worker   MV ref_mv_full = { ref_mv->row >> 3, ref_mv->col >> 3 };
440*fb1b10abSAndroid Build Coastguard Worker   int num00, tmp_err, n;
441*fb1b10abSAndroid Build Coastguard Worker   const BLOCK_SIZE bsize = xd->mi[0]->sb_type;
442*fb1b10abSAndroid Build Coastguard Worker   vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
443*fb1b10abSAndroid Build Coastguard Worker   const int new_mv_mode_penalty = NEW_MV_MODE_PENALTY;
444*fb1b10abSAndroid Build Coastguard Worker   MV center_mv_full = ref_mv_full;
445*fb1b10abSAndroid Build Coastguard Worker   unsigned int start_mv_sad;
446*fb1b10abSAndroid Build Coastguard Worker   vp9_sad_fn_ptr_t sad_fn_ptr;
447*fb1b10abSAndroid Build Coastguard Worker 
448*fb1b10abSAndroid Build Coastguard Worker   int step_param = 3;
449*fb1b10abSAndroid Build Coastguard Worker   int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
450*fb1b10abSAndroid Build Coastguard Worker   const int sr = get_search_range(cpi);
451*fb1b10abSAndroid Build Coastguard Worker   const MvLimits tmp_mv_limits = x->mv_limits;
452*fb1b10abSAndroid Build Coastguard Worker   step_param += sr;
453*fb1b10abSAndroid Build Coastguard Worker   further_steps -= sr;
454*fb1b10abSAndroid Build Coastguard Worker 
455*fb1b10abSAndroid Build Coastguard Worker   if (!intersect_limits_with_mv_max(&x->mv_limits, ref_mv)) {
456*fb1b10abSAndroid Build Coastguard Worker     return;
457*fb1b10abSAndroid Build Coastguard Worker   }
458*fb1b10abSAndroid Build Coastguard Worker 
459*fb1b10abSAndroid Build Coastguard Worker   // Override the default variance function to use MSE.
460*fb1b10abSAndroid Build Coastguard Worker   v_fn_ptr.vf = get_block_variance_fn(bsize);
461*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
462*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
463*fb1b10abSAndroid Build Coastguard Worker     v_fn_ptr.vf = highbd_get_block_variance_fn(bsize, xd->bd);
464*fb1b10abSAndroid Build Coastguard Worker   }
465*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
466*fb1b10abSAndroid Build Coastguard Worker 
467*fb1b10abSAndroid Build Coastguard Worker   // Calculate SAD of the start mv
468*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(&ref_mv_full, x->mv_limits.col_min, x->mv_limits.col_max,
469*fb1b10abSAndroid Build Coastguard Worker            x->mv_limits.row_min, x->mv_limits.row_max);
470*fb1b10abSAndroid Build Coastguard Worker   start_mv_sad = get_start_mv_sad(x, &ref_mv_full, &center_mv_full,
471*fb1b10abSAndroid Build Coastguard Worker                                   cpi->fn_ptr[bsize].sdf, x->sadperbit16);
472*fb1b10abSAndroid Build Coastguard Worker   sad_fn_ptr.sdf = cpi->fn_ptr[bsize].sdf;
473*fb1b10abSAndroid Build Coastguard Worker   sad_fn_ptr.sdx4df = cpi->fn_ptr[bsize].sdx4df;
474*fb1b10abSAndroid Build Coastguard Worker 
475*fb1b10abSAndroid Build Coastguard Worker   // Center the initial step/diamond search on best mv.
476*fb1b10abSAndroid Build Coastguard Worker   tmp_err = cpi->diamond_search_sad(x, &cpi->ss_cfg, &ref_mv_full, start_mv_sad,
477*fb1b10abSAndroid Build Coastguard Worker                                     &tmp_mv, step_param, x->sadperbit16, &num00,
478*fb1b10abSAndroid Build Coastguard Worker                                     &sad_fn_ptr, ref_mv);
479*fb1b10abSAndroid Build Coastguard Worker   if (tmp_err < INT_MAX)
480*fb1b10abSAndroid Build Coastguard Worker     tmp_err = vp9_get_mvpred_var(x, &tmp_mv, ref_mv, &v_fn_ptr, 1);
481*fb1b10abSAndroid Build Coastguard Worker   if (tmp_err < INT_MAX - new_mv_mode_penalty) tmp_err += new_mv_mode_penalty;
482*fb1b10abSAndroid Build Coastguard Worker 
483*fb1b10abSAndroid Build Coastguard Worker   if (tmp_err < *best_motion_err) {
484*fb1b10abSAndroid Build Coastguard Worker     *best_motion_err = tmp_err;
485*fb1b10abSAndroid Build Coastguard Worker     *best_mv = tmp_mv;
486*fb1b10abSAndroid Build Coastguard Worker   }
487*fb1b10abSAndroid Build Coastguard Worker 
488*fb1b10abSAndroid Build Coastguard Worker   // Carry out further step/diamond searches as necessary.
489*fb1b10abSAndroid Build Coastguard Worker   n = num00;
490*fb1b10abSAndroid Build Coastguard Worker   num00 = 0;
491*fb1b10abSAndroid Build Coastguard Worker 
492*fb1b10abSAndroid Build Coastguard Worker   while (n < further_steps) {
493*fb1b10abSAndroid Build Coastguard Worker     ++n;
494*fb1b10abSAndroid Build Coastguard Worker 
495*fb1b10abSAndroid Build Coastguard Worker     if (num00) {
496*fb1b10abSAndroid Build Coastguard Worker       --num00;
497*fb1b10abSAndroid Build Coastguard Worker     } else {
498*fb1b10abSAndroid Build Coastguard Worker       tmp_err = cpi->diamond_search_sad(
499*fb1b10abSAndroid Build Coastguard Worker           x, &cpi->ss_cfg, &ref_mv_full, start_mv_sad, &tmp_mv, step_param + n,
500*fb1b10abSAndroid Build Coastguard Worker           x->sadperbit16, &num00, &sad_fn_ptr, ref_mv);
501*fb1b10abSAndroid Build Coastguard Worker       if (tmp_err < INT_MAX)
502*fb1b10abSAndroid Build Coastguard Worker         tmp_err = vp9_get_mvpred_var(x, &tmp_mv, ref_mv, &v_fn_ptr, 1);
503*fb1b10abSAndroid Build Coastguard Worker       if (tmp_err < INT_MAX - new_mv_mode_penalty)
504*fb1b10abSAndroid Build Coastguard Worker         tmp_err += new_mv_mode_penalty;
505*fb1b10abSAndroid Build Coastguard Worker 
506*fb1b10abSAndroid Build Coastguard Worker       if (tmp_err < *best_motion_err) {
507*fb1b10abSAndroid Build Coastguard Worker         *best_motion_err = tmp_err;
508*fb1b10abSAndroid Build Coastguard Worker         *best_mv = tmp_mv;
509*fb1b10abSAndroid Build Coastguard Worker       }
510*fb1b10abSAndroid Build Coastguard Worker     }
511*fb1b10abSAndroid Build Coastguard Worker   }
512*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits = tmp_mv_limits;
513*fb1b10abSAndroid Build Coastguard Worker }
514*fb1b10abSAndroid Build Coastguard Worker 
get_bsize(const VP9_COMMON * cm,int mb_row,int mb_col)515*fb1b10abSAndroid Build Coastguard Worker static BLOCK_SIZE get_bsize(const VP9_COMMON *cm, int mb_row, int mb_col) {
516*fb1b10abSAndroid Build Coastguard Worker   if (2 * mb_col + 1 < cm->mi_cols) {
517*fb1b10abSAndroid Build Coastguard Worker     return 2 * mb_row + 1 < cm->mi_rows ? BLOCK_16X16 : BLOCK_16X8;
518*fb1b10abSAndroid Build Coastguard Worker   } else {
519*fb1b10abSAndroid Build Coastguard Worker     return 2 * mb_row + 1 < cm->mi_rows ? BLOCK_8X16 : BLOCK_8X8;
520*fb1b10abSAndroid Build Coastguard Worker   }
521*fb1b10abSAndroid Build Coastguard Worker }
522*fb1b10abSAndroid Build Coastguard Worker 
find_fp_qindex(vpx_bit_depth_t bit_depth)523*fb1b10abSAndroid Build Coastguard Worker static int find_fp_qindex(vpx_bit_depth_t bit_depth) {
524*fb1b10abSAndroid Build Coastguard Worker   int i;
525*fb1b10abSAndroid Build Coastguard Worker 
526*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < QINDEX_RANGE; ++i)
527*fb1b10abSAndroid Build Coastguard Worker     if (vp9_convert_qindex_to_q(i, bit_depth) >= FIRST_PASS_Q) break;
528*fb1b10abSAndroid Build Coastguard Worker 
529*fb1b10abSAndroid Build Coastguard Worker   if (i == QINDEX_RANGE) i--;
530*fb1b10abSAndroid Build Coastguard Worker 
531*fb1b10abSAndroid Build Coastguard Worker   return i;
532*fb1b10abSAndroid Build Coastguard Worker }
533*fb1b10abSAndroid Build Coastguard Worker 
set_first_pass_params(VP9_COMP * cpi)534*fb1b10abSAndroid Build Coastguard Worker static void set_first_pass_params(VP9_COMP *cpi) {
535*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
536*fb1b10abSAndroid Build Coastguard Worker   if (!cpi->refresh_alt_ref_frame &&
537*fb1b10abSAndroid Build Coastguard Worker       (cm->current_video_frame == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY))) {
538*fb1b10abSAndroid Build Coastguard Worker     cm->frame_type = KEY_FRAME;
539*fb1b10abSAndroid Build Coastguard Worker   } else {
540*fb1b10abSAndroid Build Coastguard Worker     cm->frame_type = INTER_FRAME;
541*fb1b10abSAndroid Build Coastguard Worker   }
542*fb1b10abSAndroid Build Coastguard Worker   // Do not use periodic key frames.
543*fb1b10abSAndroid Build Coastguard Worker   cpi->rc.frames_to_key = INT_MAX;
544*fb1b10abSAndroid Build Coastguard Worker }
545*fb1b10abSAndroid Build Coastguard Worker 
546*fb1b10abSAndroid Build Coastguard Worker // Scale an sse threshold to account for 8/10/12 bit.
scale_sse_threshold(VP9_COMMON * cm,int thresh)547*fb1b10abSAndroid Build Coastguard Worker static int scale_sse_threshold(VP9_COMMON *cm, int thresh) {
548*fb1b10abSAndroid Build Coastguard Worker   int ret_val = thresh;
549*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
550*fb1b10abSAndroid Build Coastguard Worker   if (cm->use_highbitdepth) {
551*fb1b10abSAndroid Build Coastguard Worker     switch (cm->bit_depth) {
552*fb1b10abSAndroid Build Coastguard Worker       case VPX_BITS_8: ret_val = thresh; break;
553*fb1b10abSAndroid Build Coastguard Worker       case VPX_BITS_10: ret_val = thresh << 4; break;
554*fb1b10abSAndroid Build Coastguard Worker       default:
555*fb1b10abSAndroid Build Coastguard Worker         assert(cm->bit_depth == VPX_BITS_12);
556*fb1b10abSAndroid Build Coastguard Worker         ret_val = thresh << 8;
557*fb1b10abSAndroid Build Coastguard Worker         break;
558*fb1b10abSAndroid Build Coastguard Worker     }
559*fb1b10abSAndroid Build Coastguard Worker   }
560*fb1b10abSAndroid Build Coastguard Worker #else
561*fb1b10abSAndroid Build Coastguard Worker   (void)cm;
562*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
563*fb1b10abSAndroid Build Coastguard Worker   return ret_val;
564*fb1b10abSAndroid Build Coastguard Worker }
565*fb1b10abSAndroid Build Coastguard Worker 
566*fb1b10abSAndroid Build Coastguard Worker // This threshold is used to track blocks where to all intents and purposes
567*fb1b10abSAndroid Build Coastguard Worker // the intra prediction error 0. Though the metric we test against
568*fb1b10abSAndroid Build Coastguard Worker // is technically a sse we are mainly interested in blocks where all the pixels
569*fb1b10abSAndroid Build Coastguard Worker // in the 8 bit domain have an error of <= 1 (where error = sse) so a
570*fb1b10abSAndroid Build Coastguard Worker // linear scaling for 10 and 12 bit gives similar results.
571*fb1b10abSAndroid Build Coastguard Worker #define UL_INTRA_THRESH 50
get_ul_intra_threshold(VP9_COMMON * cm)572*fb1b10abSAndroid Build Coastguard Worker static int get_ul_intra_threshold(VP9_COMMON *cm) {
573*fb1b10abSAndroid Build Coastguard Worker   int ret_val = UL_INTRA_THRESH;
574*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
575*fb1b10abSAndroid Build Coastguard Worker   if (cm->use_highbitdepth) {
576*fb1b10abSAndroid Build Coastguard Worker     switch (cm->bit_depth) {
577*fb1b10abSAndroid Build Coastguard Worker       case VPX_BITS_8: ret_val = UL_INTRA_THRESH; break;
578*fb1b10abSAndroid Build Coastguard Worker       case VPX_BITS_10: ret_val = UL_INTRA_THRESH << 2; break;
579*fb1b10abSAndroid Build Coastguard Worker       default:
580*fb1b10abSAndroid Build Coastguard Worker         assert(cm->bit_depth == VPX_BITS_12);
581*fb1b10abSAndroid Build Coastguard Worker         ret_val = UL_INTRA_THRESH << 4;
582*fb1b10abSAndroid Build Coastguard Worker         break;
583*fb1b10abSAndroid Build Coastguard Worker     }
584*fb1b10abSAndroid Build Coastguard Worker   }
585*fb1b10abSAndroid Build Coastguard Worker #else
586*fb1b10abSAndroid Build Coastguard Worker   (void)cm;
587*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
588*fb1b10abSAndroid Build Coastguard Worker   return ret_val;
589*fb1b10abSAndroid Build Coastguard Worker }
590*fb1b10abSAndroid Build Coastguard Worker 
591*fb1b10abSAndroid Build Coastguard Worker #define SMOOTH_INTRA_THRESH 4000
get_smooth_intra_threshold(VP9_COMMON * cm)592*fb1b10abSAndroid Build Coastguard Worker static int get_smooth_intra_threshold(VP9_COMMON *cm) {
593*fb1b10abSAndroid Build Coastguard Worker   int ret_val = SMOOTH_INTRA_THRESH;
594*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
595*fb1b10abSAndroid Build Coastguard Worker   if (cm->use_highbitdepth) {
596*fb1b10abSAndroid Build Coastguard Worker     switch (cm->bit_depth) {
597*fb1b10abSAndroid Build Coastguard Worker       case VPX_BITS_8: ret_val = SMOOTH_INTRA_THRESH; break;
598*fb1b10abSAndroid Build Coastguard Worker       case VPX_BITS_10: ret_val = SMOOTH_INTRA_THRESH << 4; break;
599*fb1b10abSAndroid Build Coastguard Worker       default:
600*fb1b10abSAndroid Build Coastguard Worker         assert(cm->bit_depth == VPX_BITS_12);
601*fb1b10abSAndroid Build Coastguard Worker         ret_val = SMOOTH_INTRA_THRESH << 8;
602*fb1b10abSAndroid Build Coastguard Worker         break;
603*fb1b10abSAndroid Build Coastguard Worker     }
604*fb1b10abSAndroid Build Coastguard Worker   }
605*fb1b10abSAndroid Build Coastguard Worker #else
606*fb1b10abSAndroid Build Coastguard Worker   (void)cm;
607*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
608*fb1b10abSAndroid Build Coastguard Worker   return ret_val;
609*fb1b10abSAndroid Build Coastguard Worker }
610*fb1b10abSAndroid Build Coastguard Worker 
611*fb1b10abSAndroid Build Coastguard Worker #define FP_DN_THRESH 8
612*fb1b10abSAndroid Build Coastguard Worker #define FP_MAX_DN_THRESH 24
613*fb1b10abSAndroid Build Coastguard Worker #define KERNEL_SIZE 3
614*fb1b10abSAndroid Build Coastguard Worker 
615*fb1b10abSAndroid Build Coastguard Worker // Baseline Kernel weights for first pass noise metric
616*fb1b10abSAndroid Build Coastguard Worker static uint8_t fp_dn_kernel_3[KERNEL_SIZE * KERNEL_SIZE] = { 1, 2, 1, 2, 4,
617*fb1b10abSAndroid Build Coastguard Worker                                                              2, 1, 2, 1 };
618*fb1b10abSAndroid Build Coastguard Worker 
619*fb1b10abSAndroid Build Coastguard Worker // Estimate noise at a single point based on the impact of a spatial kernel
620*fb1b10abSAndroid Build Coastguard Worker // on the point value
fp_estimate_point_noise(uint8_t * src_ptr,const int stride)621*fb1b10abSAndroid Build Coastguard Worker static int fp_estimate_point_noise(uint8_t *src_ptr, const int stride) {
622*fb1b10abSAndroid Build Coastguard Worker   int sum_weight = 0;
623*fb1b10abSAndroid Build Coastguard Worker   int sum_val = 0;
624*fb1b10abSAndroid Build Coastguard Worker   int i, j;
625*fb1b10abSAndroid Build Coastguard Worker   int max_diff = 0;
626*fb1b10abSAndroid Build Coastguard Worker   int diff;
627*fb1b10abSAndroid Build Coastguard Worker   int dn_diff;
628*fb1b10abSAndroid Build Coastguard Worker   uint8_t *tmp_ptr;
629*fb1b10abSAndroid Build Coastguard Worker   uint8_t *kernel_ptr;
630*fb1b10abSAndroid Build Coastguard Worker   uint8_t dn_val;
631*fb1b10abSAndroid Build Coastguard Worker   uint8_t centre_val = *src_ptr;
632*fb1b10abSAndroid Build Coastguard Worker 
633*fb1b10abSAndroid Build Coastguard Worker   kernel_ptr = fp_dn_kernel_3;
634*fb1b10abSAndroid Build Coastguard Worker 
635*fb1b10abSAndroid Build Coastguard Worker   // Apply the kernel
636*fb1b10abSAndroid Build Coastguard Worker   tmp_ptr = src_ptr - stride - 1;
637*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < KERNEL_SIZE; ++i) {
638*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < KERNEL_SIZE; ++j) {
639*fb1b10abSAndroid Build Coastguard Worker       diff = abs((int)centre_val - (int)tmp_ptr[j]);
640*fb1b10abSAndroid Build Coastguard Worker       max_diff = VPXMAX(max_diff, diff);
641*fb1b10abSAndroid Build Coastguard Worker       if (diff <= FP_DN_THRESH) {
642*fb1b10abSAndroid Build Coastguard Worker         sum_weight += *kernel_ptr;
643*fb1b10abSAndroid Build Coastguard Worker         sum_val += (int)tmp_ptr[j] * (int)*kernel_ptr;
644*fb1b10abSAndroid Build Coastguard Worker       }
645*fb1b10abSAndroid Build Coastguard Worker       ++kernel_ptr;
646*fb1b10abSAndroid Build Coastguard Worker     }
647*fb1b10abSAndroid Build Coastguard Worker     tmp_ptr += stride;
648*fb1b10abSAndroid Build Coastguard Worker   }
649*fb1b10abSAndroid Build Coastguard Worker 
650*fb1b10abSAndroid Build Coastguard Worker   if (max_diff < FP_MAX_DN_THRESH)
651*fb1b10abSAndroid Build Coastguard Worker     // Update the source value with the new filtered value
652*fb1b10abSAndroid Build Coastguard Worker     dn_val = (sum_val + (sum_weight >> 1)) / sum_weight;
653*fb1b10abSAndroid Build Coastguard Worker   else
654*fb1b10abSAndroid Build Coastguard Worker     dn_val = *src_ptr;
655*fb1b10abSAndroid Build Coastguard Worker 
656*fb1b10abSAndroid Build Coastguard Worker   // return the noise energy as the square of the difference between the
657*fb1b10abSAndroid Build Coastguard Worker   // denoised and raw value.
658*fb1b10abSAndroid Build Coastguard Worker   dn_diff = (int)*src_ptr - (int)dn_val;
659*fb1b10abSAndroid Build Coastguard Worker   return dn_diff * dn_diff;
660*fb1b10abSAndroid Build Coastguard Worker }
661*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
fp_highbd_estimate_point_noise(uint8_t * src_ptr,const int stride)662*fb1b10abSAndroid Build Coastguard Worker static int fp_highbd_estimate_point_noise(uint8_t *src_ptr, const int stride) {
663*fb1b10abSAndroid Build Coastguard Worker   int sum_weight = 0;
664*fb1b10abSAndroid Build Coastguard Worker   int sum_val = 0;
665*fb1b10abSAndroid Build Coastguard Worker   int i, j;
666*fb1b10abSAndroid Build Coastguard Worker   int max_diff = 0;
667*fb1b10abSAndroid Build Coastguard Worker   int diff;
668*fb1b10abSAndroid Build Coastguard Worker   int dn_diff;
669*fb1b10abSAndroid Build Coastguard Worker   uint8_t *tmp_ptr;
670*fb1b10abSAndroid Build Coastguard Worker   uint16_t *tmp_ptr16;
671*fb1b10abSAndroid Build Coastguard Worker   uint8_t *kernel_ptr;
672*fb1b10abSAndroid Build Coastguard Worker   uint16_t dn_val;
673*fb1b10abSAndroid Build Coastguard Worker   uint16_t centre_val = *CONVERT_TO_SHORTPTR(src_ptr);
674*fb1b10abSAndroid Build Coastguard Worker 
675*fb1b10abSAndroid Build Coastguard Worker   kernel_ptr = fp_dn_kernel_3;
676*fb1b10abSAndroid Build Coastguard Worker 
677*fb1b10abSAndroid Build Coastguard Worker   // Apply the kernel
678*fb1b10abSAndroid Build Coastguard Worker   tmp_ptr = src_ptr - stride - 1;
679*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < KERNEL_SIZE; ++i) {
680*fb1b10abSAndroid Build Coastguard Worker     tmp_ptr16 = CONVERT_TO_SHORTPTR(tmp_ptr);
681*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < KERNEL_SIZE; ++j) {
682*fb1b10abSAndroid Build Coastguard Worker       diff = abs((int)centre_val - (int)tmp_ptr16[j]);
683*fb1b10abSAndroid Build Coastguard Worker       max_diff = VPXMAX(max_diff, diff);
684*fb1b10abSAndroid Build Coastguard Worker       if (diff <= FP_DN_THRESH) {
685*fb1b10abSAndroid Build Coastguard Worker         sum_weight += *kernel_ptr;
686*fb1b10abSAndroid Build Coastguard Worker         sum_val += (int)tmp_ptr16[j] * (int)*kernel_ptr;
687*fb1b10abSAndroid Build Coastguard Worker       }
688*fb1b10abSAndroid Build Coastguard Worker       ++kernel_ptr;
689*fb1b10abSAndroid Build Coastguard Worker     }
690*fb1b10abSAndroid Build Coastguard Worker     tmp_ptr += stride;
691*fb1b10abSAndroid Build Coastguard Worker   }
692*fb1b10abSAndroid Build Coastguard Worker 
693*fb1b10abSAndroid Build Coastguard Worker   if (max_diff < FP_MAX_DN_THRESH)
694*fb1b10abSAndroid Build Coastguard Worker     // Update the source value with the new filtered value
695*fb1b10abSAndroid Build Coastguard Worker     dn_val = (sum_val + (sum_weight >> 1)) / sum_weight;
696*fb1b10abSAndroid Build Coastguard Worker   else
697*fb1b10abSAndroid Build Coastguard Worker     dn_val = *CONVERT_TO_SHORTPTR(src_ptr);
698*fb1b10abSAndroid Build Coastguard Worker 
699*fb1b10abSAndroid Build Coastguard Worker   // return the noise energy as the square of the difference between the
700*fb1b10abSAndroid Build Coastguard Worker   // denoised and raw value.
701*fb1b10abSAndroid Build Coastguard Worker   dn_diff = (int)(*CONVERT_TO_SHORTPTR(src_ptr)) - (int)dn_val;
702*fb1b10abSAndroid Build Coastguard Worker   return dn_diff * dn_diff;
703*fb1b10abSAndroid Build Coastguard Worker }
704*fb1b10abSAndroid Build Coastguard Worker #endif
705*fb1b10abSAndroid Build Coastguard Worker 
706*fb1b10abSAndroid Build Coastguard Worker // Estimate noise for a block.
fp_estimate_block_noise(MACROBLOCK * x,BLOCK_SIZE bsize)707*fb1b10abSAndroid Build Coastguard Worker static int fp_estimate_block_noise(MACROBLOCK *x, BLOCK_SIZE bsize) {
708*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
709*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
710*fb1b10abSAndroid Build Coastguard Worker #endif
711*fb1b10abSAndroid Build Coastguard Worker   uint8_t *src_ptr = &x->plane[0].src.buf[0];
712*fb1b10abSAndroid Build Coastguard Worker   const int width = num_4x4_blocks_wide_lookup[bsize] * 4;
713*fb1b10abSAndroid Build Coastguard Worker   const int height = num_4x4_blocks_high_lookup[bsize] * 4;
714*fb1b10abSAndroid Build Coastguard Worker   int w, h;
715*fb1b10abSAndroid Build Coastguard Worker   int stride = x->plane[0].src.stride;
716*fb1b10abSAndroid Build Coastguard Worker   int block_noise = 0;
717*fb1b10abSAndroid Build Coastguard Worker 
718*fb1b10abSAndroid Build Coastguard Worker   // Sampled points to reduce cost overhead.
719*fb1b10abSAndroid Build Coastguard Worker   for (h = 0; h < height; h += 2) {
720*fb1b10abSAndroid Build Coastguard Worker     for (w = 0; w < width; w += 2) {
721*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
722*fb1b10abSAndroid Build Coastguard Worker       if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
723*fb1b10abSAndroid Build Coastguard Worker         block_noise += fp_highbd_estimate_point_noise(src_ptr, stride);
724*fb1b10abSAndroid Build Coastguard Worker       else
725*fb1b10abSAndroid Build Coastguard Worker         block_noise += fp_estimate_point_noise(src_ptr, stride);
726*fb1b10abSAndroid Build Coastguard Worker #else
727*fb1b10abSAndroid Build Coastguard Worker       block_noise += fp_estimate_point_noise(src_ptr, stride);
728*fb1b10abSAndroid Build Coastguard Worker #endif
729*fb1b10abSAndroid Build Coastguard Worker       ++src_ptr;
730*fb1b10abSAndroid Build Coastguard Worker     }
731*fb1b10abSAndroid Build Coastguard Worker     src_ptr += (stride - width);
732*fb1b10abSAndroid Build Coastguard Worker   }
733*fb1b10abSAndroid Build Coastguard Worker   return block_noise << 2;  // Scale << 2 to account for sampling.
734*fb1b10abSAndroid Build Coastguard Worker }
735*fb1b10abSAndroid Build Coastguard Worker 
736*fb1b10abSAndroid Build Coastguard Worker // This function is called to test the functionality of row based
737*fb1b10abSAndroid Build Coastguard Worker // multi-threading in unit tests for bit-exactness
accumulate_floating_point_stats(VP9_COMP * cpi,TileDataEnc * first_tile_col)738*fb1b10abSAndroid Build Coastguard Worker static void accumulate_floating_point_stats(VP9_COMP *cpi,
739*fb1b10abSAndroid Build Coastguard Worker                                             TileDataEnc *first_tile_col) {
740*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
741*fb1b10abSAndroid Build Coastguard Worker   int mb_row, mb_col;
742*fb1b10abSAndroid Build Coastguard Worker   first_tile_col->fp_data.intra_factor = 0;
743*fb1b10abSAndroid Build Coastguard Worker   first_tile_col->fp_data.brightness_factor = 0;
744*fb1b10abSAndroid Build Coastguard Worker   first_tile_col->fp_data.neutral_count = 0;
745*fb1b10abSAndroid Build Coastguard Worker   for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
746*fb1b10abSAndroid Build Coastguard Worker     for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
747*fb1b10abSAndroid Build Coastguard Worker       const int mb_index = mb_row * cm->mb_cols + mb_col;
748*fb1b10abSAndroid Build Coastguard Worker       first_tile_col->fp_data.intra_factor +=
749*fb1b10abSAndroid Build Coastguard Worker           cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_intra_factor;
750*fb1b10abSAndroid Build Coastguard Worker       first_tile_col->fp_data.brightness_factor +=
751*fb1b10abSAndroid Build Coastguard Worker           cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_brightness_factor;
752*fb1b10abSAndroid Build Coastguard Worker       first_tile_col->fp_data.neutral_count +=
753*fb1b10abSAndroid Build Coastguard Worker           cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_neutral_count;
754*fb1b10abSAndroid Build Coastguard Worker     }
755*fb1b10abSAndroid Build Coastguard Worker   }
756*fb1b10abSAndroid Build Coastguard Worker }
757*fb1b10abSAndroid Build Coastguard Worker 
first_pass_stat_calc(VP9_COMP * cpi,FIRSTPASS_STATS * fps,FIRSTPASS_DATA * fp_acc_data)758*fb1b10abSAndroid Build Coastguard Worker static void first_pass_stat_calc(VP9_COMP *cpi, FIRSTPASS_STATS *fps,
759*fb1b10abSAndroid Build Coastguard Worker                                  FIRSTPASS_DATA *fp_acc_data) {
760*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
761*fb1b10abSAndroid Build Coastguard Worker   // The minimum error here insures some bit allocation to frames even
762*fb1b10abSAndroid Build Coastguard Worker   // in static regions. The allocation per MB declines for larger formats
763*fb1b10abSAndroid Build Coastguard Worker   // where the typical "real" energy per MB also falls.
764*fb1b10abSAndroid Build Coastguard Worker   // Initial estimate here uses sqrt(mbs) to define the min_err, where the
765*fb1b10abSAndroid Build Coastguard Worker   // number of mbs is proportional to the image area.
766*fb1b10abSAndroid Build Coastguard Worker   const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs
767*fb1b10abSAndroid Build Coastguard Worker                                                              : cpi->common.MBs;
768*fb1b10abSAndroid Build Coastguard Worker   const double min_err = 200 * sqrt(num_mbs);
769*fb1b10abSAndroid Build Coastguard Worker 
770*fb1b10abSAndroid Build Coastguard Worker   // Clamp the image start to rows/2. This number of rows is discarded top
771*fb1b10abSAndroid Build Coastguard Worker   // and bottom as dead data so rows / 2 means the frame is blank.
772*fb1b10abSAndroid Build Coastguard Worker   if ((fp_acc_data->image_data_start_row > cm->mb_rows / 2) ||
773*fb1b10abSAndroid Build Coastguard Worker       (fp_acc_data->image_data_start_row == INVALID_ROW)) {
774*fb1b10abSAndroid Build Coastguard Worker     fp_acc_data->image_data_start_row = cm->mb_rows / 2;
775*fb1b10abSAndroid Build Coastguard Worker   }
776*fb1b10abSAndroid Build Coastguard Worker   // Exclude any image dead zone
777*fb1b10abSAndroid Build Coastguard Worker   if (fp_acc_data->image_data_start_row > 0) {
778*fb1b10abSAndroid Build Coastguard Worker     fp_acc_data->intra_skip_count =
779*fb1b10abSAndroid Build Coastguard Worker         VPXMAX(0, fp_acc_data->intra_skip_count -
780*fb1b10abSAndroid Build Coastguard Worker                       (fp_acc_data->image_data_start_row * cm->mb_cols * 2));
781*fb1b10abSAndroid Build Coastguard Worker   }
782*fb1b10abSAndroid Build Coastguard Worker 
783*fb1b10abSAndroid Build Coastguard Worker   fp_acc_data->intra_factor = fp_acc_data->intra_factor / (double)num_mbs;
784*fb1b10abSAndroid Build Coastguard Worker   fp_acc_data->brightness_factor =
785*fb1b10abSAndroid Build Coastguard Worker       fp_acc_data->brightness_factor / (double)num_mbs;
786*fb1b10abSAndroid Build Coastguard Worker   fps->weight = fp_acc_data->intra_factor * fp_acc_data->brightness_factor;
787*fb1b10abSAndroid Build Coastguard Worker 
788*fb1b10abSAndroid Build Coastguard Worker   fps->frame = cm->current_video_frame;
789*fb1b10abSAndroid Build Coastguard Worker   fps->spatial_layer_id = cpi->svc.spatial_layer_id;
790*fb1b10abSAndroid Build Coastguard Worker 
791*fb1b10abSAndroid Build Coastguard Worker   fps->coded_error =
792*fb1b10abSAndroid Build Coastguard Worker       ((double)(fp_acc_data->coded_error >> 8) + min_err) / num_mbs;
793*fb1b10abSAndroid Build Coastguard Worker   fps->sr_coded_error =
794*fb1b10abSAndroid Build Coastguard Worker       ((double)(fp_acc_data->sr_coded_error >> 8) + min_err) / num_mbs;
795*fb1b10abSAndroid Build Coastguard Worker   fps->intra_error =
796*fb1b10abSAndroid Build Coastguard Worker       ((double)(fp_acc_data->intra_error >> 8) + min_err) / num_mbs;
797*fb1b10abSAndroid Build Coastguard Worker 
798*fb1b10abSAndroid Build Coastguard Worker   fps->frame_noise_energy =
799*fb1b10abSAndroid Build Coastguard Worker       (double)(fp_acc_data->frame_noise_energy) / (double)num_mbs;
800*fb1b10abSAndroid Build Coastguard Worker   fps->count = 1.0;
801*fb1b10abSAndroid Build Coastguard Worker   fps->pcnt_inter = (double)(fp_acc_data->intercount) / num_mbs;
802*fb1b10abSAndroid Build Coastguard Worker   fps->pcnt_second_ref = (double)(fp_acc_data->second_ref_count) / num_mbs;
803*fb1b10abSAndroid Build Coastguard Worker   fps->pcnt_neutral = (double)(fp_acc_data->neutral_count) / num_mbs;
804*fb1b10abSAndroid Build Coastguard Worker   fps->pcnt_intra_low = (double)(fp_acc_data->intra_count_low) / num_mbs;
805*fb1b10abSAndroid Build Coastguard Worker   fps->pcnt_intra_high = (double)(fp_acc_data->intra_count_high) / num_mbs;
806*fb1b10abSAndroid Build Coastguard Worker   fps->intra_skip_pct = (double)(fp_acc_data->intra_skip_count) / num_mbs;
807*fb1b10abSAndroid Build Coastguard Worker   fps->intra_smooth_pct = (double)(fp_acc_data->intra_smooth_count) / num_mbs;
808*fb1b10abSAndroid Build Coastguard Worker   fps->inactive_zone_rows = (double)(fp_acc_data->image_data_start_row);
809*fb1b10abSAndroid Build Coastguard Worker   // Currently set to 0 as most issues relate to letter boxing.
810*fb1b10abSAndroid Build Coastguard Worker   fps->inactive_zone_cols = (double)0;
811*fb1b10abSAndroid Build Coastguard Worker 
812*fb1b10abSAndroid Build Coastguard Worker   if (fp_acc_data->mvcount > 0) {
813*fb1b10abSAndroid Build Coastguard Worker     fps->new_mv_count = (double)(fp_acc_data->new_mv_count) / num_mbs;
814*fb1b10abSAndroid Build Coastguard Worker     fps->MVr = (double)(fp_acc_data->sum_mvr) / fp_acc_data->mvcount;
815*fb1b10abSAndroid Build Coastguard Worker     fps->mvr_abs = (double)(fp_acc_data->sum_mvr_abs) / fp_acc_data->mvcount;
816*fb1b10abSAndroid Build Coastguard Worker     fps->MVc = (double)(fp_acc_data->sum_mvc) / fp_acc_data->mvcount;
817*fb1b10abSAndroid Build Coastguard Worker     fps->mvc_abs = (double)(fp_acc_data->sum_mvc_abs) / fp_acc_data->mvcount;
818*fb1b10abSAndroid Build Coastguard Worker     fps->MVrv = ((double)(fp_acc_data->sum_mvrs) -
819*fb1b10abSAndroid Build Coastguard Worker                  ((double)(fp_acc_data->sum_mvr) * (fp_acc_data->sum_mvr) /
820*fb1b10abSAndroid Build Coastguard Worker                   fp_acc_data->mvcount)) /
821*fb1b10abSAndroid Build Coastguard Worker                 fp_acc_data->mvcount;
822*fb1b10abSAndroid Build Coastguard Worker     fps->MVcv = ((double)(fp_acc_data->sum_mvcs) -
823*fb1b10abSAndroid Build Coastguard Worker                  ((double)(fp_acc_data->sum_mvc) * (fp_acc_data->sum_mvc) /
824*fb1b10abSAndroid Build Coastguard Worker                   fp_acc_data->mvcount)) /
825*fb1b10abSAndroid Build Coastguard Worker                 fp_acc_data->mvcount;
826*fb1b10abSAndroid Build Coastguard Worker     fps->mv_in_out_count =
827*fb1b10abSAndroid Build Coastguard Worker         (double)(fp_acc_data->sum_in_vectors) / (fp_acc_data->mvcount * 2);
828*fb1b10abSAndroid Build Coastguard Worker     fps->pcnt_motion = (double)(fp_acc_data->mvcount) / num_mbs;
829*fb1b10abSAndroid Build Coastguard Worker   } else {
830*fb1b10abSAndroid Build Coastguard Worker     fps->new_mv_count = 0.0;
831*fb1b10abSAndroid Build Coastguard Worker     fps->MVr = 0.0;
832*fb1b10abSAndroid Build Coastguard Worker     fps->mvr_abs = 0.0;
833*fb1b10abSAndroid Build Coastguard Worker     fps->MVc = 0.0;
834*fb1b10abSAndroid Build Coastguard Worker     fps->mvc_abs = 0.0;
835*fb1b10abSAndroid Build Coastguard Worker     fps->MVrv = 0.0;
836*fb1b10abSAndroid Build Coastguard Worker     fps->MVcv = 0.0;
837*fb1b10abSAndroid Build Coastguard Worker     fps->mv_in_out_count = 0.0;
838*fb1b10abSAndroid Build Coastguard Worker     fps->pcnt_motion = 0.0;
839*fb1b10abSAndroid Build Coastguard Worker   }
840*fb1b10abSAndroid Build Coastguard Worker }
841*fb1b10abSAndroid Build Coastguard Worker 
accumulate_fp_mb_row_stat(TileDataEnc * this_tile,FIRSTPASS_DATA * fp_acc_data)842*fb1b10abSAndroid Build Coastguard Worker static void accumulate_fp_mb_row_stat(TileDataEnc *this_tile,
843*fb1b10abSAndroid Build Coastguard Worker                                       FIRSTPASS_DATA *fp_acc_data) {
844*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.intra_factor += fp_acc_data->intra_factor;
845*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.brightness_factor += fp_acc_data->brightness_factor;
846*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.coded_error += fp_acc_data->coded_error;
847*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sr_coded_error += fp_acc_data->sr_coded_error;
848*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.frame_noise_energy += fp_acc_data->frame_noise_energy;
849*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.intra_error += fp_acc_data->intra_error;
850*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.intercount += fp_acc_data->intercount;
851*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.second_ref_count += fp_acc_data->second_ref_count;
852*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.neutral_count += fp_acc_data->neutral_count;
853*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.intra_count_low += fp_acc_data->intra_count_low;
854*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.intra_count_high += fp_acc_data->intra_count_high;
855*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.intra_skip_count += fp_acc_data->intra_skip_count;
856*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.new_mv_count += fp_acc_data->new_mv_count;
857*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.mvcount += fp_acc_data->mvcount;
858*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sum_mvr += fp_acc_data->sum_mvr;
859*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sum_mvr_abs += fp_acc_data->sum_mvr_abs;
860*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sum_mvc += fp_acc_data->sum_mvc;
861*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sum_mvc_abs += fp_acc_data->sum_mvc_abs;
862*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sum_mvrs += fp_acc_data->sum_mvrs;
863*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sum_mvcs += fp_acc_data->sum_mvcs;
864*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.sum_in_vectors += fp_acc_data->sum_in_vectors;
865*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.intra_smooth_count += fp_acc_data->intra_smooth_count;
866*fb1b10abSAndroid Build Coastguard Worker   this_tile->fp_data.image_data_start_row =
867*fb1b10abSAndroid Build Coastguard Worker       VPXMIN(this_tile->fp_data.image_data_start_row,
868*fb1b10abSAndroid Build Coastguard Worker              fp_acc_data->image_data_start_row) == INVALID_ROW
869*fb1b10abSAndroid Build Coastguard Worker           ? VPXMAX(this_tile->fp_data.image_data_start_row,
870*fb1b10abSAndroid Build Coastguard Worker                    fp_acc_data->image_data_start_row)
871*fb1b10abSAndroid Build Coastguard Worker           : VPXMIN(this_tile->fp_data.image_data_start_row,
872*fb1b10abSAndroid Build Coastguard Worker                    fp_acc_data->image_data_start_row);
873*fb1b10abSAndroid Build Coastguard Worker }
874*fb1b10abSAndroid Build Coastguard Worker 
875*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
store_fp_motion_vector(VP9_COMP * cpi,const MV * mv,const int mb_row,const int mb_col,MV_REFERENCE_FRAME frame_type,const int mv_idx)876*fb1b10abSAndroid Build Coastguard Worker static void store_fp_motion_vector(VP9_COMP *cpi, const MV *mv,
877*fb1b10abSAndroid Build Coastguard Worker                                    const int mb_row, const int mb_col,
878*fb1b10abSAndroid Build Coastguard Worker                                    MV_REFERENCE_FRAME frame_type,
879*fb1b10abSAndroid Build Coastguard Worker                                    const int mv_idx) {
880*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
881*fb1b10abSAndroid Build Coastguard Worker   const int mb_index = mb_row * cm->mb_cols + mb_col;
882*fb1b10abSAndroid Build Coastguard Worker   MOTION_VECTOR_INFO *this_motion_vector_info =
883*fb1b10abSAndroid Build Coastguard Worker       &cpi->fp_motion_vector_info[mb_index];
884*fb1b10abSAndroid Build Coastguard Worker   this_motion_vector_info->ref_frame[mv_idx] = frame_type;
885*fb1b10abSAndroid Build Coastguard Worker   if (frame_type != INTRA_FRAME) {
886*fb1b10abSAndroid Build Coastguard Worker     this_motion_vector_info->mv[mv_idx].as_mv = *mv;
887*fb1b10abSAndroid Build Coastguard Worker   }
888*fb1b10abSAndroid Build Coastguard Worker }
889*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RATE_CTRL
890*fb1b10abSAndroid Build Coastguard Worker 
891*fb1b10abSAndroid Build Coastguard Worker #define NZ_MOTION_PENALTY 128
892*fb1b10abSAndroid Build Coastguard Worker #define INTRA_MODE_PENALTY 1024
vp9_first_pass_encode_tile_mb_row(VP9_COMP * cpi,ThreadData * td,FIRSTPASS_DATA * fp_acc_data,TileDataEnc * tile_data,MV * best_ref_mv,int mb_row)893*fb1b10abSAndroid Build Coastguard Worker void vp9_first_pass_encode_tile_mb_row(VP9_COMP *cpi, ThreadData *td,
894*fb1b10abSAndroid Build Coastguard Worker                                        FIRSTPASS_DATA *fp_acc_data,
895*fb1b10abSAndroid Build Coastguard Worker                                        TileDataEnc *tile_data, MV *best_ref_mv,
896*fb1b10abSAndroid Build Coastguard Worker                                        int mb_row) {
897*fb1b10abSAndroid Build Coastguard Worker   int mb_col;
898*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = &td->mb;
899*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
900*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
901*fb1b10abSAndroid Build Coastguard Worker   TileInfo tile = tile_data->tile_info;
902*fb1b10abSAndroid Build Coastguard Worker   const int mb_col_start = ROUND_POWER_OF_TWO(tile.mi_col_start, 1);
903*fb1b10abSAndroid Build Coastguard Worker   const int mb_col_end = ROUND_POWER_OF_TWO(tile.mi_col_end, 1);
904*fb1b10abSAndroid Build Coastguard Worker   struct macroblock_plane *const p = x->plane;
905*fb1b10abSAndroid Build Coastguard Worker   struct macroblockd_plane *const pd = xd->plane;
906*fb1b10abSAndroid Build Coastguard Worker   const PICK_MODE_CONTEXT *ctx = &td->pc_root->none;
907*fb1b10abSAndroid Build Coastguard Worker   int i, c;
908*fb1b10abSAndroid Build Coastguard Worker   int num_mb_cols = get_num_cols(tile_data->tile_info, 1);
909*fb1b10abSAndroid Build Coastguard Worker 
910*fb1b10abSAndroid Build Coastguard Worker   int recon_yoffset, recon_uvoffset;
911*fb1b10abSAndroid Build Coastguard Worker   const int intrapenalty = INTRA_MODE_PENALTY;
912*fb1b10abSAndroid Build Coastguard Worker   const MV zero_mv = { 0, 0 };
913*fb1b10abSAndroid Build Coastguard Worker   int recon_y_stride, recon_uv_stride, uv_mb_height;
914*fb1b10abSAndroid Build Coastguard Worker 
915*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
916*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
917*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
918*fb1b10abSAndroid Build Coastguard Worker   const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
919*fb1b10abSAndroid Build Coastguard Worker 
920*fb1b10abSAndroid Build Coastguard Worker   MODE_INFO mi_above, mi_left;
921*fb1b10abSAndroid Build Coastguard Worker 
922*fb1b10abSAndroid Build Coastguard Worker   double mb_intra_factor;
923*fb1b10abSAndroid Build Coastguard Worker   double mb_brightness_factor;
924*fb1b10abSAndroid Build Coastguard Worker   double mb_neutral_count;
925*fb1b10abSAndroid Build Coastguard Worker   int scaled_low_intra_thresh = scale_sse_threshold(cm, LOW_I_THRESH);
926*fb1b10abSAndroid Build Coastguard Worker 
927*fb1b10abSAndroid Build Coastguard Worker   MV *first_top_mv = &tile_data->firstpass_top_mv;
928*fb1b10abSAndroid Build Coastguard Worker   MV last_nonzero_mv = { 0, 0 };
929*fb1b10abSAndroid Build Coastguard Worker 
930*fb1b10abSAndroid Build Coastguard Worker   // First pass code requires valid last and new frame buffers.
931*fb1b10abSAndroid Build Coastguard Worker   assert(new_yv12 != NULL);
932*fb1b10abSAndroid Build Coastguard Worker   assert(frame_is_intra_only(cm) || (lst_yv12 != NULL));
933*fb1b10abSAndroid Build Coastguard Worker 
934*fb1b10abSAndroid Build Coastguard Worker   xd->mi = cm->mi_grid_visible + xd->mi_stride * (mb_row << 1) + mb_col_start;
935*fb1b10abSAndroid Build Coastguard Worker   xd->mi[0] = cm->mi + xd->mi_stride * (mb_row << 1) + mb_col_start;
936*fb1b10abSAndroid Build Coastguard Worker 
937*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < MAX_MB_PLANE; ++i) {
938*fb1b10abSAndroid Build Coastguard Worker     p[i].coeff = ctx->coeff_pbuf[i][1];
939*fb1b10abSAndroid Build Coastguard Worker     p[i].qcoeff = ctx->qcoeff_pbuf[i][1];
940*fb1b10abSAndroid Build Coastguard Worker     pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][1];
941*fb1b10abSAndroid Build Coastguard Worker     p[i].eobs = ctx->eobs_pbuf[i][1];
942*fb1b10abSAndroid Build Coastguard Worker   }
943*fb1b10abSAndroid Build Coastguard Worker 
944*fb1b10abSAndroid Build Coastguard Worker   recon_y_stride = new_yv12->y_stride;
945*fb1b10abSAndroid Build Coastguard Worker   recon_uv_stride = new_yv12->uv_stride;
946*fb1b10abSAndroid Build Coastguard Worker   uv_mb_height = 16 >> (new_yv12->y_height > new_yv12->uv_height);
947*fb1b10abSAndroid Build Coastguard Worker 
948*fb1b10abSAndroid Build Coastguard Worker   // Reset above block coeffs.
949*fb1b10abSAndroid Build Coastguard Worker   recon_yoffset = (mb_row * recon_y_stride * 16) + mb_col_start * 16;
950*fb1b10abSAndroid Build Coastguard Worker   recon_uvoffset =
951*fb1b10abSAndroid Build Coastguard Worker       (mb_row * recon_uv_stride * uv_mb_height) + mb_col_start * uv_mb_height;
952*fb1b10abSAndroid Build Coastguard Worker 
953*fb1b10abSAndroid Build Coastguard Worker   // Set up limit values for motion vectors to prevent them extending
954*fb1b10abSAndroid Build Coastguard Worker   // outside the UMV borders.
955*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits.row_min = -((mb_row * 16) + BORDER_MV_PIXELS_B16);
956*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits.row_max =
957*fb1b10abSAndroid Build Coastguard Worker       ((cm->mb_rows - 1 - mb_row) * 16) + BORDER_MV_PIXELS_B16;
958*fb1b10abSAndroid Build Coastguard Worker 
959*fb1b10abSAndroid Build Coastguard Worker   for (mb_col = mb_col_start, c = 0; mb_col < mb_col_end; ++mb_col, c++) {
960*fb1b10abSAndroid Build Coastguard Worker     int this_error;
961*fb1b10abSAndroid Build Coastguard Worker     int this_intra_error;
962*fb1b10abSAndroid Build Coastguard Worker     const int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
963*fb1b10abSAndroid Build Coastguard Worker     const BLOCK_SIZE bsize = get_bsize(cm, mb_row, mb_col);
964*fb1b10abSAndroid Build Coastguard Worker     double log_intra;
965*fb1b10abSAndroid Build Coastguard Worker     int level_sample;
966*fb1b10abSAndroid Build Coastguard Worker     const int mb_index = mb_row * cm->mb_cols + mb_col;
967*fb1b10abSAndroid Build Coastguard Worker 
968*fb1b10abSAndroid Build Coastguard Worker     (*(cpi->row_mt_sync_read_ptr))(&tile_data->row_mt_sync, mb_row, c);
969*fb1b10abSAndroid Build Coastguard Worker 
970*fb1b10abSAndroid Build Coastguard Worker     if (mb_col == mb_col_start) {
971*fb1b10abSAndroid Build Coastguard Worker       last_nonzero_mv = *first_top_mv;
972*fb1b10abSAndroid Build Coastguard Worker     }
973*fb1b10abSAndroid Build Coastguard Worker 
974*fb1b10abSAndroid Build Coastguard Worker     // Adjust to the next column of MBs.
975*fb1b10abSAndroid Build Coastguard Worker     x->plane[0].src.buf = cpi->Source->y_buffer +
976*fb1b10abSAndroid Build Coastguard Worker                           mb_row * 16 * x->plane[0].src.stride + mb_col * 16;
977*fb1b10abSAndroid Build Coastguard Worker     x->plane[1].src.buf = cpi->Source->u_buffer +
978*fb1b10abSAndroid Build Coastguard Worker                           mb_row * uv_mb_height * x->plane[1].src.stride +
979*fb1b10abSAndroid Build Coastguard Worker                           mb_col * uv_mb_height;
980*fb1b10abSAndroid Build Coastguard Worker     x->plane[2].src.buf = cpi->Source->v_buffer +
981*fb1b10abSAndroid Build Coastguard Worker                           mb_row * uv_mb_height * x->plane[1].src.stride +
982*fb1b10abSAndroid Build Coastguard Worker                           mb_col * uv_mb_height;
983*fb1b10abSAndroid Build Coastguard Worker 
984*fb1b10abSAndroid Build Coastguard Worker     vpx_clear_system_state();
985*fb1b10abSAndroid Build Coastguard Worker 
986*fb1b10abSAndroid Build Coastguard Worker     xd->plane[0].dst.buf = new_yv12->y_buffer + recon_yoffset;
987*fb1b10abSAndroid Build Coastguard Worker     xd->plane[1].dst.buf = new_yv12->u_buffer + recon_uvoffset;
988*fb1b10abSAndroid Build Coastguard Worker     xd->plane[2].dst.buf = new_yv12->v_buffer + recon_uvoffset;
989*fb1b10abSAndroid Build Coastguard Worker     xd->mi[0]->sb_type = bsize;
990*fb1b10abSAndroid Build Coastguard Worker     xd->mi[0]->ref_frame[0] = INTRA_FRAME;
991*fb1b10abSAndroid Build Coastguard Worker     set_mi_row_col(xd, &tile, mb_row << 1, num_8x8_blocks_high_lookup[bsize],
992*fb1b10abSAndroid Build Coastguard Worker                    mb_col << 1, num_8x8_blocks_wide_lookup[bsize], cm->mi_rows,
993*fb1b10abSAndroid Build Coastguard Worker                    cm->mi_cols);
994*fb1b10abSAndroid Build Coastguard Worker     // Are edges available for intra prediction?
995*fb1b10abSAndroid Build Coastguard Worker     // Since the firstpass does not populate the mi_grid_visible,
996*fb1b10abSAndroid Build Coastguard Worker     // above_mi/left_mi must be overwritten with a nonzero value when edges
997*fb1b10abSAndroid Build Coastguard Worker     // are available.  Required by vp9_predict_intra_block().
998*fb1b10abSAndroid Build Coastguard Worker     xd->above_mi = (mb_row != 0) ? &mi_above : NULL;
999*fb1b10abSAndroid Build Coastguard Worker     xd->left_mi = ((mb_col << 1) > tile.mi_col_start) ? &mi_left : NULL;
1000*fb1b10abSAndroid Build Coastguard Worker 
1001*fb1b10abSAndroid Build Coastguard Worker     // Do intra 16x16 prediction.
1002*fb1b10abSAndroid Build Coastguard Worker     x->skip_encode = 0;
1003*fb1b10abSAndroid Build Coastguard Worker     x->fp_src_pred = 0;
1004*fb1b10abSAndroid Build Coastguard Worker     // Do intra prediction based on source pixels for tile boundaries
1005*fb1b10abSAndroid Build Coastguard Worker     if (mb_col == mb_col_start && mb_col != 0) {
1006*fb1b10abSAndroid Build Coastguard Worker       xd->left_mi = &mi_left;
1007*fb1b10abSAndroid Build Coastguard Worker       x->fp_src_pred = 1;
1008*fb1b10abSAndroid Build Coastguard Worker     }
1009*fb1b10abSAndroid Build Coastguard Worker     xd->mi[0]->mode = DC_PRED;
1010*fb1b10abSAndroid Build Coastguard Worker     xd->mi[0]->tx_size =
1011*fb1b10abSAndroid Build Coastguard Worker         use_dc_pred ? (bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4;
1012*fb1b10abSAndroid Build Coastguard Worker     // Fix - zero the 16x16 block first. This ensures correct this_error for
1013*fb1b10abSAndroid Build Coastguard Worker     // block sizes smaller than 16x16.
1014*fb1b10abSAndroid Build Coastguard Worker     vp9_zero_array(x->plane[0].src_diff, 256);
1015*fb1b10abSAndroid Build Coastguard Worker     vp9_encode_intra_block_plane(x, bsize, 0, 0);
1016*fb1b10abSAndroid Build Coastguard Worker     this_error = vpx_get_mb_ss(x->plane[0].src_diff);
1017*fb1b10abSAndroid Build Coastguard Worker     this_intra_error = this_error;
1018*fb1b10abSAndroid Build Coastguard Worker 
1019*fb1b10abSAndroid Build Coastguard Worker     // Keep a record of blocks that have very low intra error residual
1020*fb1b10abSAndroid Build Coastguard Worker     // (i.e. are in effect completely flat and untextured in the intra
1021*fb1b10abSAndroid Build Coastguard Worker     // domain). In natural videos this is uncommon, but it is much more
1022*fb1b10abSAndroid Build Coastguard Worker     // common in animations, graphics and screen content, so may be used
1023*fb1b10abSAndroid Build Coastguard Worker     // as a signal to detect these types of content.
1024*fb1b10abSAndroid Build Coastguard Worker     if (this_error < get_ul_intra_threshold(cm)) {
1025*fb1b10abSAndroid Build Coastguard Worker       ++(fp_acc_data->intra_skip_count);
1026*fb1b10abSAndroid Build Coastguard Worker     } else if ((mb_col > 0) &&
1027*fb1b10abSAndroid Build Coastguard Worker                (fp_acc_data->image_data_start_row == INVALID_ROW)) {
1028*fb1b10abSAndroid Build Coastguard Worker       fp_acc_data->image_data_start_row = mb_row;
1029*fb1b10abSAndroid Build Coastguard Worker     }
1030*fb1b10abSAndroid Build Coastguard Worker 
1031*fb1b10abSAndroid Build Coastguard Worker     // Blocks that are mainly smooth in the intra domain.
1032*fb1b10abSAndroid Build Coastguard Worker     // Some special accounting for CQ but also these are better for testing
1033*fb1b10abSAndroid Build Coastguard Worker     // noise levels.
1034*fb1b10abSAndroid Build Coastguard Worker     if (this_error < get_smooth_intra_threshold(cm)) {
1035*fb1b10abSAndroid Build Coastguard Worker       ++(fp_acc_data->intra_smooth_count);
1036*fb1b10abSAndroid Build Coastguard Worker     }
1037*fb1b10abSAndroid Build Coastguard Worker 
1038*fb1b10abSAndroid Build Coastguard Worker     // Special case noise measurement for first frame.
1039*fb1b10abSAndroid Build Coastguard Worker     if (cm->current_video_frame == 0) {
1040*fb1b10abSAndroid Build Coastguard Worker       if (this_intra_error < scale_sse_threshold(cm, LOW_I_THRESH)) {
1041*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->frame_noise_energy += fp_estimate_block_noise(x, bsize);
1042*fb1b10abSAndroid Build Coastguard Worker       } else {
1043*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->frame_noise_energy += (int64_t)SECTION_NOISE_DEF;
1044*fb1b10abSAndroid Build Coastguard Worker       }
1045*fb1b10abSAndroid Build Coastguard Worker     }
1046*fb1b10abSAndroid Build Coastguard Worker 
1047*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1048*fb1b10abSAndroid Build Coastguard Worker     if (cm->use_highbitdepth) {
1049*fb1b10abSAndroid Build Coastguard Worker       switch (cm->bit_depth) {
1050*fb1b10abSAndroid Build Coastguard Worker         case VPX_BITS_8: break;
1051*fb1b10abSAndroid Build Coastguard Worker         case VPX_BITS_10: this_error >>= 4; break;
1052*fb1b10abSAndroid Build Coastguard Worker         default:
1053*fb1b10abSAndroid Build Coastguard Worker           assert(cm->bit_depth == VPX_BITS_12);
1054*fb1b10abSAndroid Build Coastguard Worker           this_error >>= 8;
1055*fb1b10abSAndroid Build Coastguard Worker           break;
1056*fb1b10abSAndroid Build Coastguard Worker       }
1057*fb1b10abSAndroid Build Coastguard Worker     }
1058*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
1059*fb1b10abSAndroid Build Coastguard Worker 
1060*fb1b10abSAndroid Build Coastguard Worker     vpx_clear_system_state();
1061*fb1b10abSAndroid Build Coastguard Worker     log_intra = log(this_error + 1.0);
1062*fb1b10abSAndroid Build Coastguard Worker     if (log_intra < 10.0) {
1063*fb1b10abSAndroid Build Coastguard Worker       mb_intra_factor = 1.0 + ((10.0 - log_intra) * 0.05);
1064*fb1b10abSAndroid Build Coastguard Worker       fp_acc_data->intra_factor += mb_intra_factor;
1065*fb1b10abSAndroid Build Coastguard Worker       if (cpi->row_mt_bit_exact)
1066*fb1b10abSAndroid Build Coastguard Worker         cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_intra_factor =
1067*fb1b10abSAndroid Build Coastguard Worker             mb_intra_factor;
1068*fb1b10abSAndroid Build Coastguard Worker     } else {
1069*fb1b10abSAndroid Build Coastguard Worker       fp_acc_data->intra_factor += 1.0;
1070*fb1b10abSAndroid Build Coastguard Worker       if (cpi->row_mt_bit_exact)
1071*fb1b10abSAndroid Build Coastguard Worker         cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_intra_factor = 1.0;
1072*fb1b10abSAndroid Build Coastguard Worker     }
1073*fb1b10abSAndroid Build Coastguard Worker 
1074*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1075*fb1b10abSAndroid Build Coastguard Worker     if (cm->use_highbitdepth)
1076*fb1b10abSAndroid Build Coastguard Worker       level_sample = CONVERT_TO_SHORTPTR(x->plane[0].src.buf)[0];
1077*fb1b10abSAndroid Build Coastguard Worker     else
1078*fb1b10abSAndroid Build Coastguard Worker       level_sample = x->plane[0].src.buf[0];
1079*fb1b10abSAndroid Build Coastguard Worker #else
1080*fb1b10abSAndroid Build Coastguard Worker     level_sample = x->plane[0].src.buf[0];
1081*fb1b10abSAndroid Build Coastguard Worker #endif
1082*fb1b10abSAndroid Build Coastguard Worker     if ((level_sample < DARK_THRESH) && (log_intra < 9.0)) {
1083*fb1b10abSAndroid Build Coastguard Worker       mb_brightness_factor = 1.0 + (0.01 * (DARK_THRESH - level_sample));
1084*fb1b10abSAndroid Build Coastguard Worker       fp_acc_data->brightness_factor += mb_brightness_factor;
1085*fb1b10abSAndroid Build Coastguard Worker       if (cpi->row_mt_bit_exact)
1086*fb1b10abSAndroid Build Coastguard Worker         cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_brightness_factor =
1087*fb1b10abSAndroid Build Coastguard Worker             mb_brightness_factor;
1088*fb1b10abSAndroid Build Coastguard Worker     } else {
1089*fb1b10abSAndroid Build Coastguard Worker       fp_acc_data->brightness_factor += 1.0;
1090*fb1b10abSAndroid Build Coastguard Worker       if (cpi->row_mt_bit_exact)
1091*fb1b10abSAndroid Build Coastguard Worker         cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_brightness_factor =
1092*fb1b10abSAndroid Build Coastguard Worker             1.0;
1093*fb1b10abSAndroid Build Coastguard Worker     }
1094*fb1b10abSAndroid Build Coastguard Worker 
1095*fb1b10abSAndroid Build Coastguard Worker     // Intrapenalty below deals with situations where the intra and inter
1096*fb1b10abSAndroid Build Coastguard Worker     // error scores are very low (e.g. a plain black frame).
1097*fb1b10abSAndroid Build Coastguard Worker     // We do not have special cases in first pass for 0,0 and nearest etc so
1098*fb1b10abSAndroid Build Coastguard Worker     // all inter modes carry an overhead cost estimate for the mv.
1099*fb1b10abSAndroid Build Coastguard Worker     // When the error score is very low this causes us to pick all or lots of
1100*fb1b10abSAndroid Build Coastguard Worker     // INTRA modes and throw lots of key frames.
1101*fb1b10abSAndroid Build Coastguard Worker     // This penalty adds a cost matching that of a 0,0 mv to the intra case.
1102*fb1b10abSAndroid Build Coastguard Worker     this_error += intrapenalty;
1103*fb1b10abSAndroid Build Coastguard Worker 
1104*fb1b10abSAndroid Build Coastguard Worker     // Accumulate the intra error.
1105*fb1b10abSAndroid Build Coastguard Worker     fp_acc_data->intra_error += (int64_t)this_error;
1106*fb1b10abSAndroid Build Coastguard Worker 
1107*fb1b10abSAndroid Build Coastguard Worker     // Set up limit values for motion vectors to prevent them extending
1108*fb1b10abSAndroid Build Coastguard Worker     // outside the UMV borders.
1109*fb1b10abSAndroid Build Coastguard Worker     x->mv_limits.col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16);
1110*fb1b10abSAndroid Build Coastguard Worker     x->mv_limits.col_max =
1111*fb1b10abSAndroid Build Coastguard Worker         ((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16;
1112*fb1b10abSAndroid Build Coastguard Worker 
1113*fb1b10abSAndroid Build Coastguard Worker     // Other than for intra-only frame do a motion search.
1114*fb1b10abSAndroid Build Coastguard Worker     if (!frame_is_intra_only(cm)) {
1115*fb1b10abSAndroid Build Coastguard Worker       int tmp_err, motion_error, this_motion_error, raw_motion_error;
1116*fb1b10abSAndroid Build Coastguard Worker       // Assume 0,0 motion with no mv overhead.
1117*fb1b10abSAndroid Build Coastguard Worker       MV mv = { 0, 0 }, tmp_mv = { 0, 0 };
1118*fb1b10abSAndroid Build Coastguard Worker       struct buf_2d unscaled_last_source_buf_2d;
1119*fb1b10abSAndroid Build Coastguard Worker       vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
1120*fb1b10abSAndroid Build Coastguard Worker 
1121*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
1122*fb1b10abSAndroid Build Coastguard Worker       if (cpi->oxcf.use_simple_encode_api) {
1123*fb1b10abSAndroid Build Coastguard Worker         // Store zero mv as default
1124*fb1b10abSAndroid Build Coastguard Worker         store_fp_motion_vector(cpi, &mv, mb_row, mb_col, LAST_FRAME, 0);
1125*fb1b10abSAndroid Build Coastguard Worker       }
1126*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RAGE_CTRL
1127*fb1b10abSAndroid Build Coastguard Worker 
1128*fb1b10abSAndroid Build Coastguard Worker       xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
1129*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1130*fb1b10abSAndroid Build Coastguard Worker       if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1131*fb1b10abSAndroid Build Coastguard Worker         motion_error = highbd_get_prediction_error(
1132*fb1b10abSAndroid Build Coastguard Worker             bsize, &x->plane[0].src, &xd->plane[0].pre[0], xd->bd);
1133*fb1b10abSAndroid Build Coastguard Worker         this_motion_error = highbd_get_prediction_error(
1134*fb1b10abSAndroid Build Coastguard Worker             bsize, &x->plane[0].src, &xd->plane[0].pre[0], 8);
1135*fb1b10abSAndroid Build Coastguard Worker       } else {
1136*fb1b10abSAndroid Build Coastguard Worker         motion_error =
1137*fb1b10abSAndroid Build Coastguard Worker             get_prediction_error(bsize, &x->plane[0].src, &xd->plane[0].pre[0]);
1138*fb1b10abSAndroid Build Coastguard Worker         this_motion_error = motion_error;
1139*fb1b10abSAndroid Build Coastguard Worker       }
1140*fb1b10abSAndroid Build Coastguard Worker #else
1141*fb1b10abSAndroid Build Coastguard Worker       motion_error =
1142*fb1b10abSAndroid Build Coastguard Worker           get_prediction_error(bsize, &x->plane[0].src, &xd->plane[0].pre[0]);
1143*fb1b10abSAndroid Build Coastguard Worker       this_motion_error = motion_error;
1144*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
1145*fb1b10abSAndroid Build Coastguard Worker 
1146*fb1b10abSAndroid Build Coastguard Worker       // Compute the motion error of the 0,0 motion using the last source
1147*fb1b10abSAndroid Build Coastguard Worker       // frame as the reference. Skip the further motion search on
1148*fb1b10abSAndroid Build Coastguard Worker       // reconstructed frame if this error is very small.
1149*fb1b10abSAndroid Build Coastguard Worker       unscaled_last_source_buf_2d.buf =
1150*fb1b10abSAndroid Build Coastguard Worker           cpi->unscaled_last_source->y_buffer + recon_yoffset;
1151*fb1b10abSAndroid Build Coastguard Worker       unscaled_last_source_buf_2d.stride = cpi->unscaled_last_source->y_stride;
1152*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1153*fb1b10abSAndroid Build Coastguard Worker       if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1154*fb1b10abSAndroid Build Coastguard Worker         raw_motion_error = highbd_get_prediction_error(
1155*fb1b10abSAndroid Build Coastguard Worker             bsize, &x->plane[0].src, &unscaled_last_source_buf_2d, xd->bd);
1156*fb1b10abSAndroid Build Coastguard Worker       } else {
1157*fb1b10abSAndroid Build Coastguard Worker         raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
1158*fb1b10abSAndroid Build Coastguard Worker                                                 &unscaled_last_source_buf_2d);
1159*fb1b10abSAndroid Build Coastguard Worker       }
1160*fb1b10abSAndroid Build Coastguard Worker #else
1161*fb1b10abSAndroid Build Coastguard Worker       raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
1162*fb1b10abSAndroid Build Coastguard Worker                                               &unscaled_last_source_buf_2d);
1163*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
1164*fb1b10abSAndroid Build Coastguard Worker 
1165*fb1b10abSAndroid Build Coastguard Worker       if (raw_motion_error > NZ_MOTION_PENALTY) {
1166*fb1b10abSAndroid Build Coastguard Worker         // Test last reference frame using the previous best mv as the
1167*fb1b10abSAndroid Build Coastguard Worker         // starting point (best reference) for the search.
1168*fb1b10abSAndroid Build Coastguard Worker         first_pass_motion_search(cpi, x, best_ref_mv, &mv, &motion_error);
1169*fb1b10abSAndroid Build Coastguard Worker 
1170*fb1b10abSAndroid Build Coastguard Worker         v_fn_ptr.vf = get_block_variance_fn(bsize);
1171*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1172*fb1b10abSAndroid Build Coastguard Worker         if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1173*fb1b10abSAndroid Build Coastguard Worker           v_fn_ptr.vf = highbd_get_block_variance_fn(bsize, xd->bd);
1174*fb1b10abSAndroid Build Coastguard Worker         }
1175*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
1176*fb1b10abSAndroid Build Coastguard Worker         this_motion_error =
1177*fb1b10abSAndroid Build Coastguard Worker             vp9_get_mvpred_var(x, &mv, best_ref_mv, &v_fn_ptr, 0);
1178*fb1b10abSAndroid Build Coastguard Worker 
1179*fb1b10abSAndroid Build Coastguard Worker         // If the current best reference mv is not centered on 0,0 then do a
1180*fb1b10abSAndroid Build Coastguard Worker         // 0,0 based search as well.
1181*fb1b10abSAndroid Build Coastguard Worker         if (!is_zero_mv(best_ref_mv)) {
1182*fb1b10abSAndroid Build Coastguard Worker           tmp_err = INT_MAX;
1183*fb1b10abSAndroid Build Coastguard Worker           first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv, &tmp_err);
1184*fb1b10abSAndroid Build Coastguard Worker 
1185*fb1b10abSAndroid Build Coastguard Worker           if (tmp_err < motion_error) {
1186*fb1b10abSAndroid Build Coastguard Worker             motion_error = tmp_err;
1187*fb1b10abSAndroid Build Coastguard Worker             mv = tmp_mv;
1188*fb1b10abSAndroid Build Coastguard Worker             this_motion_error =
1189*fb1b10abSAndroid Build Coastguard Worker                 vp9_get_mvpred_var(x, &tmp_mv, &zero_mv, &v_fn_ptr, 0);
1190*fb1b10abSAndroid Build Coastguard Worker           }
1191*fb1b10abSAndroid Build Coastguard Worker         }
1192*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
1193*fb1b10abSAndroid Build Coastguard Worker         if (cpi->oxcf.use_simple_encode_api) {
1194*fb1b10abSAndroid Build Coastguard Worker           store_fp_motion_vector(cpi, &mv, mb_row, mb_col, LAST_FRAME, 0);
1195*fb1b10abSAndroid Build Coastguard Worker         }
1196*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RAGE_CTRL
1197*fb1b10abSAndroid Build Coastguard Worker 
1198*fb1b10abSAndroid Build Coastguard Worker         // Search in an older reference frame.
1199*fb1b10abSAndroid Build Coastguard Worker         if ((cm->current_video_frame > 1) && gld_yv12 != NULL) {
1200*fb1b10abSAndroid Build Coastguard Worker           // Assume 0,0 motion with no mv overhead.
1201*fb1b10abSAndroid Build Coastguard Worker           int gf_motion_error;
1202*fb1b10abSAndroid Build Coastguard Worker 
1203*fb1b10abSAndroid Build Coastguard Worker           xd->plane[0].pre[0].buf = gld_yv12->y_buffer + recon_yoffset;
1204*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1205*fb1b10abSAndroid Build Coastguard Worker           if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
1206*fb1b10abSAndroid Build Coastguard Worker             gf_motion_error = highbd_get_prediction_error(
1207*fb1b10abSAndroid Build Coastguard Worker                 bsize, &x->plane[0].src, &xd->plane[0].pre[0], xd->bd);
1208*fb1b10abSAndroid Build Coastguard Worker           } else {
1209*fb1b10abSAndroid Build Coastguard Worker             gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
1210*fb1b10abSAndroid Build Coastguard Worker                                                    &xd->plane[0].pre[0]);
1211*fb1b10abSAndroid Build Coastguard Worker           }
1212*fb1b10abSAndroid Build Coastguard Worker #else
1213*fb1b10abSAndroid Build Coastguard Worker           gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
1214*fb1b10abSAndroid Build Coastguard Worker                                                  &xd->plane[0].pre[0]);
1215*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
1216*fb1b10abSAndroid Build Coastguard Worker 
1217*fb1b10abSAndroid Build Coastguard Worker           first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv, &gf_motion_error);
1218*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
1219*fb1b10abSAndroid Build Coastguard Worker           if (cpi->oxcf.use_simple_encode_api) {
1220*fb1b10abSAndroid Build Coastguard Worker             store_fp_motion_vector(cpi, &tmp_mv, mb_row, mb_col, GOLDEN_FRAME,
1221*fb1b10abSAndroid Build Coastguard Worker                                    1);
1222*fb1b10abSAndroid Build Coastguard Worker           }
1223*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RAGE_CTRL
1224*fb1b10abSAndroid Build Coastguard Worker 
1225*fb1b10abSAndroid Build Coastguard Worker           if (gf_motion_error < motion_error && gf_motion_error < this_error)
1226*fb1b10abSAndroid Build Coastguard Worker             ++(fp_acc_data->second_ref_count);
1227*fb1b10abSAndroid Build Coastguard Worker 
1228*fb1b10abSAndroid Build Coastguard Worker           // Reset to last frame as reference buffer.
1229*fb1b10abSAndroid Build Coastguard Worker           xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
1230*fb1b10abSAndroid Build Coastguard Worker           xd->plane[1].pre[0].buf = first_ref_buf->u_buffer + recon_uvoffset;
1231*fb1b10abSAndroid Build Coastguard Worker           xd->plane[2].pre[0].buf = first_ref_buf->v_buffer + recon_uvoffset;
1232*fb1b10abSAndroid Build Coastguard Worker 
1233*fb1b10abSAndroid Build Coastguard Worker           // In accumulating a score for the older reference frame take the
1234*fb1b10abSAndroid Build Coastguard Worker           // best of the motion predicted score and the intra coded error
1235*fb1b10abSAndroid Build Coastguard Worker           // (just as will be done for) accumulation of "coded_error" for
1236*fb1b10abSAndroid Build Coastguard Worker           // the last frame.
1237*fb1b10abSAndroid Build Coastguard Worker           if (gf_motion_error < this_error)
1238*fb1b10abSAndroid Build Coastguard Worker             fp_acc_data->sr_coded_error += gf_motion_error;
1239*fb1b10abSAndroid Build Coastguard Worker           else
1240*fb1b10abSAndroid Build Coastguard Worker             fp_acc_data->sr_coded_error += this_error;
1241*fb1b10abSAndroid Build Coastguard Worker         } else {
1242*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->sr_coded_error += motion_error;
1243*fb1b10abSAndroid Build Coastguard Worker         }
1244*fb1b10abSAndroid Build Coastguard Worker       } else {
1245*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->sr_coded_error += motion_error;
1246*fb1b10abSAndroid Build Coastguard Worker       }
1247*fb1b10abSAndroid Build Coastguard Worker 
1248*fb1b10abSAndroid Build Coastguard Worker       // Start by assuming that intra mode is best.
1249*fb1b10abSAndroid Build Coastguard Worker       best_ref_mv->row = 0;
1250*fb1b10abSAndroid Build Coastguard Worker       best_ref_mv->col = 0;
1251*fb1b10abSAndroid Build Coastguard Worker 
1252*fb1b10abSAndroid Build Coastguard Worker       if (motion_error <= this_error) {
1253*fb1b10abSAndroid Build Coastguard Worker         vpx_clear_system_state();
1254*fb1b10abSAndroid Build Coastguard Worker 
1255*fb1b10abSAndroid Build Coastguard Worker         // Keep a count of cases where the inter and intra were very close
1256*fb1b10abSAndroid Build Coastguard Worker         // and very low. This helps with scene cut detection for example in
1257*fb1b10abSAndroid Build Coastguard Worker         // cropped clips with black bars at the sides or top and bottom.
1258*fb1b10abSAndroid Build Coastguard Worker         if (((this_error - intrapenalty) * 9 <= motion_error * 10) &&
1259*fb1b10abSAndroid Build Coastguard Worker             (this_error < (2 * intrapenalty))) {
1260*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->neutral_count += 1.0;
1261*fb1b10abSAndroid Build Coastguard Worker           if (cpi->row_mt_bit_exact)
1262*fb1b10abSAndroid Build Coastguard Worker             cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_neutral_count =
1263*fb1b10abSAndroid Build Coastguard Worker                 1.0;
1264*fb1b10abSAndroid Build Coastguard Worker           // Also track cases where the intra is not much worse than the inter
1265*fb1b10abSAndroid Build Coastguard Worker           // and use this in limiting the GF/arf group length.
1266*fb1b10abSAndroid Build Coastguard Worker         } else if ((this_error > NCOUNT_INTRA_THRESH) &&
1267*fb1b10abSAndroid Build Coastguard Worker                    (this_error < (NCOUNT_INTRA_FACTOR * motion_error))) {
1268*fb1b10abSAndroid Build Coastguard Worker           mb_neutral_count =
1269*fb1b10abSAndroid Build Coastguard Worker               (double)motion_error / DOUBLE_DIVIDE_CHECK((double)this_error);
1270*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->neutral_count += mb_neutral_count;
1271*fb1b10abSAndroid Build Coastguard Worker           if (cpi->row_mt_bit_exact)
1272*fb1b10abSAndroid Build Coastguard Worker             cpi->twopass.fp_mb_float_stats[mb_index].frame_mb_neutral_count =
1273*fb1b10abSAndroid Build Coastguard Worker                 mb_neutral_count;
1274*fb1b10abSAndroid Build Coastguard Worker         }
1275*fb1b10abSAndroid Build Coastguard Worker 
1276*fb1b10abSAndroid Build Coastguard Worker         mv.row *= 8;
1277*fb1b10abSAndroid Build Coastguard Worker         mv.col *= 8;
1278*fb1b10abSAndroid Build Coastguard Worker         this_error = motion_error;
1279*fb1b10abSAndroid Build Coastguard Worker         xd->mi[0]->mode = NEWMV;
1280*fb1b10abSAndroid Build Coastguard Worker         xd->mi[0]->mv[0].as_mv = mv;
1281*fb1b10abSAndroid Build Coastguard Worker         xd->mi[0]->tx_size = TX_4X4;
1282*fb1b10abSAndroid Build Coastguard Worker         xd->mi[0]->ref_frame[0] = LAST_FRAME;
1283*fb1b10abSAndroid Build Coastguard Worker         xd->mi[0]->ref_frame[1] = NO_REF_FRAME;
1284*fb1b10abSAndroid Build Coastguard Worker         vp9_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize);
1285*fb1b10abSAndroid Build Coastguard Worker         vp9_encode_sby_pass1(x, bsize);
1286*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->sum_mvr += mv.row;
1287*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->sum_mvr_abs += abs(mv.row);
1288*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->sum_mvc += mv.col;
1289*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->sum_mvc_abs += abs(mv.col);
1290*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->sum_mvrs += mv.row * mv.row;
1291*fb1b10abSAndroid Build Coastguard Worker         fp_acc_data->sum_mvcs += mv.col * mv.col;
1292*fb1b10abSAndroid Build Coastguard Worker         ++(fp_acc_data->intercount);
1293*fb1b10abSAndroid Build Coastguard Worker 
1294*fb1b10abSAndroid Build Coastguard Worker         *best_ref_mv = mv;
1295*fb1b10abSAndroid Build Coastguard Worker 
1296*fb1b10abSAndroid Build Coastguard Worker         if (!is_zero_mv(&mv)) {
1297*fb1b10abSAndroid Build Coastguard Worker           ++(fp_acc_data->mvcount);
1298*fb1b10abSAndroid Build Coastguard Worker           if (!is_equal_mv(&mv, &last_nonzero_mv)) {
1299*fb1b10abSAndroid Build Coastguard Worker             ++(fp_acc_data->new_mv_count);
1300*fb1b10abSAndroid Build Coastguard Worker           }
1301*fb1b10abSAndroid Build Coastguard Worker           last_nonzero_mv = mv;
1302*fb1b10abSAndroid Build Coastguard Worker 
1303*fb1b10abSAndroid Build Coastguard Worker           // Does the row vector point inwards or outwards?
1304*fb1b10abSAndroid Build Coastguard Worker           if (mb_row < cm->mb_rows / 2) {
1305*fb1b10abSAndroid Build Coastguard Worker             if (mv.row > 0)
1306*fb1b10abSAndroid Build Coastguard Worker               --(fp_acc_data->sum_in_vectors);
1307*fb1b10abSAndroid Build Coastguard Worker             else if (mv.row < 0)
1308*fb1b10abSAndroid Build Coastguard Worker               ++(fp_acc_data->sum_in_vectors);
1309*fb1b10abSAndroid Build Coastguard Worker           } else if (mb_row > cm->mb_rows / 2) {
1310*fb1b10abSAndroid Build Coastguard Worker             if (mv.row > 0)
1311*fb1b10abSAndroid Build Coastguard Worker               ++(fp_acc_data->sum_in_vectors);
1312*fb1b10abSAndroid Build Coastguard Worker             else if (mv.row < 0)
1313*fb1b10abSAndroid Build Coastguard Worker               --(fp_acc_data->sum_in_vectors);
1314*fb1b10abSAndroid Build Coastguard Worker           }
1315*fb1b10abSAndroid Build Coastguard Worker 
1316*fb1b10abSAndroid Build Coastguard Worker           // Does the col vector point inwards or outwards?
1317*fb1b10abSAndroid Build Coastguard Worker           if (mb_col < cm->mb_cols / 2) {
1318*fb1b10abSAndroid Build Coastguard Worker             if (mv.col > 0)
1319*fb1b10abSAndroid Build Coastguard Worker               --(fp_acc_data->sum_in_vectors);
1320*fb1b10abSAndroid Build Coastguard Worker             else if (mv.col < 0)
1321*fb1b10abSAndroid Build Coastguard Worker               ++(fp_acc_data->sum_in_vectors);
1322*fb1b10abSAndroid Build Coastguard Worker           } else if (mb_col > cm->mb_cols / 2) {
1323*fb1b10abSAndroid Build Coastguard Worker             if (mv.col > 0)
1324*fb1b10abSAndroid Build Coastguard Worker               ++(fp_acc_data->sum_in_vectors);
1325*fb1b10abSAndroid Build Coastguard Worker             else if (mv.col < 0)
1326*fb1b10abSAndroid Build Coastguard Worker               --(fp_acc_data->sum_in_vectors);
1327*fb1b10abSAndroid Build Coastguard Worker           }
1328*fb1b10abSAndroid Build Coastguard Worker         }
1329*fb1b10abSAndroid Build Coastguard Worker         if (this_intra_error < scaled_low_intra_thresh) {
1330*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->frame_noise_energy += fp_estimate_block_noise(x, bsize);
1331*fb1b10abSAndroid Build Coastguard Worker         } else {
1332*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->frame_noise_energy += (int64_t)SECTION_NOISE_DEF;
1333*fb1b10abSAndroid Build Coastguard Worker         }
1334*fb1b10abSAndroid Build Coastguard Worker       } else {  // Intra < inter error
1335*fb1b10abSAndroid Build Coastguard Worker         if (this_intra_error < scaled_low_intra_thresh) {
1336*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->frame_noise_energy += fp_estimate_block_noise(x, bsize);
1337*fb1b10abSAndroid Build Coastguard Worker           if (this_motion_error < scaled_low_intra_thresh) {
1338*fb1b10abSAndroid Build Coastguard Worker             fp_acc_data->intra_count_low += 1.0;
1339*fb1b10abSAndroid Build Coastguard Worker           } else {
1340*fb1b10abSAndroid Build Coastguard Worker             fp_acc_data->intra_count_high += 1.0;
1341*fb1b10abSAndroid Build Coastguard Worker           }
1342*fb1b10abSAndroid Build Coastguard Worker         } else {
1343*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->frame_noise_energy += (int64_t)SECTION_NOISE_DEF;
1344*fb1b10abSAndroid Build Coastguard Worker           fp_acc_data->intra_count_high += 1.0;
1345*fb1b10abSAndroid Build Coastguard Worker         }
1346*fb1b10abSAndroid Build Coastguard Worker       }
1347*fb1b10abSAndroid Build Coastguard Worker     } else {
1348*fb1b10abSAndroid Build Coastguard Worker       fp_acc_data->sr_coded_error += (int64_t)this_error;
1349*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
1350*fb1b10abSAndroid Build Coastguard Worker       if (cpi->oxcf.use_simple_encode_api) {
1351*fb1b10abSAndroid Build Coastguard Worker         store_fp_motion_vector(cpi, NULL, mb_row, mb_col, INTRA_FRAME, 0);
1352*fb1b10abSAndroid Build Coastguard Worker       }
1353*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RAGE_CTRL
1354*fb1b10abSAndroid Build Coastguard Worker     }
1355*fb1b10abSAndroid Build Coastguard Worker     fp_acc_data->coded_error += (int64_t)this_error;
1356*fb1b10abSAndroid Build Coastguard Worker 
1357*fb1b10abSAndroid Build Coastguard Worker     if (mb_col == mb_col_start) {
1358*fb1b10abSAndroid Build Coastguard Worker       *first_top_mv = last_nonzero_mv;
1359*fb1b10abSAndroid Build Coastguard Worker     }
1360*fb1b10abSAndroid Build Coastguard Worker     recon_yoffset += 16;
1361*fb1b10abSAndroid Build Coastguard Worker     recon_uvoffset += uv_mb_height;
1362*fb1b10abSAndroid Build Coastguard Worker 
1363*fb1b10abSAndroid Build Coastguard Worker     // Accumulate row level stats to the corresponding tile stats
1364*fb1b10abSAndroid Build Coastguard Worker     if (cpi->row_mt && mb_col == mb_col_end - 1)
1365*fb1b10abSAndroid Build Coastguard Worker       accumulate_fp_mb_row_stat(tile_data, fp_acc_data);
1366*fb1b10abSAndroid Build Coastguard Worker 
1367*fb1b10abSAndroid Build Coastguard Worker     (*(cpi->row_mt_sync_write_ptr))(&tile_data->row_mt_sync, mb_row, c,
1368*fb1b10abSAndroid Build Coastguard Worker                                     num_mb_cols);
1369*fb1b10abSAndroid Build Coastguard Worker   }
1370*fb1b10abSAndroid Build Coastguard Worker   vpx_clear_system_state();
1371*fb1b10abSAndroid Build Coastguard Worker }
1372*fb1b10abSAndroid Build Coastguard Worker 
first_pass_encode(VP9_COMP * cpi,FIRSTPASS_DATA * fp_acc_data)1373*fb1b10abSAndroid Build Coastguard Worker static void first_pass_encode(VP9_COMP *cpi, FIRSTPASS_DATA *fp_acc_data) {
1374*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
1375*fb1b10abSAndroid Build Coastguard Worker   int mb_row;
1376*fb1b10abSAndroid Build Coastguard Worker   TileDataEnc tile_data;
1377*fb1b10abSAndroid Build Coastguard Worker   TileInfo *tile = &tile_data.tile_info;
1378*fb1b10abSAndroid Build Coastguard Worker   MV zero_mv = { 0, 0 };
1379*fb1b10abSAndroid Build Coastguard Worker   MV best_ref_mv;
1380*fb1b10abSAndroid Build Coastguard Worker   // Tiling is ignored in the first pass.
1381*fb1b10abSAndroid Build Coastguard Worker   vp9_tile_init(tile, cm, 0, 0);
1382*fb1b10abSAndroid Build Coastguard Worker   tile_data.firstpass_top_mv = zero_mv;
1383*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
1384*fb1b10abSAndroid Build Coastguard Worker   if (cpi->oxcf.use_simple_encode_api) {
1385*fb1b10abSAndroid Build Coastguard Worker     fp_motion_vector_info_reset(cpi->frame_info.frame_width,
1386*fb1b10abSAndroid Build Coastguard Worker                                 cpi->frame_info.frame_height,
1387*fb1b10abSAndroid Build Coastguard Worker                                 cpi->fp_motion_vector_info);
1388*fb1b10abSAndroid Build Coastguard Worker   }
1389*fb1b10abSAndroid Build Coastguard Worker #endif
1390*fb1b10abSAndroid Build Coastguard Worker 
1391*fb1b10abSAndroid Build Coastguard Worker   for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
1392*fb1b10abSAndroid Build Coastguard Worker     best_ref_mv = zero_mv;
1393*fb1b10abSAndroid Build Coastguard Worker     vp9_first_pass_encode_tile_mb_row(cpi, &cpi->td, fp_acc_data, &tile_data,
1394*fb1b10abSAndroid Build Coastguard Worker                                       &best_ref_mv, mb_row);
1395*fb1b10abSAndroid Build Coastguard Worker   }
1396*fb1b10abSAndroid Build Coastguard Worker }
1397*fb1b10abSAndroid Build Coastguard Worker 
vp9_first_pass(VP9_COMP * cpi,const struct lookahead_entry * source)1398*fb1b10abSAndroid Build Coastguard Worker void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
1399*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = &cpi->td.mb;
1400*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
1401*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
1402*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *twopass = &cpi->twopass;
1403*fb1b10abSAndroid Build Coastguard Worker 
1404*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
1405*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
1406*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
1407*fb1b10abSAndroid Build Coastguard Worker   const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
1408*fb1b10abSAndroid Build Coastguard Worker 
1409*fb1b10abSAndroid Build Coastguard Worker   BufferPool *const pool = cm->buffer_pool;
1410*fb1b10abSAndroid Build Coastguard Worker 
1411*fb1b10abSAndroid Build Coastguard Worker   FIRSTPASS_DATA fp_temp_data;
1412*fb1b10abSAndroid Build Coastguard Worker   FIRSTPASS_DATA *fp_acc_data = &fp_temp_data;
1413*fb1b10abSAndroid Build Coastguard Worker 
1414*fb1b10abSAndroid Build Coastguard Worker   vpx_clear_system_state();
1415*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(fp_temp_data);
1416*fb1b10abSAndroid Build Coastguard Worker   fp_acc_data->image_data_start_row = INVALID_ROW;
1417*fb1b10abSAndroid Build Coastguard Worker 
1418*fb1b10abSAndroid Build Coastguard Worker   // First pass code requires valid last and new frame buffers.
1419*fb1b10abSAndroid Build Coastguard Worker   assert(new_yv12 != NULL);
1420*fb1b10abSAndroid Build Coastguard Worker   assert(frame_is_intra_only(cm) || (lst_yv12 != NULL));
1421*fb1b10abSAndroid Build Coastguard Worker 
1422*fb1b10abSAndroid Build Coastguard Worker   set_first_pass_params(cpi);
1423*fb1b10abSAndroid Build Coastguard Worker   vp9_set_quantizer(cpi, find_fp_qindex(cm->bit_depth));
1424*fb1b10abSAndroid Build Coastguard Worker 
1425*fb1b10abSAndroid Build Coastguard Worker   vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
1426*fb1b10abSAndroid Build Coastguard Worker 
1427*fb1b10abSAndroid Build Coastguard Worker   vp9_setup_src_planes(x, cpi->Source, 0, 0);
1428*fb1b10abSAndroid Build Coastguard Worker   vp9_setup_dst_planes(xd->plane, new_yv12, 0, 0);
1429*fb1b10abSAndroid Build Coastguard Worker 
1430*fb1b10abSAndroid Build Coastguard Worker   if (!frame_is_intra_only(cm)) {
1431*fb1b10abSAndroid Build Coastguard Worker     vp9_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL);
1432*fb1b10abSAndroid Build Coastguard Worker   }
1433*fb1b10abSAndroid Build Coastguard Worker 
1434*fb1b10abSAndroid Build Coastguard Worker   xd->mi = cm->mi_grid_visible;
1435*fb1b10abSAndroid Build Coastguard Worker   xd->mi[0] = cm->mi;
1436*fb1b10abSAndroid Build Coastguard Worker 
1437*fb1b10abSAndroid Build Coastguard Worker   vp9_frame_init_quantizer(cpi);
1438*fb1b10abSAndroid Build Coastguard Worker 
1439*fb1b10abSAndroid Build Coastguard Worker   x->skip_recode = 0;
1440*fb1b10abSAndroid Build Coastguard Worker 
1441*fb1b10abSAndroid Build Coastguard Worker   vp9_init_mv_probs(cm);
1442*fb1b10abSAndroid Build Coastguard Worker   vp9_initialize_rd_consts(cpi);
1443*fb1b10abSAndroid Build Coastguard Worker 
1444*fb1b10abSAndroid Build Coastguard Worker   cm->log2_tile_rows = 0;
1445*fb1b10abSAndroid Build Coastguard Worker 
1446*fb1b10abSAndroid Build Coastguard Worker   if (cpi->row_mt_bit_exact && cpi->twopass.fp_mb_float_stats == NULL)
1447*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(
1448*fb1b10abSAndroid Build Coastguard Worker         &cm->error, cpi->twopass.fp_mb_float_stats,
1449*fb1b10abSAndroid Build Coastguard Worker         vpx_calloc(cm->MBs * sizeof(*cpi->twopass.fp_mb_float_stats), 1));
1450*fb1b10abSAndroid Build Coastguard Worker 
1451*fb1b10abSAndroid Build Coastguard Worker   {
1452*fb1b10abSAndroid Build Coastguard Worker     FIRSTPASS_STATS fps;
1453*fb1b10abSAndroid Build Coastguard Worker     TileDataEnc *first_tile_col;
1454*fb1b10abSAndroid Build Coastguard Worker     if (!cpi->row_mt) {
1455*fb1b10abSAndroid Build Coastguard Worker       cm->log2_tile_cols = 0;
1456*fb1b10abSAndroid Build Coastguard Worker       cpi->row_mt_sync_read_ptr = vp9_row_mt_sync_read_dummy;
1457*fb1b10abSAndroid Build Coastguard Worker       cpi->row_mt_sync_write_ptr = vp9_row_mt_sync_write_dummy;
1458*fb1b10abSAndroid Build Coastguard Worker       first_pass_encode(cpi, fp_acc_data);
1459*fb1b10abSAndroid Build Coastguard Worker       first_pass_stat_calc(cpi, &fps, fp_acc_data);
1460*fb1b10abSAndroid Build Coastguard Worker     } else {
1461*fb1b10abSAndroid Build Coastguard Worker       cpi->row_mt_sync_read_ptr = vp9_row_mt_sync_read;
1462*fb1b10abSAndroid Build Coastguard Worker       cpi->row_mt_sync_write_ptr = vp9_row_mt_sync_write;
1463*fb1b10abSAndroid Build Coastguard Worker       if (cpi->row_mt_bit_exact) {
1464*fb1b10abSAndroid Build Coastguard Worker         cm->log2_tile_cols = 0;
1465*fb1b10abSAndroid Build Coastguard Worker         vp9_zero_array(cpi->twopass.fp_mb_float_stats, cm->MBs);
1466*fb1b10abSAndroid Build Coastguard Worker       }
1467*fb1b10abSAndroid Build Coastguard Worker       vp9_encode_fp_row_mt(cpi);
1468*fb1b10abSAndroid Build Coastguard Worker       first_tile_col = &cpi->tile_data[0];
1469*fb1b10abSAndroid Build Coastguard Worker       if (cpi->row_mt_bit_exact)
1470*fb1b10abSAndroid Build Coastguard Worker         accumulate_floating_point_stats(cpi, first_tile_col);
1471*fb1b10abSAndroid Build Coastguard Worker       first_pass_stat_calc(cpi, &fps, &(first_tile_col->fp_data));
1472*fb1b10abSAndroid Build Coastguard Worker     }
1473*fb1b10abSAndroid Build Coastguard Worker 
1474*fb1b10abSAndroid Build Coastguard Worker     // Don't allow a value of 0 for duration.
1475*fb1b10abSAndroid Build Coastguard Worker     // (Section duration is also defaulted to minimum of 1.0).
1476*fb1b10abSAndroid Build Coastguard Worker     fps.duration = VPXMAX(1.0, (double)(source->ts_end - source->ts_start));
1477*fb1b10abSAndroid Build Coastguard Worker 
1478*fb1b10abSAndroid Build Coastguard Worker     // Don't want to do output stats with a stack variable!
1479*fb1b10abSAndroid Build Coastguard Worker     twopass->this_frame_stats = fps;
1480*fb1b10abSAndroid Build Coastguard Worker     output_stats(&twopass->this_frame_stats);
1481*fb1b10abSAndroid Build Coastguard Worker     accumulate_stats(&twopass->total_stats, &fps);
1482*fb1b10abSAndroid Build Coastguard Worker   }
1483*fb1b10abSAndroid Build Coastguard Worker 
1484*fb1b10abSAndroid Build Coastguard Worker   // Copy the previous Last Frame back into gf and arf buffers if
1485*fb1b10abSAndroid Build Coastguard Worker   // the prediction is good enough... but also don't allow it to lag too far.
1486*fb1b10abSAndroid Build Coastguard Worker   if ((twopass->sr_update_lag > 3) ||
1487*fb1b10abSAndroid Build Coastguard Worker       ((cm->current_video_frame > 0) &&
1488*fb1b10abSAndroid Build Coastguard Worker        (twopass->this_frame_stats.pcnt_inter > 0.20) &&
1489*fb1b10abSAndroid Build Coastguard Worker        ((twopass->this_frame_stats.intra_error /
1490*fb1b10abSAndroid Build Coastguard Worker          DOUBLE_DIVIDE_CHECK(twopass->this_frame_stats.coded_error)) > 2.0))) {
1491*fb1b10abSAndroid Build Coastguard Worker     if (gld_yv12 != NULL) {
1492*fb1b10abSAndroid Build Coastguard Worker       ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
1493*fb1b10abSAndroid Build Coastguard Worker                  cm->ref_frame_map[cpi->lst_fb_idx]);
1494*fb1b10abSAndroid Build Coastguard Worker     }
1495*fb1b10abSAndroid Build Coastguard Worker     twopass->sr_update_lag = 1;
1496*fb1b10abSAndroid Build Coastguard Worker   } else {
1497*fb1b10abSAndroid Build Coastguard Worker     ++twopass->sr_update_lag;
1498*fb1b10abSAndroid Build Coastguard Worker   }
1499*fb1b10abSAndroid Build Coastguard Worker 
1500*fb1b10abSAndroid Build Coastguard Worker   vpx_extend_frame_borders(new_yv12);
1501*fb1b10abSAndroid Build Coastguard Worker 
1502*fb1b10abSAndroid Build Coastguard Worker   // The frame we just compressed now becomes the last frame.
1503*fb1b10abSAndroid Build Coastguard Worker   ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
1504*fb1b10abSAndroid Build Coastguard Worker              cm->new_fb_idx);
1505*fb1b10abSAndroid Build Coastguard Worker 
1506*fb1b10abSAndroid Build Coastguard Worker   // Special case for the first frame. Copy into the GF buffer as a second
1507*fb1b10abSAndroid Build Coastguard Worker   // reference.
1508*fb1b10abSAndroid Build Coastguard Worker   if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) {
1509*fb1b10abSAndroid Build Coastguard Worker     ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
1510*fb1b10abSAndroid Build Coastguard Worker                cm->ref_frame_map[cpi->lst_fb_idx]);
1511*fb1b10abSAndroid Build Coastguard Worker   }
1512*fb1b10abSAndroid Build Coastguard Worker 
1513*fb1b10abSAndroid Build Coastguard Worker   // In the first pass, every frame is considered as a show frame.
1514*fb1b10abSAndroid Build Coastguard Worker   update_frame_indexes(cm, /*show_frame=*/1);
1515*fb1b10abSAndroid Build Coastguard Worker   if (cpi->use_svc) vp9_inc_frame_in_layer(cpi);
1516*fb1b10abSAndroid Build Coastguard Worker }
1517*fb1b10abSAndroid Build Coastguard Worker 
1518*fb1b10abSAndroid Build Coastguard Worker static const double q_pow_term[(QINDEX_RANGE >> 5) + 1] = { 0.65, 0.70, 0.75,
1519*fb1b10abSAndroid Build Coastguard Worker                                                             0.85, 0.90, 0.90,
1520*fb1b10abSAndroid Build Coastguard Worker                                                             0.90, 1.00, 1.25 };
1521*fb1b10abSAndroid Build Coastguard Worker 
calc_correction_factor(double err_per_mb,double err_divisor,int q)1522*fb1b10abSAndroid Build Coastguard Worker static double calc_correction_factor(double err_per_mb, double err_divisor,
1523*fb1b10abSAndroid Build Coastguard Worker                                      int q) {
1524*fb1b10abSAndroid Build Coastguard Worker   const double error_term = err_per_mb / DOUBLE_DIVIDE_CHECK(err_divisor);
1525*fb1b10abSAndroid Build Coastguard Worker   const int index = q >> 5;
1526*fb1b10abSAndroid Build Coastguard Worker   double power_term;
1527*fb1b10abSAndroid Build Coastguard Worker 
1528*fb1b10abSAndroid Build Coastguard Worker   assert((index >= 0) && (index < (QINDEX_RANGE >> 5)));
1529*fb1b10abSAndroid Build Coastguard Worker 
1530*fb1b10abSAndroid Build Coastguard Worker   // Adjustment based on quantizer to the power term.
1531*fb1b10abSAndroid Build Coastguard Worker   power_term =
1532*fb1b10abSAndroid Build Coastguard Worker       q_pow_term[index] +
1533*fb1b10abSAndroid Build Coastguard Worker       (((q_pow_term[index + 1] - q_pow_term[index]) * (q % 32)) / 32.0);
1534*fb1b10abSAndroid Build Coastguard Worker 
1535*fb1b10abSAndroid Build Coastguard Worker   // Calculate correction factor.
1536*fb1b10abSAndroid Build Coastguard Worker   if (power_term < 1.0) assert(error_term >= 0.0);
1537*fb1b10abSAndroid Build Coastguard Worker 
1538*fb1b10abSAndroid Build Coastguard Worker   return fclamp(pow(error_term, power_term), 0.05, 5.0);
1539*fb1b10abSAndroid Build Coastguard Worker }
1540*fb1b10abSAndroid Build Coastguard Worker 
wq_err_divisor(VP9_COMP * cpi)1541*fb1b10abSAndroid Build Coastguard Worker static double wq_err_divisor(VP9_COMP *cpi) {
1542*fb1b10abSAndroid Build Coastguard Worker   const VP9_COMMON *const cm = &cpi->common;
1543*fb1b10abSAndroid Build Coastguard Worker   unsigned int screen_area = (cm->width * cm->height);
1544*fb1b10abSAndroid Build Coastguard Worker 
1545*fb1b10abSAndroid Build Coastguard Worker   // Use a different error per mb factor for calculating boost for
1546*fb1b10abSAndroid Build Coastguard Worker   //  different formats.
1547*fb1b10abSAndroid Build Coastguard Worker   if (screen_area <= 640 * 360) {
1548*fb1b10abSAndroid Build Coastguard Worker     return 115.0;
1549*fb1b10abSAndroid Build Coastguard Worker   } else if (screen_area < 1280 * 720) {
1550*fb1b10abSAndroid Build Coastguard Worker     return 125.0;
1551*fb1b10abSAndroid Build Coastguard Worker   } else if (screen_area <= 1920 * 1080) {
1552*fb1b10abSAndroid Build Coastguard Worker     return 130.0;
1553*fb1b10abSAndroid Build Coastguard Worker   } else if (screen_area < 3840 * 2160) {
1554*fb1b10abSAndroid Build Coastguard Worker     return 150.0;
1555*fb1b10abSAndroid Build Coastguard Worker   }
1556*fb1b10abSAndroid Build Coastguard Worker 
1557*fb1b10abSAndroid Build Coastguard Worker   // Fall through to here only for 4K and above.
1558*fb1b10abSAndroid Build Coastguard Worker   return 200.0;
1559*fb1b10abSAndroid Build Coastguard Worker }
1560*fb1b10abSAndroid Build Coastguard Worker 
1561*fb1b10abSAndroid Build Coastguard Worker #define NOISE_FACTOR_MIN 0.9
1562*fb1b10abSAndroid Build Coastguard Worker #define NOISE_FACTOR_MAX 1.1
get_twopass_worst_quality(VP9_COMP * cpi,const double section_err,double inactive_zone,double section_noise,int section_target_bandwidth)1563*fb1b10abSAndroid Build Coastguard Worker static int get_twopass_worst_quality(VP9_COMP *cpi, const double section_err,
1564*fb1b10abSAndroid Build Coastguard Worker                                      double inactive_zone, double section_noise,
1565*fb1b10abSAndroid Build Coastguard Worker                                      int section_target_bandwidth) {
1566*fb1b10abSAndroid Build Coastguard Worker   const RATE_CONTROL *const rc = &cpi->rc;
1567*fb1b10abSAndroid Build Coastguard Worker   const VP9EncoderConfig *const oxcf = &cpi->oxcf;
1568*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
1569*fb1b10abSAndroid Build Coastguard Worker   double last_group_rate_err;
1570*fb1b10abSAndroid Build Coastguard Worker 
1571*fb1b10abSAndroid Build Coastguard Worker   // Clamp the target rate to VBR min / max limts.
1572*fb1b10abSAndroid Build Coastguard Worker   const int target_rate =
1573*fb1b10abSAndroid Build Coastguard Worker       vp9_rc_clamp_pframe_target_size(cpi, section_target_bandwidth);
1574*fb1b10abSAndroid Build Coastguard Worker   double noise_factor = pow((section_noise / SECTION_NOISE_DEF), 0.5);
1575*fb1b10abSAndroid Build Coastguard Worker   noise_factor = fclamp(noise_factor, NOISE_FACTOR_MIN, NOISE_FACTOR_MAX);
1576*fb1b10abSAndroid Build Coastguard Worker   inactive_zone = fclamp(inactive_zone, 0.0, 1.0);
1577*fb1b10abSAndroid Build Coastguard Worker 
1578*fb1b10abSAndroid Build Coastguard Worker // TODO(jimbankoski): remove #if here or below when this has been
1579*fb1b10abSAndroid Build Coastguard Worker // well tested.
1580*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_ALWAYS_ADJUST_BPM
1581*fb1b10abSAndroid Build Coastguard Worker   // based on recent history adjust expectations of bits per macroblock.
1582*fb1b10abSAndroid Build Coastguard Worker   last_group_rate_err =
1583*fb1b10abSAndroid Build Coastguard Worker       (double)twopass->rolling_arf_group_actual_bits /
1584*fb1b10abSAndroid Build Coastguard Worker       DOUBLE_DIVIDE_CHECK((double)twopass->rolling_arf_group_target_bits);
1585*fb1b10abSAndroid Build Coastguard Worker   last_group_rate_err = VPXMAX(0.25, VPXMIN(4.0, last_group_rate_err));
1586*fb1b10abSAndroid Build Coastguard Worker   twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0;
1587*fb1b10abSAndroid Build Coastguard Worker   twopass->bpm_factor = VPXMAX(0.25, VPXMIN(4.0, twopass->bpm_factor));
1588*fb1b10abSAndroid Build Coastguard Worker #endif
1589*fb1b10abSAndroid Build Coastguard Worker 
1590*fb1b10abSAndroid Build Coastguard Worker   if (target_rate <= 0) {
1591*fb1b10abSAndroid Build Coastguard Worker     return rc->worst_quality;  // Highest value allowed
1592*fb1b10abSAndroid Build Coastguard Worker   } else {
1593*fb1b10abSAndroid Build Coastguard Worker     const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE)
1594*fb1b10abSAndroid Build Coastguard Worker                             ? cpi->initial_mbs
1595*fb1b10abSAndroid Build Coastguard Worker                             : cpi->common.MBs;
1596*fb1b10abSAndroid Build Coastguard Worker     const double active_pct = VPXMAX(0.01, 1.0 - inactive_zone);
1597*fb1b10abSAndroid Build Coastguard Worker     const int active_mbs = (int)VPXMAX(1, (double)num_mbs * active_pct);
1598*fb1b10abSAndroid Build Coastguard Worker     const double av_err_per_mb = section_err / active_pct;
1599*fb1b10abSAndroid Build Coastguard Worker     const double speed_term = 1.0 + 0.04 * oxcf->speed;
1600*fb1b10abSAndroid Build Coastguard Worker     const uint64_t target_norm_bits_per_mb =
1601*fb1b10abSAndroid Build Coastguard Worker         ((uint64_t)target_rate << BPER_MB_NORMBITS) / active_mbs;
1602*fb1b10abSAndroid Build Coastguard Worker     int q;
1603*fb1b10abSAndroid Build Coastguard Worker 
1604*fb1b10abSAndroid Build Coastguard Worker // TODO(jimbankoski): remove #if here or above when this has been
1605*fb1b10abSAndroid Build Coastguard Worker // well tested.
1606*fb1b10abSAndroid Build Coastguard Worker #if !CONFIG_ALWAYS_ADJUST_BPM
1607*fb1b10abSAndroid Build Coastguard Worker     // based on recent history adjust expectations of bits per macroblock.
1608*fb1b10abSAndroid Build Coastguard Worker     last_group_rate_err =
1609*fb1b10abSAndroid Build Coastguard Worker         (double)twopass->rolling_arf_group_actual_bits /
1610*fb1b10abSAndroid Build Coastguard Worker         DOUBLE_DIVIDE_CHECK((double)twopass->rolling_arf_group_target_bits);
1611*fb1b10abSAndroid Build Coastguard Worker     last_group_rate_err = VPXMAX(0.25, VPXMIN(4.0, last_group_rate_err));
1612*fb1b10abSAndroid Build Coastguard Worker     twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0;
1613*fb1b10abSAndroid Build Coastguard Worker     twopass->bpm_factor = VPXMAX(0.25, VPXMIN(4.0, twopass->bpm_factor));
1614*fb1b10abSAndroid Build Coastguard Worker #endif
1615*fb1b10abSAndroid Build Coastguard Worker 
1616*fb1b10abSAndroid Build Coastguard Worker     // Try and pick a max Q that will be high enough to encode the
1617*fb1b10abSAndroid Build Coastguard Worker     // content at the given rate.
1618*fb1b10abSAndroid Build Coastguard Worker     for (q = rc->best_quality; q < rc->worst_quality; ++q) {
1619*fb1b10abSAndroid Build Coastguard Worker       const double factor =
1620*fb1b10abSAndroid Build Coastguard Worker           calc_correction_factor(av_err_per_mb, wq_err_divisor(cpi), q);
1621*fb1b10abSAndroid Build Coastguard Worker       const int bits_per_mb = vp9_rc_bits_per_mb(
1622*fb1b10abSAndroid Build Coastguard Worker           INTER_FRAME, q,
1623*fb1b10abSAndroid Build Coastguard Worker           factor * speed_term * cpi->twopass.bpm_factor * noise_factor,
1624*fb1b10abSAndroid Build Coastguard Worker           cpi->common.bit_depth);
1625*fb1b10abSAndroid Build Coastguard Worker       if ((uint64_t)bits_per_mb <= target_norm_bits_per_mb) break;
1626*fb1b10abSAndroid Build Coastguard Worker     }
1627*fb1b10abSAndroid Build Coastguard Worker 
1628*fb1b10abSAndroid Build Coastguard Worker     // Restriction on active max q for constrained quality mode.
1629*fb1b10abSAndroid Build Coastguard Worker     if (cpi->oxcf.rc_mode == VPX_CQ) q = VPXMAX(q, oxcf->cq_level);
1630*fb1b10abSAndroid Build Coastguard Worker     return q;
1631*fb1b10abSAndroid Build Coastguard Worker   }
1632*fb1b10abSAndroid Build Coastguard Worker }
1633*fb1b10abSAndroid Build Coastguard Worker 
setup_rf_level_maxq(VP9_COMP * cpi)1634*fb1b10abSAndroid Build Coastguard Worker static void setup_rf_level_maxq(VP9_COMP *cpi) {
1635*fb1b10abSAndroid Build Coastguard Worker   int i;
1636*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
1637*fb1b10abSAndroid Build Coastguard Worker   for (i = INTER_NORMAL; i < RATE_FACTOR_LEVELS; ++i) {
1638*fb1b10abSAndroid Build Coastguard Worker     int qdelta = vp9_frame_type_qdelta(cpi, i, rc->worst_quality);
1639*fb1b10abSAndroid Build Coastguard Worker     rc->rf_level_maxq[i] = VPXMAX(rc->worst_quality + qdelta, rc->best_quality);
1640*fb1b10abSAndroid Build Coastguard Worker   }
1641*fb1b10abSAndroid Build Coastguard Worker }
1642*fb1b10abSAndroid Build Coastguard Worker 
init_subsampling(VP9_COMP * cpi)1643*fb1b10abSAndroid Build Coastguard Worker static void init_subsampling(VP9_COMP *cpi) {
1644*fb1b10abSAndroid Build Coastguard Worker   const VP9_COMMON *const cm = &cpi->common;
1645*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
1646*fb1b10abSAndroid Build Coastguard Worker   const int w = cm->width;
1647*fb1b10abSAndroid Build Coastguard Worker   const int h = cm->height;
1648*fb1b10abSAndroid Build Coastguard Worker   int i;
1649*fb1b10abSAndroid Build Coastguard Worker 
1650*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < FRAME_SCALE_STEPS; ++i) {
1651*fb1b10abSAndroid Build Coastguard Worker     // Note: Frames with odd-sized dimensions may result from this scaling.
1652*fb1b10abSAndroid Build Coastguard Worker     rc->frame_width[i] = (w * 16) / frame_scale_factor[i];
1653*fb1b10abSAndroid Build Coastguard Worker     rc->frame_height[i] = (h * 16) / frame_scale_factor[i];
1654*fb1b10abSAndroid Build Coastguard Worker   }
1655*fb1b10abSAndroid Build Coastguard Worker 
1656*fb1b10abSAndroid Build Coastguard Worker   setup_rf_level_maxq(cpi);
1657*fb1b10abSAndroid Build Coastguard Worker }
1658*fb1b10abSAndroid Build Coastguard Worker 
calculate_coded_size(VP9_COMP * cpi,int * scaled_frame_width,int * scaled_frame_height)1659*fb1b10abSAndroid Build Coastguard Worker void calculate_coded_size(VP9_COMP *cpi, int *scaled_frame_width,
1660*fb1b10abSAndroid Build Coastguard Worker                           int *scaled_frame_height) {
1661*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
1662*fb1b10abSAndroid Build Coastguard Worker   *scaled_frame_width = rc->frame_width[rc->frame_size_selector];
1663*fb1b10abSAndroid Build Coastguard Worker   *scaled_frame_height = rc->frame_height[rc->frame_size_selector];
1664*fb1b10abSAndroid Build Coastguard Worker }
1665*fb1b10abSAndroid Build Coastguard Worker 
vp9_init_second_pass(VP9_COMP * cpi)1666*fb1b10abSAndroid Build Coastguard Worker void vp9_init_second_pass(VP9_COMP *cpi) {
1667*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig *const oxcf = &cpi->oxcf;
1668*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
1669*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
1670*fb1b10abSAndroid Build Coastguard Worker   double frame_rate;
1671*fb1b10abSAndroid Build Coastguard Worker   FIRSTPASS_STATS *stats;
1672*fb1b10abSAndroid Build Coastguard Worker 
1673*fb1b10abSAndroid Build Coastguard Worker   zero_stats(&twopass->total_stats);
1674*fb1b10abSAndroid Build Coastguard Worker   zero_stats(&twopass->total_left_stats);
1675*fb1b10abSAndroid Build Coastguard Worker 
1676*fb1b10abSAndroid Build Coastguard Worker   if (!twopass->stats_in_end) return;
1677*fb1b10abSAndroid Build Coastguard Worker 
1678*fb1b10abSAndroid Build Coastguard Worker   stats = &twopass->total_stats;
1679*fb1b10abSAndroid Build Coastguard Worker 
1680*fb1b10abSAndroid Build Coastguard Worker   *stats = *twopass->stats_in_end;
1681*fb1b10abSAndroid Build Coastguard Worker   twopass->total_left_stats = *stats;
1682*fb1b10abSAndroid Build Coastguard Worker 
1683*fb1b10abSAndroid Build Coastguard Worker   // Scan the first pass file and calculate a modified score for each
1684*fb1b10abSAndroid Build Coastguard Worker   // frame that is used to distribute bits. The modified score is assumed
1685*fb1b10abSAndroid Build Coastguard Worker   // to provide a linear basis for bit allocation. I.e., a frame A with a score
1686*fb1b10abSAndroid Build Coastguard Worker   // that is double that of frame B will be allocated 2x as many bits.
1687*fb1b10abSAndroid Build Coastguard Worker   {
1688*fb1b10abSAndroid Build Coastguard Worker     double modified_score_total = 0.0;
1689*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *s = twopass->stats_in;
1690*fb1b10abSAndroid Build Coastguard Worker     double av_err;
1691*fb1b10abSAndroid Build Coastguard Worker 
1692*fb1b10abSAndroid Build Coastguard Worker     if (oxcf->vbr_corpus_complexity) {
1693*fb1b10abSAndroid Build Coastguard Worker       twopass->mean_mod_score = (double)oxcf->vbr_corpus_complexity / 10.0;
1694*fb1b10abSAndroid Build Coastguard Worker       av_err = get_distribution_av_err(cpi, twopass);
1695*fb1b10abSAndroid Build Coastguard Worker     } else {
1696*fb1b10abSAndroid Build Coastguard Worker       av_err = get_distribution_av_err(cpi, twopass);
1697*fb1b10abSAndroid Build Coastguard Worker       // The first scan is unclamped and gives a raw average.
1698*fb1b10abSAndroid Build Coastguard Worker       while (s < twopass->stats_in_end) {
1699*fb1b10abSAndroid Build Coastguard Worker         modified_score_total += calculate_mod_frame_score(cpi, oxcf, s, av_err);
1700*fb1b10abSAndroid Build Coastguard Worker         ++s;
1701*fb1b10abSAndroid Build Coastguard Worker       }
1702*fb1b10abSAndroid Build Coastguard Worker 
1703*fb1b10abSAndroid Build Coastguard Worker       // The average error from this first scan is used to define the midpoint
1704*fb1b10abSAndroid Build Coastguard Worker       // error for the rate distribution function.
1705*fb1b10abSAndroid Build Coastguard Worker       twopass->mean_mod_score =
1706*fb1b10abSAndroid Build Coastguard Worker           modified_score_total / DOUBLE_DIVIDE_CHECK(stats->count);
1707*fb1b10abSAndroid Build Coastguard Worker     }
1708*fb1b10abSAndroid Build Coastguard Worker 
1709*fb1b10abSAndroid Build Coastguard Worker     // Second scan using clamps based on the previous cycle average.
1710*fb1b10abSAndroid Build Coastguard Worker     // This may modify the total and average somewhat but we don't bother with
1711*fb1b10abSAndroid Build Coastguard Worker     // further iterations.
1712*fb1b10abSAndroid Build Coastguard Worker     modified_score_total = 0.0;
1713*fb1b10abSAndroid Build Coastguard Worker     s = twopass->stats_in;
1714*fb1b10abSAndroid Build Coastguard Worker     while (s < twopass->stats_in_end) {
1715*fb1b10abSAndroid Build Coastguard Worker       modified_score_total +=
1716*fb1b10abSAndroid Build Coastguard Worker           calculate_norm_frame_score(cpi, twopass, oxcf, s, av_err);
1717*fb1b10abSAndroid Build Coastguard Worker       ++s;
1718*fb1b10abSAndroid Build Coastguard Worker     }
1719*fb1b10abSAndroid Build Coastguard Worker     twopass->normalized_score_left = modified_score_total;
1720*fb1b10abSAndroid Build Coastguard Worker 
1721*fb1b10abSAndroid Build Coastguard Worker     // If using Corpus wide VBR mode then update the clip target bandwidth to
1722*fb1b10abSAndroid Build Coastguard Worker     // reflect how the clip compares to the rest of the corpus.
1723*fb1b10abSAndroid Build Coastguard Worker     if (oxcf->vbr_corpus_complexity) {
1724*fb1b10abSAndroid Build Coastguard Worker       oxcf->target_bandwidth =
1725*fb1b10abSAndroid Build Coastguard Worker           (int64_t)((double)oxcf->target_bandwidth *
1726*fb1b10abSAndroid Build Coastguard Worker                     (twopass->normalized_score_left / stats->count));
1727*fb1b10abSAndroid Build Coastguard Worker     }
1728*fb1b10abSAndroid Build Coastguard Worker 
1729*fb1b10abSAndroid Build Coastguard Worker #if COMPLEXITY_STATS_OUTPUT
1730*fb1b10abSAndroid Build Coastguard Worker     {
1731*fb1b10abSAndroid Build Coastguard Worker       FILE *compstats;
1732*fb1b10abSAndroid Build Coastguard Worker       compstats = fopen("complexity_stats.stt", "a");
1733*fb1b10abSAndroid Build Coastguard Worker       fprintf(compstats, "%10.3lf\n",
1734*fb1b10abSAndroid Build Coastguard Worker               twopass->normalized_score_left / stats->count);
1735*fb1b10abSAndroid Build Coastguard Worker       fclose(compstats);
1736*fb1b10abSAndroid Build Coastguard Worker     }
1737*fb1b10abSAndroid Build Coastguard Worker #endif
1738*fb1b10abSAndroid Build Coastguard Worker   }
1739*fb1b10abSAndroid Build Coastguard Worker 
1740*fb1b10abSAndroid Build Coastguard Worker   frame_rate = 10000000.0 * stats->count / stats->duration;
1741*fb1b10abSAndroid Build Coastguard Worker   // Each frame can have a different duration, as the frame rate in the source
1742*fb1b10abSAndroid Build Coastguard Worker   // isn't guaranteed to be constant. The frame rate prior to the first frame
1743*fb1b10abSAndroid Build Coastguard Worker   // encoded in the second pass is a guess. However, the sum duration is not.
1744*fb1b10abSAndroid Build Coastguard Worker   // It is calculated based on the actual durations of all frames from the
1745*fb1b10abSAndroid Build Coastguard Worker   // first pass.
1746*fb1b10abSAndroid Build Coastguard Worker   vp9_new_framerate(cpi, frame_rate);
1747*fb1b10abSAndroid Build Coastguard Worker   twopass->bits_left =
1748*fb1b10abSAndroid Build Coastguard Worker       (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
1749*fb1b10abSAndroid Build Coastguard Worker 
1750*fb1b10abSAndroid Build Coastguard Worker   // This variable monitors how far behind the second ref update is lagging.
1751*fb1b10abSAndroid Build Coastguard Worker   twopass->sr_update_lag = 1;
1752*fb1b10abSAndroid Build Coastguard Worker 
1753*fb1b10abSAndroid Build Coastguard Worker   // Reset the vbr bits off target counters
1754*fb1b10abSAndroid Build Coastguard Worker   rc->vbr_bits_off_target = 0;
1755*fb1b10abSAndroid Build Coastguard Worker   rc->vbr_bits_off_target_fast = 0;
1756*fb1b10abSAndroid Build Coastguard Worker   rc->rate_error_estimate = 0;
1757*fb1b10abSAndroid Build Coastguard Worker 
1758*fb1b10abSAndroid Build Coastguard Worker   // Static sequence monitor variables.
1759*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_zeromotion_pct = 100;
1760*fb1b10abSAndroid Build Coastguard Worker   twopass->last_kfgroup_zeromotion_pct = 100;
1761*fb1b10abSAndroid Build Coastguard Worker 
1762*fb1b10abSAndroid Build Coastguard Worker   // Initialize bits per macro_block estimate correction factor.
1763*fb1b10abSAndroid Build Coastguard Worker   twopass->bpm_factor = 1.0;
1764*fb1b10abSAndroid Build Coastguard Worker   // Initialize actual and target bits counters for ARF groups so that
1765*fb1b10abSAndroid Build Coastguard Worker   // at the start we have a neutral bpm adjustment.
1766*fb1b10abSAndroid Build Coastguard Worker   twopass->rolling_arf_group_target_bits = 1;
1767*fb1b10abSAndroid Build Coastguard Worker   twopass->rolling_arf_group_actual_bits = 1;
1768*fb1b10abSAndroid Build Coastguard Worker 
1769*fb1b10abSAndroid Build Coastguard Worker   if (oxcf->resize_mode != RESIZE_NONE) {
1770*fb1b10abSAndroid Build Coastguard Worker     init_subsampling(cpi);
1771*fb1b10abSAndroid Build Coastguard Worker   }
1772*fb1b10abSAndroid Build Coastguard Worker 
1773*fb1b10abSAndroid Build Coastguard Worker   // Initialize the arnr strangth adjustment to 0
1774*fb1b10abSAndroid Build Coastguard Worker   twopass->arnr_strength_adjustment = 0;
1775*fb1b10abSAndroid Build Coastguard Worker }
1776*fb1b10abSAndroid Build Coastguard Worker 
1777*fb1b10abSAndroid Build Coastguard Worker /* This function considers how the quality of prediction may be deteriorating
1778*fb1b10abSAndroid Build Coastguard Worker  * with distance. It compares the coded error for the last frame and the
1779*fb1b10abSAndroid Build Coastguard Worker  * second reference frame (usually two frames old) and also applies a factor
1780*fb1b10abSAndroid Build Coastguard Worker  * based on the extent of INTRA coding.
1781*fb1b10abSAndroid Build Coastguard Worker  *
1782*fb1b10abSAndroid Build Coastguard Worker  * The decay factor is then used to reduce the contribution of frames further
1783*fb1b10abSAndroid Build Coastguard Worker  * from the alt-ref or golden frame, to the bitrate boost calculation for that
1784*fb1b10abSAndroid Build Coastguard Worker  * alt-ref or golden frame.
1785*fb1b10abSAndroid Build Coastguard Worker  */
get_sr_decay_rate(const TWO_PASS * const twopass,const FIRSTPASS_STATS * frame)1786*fb1b10abSAndroid Build Coastguard Worker static double get_sr_decay_rate(const TWO_PASS *const twopass,
1787*fb1b10abSAndroid Build Coastguard Worker                                 const FIRSTPASS_STATS *frame) {
1788*fb1b10abSAndroid Build Coastguard Worker   double sr_diff = (frame->sr_coded_error - frame->coded_error);
1789*fb1b10abSAndroid Build Coastguard Worker   double sr_decay = 1.0;
1790*fb1b10abSAndroid Build Coastguard Worker 
1791*fb1b10abSAndroid Build Coastguard Worker   // Do nothing if the second ref to last frame error difference is
1792*fb1b10abSAndroid Build Coastguard Worker   // very small or even negative.
1793*fb1b10abSAndroid Build Coastguard Worker   if ((sr_diff > LOW_SR_DIFF_TRHESH)) {
1794*fb1b10abSAndroid Build Coastguard Worker     const double sr_diff_part =
1795*fb1b10abSAndroid Build Coastguard Worker         twopass->sr_diff_factor * ((sr_diff * 0.25) / frame->intra_error);
1796*fb1b10abSAndroid Build Coastguard Worker     double modified_pct_inter = frame->pcnt_inter;
1797*fb1b10abSAndroid Build Coastguard Worker     double modified_pcnt_intra;
1798*fb1b10abSAndroid Build Coastguard Worker 
1799*fb1b10abSAndroid Build Coastguard Worker     if ((frame->coded_error > LOW_CODED_ERR_PER_MB) &&
1800*fb1b10abSAndroid Build Coastguard Worker         ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) <
1801*fb1b10abSAndroid Build Coastguard Worker          (double)NCOUNT_FRAME_II_THRESH)) {
1802*fb1b10abSAndroid Build Coastguard Worker       modified_pct_inter =
1803*fb1b10abSAndroid Build Coastguard Worker           frame->pcnt_inter + frame->pcnt_intra_low - frame->pcnt_neutral;
1804*fb1b10abSAndroid Build Coastguard Worker     }
1805*fb1b10abSAndroid Build Coastguard Worker     modified_pcnt_intra = 100 * (1.0 - modified_pct_inter);
1806*fb1b10abSAndroid Build Coastguard Worker 
1807*fb1b10abSAndroid Build Coastguard Worker     sr_decay = 1.0 - sr_diff_part - (INTRA_PART * modified_pcnt_intra);
1808*fb1b10abSAndroid Build Coastguard Worker   }
1809*fb1b10abSAndroid Build Coastguard Worker   return VPXMAX(sr_decay, twopass->sr_default_decay_limit);
1810*fb1b10abSAndroid Build Coastguard Worker }
1811*fb1b10abSAndroid Build Coastguard Worker 
1812*fb1b10abSAndroid Build Coastguard Worker // This function gives an estimate of how badly we believe the prediction
1813*fb1b10abSAndroid Build Coastguard Worker // quality is decaying from frame to frame.
get_zero_motion_factor(const TWO_PASS * const twopass,const FIRSTPASS_STATS * frame_stats)1814*fb1b10abSAndroid Build Coastguard Worker static double get_zero_motion_factor(const TWO_PASS *const twopass,
1815*fb1b10abSAndroid Build Coastguard Worker                                      const FIRSTPASS_STATS *frame_stats) {
1816*fb1b10abSAndroid Build Coastguard Worker   const double zero_motion_pct =
1817*fb1b10abSAndroid Build Coastguard Worker       frame_stats->pcnt_inter - frame_stats->pcnt_motion;
1818*fb1b10abSAndroid Build Coastguard Worker   double sr_decay = get_sr_decay_rate(twopass, frame_stats);
1819*fb1b10abSAndroid Build Coastguard Worker   return VPXMIN(sr_decay, zero_motion_pct);
1820*fb1b10abSAndroid Build Coastguard Worker }
1821*fb1b10abSAndroid Build Coastguard Worker 
get_prediction_decay_rate(const TWO_PASS * const twopass,const FIRSTPASS_STATS * frame_stats)1822*fb1b10abSAndroid Build Coastguard Worker static double get_prediction_decay_rate(const TWO_PASS *const twopass,
1823*fb1b10abSAndroid Build Coastguard Worker                                         const FIRSTPASS_STATS *frame_stats) {
1824*fb1b10abSAndroid Build Coastguard Worker   const double sr_decay_rate = get_sr_decay_rate(twopass, frame_stats);
1825*fb1b10abSAndroid Build Coastguard Worker   double zero_motion_factor =
1826*fb1b10abSAndroid Build Coastguard Worker       twopass->zm_factor * (frame_stats->pcnt_inter - frame_stats->pcnt_motion);
1827*fb1b10abSAndroid Build Coastguard Worker 
1828*fb1b10abSAndroid Build Coastguard Worker   // Check that the zero motion factor is valid
1829*fb1b10abSAndroid Build Coastguard Worker   assert(zero_motion_factor >= 0.0 && zero_motion_factor <= 1.0);
1830*fb1b10abSAndroid Build Coastguard Worker 
1831*fb1b10abSAndroid Build Coastguard Worker   return VPXMAX(zero_motion_factor,
1832*fb1b10abSAndroid Build Coastguard Worker                 (sr_decay_rate + ((1.0 - sr_decay_rate) * zero_motion_factor)));
1833*fb1b10abSAndroid Build Coastguard Worker }
1834*fb1b10abSAndroid Build Coastguard Worker 
get_show_idx(const TWO_PASS * twopass)1835*fb1b10abSAndroid Build Coastguard Worker static int get_show_idx(const TWO_PASS *twopass) {
1836*fb1b10abSAndroid Build Coastguard Worker   return (int)(twopass->stats_in - twopass->stats_in_start);
1837*fb1b10abSAndroid Build Coastguard Worker }
1838*fb1b10abSAndroid Build Coastguard Worker // Function to test for a condition where a complex transition is followed
1839*fb1b10abSAndroid Build Coastguard Worker // by a static section. For example in slide shows where there is a fade
1840*fb1b10abSAndroid Build Coastguard Worker // between slides. This is to help with more optimal kf and gf positioning.
check_transition_to_still(const FIRST_PASS_INFO * first_pass_info,int show_idx,int still_interval)1841*fb1b10abSAndroid Build Coastguard Worker static int check_transition_to_still(const FIRST_PASS_INFO *first_pass_info,
1842*fb1b10abSAndroid Build Coastguard Worker                                      int show_idx, int still_interval) {
1843*fb1b10abSAndroid Build Coastguard Worker   int j;
1844*fb1b10abSAndroid Build Coastguard Worker   int num_frames = fps_get_num_frames(first_pass_info);
1845*fb1b10abSAndroid Build Coastguard Worker   if (show_idx + still_interval > num_frames) {
1846*fb1b10abSAndroid Build Coastguard Worker     return 0;
1847*fb1b10abSAndroid Build Coastguard Worker   }
1848*fb1b10abSAndroid Build Coastguard Worker 
1849*fb1b10abSAndroid Build Coastguard Worker   // Look ahead a few frames to see if static condition persists...
1850*fb1b10abSAndroid Build Coastguard Worker   for (j = 0; j < still_interval; ++j) {
1851*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *stats =
1852*fb1b10abSAndroid Build Coastguard Worker         fps_get_frame_stats(first_pass_info, show_idx + j);
1853*fb1b10abSAndroid Build Coastguard Worker     if (stats->pcnt_inter - stats->pcnt_motion < 0.999) break;
1854*fb1b10abSAndroid Build Coastguard Worker   }
1855*fb1b10abSAndroid Build Coastguard Worker 
1856*fb1b10abSAndroid Build Coastguard Worker   // Only if it does do we signal a transition to still.
1857*fb1b10abSAndroid Build Coastguard Worker   return j == still_interval;
1858*fb1b10abSAndroid Build Coastguard Worker }
1859*fb1b10abSAndroid Build Coastguard Worker 
1860*fb1b10abSAndroid Build Coastguard Worker // This function detects a flash through the high relative pcnt_second_ref
1861*fb1b10abSAndroid Build Coastguard Worker // score in the frame following a flash frame. The offset passed in should
1862*fb1b10abSAndroid Build Coastguard Worker // reflect this.
detect_flash_from_frame_stats(const FIRSTPASS_STATS * frame_stats)1863*fb1b10abSAndroid Build Coastguard Worker static int detect_flash_from_frame_stats(const FIRSTPASS_STATS *frame_stats) {
1864*fb1b10abSAndroid Build Coastguard Worker   // What we are looking for here is a situation where there is a
1865*fb1b10abSAndroid Build Coastguard Worker   // brief break in prediction (such as a flash) but subsequent frames
1866*fb1b10abSAndroid Build Coastguard Worker   // are reasonably well predicted by an earlier (pre flash) frame.
1867*fb1b10abSAndroid Build Coastguard Worker   // The recovery after a flash is indicated by a high pcnt_second_ref
1868*fb1b10abSAndroid Build Coastguard Worker   // usage or a second ref coded error notabley lower than the last
1869*fb1b10abSAndroid Build Coastguard Worker   // frame coded error.
1870*fb1b10abSAndroid Build Coastguard Worker   if (frame_stats == NULL) {
1871*fb1b10abSAndroid Build Coastguard Worker     return 0;
1872*fb1b10abSAndroid Build Coastguard Worker   }
1873*fb1b10abSAndroid Build Coastguard Worker   return (frame_stats->sr_coded_error < frame_stats->coded_error) ||
1874*fb1b10abSAndroid Build Coastguard Worker          ((frame_stats->pcnt_second_ref > frame_stats->pcnt_inter) &&
1875*fb1b10abSAndroid Build Coastguard Worker           (frame_stats->pcnt_second_ref >= 0.5));
1876*fb1b10abSAndroid Build Coastguard Worker }
1877*fb1b10abSAndroid Build Coastguard Worker 
detect_flash(const TWO_PASS * twopass,int offset)1878*fb1b10abSAndroid Build Coastguard Worker static int detect_flash(const TWO_PASS *twopass, int offset) {
1879*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *const next_frame = read_frame_stats(twopass, offset);
1880*fb1b10abSAndroid Build Coastguard Worker   return detect_flash_from_frame_stats(next_frame);
1881*fb1b10abSAndroid Build Coastguard Worker }
1882*fb1b10abSAndroid Build Coastguard Worker 
1883*fb1b10abSAndroid Build Coastguard Worker // Update the motion related elements to the GF arf boost calculation.
accumulate_frame_motion_stats(const FIRSTPASS_STATS * stats,double * mv_in_out,double * mv_in_out_accumulator,double * abs_mv_in_out_accumulator,double * mv_ratio_accumulator)1884*fb1b10abSAndroid Build Coastguard Worker static void accumulate_frame_motion_stats(const FIRSTPASS_STATS *stats,
1885*fb1b10abSAndroid Build Coastguard Worker                                           double *mv_in_out,
1886*fb1b10abSAndroid Build Coastguard Worker                                           double *mv_in_out_accumulator,
1887*fb1b10abSAndroid Build Coastguard Worker                                           double *abs_mv_in_out_accumulator,
1888*fb1b10abSAndroid Build Coastguard Worker                                           double *mv_ratio_accumulator) {
1889*fb1b10abSAndroid Build Coastguard Worker   const double pct = stats->pcnt_motion;
1890*fb1b10abSAndroid Build Coastguard Worker 
1891*fb1b10abSAndroid Build Coastguard Worker   // Accumulate Motion In/Out of frame stats.
1892*fb1b10abSAndroid Build Coastguard Worker   *mv_in_out = stats->mv_in_out_count * pct;
1893*fb1b10abSAndroid Build Coastguard Worker   *mv_in_out_accumulator += *mv_in_out;
1894*fb1b10abSAndroid Build Coastguard Worker   *abs_mv_in_out_accumulator += fabs(*mv_in_out);
1895*fb1b10abSAndroid Build Coastguard Worker 
1896*fb1b10abSAndroid Build Coastguard Worker   // Accumulate a measure of how uniform (or conversely how random) the motion
1897*fb1b10abSAndroid Build Coastguard Worker   // field is (a ratio of abs(mv) / mv).
1898*fb1b10abSAndroid Build Coastguard Worker   if (pct > 0.05) {
1899*fb1b10abSAndroid Build Coastguard Worker     const double mvr_ratio =
1900*fb1b10abSAndroid Build Coastguard Worker         fabs(stats->mvr_abs) / DOUBLE_DIVIDE_CHECK(fabs(stats->MVr));
1901*fb1b10abSAndroid Build Coastguard Worker     const double mvc_ratio =
1902*fb1b10abSAndroid Build Coastguard Worker         fabs(stats->mvc_abs) / DOUBLE_DIVIDE_CHECK(fabs(stats->MVc));
1903*fb1b10abSAndroid Build Coastguard Worker 
1904*fb1b10abSAndroid Build Coastguard Worker     *mv_ratio_accumulator +=
1905*fb1b10abSAndroid Build Coastguard Worker         pct * (mvr_ratio < stats->mvr_abs ? mvr_ratio : stats->mvr_abs);
1906*fb1b10abSAndroid Build Coastguard Worker     *mv_ratio_accumulator +=
1907*fb1b10abSAndroid Build Coastguard Worker         pct * (mvc_ratio < stats->mvc_abs ? mvc_ratio : stats->mvc_abs);
1908*fb1b10abSAndroid Build Coastguard Worker   }
1909*fb1b10abSAndroid Build Coastguard Worker }
1910*fb1b10abSAndroid Build Coastguard Worker 
calc_frame_boost(const FRAME_INFO * frame_info,const FIRSTPASS_STATS * this_frame,const TWO_PASS * const twopass,int avg_frame_qindex,double this_frame_mv_in_out)1911*fb1b10abSAndroid Build Coastguard Worker static double calc_frame_boost(const FRAME_INFO *frame_info,
1912*fb1b10abSAndroid Build Coastguard Worker                                const FIRSTPASS_STATS *this_frame,
1913*fb1b10abSAndroid Build Coastguard Worker                                const TWO_PASS *const twopass,
1914*fb1b10abSAndroid Build Coastguard Worker                                int avg_frame_qindex,
1915*fb1b10abSAndroid Build Coastguard Worker                                double this_frame_mv_in_out) {
1916*fb1b10abSAndroid Build Coastguard Worker   double frame_boost;
1917*fb1b10abSAndroid Build Coastguard Worker   const double lq =
1918*fb1b10abSAndroid Build Coastguard Worker       vp9_convert_qindex_to_q(avg_frame_qindex, frame_info->bit_depth);
1919*fb1b10abSAndroid Build Coastguard Worker   const double boost_q_correction = VPXMIN((0.5 + (lq * 0.015)), 1.5);
1920*fb1b10abSAndroid Build Coastguard Worker   const double active_area = calculate_active_area(frame_info, this_frame);
1921*fb1b10abSAndroid Build Coastguard Worker 
1922*fb1b10abSAndroid Build Coastguard Worker   // Frame booost is based on inter error.
1923*fb1b10abSAndroid Build Coastguard Worker   frame_boost = (twopass->err_per_mb * active_area) /
1924*fb1b10abSAndroid Build Coastguard Worker                 DOUBLE_DIVIDE_CHECK(this_frame->coded_error);
1925*fb1b10abSAndroid Build Coastguard Worker 
1926*fb1b10abSAndroid Build Coastguard Worker   // Small adjustment for cases where there is a zoom out
1927*fb1b10abSAndroid Build Coastguard Worker   if (this_frame_mv_in_out > 0.0)
1928*fb1b10abSAndroid Build Coastguard Worker     frame_boost += frame_boost * (this_frame_mv_in_out * 2.0);
1929*fb1b10abSAndroid Build Coastguard Worker 
1930*fb1b10abSAndroid Build Coastguard Worker   // Q correction and scalling
1931*fb1b10abSAndroid Build Coastguard Worker   frame_boost = frame_boost * boost_q_correction;
1932*fb1b10abSAndroid Build Coastguard Worker 
1933*fb1b10abSAndroid Build Coastguard Worker   return VPXMIN(frame_boost, twopass->gf_frame_max_boost * boost_q_correction);
1934*fb1b10abSAndroid Build Coastguard Worker }
1935*fb1b10abSAndroid Build Coastguard Worker 
calc_kf_frame_boost(VP9_COMP * cpi,const FIRSTPASS_STATS * this_frame,double * sr_accumulator,double this_frame_mv_in_out,double zm_factor)1936*fb1b10abSAndroid Build Coastguard Worker static double calc_kf_frame_boost(VP9_COMP *cpi,
1937*fb1b10abSAndroid Build Coastguard Worker                                   const FIRSTPASS_STATS *this_frame,
1938*fb1b10abSAndroid Build Coastguard Worker                                   double *sr_accumulator,
1939*fb1b10abSAndroid Build Coastguard Worker                                   double this_frame_mv_in_out,
1940*fb1b10abSAndroid Build Coastguard Worker                                   double zm_factor) {
1941*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
1942*fb1b10abSAndroid Build Coastguard Worker   double frame_boost;
1943*fb1b10abSAndroid Build Coastguard Worker   const double lq = vp9_convert_qindex_to_q(
1944*fb1b10abSAndroid Build Coastguard Worker       cpi->rc.avg_frame_qindex[INTER_FRAME], cpi->common.bit_depth);
1945*fb1b10abSAndroid Build Coastguard Worker   const double boost_q_correction = VPXMIN((0.50 + (lq * 0.015)), 2.00);
1946*fb1b10abSAndroid Build Coastguard Worker   const double active_area =
1947*fb1b10abSAndroid Build Coastguard Worker       calculate_active_area(&cpi->frame_info, this_frame);
1948*fb1b10abSAndroid Build Coastguard Worker   double max_boost;
1949*fb1b10abSAndroid Build Coastguard Worker 
1950*fb1b10abSAndroid Build Coastguard Worker   // Frame booost is based on inter error.
1951*fb1b10abSAndroid Build Coastguard Worker   frame_boost = (twopass->kf_err_per_mb * active_area) /
1952*fb1b10abSAndroid Build Coastguard Worker                 DOUBLE_DIVIDE_CHECK(this_frame->coded_error + *sr_accumulator);
1953*fb1b10abSAndroid Build Coastguard Worker 
1954*fb1b10abSAndroid Build Coastguard Worker   // Update the accumulator for second ref error difference.
1955*fb1b10abSAndroid Build Coastguard Worker   // This is intended to give an indication of how much the coded error is
1956*fb1b10abSAndroid Build Coastguard Worker   // increasing over time.
1957*fb1b10abSAndroid Build Coastguard Worker   *sr_accumulator += (this_frame->sr_coded_error - this_frame->coded_error);
1958*fb1b10abSAndroid Build Coastguard Worker   *sr_accumulator = VPXMAX(0.0, *sr_accumulator);
1959*fb1b10abSAndroid Build Coastguard Worker 
1960*fb1b10abSAndroid Build Coastguard Worker   // Small adjustment for cases where there is a zoom out
1961*fb1b10abSAndroid Build Coastguard Worker   if (this_frame_mv_in_out > 0.0)
1962*fb1b10abSAndroid Build Coastguard Worker     frame_boost += frame_boost * (this_frame_mv_in_out * 2.0);
1963*fb1b10abSAndroid Build Coastguard Worker 
1964*fb1b10abSAndroid Build Coastguard Worker   // Q correction and scaling
1965*fb1b10abSAndroid Build Coastguard Worker   // The 40.0 value here is an experimentally derived baseline minimum.
1966*fb1b10abSAndroid Build Coastguard Worker   // This value is in line with the minimum per frame boost in the alt_ref
1967*fb1b10abSAndroid Build Coastguard Worker   // boost calculation.
1968*fb1b10abSAndroid Build Coastguard Worker   frame_boost =
1969*fb1b10abSAndroid Build Coastguard Worker       (frame_boost + twopass->kf_frame_min_boost) * boost_q_correction;
1970*fb1b10abSAndroid Build Coastguard Worker 
1971*fb1b10abSAndroid Build Coastguard Worker   // Maximum allowed boost this frame. May be different for first vs subsequent
1972*fb1b10abSAndroid Build Coastguard Worker   // key frames.
1973*fb1b10abSAndroid Build Coastguard Worker   max_boost = (cpi->common.current_video_frame == 0)
1974*fb1b10abSAndroid Build Coastguard Worker                   ? twopass->kf_frame_max_boost_first
1975*fb1b10abSAndroid Build Coastguard Worker                   : twopass->kf_frame_max_boost_subs;
1976*fb1b10abSAndroid Build Coastguard Worker   max_boost *= zm_factor * boost_q_correction;
1977*fb1b10abSAndroid Build Coastguard Worker 
1978*fb1b10abSAndroid Build Coastguard Worker   return VPXMIN(frame_boost, max_boost);
1979*fb1b10abSAndroid Build Coastguard Worker }
1980*fb1b10abSAndroid Build Coastguard Worker 
compute_arf_boost(const FRAME_INFO * frame_info,TWO_PASS * const twopass,int arf_show_idx,int f_frames,int b_frames,int avg_frame_qindex)1981*fb1b10abSAndroid Build Coastguard Worker static int compute_arf_boost(const FRAME_INFO *frame_info,
1982*fb1b10abSAndroid Build Coastguard Worker                              TWO_PASS *const twopass, int arf_show_idx,
1983*fb1b10abSAndroid Build Coastguard Worker                              int f_frames, int b_frames, int avg_frame_qindex) {
1984*fb1b10abSAndroid Build Coastguard Worker   const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
1985*fb1b10abSAndroid Build Coastguard Worker   int i;
1986*fb1b10abSAndroid Build Coastguard Worker   double boost_score = 0.0;
1987*fb1b10abSAndroid Build Coastguard Worker   double mv_ratio_accumulator = 0.0;
1988*fb1b10abSAndroid Build Coastguard Worker   double decay_accumulator = 1.0;
1989*fb1b10abSAndroid Build Coastguard Worker   double this_frame_mv_in_out = 0.0;
1990*fb1b10abSAndroid Build Coastguard Worker   double mv_in_out_accumulator = 0.0;
1991*fb1b10abSAndroid Build Coastguard Worker   double abs_mv_in_out_accumulator = 0.0;
1992*fb1b10abSAndroid Build Coastguard Worker   int arf_boost;
1993*fb1b10abSAndroid Build Coastguard Worker   int flash_detected = 0;
1994*fb1b10abSAndroid Build Coastguard Worker 
1995*fb1b10abSAndroid Build Coastguard Worker   // Search forward from the proposed arf/next gf position.
1996*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < f_frames; ++i) {
1997*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *this_frame =
1998*fb1b10abSAndroid Build Coastguard Worker         fps_get_frame_stats(first_pass_info, arf_show_idx + i);
1999*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *next_frame =
2000*fb1b10abSAndroid Build Coastguard Worker         fps_get_frame_stats(first_pass_info, arf_show_idx + i + 1);
2001*fb1b10abSAndroid Build Coastguard Worker     if (this_frame == NULL) break;
2002*fb1b10abSAndroid Build Coastguard Worker 
2003*fb1b10abSAndroid Build Coastguard Worker     // Update the motion related elements to the boost calculation.
2004*fb1b10abSAndroid Build Coastguard Worker     accumulate_frame_motion_stats(
2005*fb1b10abSAndroid Build Coastguard Worker         this_frame, &this_frame_mv_in_out, &mv_in_out_accumulator,
2006*fb1b10abSAndroid Build Coastguard Worker         &abs_mv_in_out_accumulator, &mv_ratio_accumulator);
2007*fb1b10abSAndroid Build Coastguard Worker 
2008*fb1b10abSAndroid Build Coastguard Worker     // We want to discount the flash frame itself and the recovery
2009*fb1b10abSAndroid Build Coastguard Worker     // frame that follows as both will have poor scores.
2010*fb1b10abSAndroid Build Coastguard Worker     flash_detected = detect_flash_from_frame_stats(this_frame) ||
2011*fb1b10abSAndroid Build Coastguard Worker                      detect_flash_from_frame_stats(next_frame);
2012*fb1b10abSAndroid Build Coastguard Worker 
2013*fb1b10abSAndroid Build Coastguard Worker     // Accumulate the effect of prediction quality decay.
2014*fb1b10abSAndroid Build Coastguard Worker     if (!flash_detected) {
2015*fb1b10abSAndroid Build Coastguard Worker       decay_accumulator *= get_prediction_decay_rate(twopass, this_frame);
2016*fb1b10abSAndroid Build Coastguard Worker       decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
2017*fb1b10abSAndroid Build Coastguard Worker                               ? MIN_DECAY_FACTOR
2018*fb1b10abSAndroid Build Coastguard Worker                               : decay_accumulator;
2019*fb1b10abSAndroid Build Coastguard Worker     }
2020*fb1b10abSAndroid Build Coastguard Worker     boost_score += decay_accumulator *
2021*fb1b10abSAndroid Build Coastguard Worker                    calc_frame_boost(frame_info, this_frame, twopass,
2022*fb1b10abSAndroid Build Coastguard Worker                                     avg_frame_qindex, this_frame_mv_in_out);
2023*fb1b10abSAndroid Build Coastguard Worker   }
2024*fb1b10abSAndroid Build Coastguard Worker 
2025*fb1b10abSAndroid Build Coastguard Worker   arf_boost = (int)boost_score;
2026*fb1b10abSAndroid Build Coastguard Worker 
2027*fb1b10abSAndroid Build Coastguard Worker   // Reset for backward looking loop.
2028*fb1b10abSAndroid Build Coastguard Worker   boost_score = 0.0;
2029*fb1b10abSAndroid Build Coastguard Worker   mv_ratio_accumulator = 0.0;
2030*fb1b10abSAndroid Build Coastguard Worker   decay_accumulator = 1.0;
2031*fb1b10abSAndroid Build Coastguard Worker   this_frame_mv_in_out = 0.0;
2032*fb1b10abSAndroid Build Coastguard Worker   mv_in_out_accumulator = 0.0;
2033*fb1b10abSAndroid Build Coastguard Worker   abs_mv_in_out_accumulator = 0.0;
2034*fb1b10abSAndroid Build Coastguard Worker 
2035*fb1b10abSAndroid Build Coastguard Worker   // Search backward towards last gf position.
2036*fb1b10abSAndroid Build Coastguard Worker   for (i = -1; i >= -b_frames; --i) {
2037*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *this_frame =
2038*fb1b10abSAndroid Build Coastguard Worker         fps_get_frame_stats(first_pass_info, arf_show_idx + i);
2039*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *next_frame =
2040*fb1b10abSAndroid Build Coastguard Worker         fps_get_frame_stats(first_pass_info, arf_show_idx + i + 1);
2041*fb1b10abSAndroid Build Coastguard Worker     if (this_frame == NULL) break;
2042*fb1b10abSAndroid Build Coastguard Worker 
2043*fb1b10abSAndroid Build Coastguard Worker     // Update the motion related elements to the boost calculation.
2044*fb1b10abSAndroid Build Coastguard Worker     accumulate_frame_motion_stats(
2045*fb1b10abSAndroid Build Coastguard Worker         this_frame, &this_frame_mv_in_out, &mv_in_out_accumulator,
2046*fb1b10abSAndroid Build Coastguard Worker         &abs_mv_in_out_accumulator, &mv_ratio_accumulator);
2047*fb1b10abSAndroid Build Coastguard Worker 
2048*fb1b10abSAndroid Build Coastguard Worker     // We want to discount the flash frame itself and the recovery
2049*fb1b10abSAndroid Build Coastguard Worker     // frame that follows as both will have poor scores.
2050*fb1b10abSAndroid Build Coastguard Worker     flash_detected = detect_flash_from_frame_stats(this_frame) ||
2051*fb1b10abSAndroid Build Coastguard Worker                      detect_flash_from_frame_stats(next_frame);
2052*fb1b10abSAndroid Build Coastguard Worker 
2053*fb1b10abSAndroid Build Coastguard Worker     // Cumulative effect of prediction quality decay.
2054*fb1b10abSAndroid Build Coastguard Worker     if (!flash_detected) {
2055*fb1b10abSAndroid Build Coastguard Worker       decay_accumulator *= get_prediction_decay_rate(twopass, this_frame);
2056*fb1b10abSAndroid Build Coastguard Worker       decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
2057*fb1b10abSAndroid Build Coastguard Worker                               ? MIN_DECAY_FACTOR
2058*fb1b10abSAndroid Build Coastguard Worker                               : decay_accumulator;
2059*fb1b10abSAndroid Build Coastguard Worker     }
2060*fb1b10abSAndroid Build Coastguard Worker     boost_score += decay_accumulator *
2061*fb1b10abSAndroid Build Coastguard Worker                    calc_frame_boost(frame_info, this_frame, twopass,
2062*fb1b10abSAndroid Build Coastguard Worker                                     avg_frame_qindex, this_frame_mv_in_out);
2063*fb1b10abSAndroid Build Coastguard Worker   }
2064*fb1b10abSAndroid Build Coastguard Worker   arf_boost += (int)boost_score;
2065*fb1b10abSAndroid Build Coastguard Worker 
2066*fb1b10abSAndroid Build Coastguard Worker   if (arf_boost < ((b_frames + f_frames) * 40))
2067*fb1b10abSAndroid Build Coastguard Worker     arf_boost = ((b_frames + f_frames) * 40);
2068*fb1b10abSAndroid Build Coastguard Worker   arf_boost = VPXMAX(arf_boost, MIN_ARF_GF_BOOST);
2069*fb1b10abSAndroid Build Coastguard Worker 
2070*fb1b10abSAndroid Build Coastguard Worker   return arf_boost;
2071*fb1b10abSAndroid Build Coastguard Worker }
2072*fb1b10abSAndroid Build Coastguard Worker 
calc_arf_boost(VP9_COMP * cpi,int f_frames,int b_frames)2073*fb1b10abSAndroid Build Coastguard Worker static int calc_arf_boost(VP9_COMP *cpi, int f_frames, int b_frames) {
2074*fb1b10abSAndroid Build Coastguard Worker   const FRAME_INFO *frame_info = &cpi->frame_info;
2075*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
2076*fb1b10abSAndroid Build Coastguard Worker   const int avg_inter_frame_qindex = cpi->rc.avg_frame_qindex[INTER_FRAME];
2077*fb1b10abSAndroid Build Coastguard Worker   int arf_show_idx = get_show_idx(twopass);
2078*fb1b10abSAndroid Build Coastguard Worker   return compute_arf_boost(frame_info, twopass, arf_show_idx, f_frames,
2079*fb1b10abSAndroid Build Coastguard Worker                            b_frames, avg_inter_frame_qindex);
2080*fb1b10abSAndroid Build Coastguard Worker }
2081*fb1b10abSAndroid Build Coastguard Worker 
2082*fb1b10abSAndroid Build Coastguard Worker // Calculate a section intra ratio used in setting max loop filter.
calculate_section_intra_ratio(const FIRSTPASS_STATS * begin,const FIRSTPASS_STATS * end,int section_length)2083*fb1b10abSAndroid Build Coastguard Worker static int calculate_section_intra_ratio(const FIRSTPASS_STATS *begin,
2084*fb1b10abSAndroid Build Coastguard Worker                                          const FIRSTPASS_STATS *end,
2085*fb1b10abSAndroid Build Coastguard Worker                                          int section_length) {
2086*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *s = begin;
2087*fb1b10abSAndroid Build Coastguard Worker   double intra_error = 0.0;
2088*fb1b10abSAndroid Build Coastguard Worker   double coded_error = 0.0;
2089*fb1b10abSAndroid Build Coastguard Worker   int i = 0;
2090*fb1b10abSAndroid Build Coastguard Worker 
2091*fb1b10abSAndroid Build Coastguard Worker   while (s < end && i < section_length) {
2092*fb1b10abSAndroid Build Coastguard Worker     intra_error += s->intra_error;
2093*fb1b10abSAndroid Build Coastguard Worker     coded_error += s->coded_error;
2094*fb1b10abSAndroid Build Coastguard Worker     ++s;
2095*fb1b10abSAndroid Build Coastguard Worker     ++i;
2096*fb1b10abSAndroid Build Coastguard Worker   }
2097*fb1b10abSAndroid Build Coastguard Worker 
2098*fb1b10abSAndroid Build Coastguard Worker   return (int)(intra_error / DOUBLE_DIVIDE_CHECK(coded_error));
2099*fb1b10abSAndroid Build Coastguard Worker }
2100*fb1b10abSAndroid Build Coastguard Worker 
2101*fb1b10abSAndroid Build Coastguard Worker // Calculate the total bits to allocate in this GF/ARF group.
calculate_total_gf_group_bits(VP9_COMP * cpi,double gf_group_err)2102*fb1b10abSAndroid Build Coastguard Worker static int64_t calculate_total_gf_group_bits(VP9_COMP *cpi,
2103*fb1b10abSAndroid Build Coastguard Worker                                              double gf_group_err) {
2104*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
2105*fb1b10abSAndroid Build Coastguard Worker   const RATE_CONTROL *const rc = &cpi->rc;
2106*fb1b10abSAndroid Build Coastguard Worker   const TWO_PASS *const twopass = &cpi->twopass;
2107*fb1b10abSAndroid Build Coastguard Worker   const int max_bits = frame_max_bits(rc, &cpi->oxcf);
2108*fb1b10abSAndroid Build Coastguard Worker   int64_t total_group_bits;
2109*fb1b10abSAndroid Build Coastguard Worker   const int is_key_frame = frame_is_intra_only(cm);
2110*fb1b10abSAndroid Build Coastguard Worker   const int arf_active_or_kf = is_key_frame || rc->source_alt_ref_active;
2111*fb1b10abSAndroid Build Coastguard Worker   int gop_frames =
2112*fb1b10abSAndroid Build Coastguard Worker       rc->baseline_gf_interval + rc->source_alt_ref_pending - arf_active_or_kf;
2113*fb1b10abSAndroid Build Coastguard Worker 
2114*fb1b10abSAndroid Build Coastguard Worker   // Calculate the bits to be allocated to the group as a whole.
2115*fb1b10abSAndroid Build Coastguard Worker   if ((twopass->kf_group_bits > 0) && (twopass->kf_group_error_left > 0.0)) {
2116*fb1b10abSAndroid Build Coastguard Worker     int key_frame_interval = rc->frames_since_key + rc->frames_to_key;
2117*fb1b10abSAndroid Build Coastguard Worker     int distance_from_next_key_frame =
2118*fb1b10abSAndroid Build Coastguard Worker         rc->frames_to_key -
2119*fb1b10abSAndroid Build Coastguard Worker         (rc->baseline_gf_interval + rc->source_alt_ref_pending);
2120*fb1b10abSAndroid Build Coastguard Worker     int max_gf_bits_bias = rc->avg_frame_bandwidth;
2121*fb1b10abSAndroid Build Coastguard Worker     double gf_interval_bias_bits_normalize_factor =
2122*fb1b10abSAndroid Build Coastguard Worker         (double)rc->baseline_gf_interval / 16;
2123*fb1b10abSAndroid Build Coastguard Worker     total_group_bits = (int64_t)(twopass->kf_group_bits *
2124*fb1b10abSAndroid Build Coastguard Worker                                  (gf_group_err / twopass->kf_group_error_left));
2125*fb1b10abSAndroid Build Coastguard Worker     // TODO(ravi): Experiment with different values of max_gf_bits_bias
2126*fb1b10abSAndroid Build Coastguard Worker     total_group_bits +=
2127*fb1b10abSAndroid Build Coastguard Worker         (int64_t)((double)distance_from_next_key_frame / key_frame_interval *
2128*fb1b10abSAndroid Build Coastguard Worker                   max_gf_bits_bias * gf_interval_bias_bits_normalize_factor);
2129*fb1b10abSAndroid Build Coastguard Worker   } else {
2130*fb1b10abSAndroid Build Coastguard Worker     total_group_bits = 0;
2131*fb1b10abSAndroid Build Coastguard Worker   }
2132*fb1b10abSAndroid Build Coastguard Worker 
2133*fb1b10abSAndroid Build Coastguard Worker   // Clamp odd edge cases.
2134*fb1b10abSAndroid Build Coastguard Worker   total_group_bits = (total_group_bits < 0) ? 0
2135*fb1b10abSAndroid Build Coastguard Worker                      : (total_group_bits > twopass->kf_group_bits)
2136*fb1b10abSAndroid Build Coastguard Worker                          ? twopass->kf_group_bits
2137*fb1b10abSAndroid Build Coastguard Worker                          : total_group_bits;
2138*fb1b10abSAndroid Build Coastguard Worker 
2139*fb1b10abSAndroid Build Coastguard Worker   // Clip based on user supplied data rate variability limit.
2140*fb1b10abSAndroid Build Coastguard Worker   if (total_group_bits > (int64_t)max_bits * gop_frames)
2141*fb1b10abSAndroid Build Coastguard Worker     total_group_bits = (int64_t)max_bits * gop_frames;
2142*fb1b10abSAndroid Build Coastguard Worker 
2143*fb1b10abSAndroid Build Coastguard Worker   return total_group_bits;
2144*fb1b10abSAndroid Build Coastguard Worker }
2145*fb1b10abSAndroid Build Coastguard Worker 
2146*fb1b10abSAndroid Build Coastguard Worker // Calculate the number bits extra to assign to boosted frames in a group.
calculate_boost_bits(int frame_count,int boost,int64_t total_group_bits)2147*fb1b10abSAndroid Build Coastguard Worker static int calculate_boost_bits(int frame_count, int boost,
2148*fb1b10abSAndroid Build Coastguard Worker                                 int64_t total_group_bits) {
2149*fb1b10abSAndroid Build Coastguard Worker   int allocation_chunks;
2150*fb1b10abSAndroid Build Coastguard Worker 
2151*fb1b10abSAndroid Build Coastguard Worker   // return 0 for invalid inputs (could arise e.g. through rounding errors)
2152*fb1b10abSAndroid Build Coastguard Worker   if (!boost || (total_group_bits <= 0) || (frame_count < 0)) return 0;
2153*fb1b10abSAndroid Build Coastguard Worker 
2154*fb1b10abSAndroid Build Coastguard Worker   allocation_chunks = (frame_count * NORMAL_BOOST) + boost;
2155*fb1b10abSAndroid Build Coastguard Worker 
2156*fb1b10abSAndroid Build Coastguard Worker   // Prevent overflow.
2157*fb1b10abSAndroid Build Coastguard Worker   if (boost > 1023) {
2158*fb1b10abSAndroid Build Coastguard Worker     int divisor = boost >> 10;
2159*fb1b10abSAndroid Build Coastguard Worker     boost /= divisor;
2160*fb1b10abSAndroid Build Coastguard Worker     allocation_chunks /= divisor;
2161*fb1b10abSAndroid Build Coastguard Worker   }
2162*fb1b10abSAndroid Build Coastguard Worker 
2163*fb1b10abSAndroid Build Coastguard Worker   // Calculate the number of extra bits for use in the boosted frame or frames.
2164*fb1b10abSAndroid Build Coastguard Worker   return VPXMAX((int)(((int64_t)boost * total_group_bits) / allocation_chunks),
2165*fb1b10abSAndroid Build Coastguard Worker                 0);
2166*fb1b10abSAndroid Build Coastguard Worker }
2167*fb1b10abSAndroid Build Coastguard Worker 
2168*fb1b10abSAndroid Build Coastguard Worker // Used in corpus vbr: Calculates the total normalized group complexity score
2169*fb1b10abSAndroid Build Coastguard Worker // for a given number of frames starting at the current position in the stats
2170*fb1b10abSAndroid Build Coastguard Worker // file.
calculate_group_score(VP9_COMP * cpi,double av_score,int frame_count)2171*fb1b10abSAndroid Build Coastguard Worker static double calculate_group_score(VP9_COMP *cpi, double av_score,
2172*fb1b10abSAndroid Build Coastguard Worker                                     int frame_count) {
2173*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig *const oxcf = &cpi->oxcf;
2174*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
2175*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *s = twopass->stats_in;
2176*fb1b10abSAndroid Build Coastguard Worker   double score_total = 0.0;
2177*fb1b10abSAndroid Build Coastguard Worker   int i = 0;
2178*fb1b10abSAndroid Build Coastguard Worker 
2179*fb1b10abSAndroid Build Coastguard Worker   // We don't ever want to return a 0 score here.
2180*fb1b10abSAndroid Build Coastguard Worker   if (frame_count == 0) return 1.0;
2181*fb1b10abSAndroid Build Coastguard Worker 
2182*fb1b10abSAndroid Build Coastguard Worker   while ((i < frame_count) && (s < twopass->stats_in_end)) {
2183*fb1b10abSAndroid Build Coastguard Worker     score_total += calculate_norm_frame_score(cpi, twopass, oxcf, s, av_score);
2184*fb1b10abSAndroid Build Coastguard Worker     ++s;
2185*fb1b10abSAndroid Build Coastguard Worker     ++i;
2186*fb1b10abSAndroid Build Coastguard Worker   }
2187*fb1b10abSAndroid Build Coastguard Worker 
2188*fb1b10abSAndroid Build Coastguard Worker   return score_total;
2189*fb1b10abSAndroid Build Coastguard Worker }
2190*fb1b10abSAndroid Build Coastguard Worker 
find_arf_order(VP9_COMP * cpi,GF_GROUP * gf_group,int * index_counter,int depth,int start,int end)2191*fb1b10abSAndroid Build Coastguard Worker static void find_arf_order(VP9_COMP *cpi, GF_GROUP *gf_group,
2192*fb1b10abSAndroid Build Coastguard Worker                            int *index_counter, int depth, int start, int end) {
2193*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *twopass = &cpi->twopass;
2194*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *const start_pos = twopass->stats_in;
2195*fb1b10abSAndroid Build Coastguard Worker   FIRSTPASS_STATS fpf_frame;
2196*fb1b10abSAndroid Build Coastguard Worker   const int mid = (start + end + 1) >> 1;
2197*fb1b10abSAndroid Build Coastguard Worker   const int min_frame_interval = 2;
2198*fb1b10abSAndroid Build Coastguard Worker   int idx;
2199*fb1b10abSAndroid Build Coastguard Worker 
2200*fb1b10abSAndroid Build Coastguard Worker   // Process regular P frames
2201*fb1b10abSAndroid Build Coastguard Worker   if ((end - start < min_frame_interval) ||
2202*fb1b10abSAndroid Build Coastguard Worker       (depth > gf_group->allowed_max_layer_depth)) {
2203*fb1b10abSAndroid Build Coastguard Worker     for (idx = start; idx <= end; ++idx) {
2204*fb1b10abSAndroid Build Coastguard Worker       gf_group->update_type[*index_counter] = LF_UPDATE;
2205*fb1b10abSAndroid Build Coastguard Worker       gf_group->arf_src_offset[*index_counter] = 0;
2206*fb1b10abSAndroid Build Coastguard Worker       gf_group->frame_gop_index[*index_counter] = idx;
2207*fb1b10abSAndroid Build Coastguard Worker       gf_group->rf_level[*index_counter] = INTER_NORMAL;
2208*fb1b10abSAndroid Build Coastguard Worker       gf_group->layer_depth[*index_counter] = depth;
2209*fb1b10abSAndroid Build Coastguard Worker       gf_group->gfu_boost[*index_counter] = NORMAL_BOOST;
2210*fb1b10abSAndroid Build Coastguard Worker       ++(*index_counter);
2211*fb1b10abSAndroid Build Coastguard Worker     }
2212*fb1b10abSAndroid Build Coastguard Worker     gf_group->max_layer_depth = VPXMAX(gf_group->max_layer_depth, depth);
2213*fb1b10abSAndroid Build Coastguard Worker     return;
2214*fb1b10abSAndroid Build Coastguard Worker   }
2215*fb1b10abSAndroid Build Coastguard Worker 
2216*fb1b10abSAndroid Build Coastguard Worker   assert(abs(mid - start) >= 1 && abs(mid - end) >= 1);
2217*fb1b10abSAndroid Build Coastguard Worker 
2218*fb1b10abSAndroid Build Coastguard Worker   // Process ARF frame
2219*fb1b10abSAndroid Build Coastguard Worker   gf_group->layer_depth[*index_counter] = depth;
2220*fb1b10abSAndroid Build Coastguard Worker   gf_group->update_type[*index_counter] = ARF_UPDATE;
2221*fb1b10abSAndroid Build Coastguard Worker   gf_group->arf_src_offset[*index_counter] = mid - start;
2222*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_gop_index[*index_counter] = mid;
2223*fb1b10abSAndroid Build Coastguard Worker   gf_group->rf_level[*index_counter] = GF_ARF_LOW;
2224*fb1b10abSAndroid Build Coastguard Worker 
2225*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx <= mid; ++idx)
2226*fb1b10abSAndroid Build Coastguard Worker     if (EOF == input_stats(twopass, &fpf_frame)) break;
2227*fb1b10abSAndroid Build Coastguard Worker 
2228*fb1b10abSAndroid Build Coastguard Worker   gf_group->gfu_boost[*index_counter] =
2229*fb1b10abSAndroid Build Coastguard Worker       VPXMAX(MIN_ARF_GF_BOOST,
2230*fb1b10abSAndroid Build Coastguard Worker              calc_arf_boost(cpi, end - mid + 1, mid - start) >> depth);
2231*fb1b10abSAndroid Build Coastguard Worker 
2232*fb1b10abSAndroid Build Coastguard Worker   reset_fpf_position(twopass, start_pos);
2233*fb1b10abSAndroid Build Coastguard Worker 
2234*fb1b10abSAndroid Build Coastguard Worker   ++(*index_counter);
2235*fb1b10abSAndroid Build Coastguard Worker 
2236*fb1b10abSAndroid Build Coastguard Worker   find_arf_order(cpi, gf_group, index_counter, depth + 1, start, mid - 1);
2237*fb1b10abSAndroid Build Coastguard Worker 
2238*fb1b10abSAndroid Build Coastguard Worker   gf_group->update_type[*index_counter] = USE_BUF_FRAME;
2239*fb1b10abSAndroid Build Coastguard Worker   gf_group->arf_src_offset[*index_counter] = 0;
2240*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_gop_index[*index_counter] = mid;
2241*fb1b10abSAndroid Build Coastguard Worker   gf_group->rf_level[*index_counter] = INTER_NORMAL;
2242*fb1b10abSAndroid Build Coastguard Worker   gf_group->layer_depth[*index_counter] = depth;
2243*fb1b10abSAndroid Build Coastguard Worker   ++(*index_counter);
2244*fb1b10abSAndroid Build Coastguard Worker 
2245*fb1b10abSAndroid Build Coastguard Worker   find_arf_order(cpi, gf_group, index_counter, depth + 1, mid + 1, end);
2246*fb1b10abSAndroid Build Coastguard Worker }
2247*fb1b10abSAndroid Build Coastguard Worker 
set_gf_overlay_frame_type(GF_GROUP * gf_group,int frame_index,int source_alt_ref_active)2248*fb1b10abSAndroid Build Coastguard Worker static INLINE void set_gf_overlay_frame_type(GF_GROUP *gf_group,
2249*fb1b10abSAndroid Build Coastguard Worker                                              int frame_index,
2250*fb1b10abSAndroid Build Coastguard Worker                                              int source_alt_ref_active) {
2251*fb1b10abSAndroid Build Coastguard Worker   if (source_alt_ref_active) {
2252*fb1b10abSAndroid Build Coastguard Worker     gf_group->update_type[frame_index] = OVERLAY_UPDATE;
2253*fb1b10abSAndroid Build Coastguard Worker     gf_group->rf_level[frame_index] = INTER_NORMAL;
2254*fb1b10abSAndroid Build Coastguard Worker     gf_group->layer_depth[frame_index] = MAX_ARF_LAYERS - 1;
2255*fb1b10abSAndroid Build Coastguard Worker     gf_group->gfu_boost[frame_index] = NORMAL_BOOST;
2256*fb1b10abSAndroid Build Coastguard Worker   } else {
2257*fb1b10abSAndroid Build Coastguard Worker     gf_group->update_type[frame_index] = GF_UPDATE;
2258*fb1b10abSAndroid Build Coastguard Worker     gf_group->rf_level[frame_index] = GF_ARF_STD;
2259*fb1b10abSAndroid Build Coastguard Worker     gf_group->layer_depth[frame_index] = 0;
2260*fb1b10abSAndroid Build Coastguard Worker   }
2261*fb1b10abSAndroid Build Coastguard Worker }
2262*fb1b10abSAndroid Build Coastguard Worker 
define_gf_group_structure(VP9_COMP * cpi)2263*fb1b10abSAndroid Build Coastguard Worker static void define_gf_group_structure(VP9_COMP *cpi) {
2264*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
2265*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
2266*fb1b10abSAndroid Build Coastguard Worker   GF_GROUP *const gf_group = &twopass->gf_group;
2267*fb1b10abSAndroid Build Coastguard Worker   int frame_index = 0;
2268*fb1b10abSAndroid Build Coastguard Worker   int key_frame = cpi->common.frame_type == KEY_FRAME;
2269*fb1b10abSAndroid Build Coastguard Worker   int layer_depth = 1;
2270*fb1b10abSAndroid Build Coastguard Worker   int gop_frames =
2271*fb1b10abSAndroid Build Coastguard Worker       rc->baseline_gf_interval - (key_frame || rc->source_alt_ref_pending);
2272*fb1b10abSAndroid Build Coastguard Worker 
2273*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_start = cpi->common.current_video_frame;
2274*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_end = gf_group->frame_start + rc->baseline_gf_interval;
2275*fb1b10abSAndroid Build Coastguard Worker   gf_group->max_layer_depth = 0;
2276*fb1b10abSAndroid Build Coastguard Worker   gf_group->allowed_max_layer_depth = 0;
2277*fb1b10abSAndroid Build Coastguard Worker 
2278*fb1b10abSAndroid Build Coastguard Worker   // For key frames the frame target rate is already set and it
2279*fb1b10abSAndroid Build Coastguard Worker   // is also the golden frame.
2280*fb1b10abSAndroid Build Coastguard Worker   // === [frame_index == 0] ===
2281*fb1b10abSAndroid Build Coastguard Worker   if (!key_frame)
2282*fb1b10abSAndroid Build Coastguard Worker     set_gf_overlay_frame_type(gf_group, frame_index, rc->source_alt_ref_active);
2283*fb1b10abSAndroid Build Coastguard Worker 
2284*fb1b10abSAndroid Build Coastguard Worker   ++frame_index;
2285*fb1b10abSAndroid Build Coastguard Worker 
2286*fb1b10abSAndroid Build Coastguard Worker   // === [frame_index == 1] ===
2287*fb1b10abSAndroid Build Coastguard Worker   if (rc->source_alt_ref_pending) {
2288*fb1b10abSAndroid Build Coastguard Worker     gf_group->update_type[frame_index] = ARF_UPDATE;
2289*fb1b10abSAndroid Build Coastguard Worker     gf_group->rf_level[frame_index] = GF_ARF_STD;
2290*fb1b10abSAndroid Build Coastguard Worker     gf_group->layer_depth[frame_index] = layer_depth;
2291*fb1b10abSAndroid Build Coastguard Worker     gf_group->arf_src_offset[frame_index] =
2292*fb1b10abSAndroid Build Coastguard Worker         (unsigned char)(rc->baseline_gf_interval - 1);
2293*fb1b10abSAndroid Build Coastguard Worker     gf_group->frame_gop_index[frame_index] = rc->baseline_gf_interval;
2294*fb1b10abSAndroid Build Coastguard Worker     gf_group->max_layer_depth = 1;
2295*fb1b10abSAndroid Build Coastguard Worker     ++frame_index;
2296*fb1b10abSAndroid Build Coastguard Worker     ++layer_depth;
2297*fb1b10abSAndroid Build Coastguard Worker     gf_group->allowed_max_layer_depth = cpi->oxcf.enable_auto_arf;
2298*fb1b10abSAndroid Build Coastguard Worker   }
2299*fb1b10abSAndroid Build Coastguard Worker 
2300*fb1b10abSAndroid Build Coastguard Worker   find_arf_order(cpi, gf_group, &frame_index, layer_depth, 1, gop_frames);
2301*fb1b10abSAndroid Build Coastguard Worker 
2302*fb1b10abSAndroid Build Coastguard Worker   // TODO(b/345523905): Why do we need to set an overlay frame in the end?
2303*fb1b10abSAndroid Build Coastguard Worker   set_gf_overlay_frame_type(gf_group, frame_index, rc->source_alt_ref_pending);
2304*fb1b10abSAndroid Build Coastguard Worker   gf_group->arf_src_offset[frame_index] = 0;
2305*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_gop_index[frame_index] = rc->baseline_gf_interval;
2306*fb1b10abSAndroid Build Coastguard Worker 
2307*fb1b10abSAndroid Build Coastguard Worker   // Set the frame ops number.
2308*fb1b10abSAndroid Build Coastguard Worker   gf_group->gf_group_size = frame_index;
2309*fb1b10abSAndroid Build Coastguard Worker }
2310*fb1b10abSAndroid Build Coastguard Worker 
gf_group_set_overlay_frame(GF_GROUP * gf_group,int frame_index,int show_frame_index)2311*fb1b10abSAndroid Build Coastguard Worker static INLINE void gf_group_set_overlay_frame(GF_GROUP *gf_group,
2312*fb1b10abSAndroid Build Coastguard Worker                                               int frame_index,
2313*fb1b10abSAndroid Build Coastguard Worker                                               int show_frame_index) {
2314*fb1b10abSAndroid Build Coastguard Worker   gf_group->update_type[frame_index] = OVERLAY_UPDATE;
2315*fb1b10abSAndroid Build Coastguard Worker   gf_group->arf_src_offset[frame_index] = 0;
2316*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_gop_index[frame_index] = show_frame_index;
2317*fb1b10abSAndroid Build Coastguard Worker   gf_group->rf_level[frame_index] = INTER_NORMAL;
2318*fb1b10abSAndroid Build Coastguard Worker   gf_group->layer_depth[frame_index] = MAX_ARF_LAYERS - 1;
2319*fb1b10abSAndroid Build Coastguard Worker }
2320*fb1b10abSAndroid Build Coastguard Worker 
gf_group_set_key_frame(GF_GROUP * gf_group,int frame_index,int show_frame_index)2321*fb1b10abSAndroid Build Coastguard Worker static INLINE void gf_group_set_key_frame(GF_GROUP *gf_group, int frame_index,
2322*fb1b10abSAndroid Build Coastguard Worker                                           int show_frame_index) {
2323*fb1b10abSAndroid Build Coastguard Worker   gf_group->update_type[frame_index] = KF_UPDATE;
2324*fb1b10abSAndroid Build Coastguard Worker   gf_group->arf_src_offset[frame_index] = 0;
2325*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_gop_index[frame_index] = show_frame_index;
2326*fb1b10abSAndroid Build Coastguard Worker   gf_group->rf_level[frame_index] = KF_STD;
2327*fb1b10abSAndroid Build Coastguard Worker   gf_group->layer_depth[frame_index] = 0;
2328*fb1b10abSAndroid Build Coastguard Worker }
2329*fb1b10abSAndroid Build Coastguard Worker 
gf_group_set_arf_frame(GF_GROUP * gf_group,int frame_index,int show_frame_index)2330*fb1b10abSAndroid Build Coastguard Worker static INLINE void gf_group_set_arf_frame(GF_GROUP *gf_group, int frame_index,
2331*fb1b10abSAndroid Build Coastguard Worker                                           int show_frame_index) {
2332*fb1b10abSAndroid Build Coastguard Worker   gf_group->update_type[frame_index] = ARF_UPDATE;
2333*fb1b10abSAndroid Build Coastguard Worker   gf_group->arf_src_offset[frame_index] =
2334*fb1b10abSAndroid Build Coastguard Worker       (unsigned char)(show_frame_index - frame_index);
2335*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_gop_index[frame_index] = show_frame_index;
2336*fb1b10abSAndroid Build Coastguard Worker   gf_group->rf_level[frame_index] = GF_ARF_STD;
2337*fb1b10abSAndroid Build Coastguard Worker   gf_group->layer_depth[frame_index] = 1;
2338*fb1b10abSAndroid Build Coastguard Worker }
2339*fb1b10abSAndroid Build Coastguard Worker 
gf_group_set_inter_normal_frame(GF_GROUP * gf_group,int frame_index,int show_frame_index)2340*fb1b10abSAndroid Build Coastguard Worker static INLINE void gf_group_set_inter_normal_frame(GF_GROUP *gf_group,
2341*fb1b10abSAndroid Build Coastguard Worker                                                    int frame_index,
2342*fb1b10abSAndroid Build Coastguard Worker                                                    int show_frame_index) {
2343*fb1b10abSAndroid Build Coastguard Worker   gf_group->update_type[frame_index] = LF_UPDATE;
2344*fb1b10abSAndroid Build Coastguard Worker   gf_group->arf_src_offset[frame_index] = 0;
2345*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_gop_index[frame_index] = show_frame_index;
2346*fb1b10abSAndroid Build Coastguard Worker   gf_group->rf_level[frame_index] = INTER_NORMAL;
2347*fb1b10abSAndroid Build Coastguard Worker   gf_group->layer_depth[frame_index] = 2;
2348*fb1b10abSAndroid Build Coastguard Worker }
2349*fb1b10abSAndroid Build Coastguard Worker 
set_gf_frame_type(vpx_rc_frame_update_type_t update_type,int show_frame_count,GF_GROUP * gf_group,int * frame_index,int * show_frame_index)2350*fb1b10abSAndroid Build Coastguard Worker static INLINE void set_gf_frame_type(vpx_rc_frame_update_type_t update_type,
2351*fb1b10abSAndroid Build Coastguard Worker                                      int show_frame_count, GF_GROUP *gf_group,
2352*fb1b10abSAndroid Build Coastguard Worker                                      int *frame_index, int *show_frame_index) {
2353*fb1b10abSAndroid Build Coastguard Worker   if (update_type == VPX_RC_KF_UPDATE) {
2354*fb1b10abSAndroid Build Coastguard Worker     gf_group_set_key_frame(gf_group, *frame_index, *show_frame_index);
2355*fb1b10abSAndroid Build Coastguard Worker     ++(*frame_index);
2356*fb1b10abSAndroid Build Coastguard Worker     ++(*show_frame_index);
2357*fb1b10abSAndroid Build Coastguard Worker   } else if (update_type == VPX_RC_OVERLAY_UPDATE) {
2358*fb1b10abSAndroid Build Coastguard Worker     gf_group_set_overlay_frame(gf_group, *frame_index, *show_frame_index);
2359*fb1b10abSAndroid Build Coastguard Worker     ++(*frame_index);
2360*fb1b10abSAndroid Build Coastguard Worker     ++(*show_frame_index);
2361*fb1b10abSAndroid Build Coastguard Worker   } else if (update_type == VPX_RC_ARF_UPDATE) {
2362*fb1b10abSAndroid Build Coastguard Worker     gf_group_set_arf_frame(gf_group, *frame_index, show_frame_count);
2363*fb1b10abSAndroid Build Coastguard Worker     ++(*frame_index);
2364*fb1b10abSAndroid Build Coastguard Worker   } else if (update_type == VPX_RC_LF_UPDATE) {
2365*fb1b10abSAndroid Build Coastguard Worker     gf_group_set_inter_normal_frame(gf_group, *frame_index, *show_frame_index);
2366*fb1b10abSAndroid Build Coastguard Worker     ++(*frame_index);
2367*fb1b10abSAndroid Build Coastguard Worker     ++(*show_frame_index);
2368*fb1b10abSAndroid Build Coastguard Worker   } else {
2369*fb1b10abSAndroid Build Coastguard Worker     assert(0);
2370*fb1b10abSAndroid Build Coastguard Worker   }
2371*fb1b10abSAndroid Build Coastguard Worker }
2372*fb1b10abSAndroid Build Coastguard Worker 
ext_rc_define_gf_group_structure(const vpx_rc_gop_decision_t * gop_decision,GF_GROUP * gf_group)2373*fb1b10abSAndroid Build Coastguard Worker static void ext_rc_define_gf_group_structure(
2374*fb1b10abSAndroid Build Coastguard Worker     const vpx_rc_gop_decision_t *gop_decision, GF_GROUP *gf_group) {
2375*fb1b10abSAndroid Build Coastguard Worker   const int gop_coding_frames = gop_decision->gop_coding_frames;
2376*fb1b10abSAndroid Build Coastguard Worker 
2377*fb1b10abSAndroid Build Coastguard Worker   const int show_frame_count = gop_coding_frames - gop_decision->use_alt_ref;
2378*fb1b10abSAndroid Build Coastguard Worker   int frame_index = 0;
2379*fb1b10abSAndroid Build Coastguard Worker   int show_frame_index = 0;
2380*fb1b10abSAndroid Build Coastguard Worker 
2381*fb1b10abSAndroid Build Coastguard Worker   for (int i = frame_index; i < gop_coding_frames; i++) {
2382*fb1b10abSAndroid Build Coastguard Worker     set_gf_frame_type(gop_decision->update_type[i], show_frame_count, gf_group,
2383*fb1b10abSAndroid Build Coastguard Worker                       &frame_index, &show_frame_index);
2384*fb1b10abSAndroid Build Coastguard Worker 
2385*fb1b10abSAndroid Build Coastguard Worker     gf_group->update_ref_idx[i] = gop_decision->update_ref_index[i];
2386*fb1b10abSAndroid Build Coastguard Worker 
2387*fb1b10abSAndroid Build Coastguard Worker     gf_group->ext_rc_ref[i].last_index = 0;
2388*fb1b10abSAndroid Build Coastguard Worker     gf_group->ext_rc_ref[i].golden_index = 0;
2389*fb1b10abSAndroid Build Coastguard Worker     gf_group->ext_rc_ref[i].altref_index = 0;
2390*fb1b10abSAndroid Build Coastguard Worker     for (int ref_frame = 0; ref_frame < 3; ref_frame++) {
2391*fb1b10abSAndroid Build Coastguard Worker       const vpx_rc_ref_frame_t *const ext_ref_frame =
2392*fb1b10abSAndroid Build Coastguard Worker           &gop_decision->ref_frame_list[i];
2393*fb1b10abSAndroid Build Coastguard Worker       const int ref_index = ext_ref_frame->index[ref_frame];
2394*fb1b10abSAndroid Build Coastguard Worker       gf_group->ref_frame_list[i][ref_frame] = ext_ref_frame->index[ref_frame];
2395*fb1b10abSAndroid Build Coastguard Worker       switch (ext_ref_frame->name[ref_frame]) {
2396*fb1b10abSAndroid Build Coastguard Worker         case VPX_RC_LAST_FRAME:
2397*fb1b10abSAndroid Build Coastguard Worker           gf_group->ext_rc_ref[i].last_index = ref_index;
2398*fb1b10abSAndroid Build Coastguard Worker           break;
2399*fb1b10abSAndroid Build Coastguard Worker         case VPX_RC_GOLDEN_FRAME:
2400*fb1b10abSAndroid Build Coastguard Worker           gf_group->ext_rc_ref[i].golden_index = ref_index;
2401*fb1b10abSAndroid Build Coastguard Worker           break;
2402*fb1b10abSAndroid Build Coastguard Worker         case VPX_RC_ALTREF_FRAME:
2403*fb1b10abSAndroid Build Coastguard Worker           gf_group->ext_rc_ref[i].altref_index = ref_index;
2404*fb1b10abSAndroid Build Coastguard Worker           break;
2405*fb1b10abSAndroid Build Coastguard Worker         default: break;
2406*fb1b10abSAndroid Build Coastguard Worker       }
2407*fb1b10abSAndroid Build Coastguard Worker     }
2408*fb1b10abSAndroid Build Coastguard Worker     if (gf_group->update_type[i] == OVERLAY_UPDATE) {
2409*fb1b10abSAndroid Build Coastguard Worker       // From ext_rc, overlay may not update any ref. But here we force it to
2410*fb1b10abSAndroid Build Coastguard Worker       // update its arf's slot. This is probably OK since the arf and this
2411*fb1b10abSAndroid Build Coastguard Worker       // overlay frame should be very similar.
2412*fb1b10abSAndroid Build Coastguard Worker       gf_group->update_ref_idx[i] = gf_group->ext_rc_ref[i].altref_index;
2413*fb1b10abSAndroid Build Coastguard Worker     }
2414*fb1b10abSAndroid Build Coastguard Worker   }
2415*fb1b10abSAndroid Build Coastguard Worker   // max_layer_depth is hardcoded to match the behavior of
2416*fb1b10abSAndroid Build Coastguard Worker   // define_gf_group_structure()
2417*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): Check whether max_layer_depth has performance impact.
2418*fb1b10abSAndroid Build Coastguard Worker   gf_group->max_layer_depth = 2;
2419*fb1b10abSAndroid Build Coastguard Worker   gf_group->allowed_max_layer_depth = 1;
2420*fb1b10abSAndroid Build Coastguard Worker   gf_group->gf_group_size = gop_coding_frames;
2421*fb1b10abSAndroid Build Coastguard Worker 
2422*fb1b10abSAndroid Build Coastguard Worker   // TODO(b/345523905): Why do we need to set an overlay frame in the end?
2423*fb1b10abSAndroid Build Coastguard Worker   assert(show_frame_count == show_frame_index);
2424*fb1b10abSAndroid Build Coastguard Worker   if (gop_decision->use_alt_ref) {
2425*fb1b10abSAndroid Build Coastguard Worker     gf_group_set_overlay_frame(gf_group, gf_group->gf_group_size,
2426*fb1b10abSAndroid Build Coastguard Worker                                show_frame_index);
2427*fb1b10abSAndroid Build Coastguard Worker   } else {
2428*fb1b10abSAndroid Build Coastguard Worker     gf_group_set_inter_normal_frame(gf_group, gf_group->gf_group_size,
2429*fb1b10abSAndroid Build Coastguard Worker                                     show_frame_index);
2430*fb1b10abSAndroid Build Coastguard Worker   }
2431*fb1b10abSAndroid Build Coastguard Worker 
2432*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_start = 0;
2433*fb1b10abSAndroid Build Coastguard Worker   gf_group->frame_end = gf_group->gf_group_size - gop_decision->use_alt_ref;
2434*fb1b10abSAndroid Build Coastguard Worker }
2435*fb1b10abSAndroid Build Coastguard Worker 
allocate_gf_group_bits(VP9_COMP * cpi,int64_t gf_group_bits,int gf_arf_bits)2436*fb1b10abSAndroid Build Coastguard Worker static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
2437*fb1b10abSAndroid Build Coastguard Worker                                    int gf_arf_bits) {
2438*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig *const oxcf = &cpi->oxcf;
2439*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
2440*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
2441*fb1b10abSAndroid Build Coastguard Worker   GF_GROUP *const gf_group = &twopass->gf_group;
2442*fb1b10abSAndroid Build Coastguard Worker   FIRSTPASS_STATS frame_stats;
2443*fb1b10abSAndroid Build Coastguard Worker   int i;
2444*fb1b10abSAndroid Build Coastguard Worker   int frame_index = 0;
2445*fb1b10abSAndroid Build Coastguard Worker   int target_frame_size;
2446*fb1b10abSAndroid Build Coastguard Worker   int key_frame;
2447*fb1b10abSAndroid Build Coastguard Worker   const int max_bits = frame_max_bits(&cpi->rc, oxcf);
2448*fb1b10abSAndroid Build Coastguard Worker   int64_t total_group_bits = gf_group_bits;
2449*fb1b10abSAndroid Build Coastguard Worker   int mid_frame_idx;
2450*fb1b10abSAndroid Build Coastguard Worker   int normal_frames;
2451*fb1b10abSAndroid Build Coastguard Worker   int normal_frame_bits;
2452*fb1b10abSAndroid Build Coastguard Worker   int last_frame_reduction = 0;
2453*fb1b10abSAndroid Build Coastguard Worker   double av_score = 1.0;
2454*fb1b10abSAndroid Build Coastguard Worker   double tot_norm_frame_score = 1.0;
2455*fb1b10abSAndroid Build Coastguard Worker   double this_frame_score = 1.0;
2456*fb1b10abSAndroid Build Coastguard Worker 
2457*fb1b10abSAndroid Build Coastguard Worker   // Define the GF structure and specify
2458*fb1b10abSAndroid Build Coastguard Worker   int gop_frames = gf_group->gf_group_size;
2459*fb1b10abSAndroid Build Coastguard Worker 
2460*fb1b10abSAndroid Build Coastguard Worker   key_frame = cpi->common.frame_type == KEY_FRAME;
2461*fb1b10abSAndroid Build Coastguard Worker 
2462*fb1b10abSAndroid Build Coastguard Worker   // For key frames the frame target rate is already set and it
2463*fb1b10abSAndroid Build Coastguard Worker   // is also the golden frame.
2464*fb1b10abSAndroid Build Coastguard Worker   // === [frame_index == 0] ===
2465*fb1b10abSAndroid Build Coastguard Worker   if (!key_frame) {
2466*fb1b10abSAndroid Build Coastguard Worker     gf_group->bit_allocation[frame_index] =
2467*fb1b10abSAndroid Build Coastguard Worker         rc->source_alt_ref_active ? 0 : gf_arf_bits;
2468*fb1b10abSAndroid Build Coastguard Worker   }
2469*fb1b10abSAndroid Build Coastguard Worker 
2470*fb1b10abSAndroid Build Coastguard Worker   // Deduct the boost bits for arf (or gf if it is not a key frame)
2471*fb1b10abSAndroid Build Coastguard Worker   // from the group total.
2472*fb1b10abSAndroid Build Coastguard Worker   if (rc->source_alt_ref_pending || !key_frame) total_group_bits -= gf_arf_bits;
2473*fb1b10abSAndroid Build Coastguard Worker 
2474*fb1b10abSAndroid Build Coastguard Worker   ++frame_index;
2475*fb1b10abSAndroid Build Coastguard Worker 
2476*fb1b10abSAndroid Build Coastguard Worker   // === [frame_index == 1] ===
2477*fb1b10abSAndroid Build Coastguard Worker   // Store the bits to spend on the ARF if there is one.
2478*fb1b10abSAndroid Build Coastguard Worker   if (rc->source_alt_ref_pending) {
2479*fb1b10abSAndroid Build Coastguard Worker     gf_group->bit_allocation[frame_index] = gf_arf_bits;
2480*fb1b10abSAndroid Build Coastguard Worker 
2481*fb1b10abSAndroid Build Coastguard Worker     ++frame_index;
2482*fb1b10abSAndroid Build Coastguard Worker   }
2483*fb1b10abSAndroid Build Coastguard Worker 
2484*fb1b10abSAndroid Build Coastguard Worker   // Define middle frame
2485*fb1b10abSAndroid Build Coastguard Worker   mid_frame_idx = frame_index + (rc->baseline_gf_interval >> 1) - 1;
2486*fb1b10abSAndroid Build Coastguard Worker 
2487*fb1b10abSAndroid Build Coastguard Worker   normal_frames = (rc->baseline_gf_interval - 1);
2488*fb1b10abSAndroid Build Coastguard Worker   if (normal_frames > 1)
2489*fb1b10abSAndroid Build Coastguard Worker     normal_frame_bits = (int)(total_group_bits / normal_frames);
2490*fb1b10abSAndroid Build Coastguard Worker   else
2491*fb1b10abSAndroid Build Coastguard Worker     normal_frame_bits = (int)total_group_bits;
2492*fb1b10abSAndroid Build Coastguard Worker 
2493*fb1b10abSAndroid Build Coastguard Worker   gf_group->gfu_boost[1] = rc->gfu_boost;
2494*fb1b10abSAndroid Build Coastguard Worker 
2495*fb1b10abSAndroid Build Coastguard Worker   if (cpi->multi_layer_arf) {
2496*fb1b10abSAndroid Build Coastguard Worker     int idx;
2497*fb1b10abSAndroid Build Coastguard Worker     int arf_depth_bits[MAX_ARF_LAYERS] = { 0 };
2498*fb1b10abSAndroid Build Coastguard Worker     int arf_depth_count[MAX_ARF_LAYERS] = { 0 };
2499*fb1b10abSAndroid Build Coastguard Worker     int arf_depth_boost[MAX_ARF_LAYERS] = { 0 };
2500*fb1b10abSAndroid Build Coastguard Worker     int total_arfs = 1;  // Account for the base layer ARF.
2501*fb1b10abSAndroid Build Coastguard Worker 
2502*fb1b10abSAndroid Build Coastguard Worker     for (idx = 0; idx < gop_frames; ++idx) {
2503*fb1b10abSAndroid Build Coastguard Worker       if (gf_group->update_type[idx] == ARF_UPDATE) {
2504*fb1b10abSAndroid Build Coastguard Worker         arf_depth_boost[gf_group->layer_depth[idx]] += gf_group->gfu_boost[idx];
2505*fb1b10abSAndroid Build Coastguard Worker         ++arf_depth_count[gf_group->layer_depth[idx]];
2506*fb1b10abSAndroid Build Coastguard Worker       }
2507*fb1b10abSAndroid Build Coastguard Worker     }
2508*fb1b10abSAndroid Build Coastguard Worker 
2509*fb1b10abSAndroid Build Coastguard Worker     for (idx = 2; idx < MAX_ARF_LAYERS; ++idx) {
2510*fb1b10abSAndroid Build Coastguard Worker       if (arf_depth_boost[idx] == 0) break;
2511*fb1b10abSAndroid Build Coastguard Worker       arf_depth_bits[idx] = calculate_boost_bits(
2512*fb1b10abSAndroid Build Coastguard Worker           rc->baseline_gf_interval - total_arfs - arf_depth_count[idx],
2513*fb1b10abSAndroid Build Coastguard Worker           arf_depth_boost[idx], total_group_bits);
2514*fb1b10abSAndroid Build Coastguard Worker 
2515*fb1b10abSAndroid Build Coastguard Worker       total_group_bits -= arf_depth_bits[idx];
2516*fb1b10abSAndroid Build Coastguard Worker       total_arfs += arf_depth_count[idx];
2517*fb1b10abSAndroid Build Coastguard Worker     }
2518*fb1b10abSAndroid Build Coastguard Worker 
2519*fb1b10abSAndroid Build Coastguard Worker     // offset the base layer arf
2520*fb1b10abSAndroid Build Coastguard Worker     normal_frames -= (total_arfs - 1);
2521*fb1b10abSAndroid Build Coastguard Worker     if (normal_frames > 1)
2522*fb1b10abSAndroid Build Coastguard Worker       normal_frame_bits = (int)(total_group_bits / normal_frames);
2523*fb1b10abSAndroid Build Coastguard Worker     else
2524*fb1b10abSAndroid Build Coastguard Worker       normal_frame_bits = (int)total_group_bits;
2525*fb1b10abSAndroid Build Coastguard Worker 
2526*fb1b10abSAndroid Build Coastguard Worker     target_frame_size = normal_frame_bits;
2527*fb1b10abSAndroid Build Coastguard Worker     target_frame_size =
2528*fb1b10abSAndroid Build Coastguard Worker         clamp(target_frame_size, 0, VPXMIN(max_bits, (int)total_group_bits));
2529*fb1b10abSAndroid Build Coastguard Worker 
2530*fb1b10abSAndroid Build Coastguard Worker     // The first layer ARF has its bit allocation assigned.
2531*fb1b10abSAndroid Build Coastguard Worker     for (idx = frame_index; idx < gop_frames; ++idx) {
2532*fb1b10abSAndroid Build Coastguard Worker       switch (gf_group->update_type[idx]) {
2533*fb1b10abSAndroid Build Coastguard Worker         case ARF_UPDATE:
2534*fb1b10abSAndroid Build Coastguard Worker           gf_group->bit_allocation[idx] =
2535*fb1b10abSAndroid Build Coastguard Worker               (int)(((int64_t)arf_depth_bits[gf_group->layer_depth[idx]] *
2536*fb1b10abSAndroid Build Coastguard Worker                      gf_group->gfu_boost[idx]) /
2537*fb1b10abSAndroid Build Coastguard Worker                     arf_depth_boost[gf_group->layer_depth[idx]]);
2538*fb1b10abSAndroid Build Coastguard Worker           break;
2539*fb1b10abSAndroid Build Coastguard Worker         case USE_BUF_FRAME: gf_group->bit_allocation[idx] = 0; break;
2540*fb1b10abSAndroid Build Coastguard Worker         default: gf_group->bit_allocation[idx] = target_frame_size; break;
2541*fb1b10abSAndroid Build Coastguard Worker       }
2542*fb1b10abSAndroid Build Coastguard Worker     }
2543*fb1b10abSAndroid Build Coastguard Worker     gf_group->bit_allocation[idx] = 0;
2544*fb1b10abSAndroid Build Coastguard Worker 
2545*fb1b10abSAndroid Build Coastguard Worker     return;
2546*fb1b10abSAndroid Build Coastguard Worker   }
2547*fb1b10abSAndroid Build Coastguard Worker 
2548*fb1b10abSAndroid Build Coastguard Worker   if (oxcf->vbr_corpus_complexity) {
2549*fb1b10abSAndroid Build Coastguard Worker     av_score = get_distribution_av_err(cpi, twopass);
2550*fb1b10abSAndroid Build Coastguard Worker     tot_norm_frame_score = calculate_group_score(cpi, av_score, normal_frames);
2551*fb1b10abSAndroid Build Coastguard Worker   }
2552*fb1b10abSAndroid Build Coastguard Worker 
2553*fb1b10abSAndroid Build Coastguard Worker   // Allocate bits to the other frames in the group.
2554*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < normal_frames; ++i) {
2555*fb1b10abSAndroid Build Coastguard Worker     if (EOF == input_stats(twopass, &frame_stats)) break;
2556*fb1b10abSAndroid Build Coastguard Worker     if (oxcf->vbr_corpus_complexity) {
2557*fb1b10abSAndroid Build Coastguard Worker       this_frame_score = calculate_norm_frame_score(cpi, twopass, oxcf,
2558*fb1b10abSAndroid Build Coastguard Worker                                                     &frame_stats, av_score);
2559*fb1b10abSAndroid Build Coastguard Worker       normal_frame_bits = (int)((double)total_group_bits *
2560*fb1b10abSAndroid Build Coastguard Worker                                 (this_frame_score / tot_norm_frame_score));
2561*fb1b10abSAndroid Build Coastguard Worker     }
2562*fb1b10abSAndroid Build Coastguard Worker 
2563*fb1b10abSAndroid Build Coastguard Worker     target_frame_size = normal_frame_bits;
2564*fb1b10abSAndroid Build Coastguard Worker     if ((i == (normal_frames - 1)) && (i >= 1)) {
2565*fb1b10abSAndroid Build Coastguard Worker       last_frame_reduction = normal_frame_bits / 16;
2566*fb1b10abSAndroid Build Coastguard Worker       target_frame_size -= last_frame_reduction;
2567*fb1b10abSAndroid Build Coastguard Worker     }
2568*fb1b10abSAndroid Build Coastguard Worker 
2569*fb1b10abSAndroid Build Coastguard Worker     target_frame_size =
2570*fb1b10abSAndroid Build Coastguard Worker         clamp(target_frame_size, 0, VPXMIN(max_bits, (int)total_group_bits));
2571*fb1b10abSAndroid Build Coastguard Worker 
2572*fb1b10abSAndroid Build Coastguard Worker     gf_group->bit_allocation[frame_index] = target_frame_size;
2573*fb1b10abSAndroid Build Coastguard Worker     ++frame_index;
2574*fb1b10abSAndroid Build Coastguard Worker   }
2575*fb1b10abSAndroid Build Coastguard Worker 
2576*fb1b10abSAndroid Build Coastguard Worker   // Add in some extra bits for the middle frame in the group.
2577*fb1b10abSAndroid Build Coastguard Worker   gf_group->bit_allocation[mid_frame_idx] += last_frame_reduction;
2578*fb1b10abSAndroid Build Coastguard Worker 
2579*fb1b10abSAndroid Build Coastguard Worker   // Note:
2580*fb1b10abSAndroid Build Coastguard Worker   // We need to configure the frame at the end of the sequence + 1 that will be
2581*fb1b10abSAndroid Build Coastguard Worker   // the start frame for the next group. Otherwise prior to the call to
2582*fb1b10abSAndroid Build Coastguard Worker   // vp9_rc_get_second_pass_params() the data will be undefined.
2583*fb1b10abSAndroid Build Coastguard Worker }
2584*fb1b10abSAndroid Build Coastguard Worker 
2585*fb1b10abSAndroid Build Coastguard Worker // Adjusts the ARNF filter for a GF group.
adjust_group_arnr_filter(VP9_COMP * cpi,double section_noise,double section_inter,double section_motion)2586*fb1b10abSAndroid Build Coastguard Worker static void adjust_group_arnr_filter(VP9_COMP *cpi, double section_noise,
2587*fb1b10abSAndroid Build Coastguard Worker                                      double section_inter,
2588*fb1b10abSAndroid Build Coastguard Worker                                      double section_motion) {
2589*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
2590*fb1b10abSAndroid Build Coastguard Worker   double section_zeromv = section_inter - section_motion;
2591*fb1b10abSAndroid Build Coastguard Worker 
2592*fb1b10abSAndroid Build Coastguard Worker   twopass->arnr_strength_adjustment = 0;
2593*fb1b10abSAndroid Build Coastguard Worker 
2594*fb1b10abSAndroid Build Coastguard Worker   if (section_noise < 150) {
2595*fb1b10abSAndroid Build Coastguard Worker     twopass->arnr_strength_adjustment -= 1;
2596*fb1b10abSAndroid Build Coastguard Worker     if (section_noise < 75) twopass->arnr_strength_adjustment -= 1;
2597*fb1b10abSAndroid Build Coastguard Worker   } else if (section_noise > 250)
2598*fb1b10abSAndroid Build Coastguard Worker     twopass->arnr_strength_adjustment += 1;
2599*fb1b10abSAndroid Build Coastguard Worker 
2600*fb1b10abSAndroid Build Coastguard Worker   if (section_zeromv > 0.50) twopass->arnr_strength_adjustment += 1;
2601*fb1b10abSAndroid Build Coastguard Worker }
2602*fb1b10abSAndroid Build Coastguard Worker 
2603*fb1b10abSAndroid Build Coastguard Worker // Analyse and define a gf/arf group.
2604*fb1b10abSAndroid Build Coastguard Worker #define ARF_ABS_ZOOM_THRESH 4.0
2605*fb1b10abSAndroid Build Coastguard Worker 
2606*fb1b10abSAndroid Build Coastguard Worker #define MAX_GF_BOOST 5400
2607*fb1b10abSAndroid Build Coastguard Worker 
2608*fb1b10abSAndroid Build Coastguard Worker typedef struct RANGE {
2609*fb1b10abSAndroid Build Coastguard Worker   int min;
2610*fb1b10abSAndroid Build Coastguard Worker   int max;
2611*fb1b10abSAndroid Build Coastguard Worker } RANGE;
2612*fb1b10abSAndroid Build Coastguard Worker 
2613*fb1b10abSAndroid Build Coastguard Worker /* get_gop_coding_frame_num() depends on several fields in RATE_CONTROL *rc as
2614*fb1b10abSAndroid Build Coastguard Worker  * follows.
2615*fb1b10abSAndroid Build Coastguard Worker  * Static fields:
2616*fb1b10abSAndroid Build Coastguard Worker  * (The following fields will remain unchanged after initialization of encoder.)
2617*fb1b10abSAndroid Build Coastguard Worker  *   rc->static_scene_max_gf_interval
2618*fb1b10abSAndroid Build Coastguard Worker  *   rc->min_gf_interval
2619*fb1b10abSAndroid Build Coastguard Worker  *   twopass->sr_diff_factor
2620*fb1b10abSAndroid Build Coastguard Worker  *   twopass->sr_default_decay_limit
2621*fb1b10abSAndroid Build Coastguard Worker  *   twopass->zm_factor
2622*fb1b10abSAndroid Build Coastguard Worker  *
2623*fb1b10abSAndroid Build Coastguard Worker  * Dynamic fields:
2624*fb1b10abSAndroid Build Coastguard Worker  * (The following fields will be updated before or after coding each frame.)
2625*fb1b10abSAndroid Build Coastguard Worker  *   rc->frames_to_key
2626*fb1b10abSAndroid Build Coastguard Worker  *   rc->frames_since_key
2627*fb1b10abSAndroid Build Coastguard Worker  *   rc->source_alt_ref_active
2628*fb1b10abSAndroid Build Coastguard Worker  *
2629*fb1b10abSAndroid Build Coastguard Worker  * Special case: if CONFIG_RATE_CTRL is true, the external arf indexes will
2630*fb1b10abSAndroid Build Coastguard Worker  * determine the arf position.
2631*fb1b10abSAndroid Build Coastguard Worker  *
2632*fb1b10abSAndroid Build Coastguard Worker  * TODO(angiebird): Separate the dynamic fields and static fields into two
2633*fb1b10abSAndroid Build Coastguard Worker  * structs.
2634*fb1b10abSAndroid Build Coastguard Worker  */
get_gop_coding_frame_num(int * use_alt_ref,const FRAME_INFO * frame_info,const TWO_PASS * const twopass,const RATE_CONTROL * rc,int gf_start_show_idx,const RANGE * active_gf_interval,double gop_intra_factor,int lag_in_frames,int * end_of_sequence)2635*fb1b10abSAndroid Build Coastguard Worker static int get_gop_coding_frame_num(
2636*fb1b10abSAndroid Build Coastguard Worker     int *use_alt_ref, const FRAME_INFO *frame_info,
2637*fb1b10abSAndroid Build Coastguard Worker     const TWO_PASS *const twopass, const RATE_CONTROL *rc,
2638*fb1b10abSAndroid Build Coastguard Worker     int gf_start_show_idx, const RANGE *active_gf_interval,
2639*fb1b10abSAndroid Build Coastguard Worker     double gop_intra_factor, int lag_in_frames, int *end_of_sequence) {
2640*fb1b10abSAndroid Build Coastguard Worker   const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
2641*fb1b10abSAndroid Build Coastguard Worker   double loop_decay_rate = 1.00;
2642*fb1b10abSAndroid Build Coastguard Worker   double mv_ratio_accumulator = 0.0;
2643*fb1b10abSAndroid Build Coastguard Worker   double this_frame_mv_in_out = 0.0;
2644*fb1b10abSAndroid Build Coastguard Worker   double mv_in_out_accumulator = 0.0;
2645*fb1b10abSAndroid Build Coastguard Worker   double abs_mv_in_out_accumulator = 0.0;
2646*fb1b10abSAndroid Build Coastguard Worker   double sr_accumulator = 0.0;
2647*fb1b10abSAndroid Build Coastguard Worker   // Motion breakout threshold for loop below depends on image size.
2648*fb1b10abSAndroid Build Coastguard Worker   double mv_ratio_accumulator_thresh =
2649*fb1b10abSAndroid Build Coastguard Worker       (frame_info->frame_height + frame_info->frame_width) / 4.0;
2650*fb1b10abSAndroid Build Coastguard Worker   double zero_motion_accumulator = 1.0;
2651*fb1b10abSAndroid Build Coastguard Worker   int gop_coding_frames;
2652*fb1b10abSAndroid Build Coastguard Worker 
2653*fb1b10abSAndroid Build Coastguard Worker   *use_alt_ref = 1;
2654*fb1b10abSAndroid Build Coastguard Worker   gop_coding_frames = 0;
2655*fb1b10abSAndroid Build Coastguard Worker   while (gop_coding_frames < rc->static_scene_max_gf_interval &&
2656*fb1b10abSAndroid Build Coastguard Worker          gop_coding_frames < rc->frames_to_key) {
2657*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *next_next_frame;
2658*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *next_frame;
2659*fb1b10abSAndroid Build Coastguard Worker     int flash_detected;
2660*fb1b10abSAndroid Build Coastguard Worker     ++gop_coding_frames;
2661*fb1b10abSAndroid Build Coastguard Worker 
2662*fb1b10abSAndroid Build Coastguard Worker     next_frame = fps_get_frame_stats(first_pass_info,
2663*fb1b10abSAndroid Build Coastguard Worker                                      gf_start_show_idx + gop_coding_frames);
2664*fb1b10abSAndroid Build Coastguard Worker     if (next_frame == NULL) {
2665*fb1b10abSAndroid Build Coastguard Worker       *end_of_sequence = gop_coding_frames == 1 && rc->source_alt_ref_active;
2666*fb1b10abSAndroid Build Coastguard Worker       break;
2667*fb1b10abSAndroid Build Coastguard Worker     }
2668*fb1b10abSAndroid Build Coastguard Worker 
2669*fb1b10abSAndroid Build Coastguard Worker     // Test for the case where there is a brief flash but the prediction
2670*fb1b10abSAndroid Build Coastguard Worker     // quality back to an earlier frame is then restored.
2671*fb1b10abSAndroid Build Coastguard Worker     next_next_frame = fps_get_frame_stats(
2672*fb1b10abSAndroid Build Coastguard Worker         first_pass_info, gf_start_show_idx + gop_coding_frames + 1);
2673*fb1b10abSAndroid Build Coastguard Worker     flash_detected = detect_flash_from_frame_stats(next_next_frame);
2674*fb1b10abSAndroid Build Coastguard Worker 
2675*fb1b10abSAndroid Build Coastguard Worker     // Update the motion related elements to the boost calculation.
2676*fb1b10abSAndroid Build Coastguard Worker     accumulate_frame_motion_stats(
2677*fb1b10abSAndroid Build Coastguard Worker         next_frame, &this_frame_mv_in_out, &mv_in_out_accumulator,
2678*fb1b10abSAndroid Build Coastguard Worker         &abs_mv_in_out_accumulator, &mv_ratio_accumulator);
2679*fb1b10abSAndroid Build Coastguard Worker 
2680*fb1b10abSAndroid Build Coastguard Worker     // Monitor for static sections.
2681*fb1b10abSAndroid Build Coastguard Worker     if ((rc->frames_since_key + gop_coding_frames - 1) > 1) {
2682*fb1b10abSAndroid Build Coastguard Worker       zero_motion_accumulator = VPXMIN(
2683*fb1b10abSAndroid Build Coastguard Worker           zero_motion_accumulator, get_zero_motion_factor(twopass, next_frame));
2684*fb1b10abSAndroid Build Coastguard Worker     }
2685*fb1b10abSAndroid Build Coastguard Worker 
2686*fb1b10abSAndroid Build Coastguard Worker     // Accumulate the effect of prediction quality decay.
2687*fb1b10abSAndroid Build Coastguard Worker     if (!flash_detected) {
2688*fb1b10abSAndroid Build Coastguard Worker       double last_loop_decay_rate = loop_decay_rate;
2689*fb1b10abSAndroid Build Coastguard Worker       loop_decay_rate = get_prediction_decay_rate(twopass, next_frame);
2690*fb1b10abSAndroid Build Coastguard Worker 
2691*fb1b10abSAndroid Build Coastguard Worker       // Break clause to detect very still sections after motion. For example,
2692*fb1b10abSAndroid Build Coastguard Worker       // a static image after a fade or other transition.
2693*fb1b10abSAndroid Build Coastguard Worker       if (gop_coding_frames > rc->min_gf_interval && loop_decay_rate >= 0.999 &&
2694*fb1b10abSAndroid Build Coastguard Worker           last_loop_decay_rate < 0.9) {
2695*fb1b10abSAndroid Build Coastguard Worker         int still_interval = 5;
2696*fb1b10abSAndroid Build Coastguard Worker         if (check_transition_to_still(first_pass_info,
2697*fb1b10abSAndroid Build Coastguard Worker                                       gf_start_show_idx + gop_coding_frames,
2698*fb1b10abSAndroid Build Coastguard Worker                                       still_interval)) {
2699*fb1b10abSAndroid Build Coastguard Worker           *use_alt_ref = 0;
2700*fb1b10abSAndroid Build Coastguard Worker           break;
2701*fb1b10abSAndroid Build Coastguard Worker         }
2702*fb1b10abSAndroid Build Coastguard Worker       }
2703*fb1b10abSAndroid Build Coastguard Worker 
2704*fb1b10abSAndroid Build Coastguard Worker       // Update the accumulator for second ref error difference.
2705*fb1b10abSAndroid Build Coastguard Worker       // This is intended to give an indication of how much the coded error is
2706*fb1b10abSAndroid Build Coastguard Worker       // increasing over time.
2707*fb1b10abSAndroid Build Coastguard Worker       if (gop_coding_frames == 1) {
2708*fb1b10abSAndroid Build Coastguard Worker         sr_accumulator += next_frame->coded_error;
2709*fb1b10abSAndroid Build Coastguard Worker       } else {
2710*fb1b10abSAndroid Build Coastguard Worker         sr_accumulator +=
2711*fb1b10abSAndroid Build Coastguard Worker             (next_frame->sr_coded_error - next_frame->coded_error);
2712*fb1b10abSAndroid Build Coastguard Worker       }
2713*fb1b10abSAndroid Build Coastguard Worker     }
2714*fb1b10abSAndroid Build Coastguard Worker 
2715*fb1b10abSAndroid Build Coastguard Worker     // Break out conditions.
2716*fb1b10abSAndroid Build Coastguard Worker     // Break at maximum of active_gf_interval->max unless almost totally
2717*fb1b10abSAndroid Build Coastguard Worker     // static.
2718*fb1b10abSAndroid Build Coastguard Worker     //
2719*fb1b10abSAndroid Build Coastguard Worker     // Note that the addition of a test of rc->source_alt_ref_active is
2720*fb1b10abSAndroid Build Coastguard Worker     // deliberate. The effect of this is that after a normal altref group even
2721*fb1b10abSAndroid Build Coastguard Worker     // if the material is static there will be one normal length GF group
2722*fb1b10abSAndroid Build Coastguard Worker     // before allowing longer GF groups. The reason for this is that in cases
2723*fb1b10abSAndroid Build Coastguard Worker     // such as slide shows where slides are separated by a complex transition
2724*fb1b10abSAndroid Build Coastguard Worker     // such as a fade, the arf group spanning the transition may not be coded
2725*fb1b10abSAndroid Build Coastguard Worker     // at a very high quality and hence this frame (with its overlay) is a
2726*fb1b10abSAndroid Build Coastguard Worker     // poor golden frame to use for an extended group.
2727*fb1b10abSAndroid Build Coastguard Worker     if ((gop_coding_frames >= active_gf_interval->max) &&
2728*fb1b10abSAndroid Build Coastguard Worker         ((zero_motion_accumulator < 0.995) || (rc->source_alt_ref_active))) {
2729*fb1b10abSAndroid Build Coastguard Worker       break;
2730*fb1b10abSAndroid Build Coastguard Worker     }
2731*fb1b10abSAndroid Build Coastguard Worker     if (
2732*fb1b10abSAndroid Build Coastguard Worker         // Don't break out with a very short interval.
2733*fb1b10abSAndroid Build Coastguard Worker         (gop_coding_frames >= active_gf_interval->min) &&
2734*fb1b10abSAndroid Build Coastguard Worker         // If possible don't break very close to a kf
2735*fb1b10abSAndroid Build Coastguard Worker         ((rc->frames_to_key - gop_coding_frames) >= rc->min_gf_interval) &&
2736*fb1b10abSAndroid Build Coastguard Worker         (gop_coding_frames & 0x01) && (!flash_detected) &&
2737*fb1b10abSAndroid Build Coastguard Worker         ((mv_ratio_accumulator > mv_ratio_accumulator_thresh) ||
2738*fb1b10abSAndroid Build Coastguard Worker          (abs_mv_in_out_accumulator > ARF_ABS_ZOOM_THRESH) ||
2739*fb1b10abSAndroid Build Coastguard Worker          (sr_accumulator > gop_intra_factor * next_frame->intra_error))) {
2740*fb1b10abSAndroid Build Coastguard Worker       break;
2741*fb1b10abSAndroid Build Coastguard Worker     }
2742*fb1b10abSAndroid Build Coastguard Worker   }
2743*fb1b10abSAndroid Build Coastguard Worker   *use_alt_ref &= zero_motion_accumulator < 0.995;
2744*fb1b10abSAndroid Build Coastguard Worker   *use_alt_ref &= gop_coding_frames < lag_in_frames;
2745*fb1b10abSAndroid Build Coastguard Worker   *use_alt_ref &= gop_coding_frames >= rc->min_gf_interval;
2746*fb1b10abSAndroid Build Coastguard Worker   return gop_coding_frames;
2747*fb1b10abSAndroid Build Coastguard Worker }
2748*fb1b10abSAndroid Build Coastguard Worker 
get_active_gf_inverval_range_simple(int min_gf_interval,int arf_active_or_kf,int frames_to_key)2749*fb1b10abSAndroid Build Coastguard Worker static RANGE get_active_gf_inverval_range_simple(int min_gf_interval,
2750*fb1b10abSAndroid Build Coastguard Worker                                                  int arf_active_or_kf,
2751*fb1b10abSAndroid Build Coastguard Worker                                                  int frames_to_key) {
2752*fb1b10abSAndroid Build Coastguard Worker   RANGE active_gf_interval;
2753*fb1b10abSAndroid Build Coastguard Worker   active_gf_interval.min = min_gf_interval + arf_active_or_kf + 2;
2754*fb1b10abSAndroid Build Coastguard Worker   active_gf_interval.max = 16 + arf_active_or_kf;
2755*fb1b10abSAndroid Build Coastguard Worker 
2756*fb1b10abSAndroid Build Coastguard Worker   if ((active_gf_interval.max <= frames_to_key) &&
2757*fb1b10abSAndroid Build Coastguard Worker       (active_gf_interval.max >= (frames_to_key - min_gf_interval))) {
2758*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval.min = frames_to_key / 2;
2759*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval.max = frames_to_key / 2;
2760*fb1b10abSAndroid Build Coastguard Worker   }
2761*fb1b10abSAndroid Build Coastguard Worker   return active_gf_interval;
2762*fb1b10abSAndroid Build Coastguard Worker }
2763*fb1b10abSAndroid Build Coastguard Worker 
get_active_gf_inverval_range(const FRAME_INFO * frame_info,const RATE_CONTROL * rc,int arf_active_or_kf,int gf_start_show_idx,int active_worst_quality,int last_boosted_qindex)2764*fb1b10abSAndroid Build Coastguard Worker static RANGE get_active_gf_inverval_range(
2765*fb1b10abSAndroid Build Coastguard Worker     const FRAME_INFO *frame_info, const RATE_CONTROL *rc, int arf_active_or_kf,
2766*fb1b10abSAndroid Build Coastguard Worker     int gf_start_show_idx, int active_worst_quality, int last_boosted_qindex) {
2767*fb1b10abSAndroid Build Coastguard Worker   RANGE active_gf_interval;
2768*fb1b10abSAndroid Build Coastguard Worker   int int_max_q = (int)(vp9_convert_qindex_to_q(active_worst_quality,
2769*fb1b10abSAndroid Build Coastguard Worker                                                 frame_info->bit_depth));
2770*fb1b10abSAndroid Build Coastguard Worker   int q_term = (gf_start_show_idx == 0)
2771*fb1b10abSAndroid Build Coastguard Worker                    ? int_max_q / 32
2772*fb1b10abSAndroid Build Coastguard Worker                    : (int)(vp9_convert_qindex_to_q(last_boosted_qindex,
2773*fb1b10abSAndroid Build Coastguard Worker                                                    frame_info->bit_depth) /
2774*fb1b10abSAndroid Build Coastguard Worker                            6);
2775*fb1b10abSAndroid Build Coastguard Worker   active_gf_interval.min =
2776*fb1b10abSAndroid Build Coastguard Worker       rc->min_gf_interval + arf_active_or_kf + VPXMIN(2, int_max_q / 200);
2777*fb1b10abSAndroid Build Coastguard Worker   active_gf_interval.min =
2778*fb1b10abSAndroid Build Coastguard Worker       VPXMIN(active_gf_interval.min, rc->max_gf_interval + arf_active_or_kf);
2779*fb1b10abSAndroid Build Coastguard Worker 
2780*fb1b10abSAndroid Build Coastguard Worker   // The value chosen depends on the active Q range. At low Q we have
2781*fb1b10abSAndroid Build Coastguard Worker   // bits to spare and are better with a smaller interval and smaller boost.
2782*fb1b10abSAndroid Build Coastguard Worker   // At high Q when there are few bits to spare we are better with a longer
2783*fb1b10abSAndroid Build Coastguard Worker   // interval to spread the cost of the GF.
2784*fb1b10abSAndroid Build Coastguard Worker   active_gf_interval.max = 11 + arf_active_or_kf + VPXMIN(5, q_term);
2785*fb1b10abSAndroid Build Coastguard Worker 
2786*fb1b10abSAndroid Build Coastguard Worker   // Force max GF interval to be odd.
2787*fb1b10abSAndroid Build Coastguard Worker   active_gf_interval.max = active_gf_interval.max | 0x01;
2788*fb1b10abSAndroid Build Coastguard Worker 
2789*fb1b10abSAndroid Build Coastguard Worker   // We have: active_gf_interval.min <=
2790*fb1b10abSAndroid Build Coastguard Worker   // rc->max_gf_interval + arf_active_or_kf.
2791*fb1b10abSAndroid Build Coastguard Worker   if (active_gf_interval.max < active_gf_interval.min) {
2792*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval.max = active_gf_interval.min;
2793*fb1b10abSAndroid Build Coastguard Worker   } else {
2794*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval.max =
2795*fb1b10abSAndroid Build Coastguard Worker         VPXMIN(active_gf_interval.max, rc->max_gf_interval + arf_active_or_kf);
2796*fb1b10abSAndroid Build Coastguard Worker   }
2797*fb1b10abSAndroid Build Coastguard Worker 
2798*fb1b10abSAndroid Build Coastguard Worker   // Would the active max drop us out just before the near the next kf?
2799*fb1b10abSAndroid Build Coastguard Worker   if ((active_gf_interval.max <= rc->frames_to_key) &&
2800*fb1b10abSAndroid Build Coastguard Worker       (active_gf_interval.max >= (rc->frames_to_key - rc->min_gf_interval))) {
2801*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval.max = rc->frames_to_key / 2;
2802*fb1b10abSAndroid Build Coastguard Worker   }
2803*fb1b10abSAndroid Build Coastguard Worker   active_gf_interval.max =
2804*fb1b10abSAndroid Build Coastguard Worker       VPXMAX(active_gf_interval.max, active_gf_interval.min);
2805*fb1b10abSAndroid Build Coastguard Worker   return active_gf_interval;
2806*fb1b10abSAndroid Build Coastguard Worker }
2807*fb1b10abSAndroid Build Coastguard Worker 
get_arf_layers(int multi_layer_arf,int max_layers,int coding_frame_num)2808*fb1b10abSAndroid Build Coastguard Worker static int get_arf_layers(int multi_layer_arf, int max_layers,
2809*fb1b10abSAndroid Build Coastguard Worker                           int coding_frame_num) {
2810*fb1b10abSAndroid Build Coastguard Worker   assert(max_layers <= MAX_ARF_LAYERS);
2811*fb1b10abSAndroid Build Coastguard Worker   if (multi_layer_arf) {
2812*fb1b10abSAndroid Build Coastguard Worker     int layers = 0;
2813*fb1b10abSAndroid Build Coastguard Worker     int i;
2814*fb1b10abSAndroid Build Coastguard Worker     for (i = coding_frame_num; i > 0; i >>= 1) {
2815*fb1b10abSAndroid Build Coastguard Worker       ++layers;
2816*fb1b10abSAndroid Build Coastguard Worker     }
2817*fb1b10abSAndroid Build Coastguard Worker     layers = VPXMIN(max_layers, layers);
2818*fb1b10abSAndroid Build Coastguard Worker     return layers;
2819*fb1b10abSAndroid Build Coastguard Worker   } else {
2820*fb1b10abSAndroid Build Coastguard Worker     return 1;
2821*fb1b10abSAndroid Build Coastguard Worker   }
2822*fb1b10abSAndroid Build Coastguard Worker }
2823*fb1b10abSAndroid Build Coastguard Worker 
define_gf_group(VP9_COMP * cpi,int gf_start_show_idx)2824*fb1b10abSAndroid Build Coastguard Worker static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) {
2825*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
2826*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
2827*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig *const oxcf = &cpi->oxcf;
2828*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
2829*fb1b10abSAndroid Build Coastguard Worker   const FRAME_INFO *frame_info = &cpi->frame_info;
2830*fb1b10abSAndroid Build Coastguard Worker   const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
2831*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *const start_pos = twopass->stats_in;
2832*fb1b10abSAndroid Build Coastguard Worker   int gop_coding_frames;
2833*fb1b10abSAndroid Build Coastguard Worker 
2834*fb1b10abSAndroid Build Coastguard Worker   double gf_group_err = 0.0;
2835*fb1b10abSAndroid Build Coastguard Worker   double gf_group_raw_error = 0.0;
2836*fb1b10abSAndroid Build Coastguard Worker   double gf_group_noise = 0.0;
2837*fb1b10abSAndroid Build Coastguard Worker   double gf_group_skip_pct = 0.0;
2838*fb1b10abSAndroid Build Coastguard Worker   double gf_group_inactive_zone_rows = 0.0;
2839*fb1b10abSAndroid Build Coastguard Worker   double gf_group_inter = 0.0;
2840*fb1b10abSAndroid Build Coastguard Worker   double gf_group_motion = 0.0;
2841*fb1b10abSAndroid Build Coastguard Worker 
2842*fb1b10abSAndroid Build Coastguard Worker   int allow_alt_ref = is_altref_enabled(cpi);
2843*fb1b10abSAndroid Build Coastguard Worker   int use_alt_ref;
2844*fb1b10abSAndroid Build Coastguard Worker 
2845*fb1b10abSAndroid Build Coastguard Worker   int64_t gf_group_bits;
2846*fb1b10abSAndroid Build Coastguard Worker   int gf_arf_bits;
2847*fb1b10abSAndroid Build Coastguard Worker   int is_key_frame = frame_is_intra_only(cm);
2848*fb1b10abSAndroid Build Coastguard Worker 
2849*fb1b10abSAndroid Build Coastguard Worker   vpx_rc_gop_decision_t gop_decision;
2850*fb1b10abSAndroid Build Coastguard Worker   int gop_decision_ready = 0;
2851*fb1b10abSAndroid Build Coastguard Worker   if (cpi->ext_ratectrl.ready &&
2852*fb1b10abSAndroid Build Coastguard Worker       (cpi->ext_ratectrl.funcs.rc_type & VPX_RC_GOP) != 0 &&
2853*fb1b10abSAndroid Build Coastguard Worker       cpi->ext_ratectrl.funcs.get_gop_decision != NULL) {
2854*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_err_t codec_status =
2855*fb1b10abSAndroid Build Coastguard Worker         vp9_extrc_get_gop_decision(&cpi->ext_ratectrl, &gop_decision);
2856*fb1b10abSAndroid Build Coastguard Worker     if (codec_status != VPX_CODEC_OK) {
2857*fb1b10abSAndroid Build Coastguard Worker       vpx_internal_error(&cm->error, codec_status,
2858*fb1b10abSAndroid Build Coastguard Worker                          "vp9_extrc_get_gop_decision() failed");
2859*fb1b10abSAndroid Build Coastguard Worker     }
2860*fb1b10abSAndroid Build Coastguard Worker     is_key_frame = gop_decision.use_key_frame;
2861*fb1b10abSAndroid Build Coastguard Worker     gop_decision_ready = 1;
2862*fb1b10abSAndroid Build Coastguard Worker   }
2863*fb1b10abSAndroid Build Coastguard Worker 
2864*fb1b10abSAndroid Build Coastguard Worker   // If this is a key frame or the overlay from a previous arf then
2865*fb1b10abSAndroid Build Coastguard Worker   // the error score / cost of this frame has already been accounted for.
2866*fb1b10abSAndroid Build Coastguard Worker   const int arf_active_or_kf = is_key_frame || rc->source_alt_ref_active;
2867*fb1b10abSAndroid Build Coastguard Worker   int is_alt_ref_flash = 0;
2868*fb1b10abSAndroid Build Coastguard Worker 
2869*fb1b10abSAndroid Build Coastguard Worker   double gop_intra_factor;
2870*fb1b10abSAndroid Build Coastguard Worker   int gop_frames;
2871*fb1b10abSAndroid Build Coastguard Worker   RANGE active_gf_interval;
2872*fb1b10abSAndroid Build Coastguard Worker   // Whether this is at the end of last GOP of this sequence.
2873*fb1b10abSAndroid Build Coastguard Worker   int end_of_sequence = 0;
2874*fb1b10abSAndroid Build Coastguard Worker 
2875*fb1b10abSAndroid Build Coastguard Worker   // Reset the GF group data structures unless this is a key
2876*fb1b10abSAndroid Build Coastguard Worker   // frame in which case it will already have been done.
2877*fb1b10abSAndroid Build Coastguard Worker   if (is_key_frame == 0) {
2878*fb1b10abSAndroid Build Coastguard Worker     vp9_zero(twopass->gf_group);
2879*fb1b10abSAndroid Build Coastguard Worker     ++rc->gop_global_index;
2880*fb1b10abSAndroid Build Coastguard Worker   } else {
2881*fb1b10abSAndroid Build Coastguard Worker     rc->gop_global_index = 0;
2882*fb1b10abSAndroid Build Coastguard Worker   }
2883*fb1b10abSAndroid Build Coastguard Worker 
2884*fb1b10abSAndroid Build Coastguard Worker   vpx_clear_system_state();
2885*fb1b10abSAndroid Build Coastguard Worker 
2886*fb1b10abSAndroid Build Coastguard Worker   if (oxcf->use_simple_encode_api) {
2887*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval = get_active_gf_inverval_range_simple(
2888*fb1b10abSAndroid Build Coastguard Worker         rc->min_gf_interval, arf_active_or_kf, rc->frames_to_key);
2889*fb1b10abSAndroid Build Coastguard Worker   } else {
2890*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval = get_active_gf_inverval_range(
2891*fb1b10abSAndroid Build Coastguard Worker         frame_info, rc, arf_active_or_kf, gf_start_show_idx,
2892*fb1b10abSAndroid Build Coastguard Worker         twopass->active_worst_quality, rc->last_boosted_qindex);
2893*fb1b10abSAndroid Build Coastguard Worker   }
2894*fb1b10abSAndroid Build Coastguard Worker 
2895*fb1b10abSAndroid Build Coastguard Worker   if (cpi->multi_layer_arf) {
2896*fb1b10abSAndroid Build Coastguard Worker     int arf_layers = get_arf_layers(cpi->multi_layer_arf, oxcf->enable_auto_arf,
2897*fb1b10abSAndroid Build Coastguard Worker                                     active_gf_interval.max);
2898*fb1b10abSAndroid Build Coastguard Worker     gop_intra_factor = 1.0 + 0.25 * arf_layers;
2899*fb1b10abSAndroid Build Coastguard Worker   } else {
2900*fb1b10abSAndroid Build Coastguard Worker     gop_intra_factor = 1.0;
2901*fb1b10abSAndroid Build Coastguard Worker   }
2902*fb1b10abSAndroid Build Coastguard Worker 
2903*fb1b10abSAndroid Build Coastguard Worker   gop_coding_frames = get_gop_coding_frame_num(
2904*fb1b10abSAndroid Build Coastguard Worker       &use_alt_ref, frame_info, twopass, rc, gf_start_show_idx,
2905*fb1b10abSAndroid Build Coastguard Worker       &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames,
2906*fb1b10abSAndroid Build Coastguard Worker       &end_of_sequence);
2907*fb1b10abSAndroid Build Coastguard Worker   use_alt_ref &= allow_alt_ref;
2908*fb1b10abSAndroid Build Coastguard Worker 
2909*fb1b10abSAndroid Build Coastguard Worker   if (gop_decision_ready) {
2910*fb1b10abSAndroid Build Coastguard Worker     gop_coding_frames = gop_decision.gop_coding_frames;
2911*fb1b10abSAndroid Build Coastguard Worker     use_alt_ref = gop_decision.use_alt_ref;
2912*fb1b10abSAndroid Build Coastguard Worker   }
2913*fb1b10abSAndroid Build Coastguard Worker 
2914*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
2915*fb1b10abSAndroid Build Coastguard Worker   // If the external gop_command is on, we will override the decisions
2916*fb1b10abSAndroid Build Coastguard Worker   // of gop_coding_frames and use_alt_ref.
2917*fb1b10abSAndroid Build Coastguard Worker   if (cpi->oxcf.use_simple_encode_api) {
2918*fb1b10abSAndroid Build Coastguard Worker     const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
2919*fb1b10abSAndroid Build Coastguard Worker     assert(allow_alt_ref == 1);
2920*fb1b10abSAndroid Build Coastguard Worker     if (gop_command->use) {
2921*fb1b10abSAndroid Build Coastguard Worker       gop_coding_frames = gop_command_coding_frame_count(gop_command);
2922*fb1b10abSAndroid Build Coastguard Worker       use_alt_ref = gop_command->use_alt_ref;
2923*fb1b10abSAndroid Build Coastguard Worker     }
2924*fb1b10abSAndroid Build Coastguard Worker   }
2925*fb1b10abSAndroid Build Coastguard Worker #endif
2926*fb1b10abSAndroid Build Coastguard Worker 
2927*fb1b10abSAndroid Build Coastguard Worker   // Was the group length constrained by the requirement for a new KF?
2928*fb1b10abSAndroid Build Coastguard Worker   rc->constrained_gf_group = (gop_coding_frames >= rc->frames_to_key) ? 1 : 0;
2929*fb1b10abSAndroid Build Coastguard Worker 
2930*fb1b10abSAndroid Build Coastguard Worker   // Should we use the alternate reference frame.
2931*fb1b10abSAndroid Build Coastguard Worker   if (use_alt_ref) {
2932*fb1b10abSAndroid Build Coastguard Worker     const int f_frames =
2933*fb1b10abSAndroid Build Coastguard Worker         (rc->frames_to_key - gop_coding_frames >= gop_coding_frames - 1)
2934*fb1b10abSAndroid Build Coastguard Worker             ? gop_coding_frames - 1
2935*fb1b10abSAndroid Build Coastguard Worker             : VPXMAX(0, rc->frames_to_key - gop_coding_frames);
2936*fb1b10abSAndroid Build Coastguard Worker     const int b_frames = gop_coding_frames - 1;
2937*fb1b10abSAndroid Build Coastguard Worker     const int avg_inter_frame_qindex = rc->avg_frame_qindex[INTER_FRAME];
2938*fb1b10abSAndroid Build Coastguard Worker     // TODO(angiebird): figure out why arf's location is assigned this way
2939*fb1b10abSAndroid Build Coastguard Worker     const int arf_show_idx = VPXMIN(gf_start_show_idx + gop_coding_frames + 1,
2940*fb1b10abSAndroid Build Coastguard Worker                                     fps_get_num_frames(first_pass_info));
2941*fb1b10abSAndroid Build Coastguard Worker 
2942*fb1b10abSAndroid Build Coastguard Worker     // Calculate the boost for alt ref.
2943*fb1b10abSAndroid Build Coastguard Worker     rc->gfu_boost =
2944*fb1b10abSAndroid Build Coastguard Worker         compute_arf_boost(frame_info, twopass, arf_show_idx, f_frames, b_frames,
2945*fb1b10abSAndroid Build Coastguard Worker                           avg_inter_frame_qindex);
2946*fb1b10abSAndroid Build Coastguard Worker     rc->source_alt_ref_pending = 1;
2947*fb1b10abSAndroid Build Coastguard Worker   } else {
2948*fb1b10abSAndroid Build Coastguard Worker     const int f_frames = gop_coding_frames - 1;
2949*fb1b10abSAndroid Build Coastguard Worker     const int b_frames = 0;
2950*fb1b10abSAndroid Build Coastguard Worker     const int avg_inter_frame_qindex = rc->avg_frame_qindex[INTER_FRAME];
2951*fb1b10abSAndroid Build Coastguard Worker     // TODO(angiebird): figure out why arf's location is assigned this way
2952*fb1b10abSAndroid Build Coastguard Worker     const int gld_show_idx =
2953*fb1b10abSAndroid Build Coastguard Worker         VPXMIN(gf_start_show_idx + 1, fps_get_num_frames(first_pass_info));
2954*fb1b10abSAndroid Build Coastguard Worker     const int arf_boost =
2955*fb1b10abSAndroid Build Coastguard Worker         compute_arf_boost(frame_info, twopass, gld_show_idx, f_frames, b_frames,
2956*fb1b10abSAndroid Build Coastguard Worker                           avg_inter_frame_qindex);
2957*fb1b10abSAndroid Build Coastguard Worker     rc->gfu_boost = VPXMIN((int)twopass->gf_max_total_boost, arf_boost);
2958*fb1b10abSAndroid Build Coastguard Worker     rc->source_alt_ref_pending = 0;
2959*fb1b10abSAndroid Build Coastguard Worker   }
2960*fb1b10abSAndroid Build Coastguard Worker 
2961*fb1b10abSAndroid Build Coastguard Worker #define LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR 0.2
2962*fb1b10abSAndroid Build Coastguard Worker   rc->arf_active_best_quality_adjustment_factor = 1.0;
2963*fb1b10abSAndroid Build Coastguard Worker   rc->arf_increase_active_best_quality = 0;
2964*fb1b10abSAndroid Build Coastguard Worker 
2965*fb1b10abSAndroid Build Coastguard Worker   if (!is_lossless_requested(&cpi->oxcf)) {
2966*fb1b10abSAndroid Build Coastguard Worker     if (rc->frames_since_key >= rc->frames_to_key) {
2967*fb1b10abSAndroid Build Coastguard Worker       // Increase the active best quality in the second half of key frame
2968*fb1b10abSAndroid Build Coastguard Worker       // interval.
2969*fb1b10abSAndroid Build Coastguard Worker       rc->arf_active_best_quality_adjustment_factor =
2970*fb1b10abSAndroid Build Coastguard Worker           LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR +
2971*fb1b10abSAndroid Build Coastguard Worker           (1.0 - LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR) *
2972*fb1b10abSAndroid Build Coastguard Worker               (rc->frames_to_key - gop_coding_frames) /
2973*fb1b10abSAndroid Build Coastguard Worker               (VPXMAX(1, ((rc->frames_to_key + rc->frames_since_key) / 2 -
2974*fb1b10abSAndroid Build Coastguard Worker                           gop_coding_frames)));
2975*fb1b10abSAndroid Build Coastguard Worker       rc->arf_increase_active_best_quality = 1;
2976*fb1b10abSAndroid Build Coastguard Worker     } else if ((rc->frames_to_key - gop_coding_frames) > 0) {
2977*fb1b10abSAndroid Build Coastguard Worker       // Reduce the active best quality in the first half of key frame interval.
2978*fb1b10abSAndroid Build Coastguard Worker       rc->arf_active_best_quality_adjustment_factor =
2979*fb1b10abSAndroid Build Coastguard Worker           LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR +
2980*fb1b10abSAndroid Build Coastguard Worker           (1.0 - LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR) *
2981*fb1b10abSAndroid Build Coastguard Worker               (rc->frames_since_key + gop_coding_frames) /
2982*fb1b10abSAndroid Build Coastguard Worker               (VPXMAX(1, (rc->frames_to_key + rc->frames_since_key) / 2 +
2983*fb1b10abSAndroid Build Coastguard Worker                              gop_coding_frames));
2984*fb1b10abSAndroid Build Coastguard Worker       rc->arf_increase_active_best_quality = -1;
2985*fb1b10abSAndroid Build Coastguard Worker     }
2986*fb1b10abSAndroid Build Coastguard Worker   }
2987*fb1b10abSAndroid Build Coastguard Worker 
2988*fb1b10abSAndroid Build Coastguard Worker #ifdef AGGRESSIVE_VBR
2989*fb1b10abSAndroid Build Coastguard Worker   // Limit maximum boost based on interval length.
2990*fb1b10abSAndroid Build Coastguard Worker   rc->gfu_boost = VPXMIN((int)rc->gfu_boost, gop_coding_frames * 140);
2991*fb1b10abSAndroid Build Coastguard Worker #else
2992*fb1b10abSAndroid Build Coastguard Worker   rc->gfu_boost = VPXMIN((int)rc->gfu_boost, gop_coding_frames * 200);
2993*fb1b10abSAndroid Build Coastguard Worker #endif
2994*fb1b10abSAndroid Build Coastguard Worker 
2995*fb1b10abSAndroid Build Coastguard Worker   // Cap the ARF boost when perceptual quality AQ mode is enabled. This is
2996*fb1b10abSAndroid Build Coastguard Worker   // designed to improve the perceptual quality of high value content and to
2997*fb1b10abSAndroid Build Coastguard Worker   // make consistent quality across consecutive frames. It will hurt objective
2998*fb1b10abSAndroid Build Coastguard Worker   // quality.
2999*fb1b10abSAndroid Build Coastguard Worker   if (oxcf->aq_mode == PERCEPTUAL_AQ)
3000*fb1b10abSAndroid Build Coastguard Worker     rc->gfu_boost = VPXMIN(rc->gfu_boost, MIN_ARF_GF_BOOST);
3001*fb1b10abSAndroid Build Coastguard Worker 
3002*fb1b10abSAndroid Build Coastguard Worker   rc->baseline_gf_interval = gop_coding_frames - rc->source_alt_ref_pending;
3003*fb1b10abSAndroid Build Coastguard Worker 
3004*fb1b10abSAndroid Build Coastguard Worker   if (rc->source_alt_ref_pending)
3005*fb1b10abSAndroid Build Coastguard Worker     is_alt_ref_flash = detect_flash(twopass, rc->baseline_gf_interval);
3006*fb1b10abSAndroid Build Coastguard Worker 
3007*fb1b10abSAndroid Build Coastguard Worker   {
3008*fb1b10abSAndroid Build Coastguard Worker     const double av_err = get_distribution_av_err(cpi, twopass);
3009*fb1b10abSAndroid Build Coastguard Worker     const double mean_mod_score = twopass->mean_mod_score;
3010*fb1b10abSAndroid Build Coastguard Worker     // If the first frame is a key frame or the overlay from a previous arf then
3011*fb1b10abSAndroid Build Coastguard Worker     // the error score / cost of this frame has already been accounted for.
3012*fb1b10abSAndroid Build Coastguard Worker     int start_idx = arf_active_or_kf ? 1 : 0;
3013*fb1b10abSAndroid Build Coastguard Worker     int j;
3014*fb1b10abSAndroid Build Coastguard Worker     for (j = start_idx; j < gop_coding_frames; ++j) {
3015*fb1b10abSAndroid Build Coastguard Worker       int show_idx = gf_start_show_idx + j;
3016*fb1b10abSAndroid Build Coastguard Worker       const FIRSTPASS_STATS *frame_stats =
3017*fb1b10abSAndroid Build Coastguard Worker           fps_get_frame_stats(first_pass_info, show_idx);
3018*fb1b10abSAndroid Build Coastguard Worker       // TODO(b/345831640): Why do we set gop_coding_frames as the upperbound of
3019*fb1b10abSAndroid Build Coastguard Worker       // the for loop here? gop_coding_frames does not reflect the "show frame
3020*fb1b10abSAndroid Build Coastguard Worker       // count" in a GOP. Therefore, it's possible to get a NULL pointer from
3021*fb1b10abSAndroid Build Coastguard Worker       // fps_get_frame_stats(). Here we mitigate the issue using break whenever
3022*fb1b10abSAndroid Build Coastguard Worker       // frame_stats == NULL. Show we set the upperbound to show frame count?
3023*fb1b10abSAndroid Build Coastguard Worker       if (frame_stats == NULL) {
3024*fb1b10abSAndroid Build Coastguard Worker         if (cpi->ext_ratectrl.ready &&
3025*fb1b10abSAndroid Build Coastguard Worker             (cpi->ext_ratectrl.funcs.rc_type & VPX_RC_GOP) != 0 &&
3026*fb1b10abSAndroid Build Coastguard Worker             cpi->ext_ratectrl.funcs.get_gop_decision != NULL) {
3027*fb1b10abSAndroid Build Coastguard Worker           // Since in ext_ratectrl, gop_coding_frames means the count of both
3028*fb1b10abSAndroid Build Coastguard Worker           // show and no show frames. Using this variable to access
3029*fb1b10abSAndroid Build Coastguard Worker           // first_pass_info will trigger out-of-range error because
3030*fb1b10abSAndroid Build Coastguard Worker           // first_pass_info only contains show frames. This part is used for
3031*fb1b10abSAndroid Build Coastguard Worker           // computing gf_group_err which will be used to compute gf_group_bits
3032*fb1b10abSAndroid Build Coastguard Worker           // for libvpx internal rate control. Since ext_ratectrl is using
3033*fb1b10abSAndroid Build Coastguard Worker           // external rate control module, this part becomes non-critical.
3034*fb1b10abSAndroid Build Coastguard Worker           // Hence, we can safely turn off this error reporting. In the future,
3035*fb1b10abSAndroid Build Coastguard Worker           // we should refactor the code so that this part is not used by
3036*fb1b10abSAndroid Build Coastguard Worker           // ext_ratectrl.
3037*fb1b10abSAndroid Build Coastguard Worker           break;
3038*fb1b10abSAndroid Build Coastguard Worker         }
3039*fb1b10abSAndroid Build Coastguard Worker         vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
3040*fb1b10abSAndroid Build Coastguard Worker                            "In define_gf_group(), frame_stats is NULL when "
3041*fb1b10abSAndroid Build Coastguard Worker                            "calculating gf_group_err.");
3042*fb1b10abSAndroid Build Coastguard Worker         break;
3043*fb1b10abSAndroid Build Coastguard Worker       }
3044*fb1b10abSAndroid Build Coastguard Worker       // Accumulate error score of frames in this gf group.
3045*fb1b10abSAndroid Build Coastguard Worker       gf_group_err += calc_norm_frame_score(oxcf, frame_info, frame_stats,
3046*fb1b10abSAndroid Build Coastguard Worker                                             mean_mod_score, av_err);
3047*fb1b10abSAndroid Build Coastguard Worker       gf_group_raw_error += frame_stats->coded_error;
3048*fb1b10abSAndroid Build Coastguard Worker       gf_group_noise += frame_stats->frame_noise_energy;
3049*fb1b10abSAndroid Build Coastguard Worker       gf_group_skip_pct += frame_stats->intra_skip_pct;
3050*fb1b10abSAndroid Build Coastguard Worker       gf_group_inactive_zone_rows += frame_stats->inactive_zone_rows;
3051*fb1b10abSAndroid Build Coastguard Worker       gf_group_inter += frame_stats->pcnt_inter;
3052*fb1b10abSAndroid Build Coastguard Worker       gf_group_motion += frame_stats->pcnt_motion;
3053*fb1b10abSAndroid Build Coastguard Worker     }
3054*fb1b10abSAndroid Build Coastguard Worker   }
3055*fb1b10abSAndroid Build Coastguard Worker 
3056*fb1b10abSAndroid Build Coastguard Worker   // Calculate the bits to be allocated to the gf/arf group as a whole
3057*fb1b10abSAndroid Build Coastguard Worker   gf_group_bits = calculate_total_gf_group_bits(cpi, gf_group_err);
3058*fb1b10abSAndroid Build Coastguard Worker 
3059*fb1b10abSAndroid Build Coastguard Worker   gop_frames =
3060*fb1b10abSAndroid Build Coastguard Worker       rc->baseline_gf_interval + rc->source_alt_ref_pending - arf_active_or_kf;
3061*fb1b10abSAndroid Build Coastguard Worker 
3062*fb1b10abSAndroid Build Coastguard Worker   // Store the average moise level measured for the group
3063*fb1b10abSAndroid Build Coastguard Worker   // TODO(any): Experiment with removal of else condition (gop_frames = 0) so
3064*fb1b10abSAndroid Build Coastguard Worker   // that consumption of group noise energy is based on previous gf group
3065*fb1b10abSAndroid Build Coastguard Worker   if (gop_frames > 0)
3066*fb1b10abSAndroid Build Coastguard Worker     twopass->gf_group.group_noise_energy = (int)(gf_group_noise / gop_frames);
3067*fb1b10abSAndroid Build Coastguard Worker   else
3068*fb1b10abSAndroid Build Coastguard Worker     twopass->gf_group.group_noise_energy = 0;
3069*fb1b10abSAndroid Build Coastguard Worker 
3070*fb1b10abSAndroid Build Coastguard Worker   // Calculate an estimate of the maxq needed for the group.
3071*fb1b10abSAndroid Build Coastguard Worker   // We are more aggressive about correcting for sections
3072*fb1b10abSAndroid Build Coastguard Worker   // where there could be significant overshoot than for easier
3073*fb1b10abSAndroid Build Coastguard Worker   // sections where we do not wish to risk creating an overshoot
3074*fb1b10abSAndroid Build Coastguard Worker   // of the allocated bit budget.
3075*fb1b10abSAndroid Build Coastguard Worker   if ((cpi->oxcf.rc_mode != VPX_Q) && (rc->baseline_gf_interval > 1)) {
3076*fb1b10abSAndroid Build Coastguard Worker     const int vbr_group_bits_per_frame = (int)(gf_group_bits / gop_frames);
3077*fb1b10abSAndroid Build Coastguard Worker     const double group_av_err = gf_group_raw_error / gop_frames;
3078*fb1b10abSAndroid Build Coastguard Worker     const double group_av_noise = gf_group_noise / gop_frames;
3079*fb1b10abSAndroid Build Coastguard Worker     const double group_av_skip_pct = gf_group_skip_pct / gop_frames;
3080*fb1b10abSAndroid Build Coastguard Worker     const double group_av_inactive_zone = ((gf_group_inactive_zone_rows * 2) /
3081*fb1b10abSAndroid Build Coastguard Worker                                            (gop_frames * (double)cm->mb_rows));
3082*fb1b10abSAndroid Build Coastguard Worker     int tmp_q = get_twopass_worst_quality(
3083*fb1b10abSAndroid Build Coastguard Worker         cpi, group_av_err, (group_av_skip_pct + group_av_inactive_zone),
3084*fb1b10abSAndroid Build Coastguard Worker         group_av_noise, vbr_group_bits_per_frame);
3085*fb1b10abSAndroid Build Coastguard Worker     twopass->active_worst_quality =
3086*fb1b10abSAndroid Build Coastguard Worker         (int)((tmp_q + (twopass->active_worst_quality *
3087*fb1b10abSAndroid Build Coastguard Worker                         (twopass->active_wq_factor - 1))) /
3088*fb1b10abSAndroid Build Coastguard Worker               twopass->active_wq_factor);
3089*fb1b10abSAndroid Build Coastguard Worker 
3090*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_ALWAYS_ADJUST_BPM
3091*fb1b10abSAndroid Build Coastguard Worker     // Reset rolling actual and target bits counters for ARF groups.
3092*fb1b10abSAndroid Build Coastguard Worker     twopass->rolling_arf_group_target_bits = 0;
3093*fb1b10abSAndroid Build Coastguard Worker     twopass->rolling_arf_group_actual_bits = 0;
3094*fb1b10abSAndroid Build Coastguard Worker #endif
3095*fb1b10abSAndroid Build Coastguard Worker   }
3096*fb1b10abSAndroid Build Coastguard Worker 
3097*fb1b10abSAndroid Build Coastguard Worker   // Context Adjustment of ARNR filter strength
3098*fb1b10abSAndroid Build Coastguard Worker   if (rc->baseline_gf_interval > 1) {
3099*fb1b10abSAndroid Build Coastguard Worker     adjust_group_arnr_filter(cpi, (gf_group_noise / gop_frames),
3100*fb1b10abSAndroid Build Coastguard Worker                              (gf_group_inter / gop_frames),
3101*fb1b10abSAndroid Build Coastguard Worker                              (gf_group_motion / gop_frames));
3102*fb1b10abSAndroid Build Coastguard Worker   } else {
3103*fb1b10abSAndroid Build Coastguard Worker     twopass->arnr_strength_adjustment = 0;
3104*fb1b10abSAndroid Build Coastguard Worker   }
3105*fb1b10abSAndroid Build Coastguard Worker 
3106*fb1b10abSAndroid Build Coastguard Worker   // Calculate the extra bits to be used for boosted frame(s)
3107*fb1b10abSAndroid Build Coastguard Worker   gf_arf_bits = calculate_boost_bits((rc->baseline_gf_interval - 1),
3108*fb1b10abSAndroid Build Coastguard Worker                                      rc->gfu_boost, gf_group_bits);
3109*fb1b10abSAndroid Build Coastguard Worker 
3110*fb1b10abSAndroid Build Coastguard Worker   // Adjust KF group bits and error remaining.
3111*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_group_error_left -= gf_group_err;
3112*fb1b10abSAndroid Build Coastguard Worker 
3113*fb1b10abSAndroid Build Coastguard Worker   // Decide GOP structure.
3114*fb1b10abSAndroid Build Coastguard Worker   if (gop_decision_ready) {
3115*fb1b10abSAndroid Build Coastguard Worker     ext_rc_define_gf_group_structure(&gop_decision, &twopass->gf_group);
3116*fb1b10abSAndroid Build Coastguard Worker     // Set the fb idx for the first frame in this GOP.
3117*fb1b10abSAndroid Build Coastguard Worker     cpi->lst_fb_idx = twopass->gf_group.ext_rc_ref[0].last_index;
3118*fb1b10abSAndroid Build Coastguard Worker     cpi->gld_fb_idx = twopass->gf_group.ext_rc_ref[0].golden_index;
3119*fb1b10abSAndroid Build Coastguard Worker     cpi->alt_fb_idx = twopass->gf_group.ext_rc_ref[0].altref_index;
3120*fb1b10abSAndroid Build Coastguard Worker   } else {
3121*fb1b10abSAndroid Build Coastguard Worker     define_gf_group_structure(cpi);
3122*fb1b10abSAndroid Build Coastguard Worker   }
3123*fb1b10abSAndroid Build Coastguard Worker 
3124*fb1b10abSAndroid Build Coastguard Worker   // Allocate bits to each of the frames in the GF group.
3125*fb1b10abSAndroid Build Coastguard Worker   allocate_gf_group_bits(cpi, gf_group_bits, gf_arf_bits);
3126*fb1b10abSAndroid Build Coastguard Worker 
3127*fb1b10abSAndroid Build Coastguard Worker   // Reset the file position.
3128*fb1b10abSAndroid Build Coastguard Worker   reset_fpf_position(twopass, start_pos);
3129*fb1b10abSAndroid Build Coastguard Worker 
3130*fb1b10abSAndroid Build Coastguard Worker   // Calculate a section intra ratio used in setting max loop filter.
3131*fb1b10abSAndroid Build Coastguard Worker   twopass->section_intra_rating = calculate_section_intra_ratio(
3132*fb1b10abSAndroid Build Coastguard Worker       start_pos, twopass->stats_in_end, rc->baseline_gf_interval);
3133*fb1b10abSAndroid Build Coastguard Worker 
3134*fb1b10abSAndroid Build Coastguard Worker   if (oxcf->resize_mode == RESIZE_DYNAMIC) {
3135*fb1b10abSAndroid Build Coastguard Worker     // Default to starting GF groups at normal frame size.
3136*fb1b10abSAndroid Build Coastguard Worker     cpi->rc.next_frame_size_selector = UNSCALED;
3137*fb1b10abSAndroid Build Coastguard Worker   }
3138*fb1b10abSAndroid Build Coastguard Worker #if !CONFIG_ALWAYS_ADJUST_BPM
3139*fb1b10abSAndroid Build Coastguard Worker   // Reset rolling actual and target bits counters for ARF groups.
3140*fb1b10abSAndroid Build Coastguard Worker   twopass->rolling_arf_group_target_bits = 0;
3141*fb1b10abSAndroid Build Coastguard Worker   twopass->rolling_arf_group_actual_bits = 0;
3142*fb1b10abSAndroid Build Coastguard Worker #endif
3143*fb1b10abSAndroid Build Coastguard Worker   rc->preserve_arf_as_gld = rc->preserve_next_arf_as_gld;
3144*fb1b10abSAndroid Build Coastguard Worker   rc->preserve_next_arf_as_gld = 0;
3145*fb1b10abSAndroid Build Coastguard Worker   // If alt ref frame is flash do not set preserve_arf_as_gld
3146*fb1b10abSAndroid Build Coastguard Worker   if (!is_lossless_requested(&cpi->oxcf) && !cpi->use_svc &&
3147*fb1b10abSAndroid Build Coastguard Worker       cpi->oxcf.aq_mode == NO_AQ && cpi->multi_layer_arf && !is_alt_ref_flash)
3148*fb1b10abSAndroid Build Coastguard Worker     rc->preserve_next_arf_as_gld = 1;
3149*fb1b10abSAndroid Build Coastguard Worker }
3150*fb1b10abSAndroid Build Coastguard Worker 
3151*fb1b10abSAndroid Build Coastguard Worker // Intra / Inter threshold very low
3152*fb1b10abSAndroid Build Coastguard Worker #define VERY_LOW_II 1.5
3153*fb1b10abSAndroid Build Coastguard Worker // Clean slide transitions we expect a sharp single frame spike in error.
3154*fb1b10abSAndroid Build Coastguard Worker #define ERROR_SPIKE 5.0
3155*fb1b10abSAndroid Build Coastguard Worker 
3156*fb1b10abSAndroid Build Coastguard Worker // Slide show transition detection.
3157*fb1b10abSAndroid Build Coastguard Worker // Tests for case where there is very low error either side of the current frame
3158*fb1b10abSAndroid Build Coastguard Worker // but much higher just for this frame. This can help detect key frames in
3159*fb1b10abSAndroid Build Coastguard Worker // slide shows even where the slides are pictures of different sizes.
3160*fb1b10abSAndroid Build Coastguard Worker // Also requires that intra and inter errors are very similar to help eliminate
3161*fb1b10abSAndroid Build Coastguard Worker // harmful false positives.
3162*fb1b10abSAndroid Build Coastguard Worker // It will not help if the transition is a fade or other multi-frame effect.
slide_transition(const FIRSTPASS_STATS * this_frame,const FIRSTPASS_STATS * last_frame,const FIRSTPASS_STATS * next_frame)3163*fb1b10abSAndroid Build Coastguard Worker static int slide_transition(const FIRSTPASS_STATS *this_frame,
3164*fb1b10abSAndroid Build Coastguard Worker                             const FIRSTPASS_STATS *last_frame,
3165*fb1b10abSAndroid Build Coastguard Worker                             const FIRSTPASS_STATS *next_frame) {
3166*fb1b10abSAndroid Build Coastguard Worker   return (this_frame->intra_error < (this_frame->coded_error * VERY_LOW_II)) &&
3167*fb1b10abSAndroid Build Coastguard Worker          (this_frame->coded_error > (last_frame->coded_error * ERROR_SPIKE)) &&
3168*fb1b10abSAndroid Build Coastguard Worker          (this_frame->coded_error > (next_frame->coded_error * ERROR_SPIKE));
3169*fb1b10abSAndroid Build Coastguard Worker }
3170*fb1b10abSAndroid Build Coastguard Worker 
3171*fb1b10abSAndroid Build Coastguard Worker // This test looks for anomalous changes in the nature of the intra signal
3172*fb1b10abSAndroid Build Coastguard Worker // related to the previous and next frame as an indicator for coding a key
3173*fb1b10abSAndroid Build Coastguard Worker // frame. This test serves to detect some additional scene cuts,
3174*fb1b10abSAndroid Build Coastguard Worker // especially in lowish motion and low contrast sections, that are missed
3175*fb1b10abSAndroid Build Coastguard Worker // by the other tests.
intra_step_transition(const FIRSTPASS_STATS * this_frame,const FIRSTPASS_STATS * last_frame,const FIRSTPASS_STATS * next_frame)3176*fb1b10abSAndroid Build Coastguard Worker static int intra_step_transition(const FIRSTPASS_STATS *this_frame,
3177*fb1b10abSAndroid Build Coastguard Worker                                  const FIRSTPASS_STATS *last_frame,
3178*fb1b10abSAndroid Build Coastguard Worker                                  const FIRSTPASS_STATS *next_frame) {
3179*fb1b10abSAndroid Build Coastguard Worker   double last_ii_ratio;
3180*fb1b10abSAndroid Build Coastguard Worker   double this_ii_ratio;
3181*fb1b10abSAndroid Build Coastguard Worker   double next_ii_ratio;
3182*fb1b10abSAndroid Build Coastguard Worker   double last_pcnt_intra = 1.0 - last_frame->pcnt_inter;
3183*fb1b10abSAndroid Build Coastguard Worker   double this_pcnt_intra = 1.0 - this_frame->pcnt_inter;
3184*fb1b10abSAndroid Build Coastguard Worker   double next_pcnt_intra = 1.0 - next_frame->pcnt_inter;
3185*fb1b10abSAndroid Build Coastguard Worker   double mod_this_intra = this_pcnt_intra + this_frame->pcnt_neutral;
3186*fb1b10abSAndroid Build Coastguard Worker 
3187*fb1b10abSAndroid Build Coastguard Worker   // Calculate ii ratio for this frame last frame and next frame.
3188*fb1b10abSAndroid Build Coastguard Worker   last_ii_ratio =
3189*fb1b10abSAndroid Build Coastguard Worker       last_frame->intra_error / DOUBLE_DIVIDE_CHECK(last_frame->coded_error);
3190*fb1b10abSAndroid Build Coastguard Worker   this_ii_ratio =
3191*fb1b10abSAndroid Build Coastguard Worker       this_frame->intra_error / DOUBLE_DIVIDE_CHECK(this_frame->coded_error);
3192*fb1b10abSAndroid Build Coastguard Worker   next_ii_ratio =
3193*fb1b10abSAndroid Build Coastguard Worker       next_frame->intra_error / DOUBLE_DIVIDE_CHECK(next_frame->coded_error);
3194*fb1b10abSAndroid Build Coastguard Worker 
3195*fb1b10abSAndroid Build Coastguard Worker   // Return true the intra/inter ratio for the current frame is
3196*fb1b10abSAndroid Build Coastguard Worker   // low but better in the next and previous frame and the relative usage of
3197*fb1b10abSAndroid Build Coastguard Worker   // intra in the current frame is markedly higher than the last and next frame.
3198*fb1b10abSAndroid Build Coastguard Worker   if ((this_ii_ratio < 2.0) && (last_ii_ratio > 2.25) &&
3199*fb1b10abSAndroid Build Coastguard Worker       (next_ii_ratio > 2.25) && (this_pcnt_intra > (3 * last_pcnt_intra)) &&
3200*fb1b10abSAndroid Build Coastguard Worker       (this_pcnt_intra > (3 * next_pcnt_intra)) &&
3201*fb1b10abSAndroid Build Coastguard Worker       ((this_pcnt_intra > 0.075) || (mod_this_intra > 0.85))) {
3202*fb1b10abSAndroid Build Coastguard Worker     return 1;
3203*fb1b10abSAndroid Build Coastguard Worker     // Very low inter intra ratio (i.e. not much gain from inter coding), most
3204*fb1b10abSAndroid Build Coastguard Worker     // blocks neutral on coding method and better inter prediction either side
3205*fb1b10abSAndroid Build Coastguard Worker   } else if ((this_ii_ratio < 1.25) && (mod_this_intra > 0.85) &&
3206*fb1b10abSAndroid Build Coastguard Worker              (this_ii_ratio < last_ii_ratio * 0.9) &&
3207*fb1b10abSAndroid Build Coastguard Worker              (this_ii_ratio < next_ii_ratio * 0.9)) {
3208*fb1b10abSAndroid Build Coastguard Worker     return 1;
3209*fb1b10abSAndroid Build Coastguard Worker   } else {
3210*fb1b10abSAndroid Build Coastguard Worker     return 0;
3211*fb1b10abSAndroid Build Coastguard Worker   }
3212*fb1b10abSAndroid Build Coastguard Worker }
3213*fb1b10abSAndroid Build Coastguard Worker 
3214*fb1b10abSAndroid Build Coastguard Worker // Minimum % intra coding observed in first pass (1.0 = 100%)
3215*fb1b10abSAndroid Build Coastguard Worker #define MIN_INTRA_LEVEL 0.25
3216*fb1b10abSAndroid Build Coastguard Worker // Threshold for use of the lagging second reference frame. Scene cuts do not
3217*fb1b10abSAndroid Build Coastguard Worker // usually have a high second ref usage.
3218*fb1b10abSAndroid Build Coastguard Worker #define SECOND_REF_USAGE_THRESH 0.2
3219*fb1b10abSAndroid Build Coastguard Worker // Hard threshold where the first pass chooses intra for almost all blocks.
3220*fb1b10abSAndroid Build Coastguard Worker // In such a case even if the frame is not a scene cut coding a key frame
3221*fb1b10abSAndroid Build Coastguard Worker // may be a good option.
3222*fb1b10abSAndroid Build Coastguard Worker #define VERY_LOW_INTER_THRESH 0.05
3223*fb1b10abSAndroid Build Coastguard Worker // Maximum threshold for the relative ratio of intra error score vs best
3224*fb1b10abSAndroid Build Coastguard Worker // inter error score.
3225*fb1b10abSAndroid Build Coastguard Worker #define KF_II_ERR_THRESHOLD 2.5
3226*fb1b10abSAndroid Build Coastguard Worker #define KF_II_MAX 128.0
3227*fb1b10abSAndroid Build Coastguard Worker #define II_FACTOR 12.5
3228*fb1b10abSAndroid Build Coastguard Worker // Test for very low intra complexity which could cause false key frames
3229*fb1b10abSAndroid Build Coastguard Worker #define V_LOW_INTRA 0.5
3230*fb1b10abSAndroid Build Coastguard Worker 
test_candidate_kf(const FIRST_PASS_INFO * first_pass_info,int show_idx)3231*fb1b10abSAndroid Build Coastguard Worker static int test_candidate_kf(const FIRST_PASS_INFO *first_pass_info,
3232*fb1b10abSAndroid Build Coastguard Worker                              int show_idx) {
3233*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *last_frame =
3234*fb1b10abSAndroid Build Coastguard Worker       fps_get_frame_stats(first_pass_info, show_idx - 1);
3235*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *this_frame =
3236*fb1b10abSAndroid Build Coastguard Worker       fps_get_frame_stats(first_pass_info, show_idx);
3237*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *next_frame =
3238*fb1b10abSAndroid Build Coastguard Worker       fps_get_frame_stats(first_pass_info, show_idx + 1);
3239*fb1b10abSAndroid Build Coastguard Worker   int is_viable_kf = 0;
3240*fb1b10abSAndroid Build Coastguard Worker   double pcnt_intra = 1.0 - this_frame->pcnt_inter;
3241*fb1b10abSAndroid Build Coastguard Worker 
3242*fb1b10abSAndroid Build Coastguard Worker   // Does the frame satisfy the primary criteria of a key frame?
3243*fb1b10abSAndroid Build Coastguard Worker   // See above for an explanation of the test criteria.
3244*fb1b10abSAndroid Build Coastguard Worker   // If so, then examine how well it predicts subsequent frames.
3245*fb1b10abSAndroid Build Coastguard Worker   detect_flash_from_frame_stats(next_frame);
3246*fb1b10abSAndroid Build Coastguard Worker   if (!detect_flash_from_frame_stats(this_frame) &&
3247*fb1b10abSAndroid Build Coastguard Worker       !detect_flash_from_frame_stats(next_frame) &&
3248*fb1b10abSAndroid Build Coastguard Worker       (this_frame->pcnt_second_ref < SECOND_REF_USAGE_THRESH) &&
3249*fb1b10abSAndroid Build Coastguard Worker       ((this_frame->pcnt_inter < VERY_LOW_INTER_THRESH) ||
3250*fb1b10abSAndroid Build Coastguard Worker        (slide_transition(this_frame, last_frame, next_frame)) ||
3251*fb1b10abSAndroid Build Coastguard Worker        (intra_step_transition(this_frame, last_frame, next_frame)) ||
3252*fb1b10abSAndroid Build Coastguard Worker        (((this_frame->coded_error > (next_frame->coded_error * 1.2)) &&
3253*fb1b10abSAndroid Build Coastguard Worker          (this_frame->coded_error > (last_frame->coded_error * 1.2))) &&
3254*fb1b10abSAndroid Build Coastguard Worker         (pcnt_intra > MIN_INTRA_LEVEL) &&
3255*fb1b10abSAndroid Build Coastguard Worker         ((pcnt_intra + this_frame->pcnt_neutral) > 0.5) &&
3256*fb1b10abSAndroid Build Coastguard Worker         ((this_frame->intra_error /
3257*fb1b10abSAndroid Build Coastguard Worker           DOUBLE_DIVIDE_CHECK(this_frame->coded_error)) <
3258*fb1b10abSAndroid Build Coastguard Worker          KF_II_ERR_THRESHOLD)))) {
3259*fb1b10abSAndroid Build Coastguard Worker     int i;
3260*fb1b10abSAndroid Build Coastguard Worker     double boost_score = 0.0;
3261*fb1b10abSAndroid Build Coastguard Worker     double old_boost_score = 0.0;
3262*fb1b10abSAndroid Build Coastguard Worker     double decay_accumulator = 1.0;
3263*fb1b10abSAndroid Build Coastguard Worker 
3264*fb1b10abSAndroid Build Coastguard Worker     // Examine how well the key frame predicts subsequent frames.
3265*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 16; ++i) {
3266*fb1b10abSAndroid Build Coastguard Worker       const FIRSTPASS_STATS *frame_stats =
3267*fb1b10abSAndroid Build Coastguard Worker           fps_get_frame_stats(first_pass_info, show_idx + 1 + i);
3268*fb1b10abSAndroid Build Coastguard Worker       double next_iiratio = (II_FACTOR * frame_stats->intra_error /
3269*fb1b10abSAndroid Build Coastguard Worker                              DOUBLE_DIVIDE_CHECK(frame_stats->coded_error));
3270*fb1b10abSAndroid Build Coastguard Worker 
3271*fb1b10abSAndroid Build Coastguard Worker       if (next_iiratio > KF_II_MAX) next_iiratio = KF_II_MAX;
3272*fb1b10abSAndroid Build Coastguard Worker 
3273*fb1b10abSAndroid Build Coastguard Worker       // Cumulative effect of decay in prediction quality.
3274*fb1b10abSAndroid Build Coastguard Worker       if (frame_stats->pcnt_inter > 0.85)
3275*fb1b10abSAndroid Build Coastguard Worker         decay_accumulator *= frame_stats->pcnt_inter;
3276*fb1b10abSAndroid Build Coastguard Worker       else
3277*fb1b10abSAndroid Build Coastguard Worker         decay_accumulator *= (0.85 + frame_stats->pcnt_inter) / 2.0;
3278*fb1b10abSAndroid Build Coastguard Worker 
3279*fb1b10abSAndroid Build Coastguard Worker       // Keep a running total.
3280*fb1b10abSAndroid Build Coastguard Worker       boost_score += (decay_accumulator * next_iiratio);
3281*fb1b10abSAndroid Build Coastguard Worker 
3282*fb1b10abSAndroid Build Coastguard Worker       // Test various breakout clauses.
3283*fb1b10abSAndroid Build Coastguard Worker       if ((frame_stats->pcnt_inter < 0.05) || (next_iiratio < 1.5) ||
3284*fb1b10abSAndroid Build Coastguard Worker           (((frame_stats->pcnt_inter - frame_stats->pcnt_neutral) < 0.20) &&
3285*fb1b10abSAndroid Build Coastguard Worker            (next_iiratio < 3.0)) ||
3286*fb1b10abSAndroid Build Coastguard Worker           ((boost_score - old_boost_score) < 3.0) ||
3287*fb1b10abSAndroid Build Coastguard Worker           (frame_stats->intra_error < V_LOW_INTRA)) {
3288*fb1b10abSAndroid Build Coastguard Worker         break;
3289*fb1b10abSAndroid Build Coastguard Worker       }
3290*fb1b10abSAndroid Build Coastguard Worker 
3291*fb1b10abSAndroid Build Coastguard Worker       old_boost_score = boost_score;
3292*fb1b10abSAndroid Build Coastguard Worker 
3293*fb1b10abSAndroid Build Coastguard Worker       // Get the next frame details
3294*fb1b10abSAndroid Build Coastguard Worker       if (show_idx + 1 + i == fps_get_num_frames(first_pass_info) - 1) break;
3295*fb1b10abSAndroid Build Coastguard Worker     }
3296*fb1b10abSAndroid Build Coastguard Worker 
3297*fb1b10abSAndroid Build Coastguard Worker     // If there is tolerable prediction for at least the next 3 frames then
3298*fb1b10abSAndroid Build Coastguard Worker     // break out else discard this potential key frame and move on
3299*fb1b10abSAndroid Build Coastguard Worker     if (boost_score > 30.0 && (i > 3)) {
3300*fb1b10abSAndroid Build Coastguard Worker       is_viable_kf = 1;
3301*fb1b10abSAndroid Build Coastguard Worker     } else {
3302*fb1b10abSAndroid Build Coastguard Worker       is_viable_kf = 0;
3303*fb1b10abSAndroid Build Coastguard Worker     }
3304*fb1b10abSAndroid Build Coastguard Worker   }
3305*fb1b10abSAndroid Build Coastguard Worker 
3306*fb1b10abSAndroid Build Coastguard Worker   return is_viable_kf;
3307*fb1b10abSAndroid Build Coastguard Worker }
3308*fb1b10abSAndroid Build Coastguard Worker 
3309*fb1b10abSAndroid Build Coastguard Worker #define FRAMES_TO_CHECK_DECAY 8
3310*fb1b10abSAndroid Build Coastguard Worker #define MIN_KF_TOT_BOOST 300
3311*fb1b10abSAndroid Build Coastguard Worker #define DEFAULT_SCAN_FRAMES_FOR_KF_BOOST 32
3312*fb1b10abSAndroid Build Coastguard Worker #define MAX_SCAN_FRAMES_FOR_KF_BOOST 48
3313*fb1b10abSAndroid Build Coastguard Worker #define MIN_SCAN_FRAMES_FOR_KF_BOOST 32
3314*fb1b10abSAndroid Build Coastguard Worker #define KF_ABS_ZOOM_THRESH 6.0
3315*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_frames_to_next_key(const VP9EncoderConfig * oxcf,const TWO_PASS * const twopass,int kf_show_idx,int min_gf_interval)3316*fb1b10abSAndroid Build Coastguard Worker int vp9_get_frames_to_next_key(const VP9EncoderConfig *oxcf,
3317*fb1b10abSAndroid Build Coastguard Worker                                const TWO_PASS *const twopass, int kf_show_idx,
3318*fb1b10abSAndroid Build Coastguard Worker                                int min_gf_interval) {
3319*fb1b10abSAndroid Build Coastguard Worker   const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
3320*fb1b10abSAndroid Build Coastguard Worker   double recent_loop_decay[FRAMES_TO_CHECK_DECAY];
3321*fb1b10abSAndroid Build Coastguard Worker   int j;
3322*fb1b10abSAndroid Build Coastguard Worker   int frames_to_key;
3323*fb1b10abSAndroid Build Coastguard Worker   int max_frames_to_key = first_pass_info->num_frames - kf_show_idx;
3324*fb1b10abSAndroid Build Coastguard Worker   max_frames_to_key = VPXMIN(max_frames_to_key, oxcf->key_freq);
3325*fb1b10abSAndroid Build Coastguard Worker 
3326*fb1b10abSAndroid Build Coastguard Worker   // Initialize the decay rates for the recent frames to check
3327*fb1b10abSAndroid Build Coastguard Worker   for (j = 0; j < FRAMES_TO_CHECK_DECAY; ++j) recent_loop_decay[j] = 1.0;
3328*fb1b10abSAndroid Build Coastguard Worker   // Find the next keyframe.
3329*fb1b10abSAndroid Build Coastguard Worker   if (!oxcf->auto_key) {
3330*fb1b10abSAndroid Build Coastguard Worker     frames_to_key = max_frames_to_key;
3331*fb1b10abSAndroid Build Coastguard Worker   } else {
3332*fb1b10abSAndroid Build Coastguard Worker     frames_to_key = 1;
3333*fb1b10abSAndroid Build Coastguard Worker     while (frames_to_key < max_frames_to_key) {
3334*fb1b10abSAndroid Build Coastguard Worker       // Provided that we are not at the end of the file...
3335*fb1b10abSAndroid Build Coastguard Worker       if (kf_show_idx + frames_to_key + 1 < first_pass_info->num_frames) {
3336*fb1b10abSAndroid Build Coastguard Worker         double loop_decay_rate;
3337*fb1b10abSAndroid Build Coastguard Worker         double decay_accumulator;
3338*fb1b10abSAndroid Build Coastguard Worker         const FIRSTPASS_STATS *next_frame = fps_get_frame_stats(
3339*fb1b10abSAndroid Build Coastguard Worker             first_pass_info, kf_show_idx + frames_to_key + 1);
3340*fb1b10abSAndroid Build Coastguard Worker 
3341*fb1b10abSAndroid Build Coastguard Worker         // Check for a scene cut.
3342*fb1b10abSAndroid Build Coastguard Worker         if (test_candidate_kf(first_pass_info, kf_show_idx + frames_to_key))
3343*fb1b10abSAndroid Build Coastguard Worker           break;
3344*fb1b10abSAndroid Build Coastguard Worker 
3345*fb1b10abSAndroid Build Coastguard Worker         // How fast is the prediction quality decaying?
3346*fb1b10abSAndroid Build Coastguard Worker         loop_decay_rate = get_prediction_decay_rate(twopass, next_frame);
3347*fb1b10abSAndroid Build Coastguard Worker 
3348*fb1b10abSAndroid Build Coastguard Worker         // We want to know something about the recent past... rather than
3349*fb1b10abSAndroid Build Coastguard Worker         // as used elsewhere where we are concerned with decay in prediction
3350*fb1b10abSAndroid Build Coastguard Worker         // quality since the last GF or KF.
3351*fb1b10abSAndroid Build Coastguard Worker         recent_loop_decay[(frames_to_key - 1) % FRAMES_TO_CHECK_DECAY] =
3352*fb1b10abSAndroid Build Coastguard Worker             loop_decay_rate;
3353*fb1b10abSAndroid Build Coastguard Worker         decay_accumulator = 1.0;
3354*fb1b10abSAndroid Build Coastguard Worker         for (j = 0; j < FRAMES_TO_CHECK_DECAY; ++j)
3355*fb1b10abSAndroid Build Coastguard Worker           decay_accumulator *= recent_loop_decay[j];
3356*fb1b10abSAndroid Build Coastguard Worker 
3357*fb1b10abSAndroid Build Coastguard Worker         // Special check for transition or high motion followed by a
3358*fb1b10abSAndroid Build Coastguard Worker         // static scene.
3359*fb1b10abSAndroid Build Coastguard Worker         if ((frames_to_key - 1) > min_gf_interval && loop_decay_rate >= 0.999 &&
3360*fb1b10abSAndroid Build Coastguard Worker             decay_accumulator < 0.9) {
3361*fb1b10abSAndroid Build Coastguard Worker           int still_interval = oxcf->key_freq - (frames_to_key - 1);
3362*fb1b10abSAndroid Build Coastguard Worker           // TODO(angiebird): Figure out why we use "+1" here
3363*fb1b10abSAndroid Build Coastguard Worker           int show_idx = kf_show_idx + frames_to_key;
3364*fb1b10abSAndroid Build Coastguard Worker           if (check_transition_to_still(first_pass_info, show_idx,
3365*fb1b10abSAndroid Build Coastguard Worker                                         still_interval)) {
3366*fb1b10abSAndroid Build Coastguard Worker             break;
3367*fb1b10abSAndroid Build Coastguard Worker           }
3368*fb1b10abSAndroid Build Coastguard Worker         }
3369*fb1b10abSAndroid Build Coastguard Worker       }
3370*fb1b10abSAndroid Build Coastguard Worker       ++frames_to_key;
3371*fb1b10abSAndroid Build Coastguard Worker     }
3372*fb1b10abSAndroid Build Coastguard Worker   }
3373*fb1b10abSAndroid Build Coastguard Worker   return frames_to_key;
3374*fb1b10abSAndroid Build Coastguard Worker }
3375*fb1b10abSAndroid Build Coastguard Worker 
find_next_key_frame(VP9_COMP * cpi,int kf_show_idx)3376*fb1b10abSAndroid Build Coastguard Worker static void find_next_key_frame(VP9_COMP *cpi, int kf_show_idx) {
3377*fb1b10abSAndroid Build Coastguard Worker   int i;
3378*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
3379*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
3380*fb1b10abSAndroid Build Coastguard Worker   GF_GROUP *const gf_group = &twopass->gf_group;
3381*fb1b10abSAndroid Build Coastguard Worker   const VP9EncoderConfig *const oxcf = &cpi->oxcf;
3382*fb1b10abSAndroid Build Coastguard Worker   const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
3383*fb1b10abSAndroid Build Coastguard Worker   const FRAME_INFO *frame_info = &cpi->frame_info;
3384*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *const start_position = twopass->stats_in;
3385*fb1b10abSAndroid Build Coastguard Worker   const FIRSTPASS_STATS *keyframe_stats =
3386*fb1b10abSAndroid Build Coastguard Worker       fps_get_frame_stats(first_pass_info, kf_show_idx);
3387*fb1b10abSAndroid Build Coastguard Worker   FIRSTPASS_STATS next_frame;
3388*fb1b10abSAndroid Build Coastguard Worker   int kf_bits = 0;
3389*fb1b10abSAndroid Build Coastguard Worker   int64_t max_kf_bits;
3390*fb1b10abSAndroid Build Coastguard Worker   double zero_motion_accumulator = 1.0;
3391*fb1b10abSAndroid Build Coastguard Worker   double zero_motion_sum = 0.0;
3392*fb1b10abSAndroid Build Coastguard Worker   double zero_motion_avg;
3393*fb1b10abSAndroid Build Coastguard Worker   double motion_compensable_sum = 0.0;
3394*fb1b10abSAndroid Build Coastguard Worker   double motion_compensable_avg;
3395*fb1b10abSAndroid Build Coastguard Worker   int num_frames = 0;
3396*fb1b10abSAndroid Build Coastguard Worker   int kf_boost_scan_frames = DEFAULT_SCAN_FRAMES_FOR_KF_BOOST;
3397*fb1b10abSAndroid Build Coastguard Worker   double boost_score = 0.0;
3398*fb1b10abSAndroid Build Coastguard Worker   double kf_mod_err = 0.0;
3399*fb1b10abSAndroid Build Coastguard Worker   double kf_raw_err = 0.0;
3400*fb1b10abSAndroid Build Coastguard Worker   double kf_group_err = 0.0;
3401*fb1b10abSAndroid Build Coastguard Worker   double sr_accumulator = 0.0;
3402*fb1b10abSAndroid Build Coastguard Worker   double abs_mv_in_out_accumulator = 0.0;
3403*fb1b10abSAndroid Build Coastguard Worker   const double av_err = get_distribution_av_err(cpi, twopass);
3404*fb1b10abSAndroid Build Coastguard Worker   const double mean_mod_score = twopass->mean_mod_score;
3405*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(next_frame);
3406*fb1b10abSAndroid Build Coastguard Worker 
3407*fb1b10abSAndroid Build Coastguard Worker   cpi->common.frame_type = KEY_FRAME;
3408*fb1b10abSAndroid Build Coastguard Worker   rc->frames_since_key = 0;
3409*fb1b10abSAndroid Build Coastguard Worker 
3410*fb1b10abSAndroid Build Coastguard Worker   // Reset the GF group data structures.
3411*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(*gf_group);
3412*fb1b10abSAndroid Build Coastguard Worker 
3413*fb1b10abSAndroid Build Coastguard Worker   // Is this a forced key frame by interval.
3414*fb1b10abSAndroid Build Coastguard Worker   rc->this_key_frame_forced = rc->next_key_frame_forced;
3415*fb1b10abSAndroid Build Coastguard Worker 
3416*fb1b10abSAndroid Build Coastguard Worker   // Clear the alt ref active flag and last group multi arf flags as they
3417*fb1b10abSAndroid Build Coastguard Worker   // can never be set for a key frame.
3418*fb1b10abSAndroid Build Coastguard Worker   rc->source_alt_ref_active = 0;
3419*fb1b10abSAndroid Build Coastguard Worker 
3420*fb1b10abSAndroid Build Coastguard Worker   // KF is always a GF so clear frames till next gf counter.
3421*fb1b10abSAndroid Build Coastguard Worker   rc->frames_till_gf_update_due = 0;
3422*fb1b10abSAndroid Build Coastguard Worker 
3423*fb1b10abSAndroid Build Coastguard Worker   rc->frames_to_key = 1;
3424*fb1b10abSAndroid Build Coastguard Worker 
3425*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_group_bits = 0;          // Total bits available to kf group
3426*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_group_error_left = 0.0;  // Group modified error score.
3427*fb1b10abSAndroid Build Coastguard Worker 
3428*fb1b10abSAndroid Build Coastguard Worker   kf_raw_err = keyframe_stats->intra_error;
3429*fb1b10abSAndroid Build Coastguard Worker   kf_mod_err = calc_norm_frame_score(oxcf, frame_info, keyframe_stats,
3430*fb1b10abSAndroid Build Coastguard Worker                                      mean_mod_score, av_err);
3431*fb1b10abSAndroid Build Coastguard Worker 
3432*fb1b10abSAndroid Build Coastguard Worker   if (cpi->ext_ratectrl.ready &&
3433*fb1b10abSAndroid Build Coastguard Worker       (cpi->ext_ratectrl.funcs.rc_type & VPX_RC_GOP) != 0 &&
3434*fb1b10abSAndroid Build Coastguard Worker       cpi->ext_ratectrl.funcs.get_key_frame_decision != NULL) {
3435*fb1b10abSAndroid Build Coastguard Worker     vpx_rc_key_frame_decision_t key_frame_decision;
3436*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_err_t codec_status = vp9_extrc_get_key_frame_decision(
3437*fb1b10abSAndroid Build Coastguard Worker         &cpi->ext_ratectrl, &key_frame_decision);
3438*fb1b10abSAndroid Build Coastguard Worker     if (codec_status == VPX_CODEC_OK) {
3439*fb1b10abSAndroid Build Coastguard Worker       rc->frames_to_key = key_frame_decision.key_frame_group_size;
3440*fb1b10abSAndroid Build Coastguard Worker     } else {
3441*fb1b10abSAndroid Build Coastguard Worker       vpx_internal_error(&cpi->common.error, codec_status,
3442*fb1b10abSAndroid Build Coastguard Worker                          "vp9_extrc_get_key_frame_decision() failed");
3443*fb1b10abSAndroid Build Coastguard Worker     }
3444*fb1b10abSAndroid Build Coastguard Worker   } else {
3445*fb1b10abSAndroid Build Coastguard Worker     rc->frames_to_key = vp9_get_frames_to_next_key(oxcf, twopass, kf_show_idx,
3446*fb1b10abSAndroid Build Coastguard Worker                                                    rc->min_gf_interval);
3447*fb1b10abSAndroid Build Coastguard Worker   }
3448*fb1b10abSAndroid Build Coastguard Worker 
3449*fb1b10abSAndroid Build Coastguard Worker   // If there is a max kf interval set by the user we must obey it.
3450*fb1b10abSAndroid Build Coastguard Worker   // We already breakout of the loop above at 2x max.
3451*fb1b10abSAndroid Build Coastguard Worker   // This code centers the extra kf if the actual natural interval
3452*fb1b10abSAndroid Build Coastguard Worker   // is between 1x and 2x.
3453*fb1b10abSAndroid Build Coastguard Worker   if (rc->frames_to_key >= cpi->oxcf.key_freq) {
3454*fb1b10abSAndroid Build Coastguard Worker     rc->next_key_frame_forced = 1;
3455*fb1b10abSAndroid Build Coastguard Worker   } else {
3456*fb1b10abSAndroid Build Coastguard Worker     rc->next_key_frame_forced = 0;
3457*fb1b10abSAndroid Build Coastguard Worker   }
3458*fb1b10abSAndroid Build Coastguard Worker 
3459*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < rc->frames_to_key; ++i) {
3460*fb1b10abSAndroid Build Coastguard Worker     const FIRSTPASS_STATS *frame_stats =
3461*fb1b10abSAndroid Build Coastguard Worker         fps_get_frame_stats(first_pass_info, kf_show_idx + i);
3462*fb1b10abSAndroid Build Coastguard Worker     // Accumulate kf group error.
3463*fb1b10abSAndroid Build Coastguard Worker     kf_group_err += calc_norm_frame_score(oxcf, frame_info, frame_stats,
3464*fb1b10abSAndroid Build Coastguard Worker                                           mean_mod_score, av_err);
3465*fb1b10abSAndroid Build Coastguard Worker   }
3466*fb1b10abSAndroid Build Coastguard Worker 
3467*fb1b10abSAndroid Build Coastguard Worker   // Calculate the number of bits that should be assigned to the kf group.
3468*fb1b10abSAndroid Build Coastguard Worker   if (twopass->bits_left > 0 && twopass->normalized_score_left > 0.0) {
3469*fb1b10abSAndroid Build Coastguard Worker     // Maximum number of bits for a single normal frame (not key frame).
3470*fb1b10abSAndroid Build Coastguard Worker     const int max_bits = frame_max_bits(rc, &cpi->oxcf);
3471*fb1b10abSAndroid Build Coastguard Worker 
3472*fb1b10abSAndroid Build Coastguard Worker     // Maximum number of bits allocated to the key frame group.
3473*fb1b10abSAndroid Build Coastguard Worker     int64_t max_grp_bits;
3474*fb1b10abSAndroid Build Coastguard Worker 
3475*fb1b10abSAndroid Build Coastguard Worker     // Default allocation based on bits left and relative
3476*fb1b10abSAndroid Build Coastguard Worker     // complexity of the section.
3477*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_group_bits =
3478*fb1b10abSAndroid Build Coastguard Worker         (int64_t)(twopass->bits_left *
3479*fb1b10abSAndroid Build Coastguard Worker                   (kf_group_err / twopass->normalized_score_left));
3480*fb1b10abSAndroid Build Coastguard Worker 
3481*fb1b10abSAndroid Build Coastguard Worker     // Clip based on maximum per frame rate defined by the user.
3482*fb1b10abSAndroid Build Coastguard Worker     max_grp_bits = (int64_t)max_bits * (int64_t)rc->frames_to_key;
3483*fb1b10abSAndroid Build Coastguard Worker     if (twopass->kf_group_bits > max_grp_bits)
3484*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_group_bits = max_grp_bits;
3485*fb1b10abSAndroid Build Coastguard Worker   } else {
3486*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_group_bits = 0;
3487*fb1b10abSAndroid Build Coastguard Worker   }
3488*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_group_bits = VPXMAX(0, twopass->kf_group_bits);
3489*fb1b10abSAndroid Build Coastguard Worker 
3490*fb1b10abSAndroid Build Coastguard Worker   // Scan through the kf group collating various stats used to determine
3491*fb1b10abSAndroid Build Coastguard Worker   // how many bits to spend on it.
3492*fb1b10abSAndroid Build Coastguard Worker   boost_score = 0.0;
3493*fb1b10abSAndroid Build Coastguard Worker 
3494*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < VPXMIN(MAX_SCAN_FRAMES_FOR_KF_BOOST, (rc->frames_to_key - 1));
3495*fb1b10abSAndroid Build Coastguard Worker        ++i) {
3496*fb1b10abSAndroid Build Coastguard Worker     if (EOF == input_stats(twopass, &next_frame)) break;
3497*fb1b10abSAndroid Build Coastguard Worker 
3498*fb1b10abSAndroid Build Coastguard Worker     zero_motion_sum += next_frame.pcnt_inter - next_frame.pcnt_motion;
3499*fb1b10abSAndroid Build Coastguard Worker     motion_compensable_sum +=
3500*fb1b10abSAndroid Build Coastguard Worker         1 - (double)next_frame.coded_error / next_frame.intra_error;
3501*fb1b10abSAndroid Build Coastguard Worker     num_frames++;
3502*fb1b10abSAndroid Build Coastguard Worker   }
3503*fb1b10abSAndroid Build Coastguard Worker 
3504*fb1b10abSAndroid Build Coastguard Worker   if (num_frames >= MIN_SCAN_FRAMES_FOR_KF_BOOST) {
3505*fb1b10abSAndroid Build Coastguard Worker     zero_motion_avg = zero_motion_sum / num_frames;
3506*fb1b10abSAndroid Build Coastguard Worker     motion_compensable_avg = motion_compensable_sum / num_frames;
3507*fb1b10abSAndroid Build Coastguard Worker     kf_boost_scan_frames = (int)(VPXMAX(64 * zero_motion_avg - 16,
3508*fb1b10abSAndroid Build Coastguard Worker                                         160 * motion_compensable_avg - 112));
3509*fb1b10abSAndroid Build Coastguard Worker     kf_boost_scan_frames =
3510*fb1b10abSAndroid Build Coastguard Worker         VPXMAX(VPXMIN(kf_boost_scan_frames, MAX_SCAN_FRAMES_FOR_KF_BOOST),
3511*fb1b10abSAndroid Build Coastguard Worker                MIN_SCAN_FRAMES_FOR_KF_BOOST);
3512*fb1b10abSAndroid Build Coastguard Worker   }
3513*fb1b10abSAndroid Build Coastguard Worker   reset_fpf_position(twopass, start_position);
3514*fb1b10abSAndroid Build Coastguard Worker 
3515*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < (rc->frames_to_key - 1); ++i) {
3516*fb1b10abSAndroid Build Coastguard Worker     if (EOF == input_stats(twopass, &next_frame)) break;
3517*fb1b10abSAndroid Build Coastguard Worker 
3518*fb1b10abSAndroid Build Coastguard Worker     // The zero motion test here insures that if we mark a kf group as static
3519*fb1b10abSAndroid Build Coastguard Worker     // it is static throughout not just the first KF_BOOST_SCAN_MAX_FRAMES.
3520*fb1b10abSAndroid Build Coastguard Worker     // It also allows for a larger boost on long static groups.
3521*fb1b10abSAndroid Build Coastguard Worker     if ((i <= kf_boost_scan_frames) || (zero_motion_accumulator >= 0.99)) {
3522*fb1b10abSAndroid Build Coastguard Worker       double frame_boost;
3523*fb1b10abSAndroid Build Coastguard Worker       double zm_factor;
3524*fb1b10abSAndroid Build Coastguard Worker 
3525*fb1b10abSAndroid Build Coastguard Worker       // Monitor for static sections.
3526*fb1b10abSAndroid Build Coastguard Worker       // First frame in kf group the second ref indicator is invalid.
3527*fb1b10abSAndroid Build Coastguard Worker       if (i > 0) {
3528*fb1b10abSAndroid Build Coastguard Worker         zero_motion_accumulator =
3529*fb1b10abSAndroid Build Coastguard Worker             VPXMIN(zero_motion_accumulator,
3530*fb1b10abSAndroid Build Coastguard Worker                    get_zero_motion_factor(twopass, &next_frame));
3531*fb1b10abSAndroid Build Coastguard Worker       } else {
3532*fb1b10abSAndroid Build Coastguard Worker         zero_motion_accumulator =
3533*fb1b10abSAndroid Build Coastguard Worker             next_frame.pcnt_inter - next_frame.pcnt_motion;
3534*fb1b10abSAndroid Build Coastguard Worker       }
3535*fb1b10abSAndroid Build Coastguard Worker 
3536*fb1b10abSAndroid Build Coastguard Worker       // Factor 0.75-1.25 based on how much of frame is static.
3537*fb1b10abSAndroid Build Coastguard Worker       zm_factor = (0.75 + (zero_motion_accumulator / 2.0));
3538*fb1b10abSAndroid Build Coastguard Worker 
3539*fb1b10abSAndroid Build Coastguard Worker       // The second (lagging) ref error is not valid immediately after
3540*fb1b10abSAndroid Build Coastguard Worker       // a key frame because either the lag has not built up (in the case of
3541*fb1b10abSAndroid Build Coastguard Worker       // the first key frame or it points to a reference before the new key
3542*fb1b10abSAndroid Build Coastguard Worker       // frame.
3543*fb1b10abSAndroid Build Coastguard Worker       if (i < 2) sr_accumulator = 0.0;
3544*fb1b10abSAndroid Build Coastguard Worker       frame_boost =
3545*fb1b10abSAndroid Build Coastguard Worker           calc_kf_frame_boost(cpi, &next_frame, &sr_accumulator, 0, zm_factor);
3546*fb1b10abSAndroid Build Coastguard Worker 
3547*fb1b10abSAndroid Build Coastguard Worker       boost_score += frame_boost;
3548*fb1b10abSAndroid Build Coastguard Worker 
3549*fb1b10abSAndroid Build Coastguard Worker       // Measure of zoom. Large zoom tends to indicate reduced boost.
3550*fb1b10abSAndroid Build Coastguard Worker       abs_mv_in_out_accumulator +=
3551*fb1b10abSAndroid Build Coastguard Worker           fabs(next_frame.mv_in_out_count * next_frame.pcnt_motion);
3552*fb1b10abSAndroid Build Coastguard Worker 
3553*fb1b10abSAndroid Build Coastguard Worker       if ((frame_boost < 25.00) ||
3554*fb1b10abSAndroid Build Coastguard Worker           (abs_mv_in_out_accumulator > KF_ABS_ZOOM_THRESH) ||
3555*fb1b10abSAndroid Build Coastguard Worker           (sr_accumulator > (kf_raw_err * 1.50)))
3556*fb1b10abSAndroid Build Coastguard Worker         break;
3557*fb1b10abSAndroid Build Coastguard Worker     } else {
3558*fb1b10abSAndroid Build Coastguard Worker       break;
3559*fb1b10abSAndroid Build Coastguard Worker     }
3560*fb1b10abSAndroid Build Coastguard Worker   }
3561*fb1b10abSAndroid Build Coastguard Worker 
3562*fb1b10abSAndroid Build Coastguard Worker   reset_fpf_position(twopass, start_position);
3563*fb1b10abSAndroid Build Coastguard Worker 
3564*fb1b10abSAndroid Build Coastguard Worker   // Store the zero motion percentage
3565*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_zeromotion_pct = (int)(zero_motion_accumulator * 100.0);
3566*fb1b10abSAndroid Build Coastguard Worker 
3567*fb1b10abSAndroid Build Coastguard Worker   // Calculate a section intra ratio used in setting max loop filter.
3568*fb1b10abSAndroid Build Coastguard Worker   twopass->key_frame_section_intra_rating = calculate_section_intra_ratio(
3569*fb1b10abSAndroid Build Coastguard Worker       start_position, twopass->stats_in_end, rc->frames_to_key);
3570*fb1b10abSAndroid Build Coastguard Worker 
3571*fb1b10abSAndroid Build Coastguard Worker   // Special case for static / slide show content but don't apply
3572*fb1b10abSAndroid Build Coastguard Worker   // if the kf group is very short.
3573*fb1b10abSAndroid Build Coastguard Worker   if ((zero_motion_accumulator > 0.99) && (rc->frames_to_key > 8)) {
3574*fb1b10abSAndroid Build Coastguard Worker     rc->kf_boost = (int)(twopass->kf_max_total_boost);
3575*fb1b10abSAndroid Build Coastguard Worker   } else {
3576*fb1b10abSAndroid Build Coastguard Worker     // Apply various clamps for min and max oost
3577*fb1b10abSAndroid Build Coastguard Worker     rc->kf_boost = VPXMAX((int)boost_score, (rc->frames_to_key * 3));
3578*fb1b10abSAndroid Build Coastguard Worker     rc->kf_boost = VPXMAX(rc->kf_boost, MIN_KF_TOT_BOOST);
3579*fb1b10abSAndroid Build Coastguard Worker     rc->kf_boost = VPXMIN(rc->kf_boost, (int)(twopass->kf_max_total_boost));
3580*fb1b10abSAndroid Build Coastguard Worker   }
3581*fb1b10abSAndroid Build Coastguard Worker 
3582*fb1b10abSAndroid Build Coastguard Worker   // Work out how many bits to allocate for the key frame itself.
3583*fb1b10abSAndroid Build Coastguard Worker   kf_bits = calculate_boost_bits((rc->frames_to_key - 1), rc->kf_boost,
3584*fb1b10abSAndroid Build Coastguard Worker                                  twopass->kf_group_bits);
3585*fb1b10abSAndroid Build Coastguard Worker   // Based on the spatial complexity, increase the bits allocated to key frame.
3586*fb1b10abSAndroid Build Coastguard Worker   kf_bits +=
3587*fb1b10abSAndroid Build Coastguard Worker       (int)((twopass->kf_group_bits - kf_bits) * (kf_mod_err / kf_group_err));
3588*fb1b10abSAndroid Build Coastguard Worker   max_kf_bits =
3589*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_group_bits - (rc->frames_to_key - 1) * FRAME_OVERHEAD_BITS;
3590*fb1b10abSAndroid Build Coastguard Worker   max_kf_bits = lclamp(max_kf_bits, 0, INT_MAX);
3591*fb1b10abSAndroid Build Coastguard Worker   kf_bits = VPXMIN(kf_bits, (int)max_kf_bits);
3592*fb1b10abSAndroid Build Coastguard Worker 
3593*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_group_bits -= kf_bits;
3594*fb1b10abSAndroid Build Coastguard Worker 
3595*fb1b10abSAndroid Build Coastguard Worker   // Save the bits to spend on the key frame.
3596*fb1b10abSAndroid Build Coastguard Worker   gf_group->bit_allocation[0] = kf_bits;
3597*fb1b10abSAndroid Build Coastguard Worker   gf_group->update_type[0] = KF_UPDATE;
3598*fb1b10abSAndroid Build Coastguard Worker   gf_group->rf_level[0] = KF_STD;
3599*fb1b10abSAndroid Build Coastguard Worker   gf_group->layer_depth[0] = 0;
3600*fb1b10abSAndroid Build Coastguard Worker 
3601*fb1b10abSAndroid Build Coastguard Worker   // Note the total error score of the kf group minus the key frame itself.
3602*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_group_error_left = (kf_group_err - kf_mod_err);
3603*fb1b10abSAndroid Build Coastguard Worker 
3604*fb1b10abSAndroid Build Coastguard Worker   // Adjust the count of total modified error left.
3605*fb1b10abSAndroid Build Coastguard Worker   // The count of bits left is adjusted elsewhere based on real coded frame
3606*fb1b10abSAndroid Build Coastguard Worker   // sizes.
3607*fb1b10abSAndroid Build Coastguard Worker   twopass->normalized_score_left -= kf_group_err;
3608*fb1b10abSAndroid Build Coastguard Worker 
3609*fb1b10abSAndroid Build Coastguard Worker   if (oxcf->resize_mode == RESIZE_DYNAMIC) {
3610*fb1b10abSAndroid Build Coastguard Worker     // Default to normal-sized frame on keyframes.
3611*fb1b10abSAndroid Build Coastguard Worker     cpi->rc.next_frame_size_selector = UNSCALED;
3612*fb1b10abSAndroid Build Coastguard Worker   }
3613*fb1b10abSAndroid Build Coastguard Worker }
3614*fb1b10abSAndroid Build Coastguard Worker 
3615*fb1b10abSAndroid Build Coastguard Worker // Configure image size specific vizier parameters.
3616*fb1b10abSAndroid Build Coastguard Worker // Later these will be set via additional command line options
vp9_init_vizier_params(TWO_PASS * const twopass,int screen_area)3617*fb1b10abSAndroid Build Coastguard Worker void vp9_init_vizier_params(TWO_PASS *const twopass, int screen_area) {
3618*fb1b10abSAndroid Build Coastguard Worker   // When |use_vizier_rc_params| is 1, we expect the rc parameters below to
3619*fb1b10abSAndroid Build Coastguard Worker   // have been initialised on the command line as adjustment factors such
3620*fb1b10abSAndroid Build Coastguard Worker   // that a factor of 1.0 will match the default behavior when
3621*fb1b10abSAndroid Build Coastguard Worker   // |use_vizier_rc_params| is 0
3622*fb1b10abSAndroid Build Coastguard Worker   if (twopass->use_vizier_rc_params) {
3623*fb1b10abSAndroid Build Coastguard Worker     twopass->active_wq_factor *= AV_WQ_FACTOR;
3624*fb1b10abSAndroid Build Coastguard Worker     twopass->err_per_mb *= BASELINE_ERR_PER_MB;
3625*fb1b10abSAndroid Build Coastguard Worker     twopass->sr_default_decay_limit *= DEFAULT_DECAY_LIMIT;
3626*fb1b10abSAndroid Build Coastguard Worker     if (twopass->sr_default_decay_limit > 1.0)  // > 1.0 here makes no sense
3627*fb1b10abSAndroid Build Coastguard Worker       twopass->sr_default_decay_limit = 1.0;
3628*fb1b10abSAndroid Build Coastguard Worker     twopass->sr_diff_factor *= 1.0;
3629*fb1b10abSAndroid Build Coastguard Worker     twopass->gf_frame_max_boost *= GF_MAX_FRAME_BOOST;
3630*fb1b10abSAndroid Build Coastguard Worker     twopass->gf_max_total_boost *= MAX_GF_BOOST;
3631*fb1b10abSAndroid Build Coastguard Worker     // NOTE: In use max boost has precedence over min boost. So even if min is
3632*fb1b10abSAndroid Build Coastguard Worker     // somehow set higher than max the final boost value will be clamped to the
3633*fb1b10abSAndroid Build Coastguard Worker     // appropriate maximum.
3634*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_frame_min_boost *= KF_MIN_FRAME_BOOST;
3635*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_frame_max_boost_first *= KF_MAX_FRAME_BOOST;
3636*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_frame_max_boost_subs *= KF_MAX_FRAME_BOOST;
3637*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_max_total_boost *= MAX_KF_TOT_BOOST;
3638*fb1b10abSAndroid Build Coastguard Worker     twopass->zm_factor *= DEFAULT_ZM_FACTOR;
3639*fb1b10abSAndroid Build Coastguard Worker     if (twopass->zm_factor > 1.0)  // > 1.0 here makes no sense
3640*fb1b10abSAndroid Build Coastguard Worker       twopass->zm_factor = 1.0;
3641*fb1b10abSAndroid Build Coastguard Worker 
3642*fb1b10abSAndroid Build Coastguard Worker     // Correction for the fact that the kf_err_per_mb_factor default is
3643*fb1b10abSAndroid Build Coastguard Worker     // already different for different video formats and ensures that a passed
3644*fb1b10abSAndroid Build Coastguard Worker     // in value of 1.0 on the vizier command line will still match the current
3645*fb1b10abSAndroid Build Coastguard Worker     // default.
3646*fb1b10abSAndroid Build Coastguard Worker     if (screen_area < 1280 * 720) {
3647*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_err_per_mb *= 2000.0;
3648*fb1b10abSAndroid Build Coastguard Worker     } else if (screen_area < 1920 * 1080) {
3649*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_err_per_mb *= 500.0;
3650*fb1b10abSAndroid Build Coastguard Worker     } else {
3651*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_err_per_mb *= 250.0;
3652*fb1b10abSAndroid Build Coastguard Worker     }
3653*fb1b10abSAndroid Build Coastguard Worker   } else {
3654*fb1b10abSAndroid Build Coastguard Worker     // When |use_vizier_rc_params| is 0, use defaults.
3655*fb1b10abSAndroid Build Coastguard Worker     twopass->active_wq_factor = AV_WQ_FACTOR;
3656*fb1b10abSAndroid Build Coastguard Worker     twopass->err_per_mb = BASELINE_ERR_PER_MB;
3657*fb1b10abSAndroid Build Coastguard Worker     twopass->sr_default_decay_limit = DEFAULT_DECAY_LIMIT;
3658*fb1b10abSAndroid Build Coastguard Worker     twopass->sr_diff_factor = 1.0;
3659*fb1b10abSAndroid Build Coastguard Worker     twopass->gf_frame_max_boost = GF_MAX_FRAME_BOOST;
3660*fb1b10abSAndroid Build Coastguard Worker     twopass->gf_max_total_boost = MAX_GF_BOOST;
3661*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_frame_min_boost = KF_MIN_FRAME_BOOST;
3662*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST;
3663*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_frame_max_boost_subs = KF_MAX_FRAME_BOOST;
3664*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_max_total_boost = MAX_KF_TOT_BOOST;
3665*fb1b10abSAndroid Build Coastguard Worker     twopass->zm_factor = DEFAULT_ZM_FACTOR;
3666*fb1b10abSAndroid Build Coastguard Worker 
3667*fb1b10abSAndroid Build Coastguard Worker     if (screen_area < 1280 * 720) {
3668*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_err_per_mb = 2000.0;
3669*fb1b10abSAndroid Build Coastguard Worker     } else if (screen_area < 1920 * 1080) {
3670*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_err_per_mb = 500.0;
3671*fb1b10abSAndroid Build Coastguard Worker     } else {
3672*fb1b10abSAndroid Build Coastguard Worker       twopass->kf_err_per_mb = 250.0;
3673*fb1b10abSAndroid Build Coastguard Worker     }
3674*fb1b10abSAndroid Build Coastguard Worker   }
3675*fb1b10abSAndroid Build Coastguard Worker }
3676*fb1b10abSAndroid Build Coastguard Worker 
vp9_rc_get_second_pass_params(VP9_COMP * cpi)3677*fb1b10abSAndroid Build Coastguard Worker void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
3678*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
3679*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
3680*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
3681*fb1b10abSAndroid Build Coastguard Worker   GF_GROUP *const gf_group = &twopass->gf_group;
3682*fb1b10abSAndroid Build Coastguard Worker   FIRSTPASS_STATS this_frame;
3683*fb1b10abSAndroid Build Coastguard Worker   const int show_idx = cm->current_video_frame;
3684*fb1b10abSAndroid Build Coastguard Worker 
3685*fb1b10abSAndroid Build Coastguard Worker   if (cpi->common.current_frame_coding_index == 0 &&
3686*fb1b10abSAndroid Build Coastguard Worker       cpi->ext_ratectrl.funcs.send_firstpass_stats != NULL) {
3687*fb1b10abSAndroid Build Coastguard Worker     const vpx_codec_err_t codec_status = vp9_extrc_send_firstpass_stats(
3688*fb1b10abSAndroid Build Coastguard Worker         &cpi->ext_ratectrl, &cpi->twopass.first_pass_info);
3689*fb1b10abSAndroid Build Coastguard Worker     if (codec_status != VPX_CODEC_OK) {
3690*fb1b10abSAndroid Build Coastguard Worker       vpx_internal_error(&cm->error, codec_status,
3691*fb1b10abSAndroid Build Coastguard Worker                          "vp9_extrc_send_firstpass_stats() failed");
3692*fb1b10abSAndroid Build Coastguard Worker     }
3693*fb1b10abSAndroid Build Coastguard Worker   }
3694*fb1b10abSAndroid Build Coastguard Worker 
3695*fb1b10abSAndroid Build Coastguard Worker   if (!twopass->stats_in) return;
3696*fb1b10abSAndroid Build Coastguard Worker 
3697*fb1b10abSAndroid Build Coastguard Worker   // Configure image size specific vizier parameters
3698*fb1b10abSAndroid Build Coastguard Worker   if (cm->current_video_frame == 0) {
3699*fb1b10abSAndroid Build Coastguard Worker     unsigned int screen_area = (cm->width * cm->height);
3700*fb1b10abSAndroid Build Coastguard Worker 
3701*fb1b10abSAndroid Build Coastguard Worker     vp9_init_vizier_params(twopass, screen_area);
3702*fb1b10abSAndroid Build Coastguard Worker   }
3703*fb1b10abSAndroid Build Coastguard Worker 
3704*fb1b10abSAndroid Build Coastguard Worker   // If this is an arf frame then we don't want to read the stats file or
3705*fb1b10abSAndroid Build Coastguard Worker   // advance the input pointer as we already have what we need.
3706*fb1b10abSAndroid Build Coastguard Worker   if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
3707*fb1b10abSAndroid Build Coastguard Worker     int target_rate;
3708*fb1b10abSAndroid Build Coastguard Worker 
3709*fb1b10abSAndroid Build Coastguard Worker     vp9_zero(this_frame);
3710*fb1b10abSAndroid Build Coastguard Worker     this_frame =
3711*fb1b10abSAndroid Build Coastguard Worker         cpi->twopass.stats_in_start[cm->current_video_frame +
3712*fb1b10abSAndroid Build Coastguard Worker                                     gf_group->arf_src_offset[gf_group->index]];
3713*fb1b10abSAndroid Build Coastguard Worker 
3714*fb1b10abSAndroid Build Coastguard Worker     vp9_configure_buffer_updates(cpi, gf_group->index);
3715*fb1b10abSAndroid Build Coastguard Worker 
3716*fb1b10abSAndroid Build Coastguard Worker     target_rate = gf_group->bit_allocation[gf_group->index];
3717*fb1b10abSAndroid Build Coastguard Worker     target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate);
3718*fb1b10abSAndroid Build Coastguard Worker     rc->base_frame_target = target_rate;
3719*fb1b10abSAndroid Build Coastguard Worker 
3720*fb1b10abSAndroid Build Coastguard Worker     cm->frame_type = INTER_FRAME;
3721*fb1b10abSAndroid Build Coastguard Worker 
3722*fb1b10abSAndroid Build Coastguard Worker     // The multiplication by 256 reverses a scaling factor of (>> 8)
3723*fb1b10abSAndroid Build Coastguard Worker     // applied when combining MB error values for the frame.
3724*fb1b10abSAndroid Build Coastguard Worker     twopass->mb_av_energy = log((this_frame.intra_error * 256.0) + 1.0);
3725*fb1b10abSAndroid Build Coastguard Worker     twopass->mb_smooth_pct = this_frame.intra_smooth_pct;
3726*fb1b10abSAndroid Build Coastguard Worker 
3727*fb1b10abSAndroid Build Coastguard Worker     return;
3728*fb1b10abSAndroid Build Coastguard Worker   }
3729*fb1b10abSAndroid Build Coastguard Worker 
3730*fb1b10abSAndroid Build Coastguard Worker   vpx_clear_system_state();
3731*fb1b10abSAndroid Build Coastguard Worker 
3732*fb1b10abSAndroid Build Coastguard Worker   if (cpi->oxcf.rc_mode == VPX_Q) {
3733*fb1b10abSAndroid Build Coastguard Worker     twopass->active_worst_quality = cpi->oxcf.cq_level;
3734*fb1b10abSAndroid Build Coastguard Worker   } else if (cm->current_video_frame == 0) {
3735*fb1b10abSAndroid Build Coastguard Worker     const int frames_left =
3736*fb1b10abSAndroid Build Coastguard Worker         (int)(twopass->total_stats.count - cm->current_video_frame);
3737*fb1b10abSAndroid Build Coastguard Worker     // Special case code for first frame.
3738*fb1b10abSAndroid Build Coastguard Worker     int64_t section_target_bandwidth = twopass->bits_left / frames_left;
3739*fb1b10abSAndroid Build Coastguard Worker     section_target_bandwidth = VPXMIN(section_target_bandwidth, INT_MAX);
3740*fb1b10abSAndroid Build Coastguard Worker     const double section_length = twopass->total_left_stats.count;
3741*fb1b10abSAndroid Build Coastguard Worker     const double section_error =
3742*fb1b10abSAndroid Build Coastguard Worker         twopass->total_left_stats.coded_error / section_length;
3743*fb1b10abSAndroid Build Coastguard Worker     const double section_intra_skip =
3744*fb1b10abSAndroid Build Coastguard Worker         twopass->total_left_stats.intra_skip_pct / section_length;
3745*fb1b10abSAndroid Build Coastguard Worker     const double section_inactive_zone =
3746*fb1b10abSAndroid Build Coastguard Worker         (twopass->total_left_stats.inactive_zone_rows * 2) /
3747*fb1b10abSAndroid Build Coastguard Worker         ((double)cm->mb_rows * section_length);
3748*fb1b10abSAndroid Build Coastguard Worker     const double section_noise =
3749*fb1b10abSAndroid Build Coastguard Worker         twopass->total_left_stats.frame_noise_energy / section_length;
3750*fb1b10abSAndroid Build Coastguard Worker     int tmp_q;
3751*fb1b10abSAndroid Build Coastguard Worker 
3752*fb1b10abSAndroid Build Coastguard Worker     tmp_q = get_twopass_worst_quality(
3753*fb1b10abSAndroid Build Coastguard Worker         cpi, section_error, section_intra_skip + section_inactive_zone,
3754*fb1b10abSAndroid Build Coastguard Worker         section_noise, (int)section_target_bandwidth);
3755*fb1b10abSAndroid Build Coastguard Worker 
3756*fb1b10abSAndroid Build Coastguard Worker     twopass->active_worst_quality = tmp_q;
3757*fb1b10abSAndroid Build Coastguard Worker     twopass->baseline_active_worst_quality = tmp_q;
3758*fb1b10abSAndroid Build Coastguard Worker     rc->ni_av_qi = tmp_q;
3759*fb1b10abSAndroid Build Coastguard Worker     rc->last_q[INTER_FRAME] = tmp_q;
3760*fb1b10abSAndroid Build Coastguard Worker     rc->avg_q = vp9_convert_qindex_to_q(tmp_q, cm->bit_depth);
3761*fb1b10abSAndroid Build Coastguard Worker     rc->avg_frame_qindex[INTER_FRAME] = tmp_q;
3762*fb1b10abSAndroid Build Coastguard Worker     rc->last_q[KEY_FRAME] = (tmp_q + cpi->oxcf.best_allowed_q) / 2;
3763*fb1b10abSAndroid Build Coastguard Worker     rc->avg_frame_qindex[KEY_FRAME] = rc->last_q[KEY_FRAME];
3764*fb1b10abSAndroid Build Coastguard Worker   }
3765*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(this_frame);
3766*fb1b10abSAndroid Build Coastguard Worker   if (EOF == input_stats(twopass, &this_frame)) return;
3767*fb1b10abSAndroid Build Coastguard Worker 
3768*fb1b10abSAndroid Build Coastguard Worker   // Set the frame content type flag.
3769*fb1b10abSAndroid Build Coastguard Worker   if (this_frame.intra_skip_pct >= FC_ANIMATION_THRESH)
3770*fb1b10abSAndroid Build Coastguard Worker     twopass->fr_content_type = FC_GRAPHICS_ANIMATION;
3771*fb1b10abSAndroid Build Coastguard Worker   else
3772*fb1b10abSAndroid Build Coastguard Worker     twopass->fr_content_type = FC_NORMAL;
3773*fb1b10abSAndroid Build Coastguard Worker 
3774*fb1b10abSAndroid Build Coastguard Worker   // Keyframe and section processing.
3775*fb1b10abSAndroid Build Coastguard Worker   if (rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY)) {
3776*fb1b10abSAndroid Build Coastguard Worker     // Define next KF group and assign bits to it.
3777*fb1b10abSAndroid Build Coastguard Worker     find_next_key_frame(cpi, show_idx);
3778*fb1b10abSAndroid Build Coastguard Worker   } else {
3779*fb1b10abSAndroid Build Coastguard Worker     cm->frame_type = INTER_FRAME;
3780*fb1b10abSAndroid Build Coastguard Worker   }
3781*fb1b10abSAndroid Build Coastguard Worker 
3782*fb1b10abSAndroid Build Coastguard Worker   // Define a new GF/ARF group. (Should always enter here for key frames).
3783*fb1b10abSAndroid Build Coastguard Worker   if (rc->frames_till_gf_update_due == 0) {
3784*fb1b10abSAndroid Build Coastguard Worker     define_gf_group(cpi, show_idx);
3785*fb1b10abSAndroid Build Coastguard Worker 
3786*fb1b10abSAndroid Build Coastguard Worker #if ARF_STATS_OUTPUT
3787*fb1b10abSAndroid Build Coastguard Worker     {
3788*fb1b10abSAndroid Build Coastguard Worker       FILE *fpfile;
3789*fb1b10abSAndroid Build Coastguard Worker       fpfile = fopen("arf.stt", "a");
3790*fb1b10abSAndroid Build Coastguard Worker       ++arf_count;
3791*fb1b10abSAndroid Build Coastguard Worker       fprintf(fpfile, "%10d %10ld %10d %10d %10ld %10ld\n",
3792*fb1b10abSAndroid Build Coastguard Worker               cm->current_video_frame, rc->baseline_gf_interval, rc->kf_boost,
3793*fb1b10abSAndroid Build Coastguard Worker               arf_count, rc->gfu_boost, cm->frame_type);
3794*fb1b10abSAndroid Build Coastguard Worker 
3795*fb1b10abSAndroid Build Coastguard Worker       fclose(fpfile);
3796*fb1b10abSAndroid Build Coastguard Worker     }
3797*fb1b10abSAndroid Build Coastguard Worker #endif
3798*fb1b10abSAndroid Build Coastguard Worker   }
3799*fb1b10abSAndroid Build Coastguard Worker 
3800*fb1b10abSAndroid Build Coastguard Worker   if (rc->frames_till_gf_update_due == 0) {
3801*fb1b10abSAndroid Build Coastguard Worker     if (cpi->ext_ratectrl.ready && cpi->ext_ratectrl.log_file) {
3802*fb1b10abSAndroid Build Coastguard Worker       fprintf(cpi->ext_ratectrl.log_file, "GOP_INFO show_frame_count %d\n",
3803*fb1b10abSAndroid Build Coastguard Worker               rc->baseline_gf_interval);
3804*fb1b10abSAndroid Build Coastguard Worker     }
3805*fb1b10abSAndroid Build Coastguard Worker     rc->frames_till_gf_update_due = rc->baseline_gf_interval;
3806*fb1b10abSAndroid Build Coastguard Worker   }
3807*fb1b10abSAndroid Build Coastguard Worker 
3808*fb1b10abSAndroid Build Coastguard Worker   vp9_configure_buffer_updates(cpi, gf_group->index);
3809*fb1b10abSAndroid Build Coastguard Worker 
3810*fb1b10abSAndroid Build Coastguard Worker   rc->base_frame_target = gf_group->bit_allocation[gf_group->index];
3811*fb1b10abSAndroid Build Coastguard Worker 
3812*fb1b10abSAndroid Build Coastguard Worker   // The multiplication by 256 reverses a scaling factor of (>> 8)
3813*fb1b10abSAndroid Build Coastguard Worker   // applied when combining MB error values for the frame.
3814*fb1b10abSAndroid Build Coastguard Worker   twopass->mb_av_energy = log((this_frame.intra_error * 256.0) + 1.0);
3815*fb1b10abSAndroid Build Coastguard Worker   twopass->mb_smooth_pct = this_frame.intra_smooth_pct;
3816*fb1b10abSAndroid Build Coastguard Worker 
3817*fb1b10abSAndroid Build Coastguard Worker   // Update the total stats remaining structure.
3818*fb1b10abSAndroid Build Coastguard Worker   subtract_stats(&twopass->total_left_stats, &this_frame);
3819*fb1b10abSAndroid Build Coastguard Worker }
3820*fb1b10abSAndroid Build Coastguard Worker 
vp9_twopass_postencode_update(VP9_COMP * cpi)3821*fb1b10abSAndroid Build Coastguard Worker void vp9_twopass_postencode_update(VP9_COMP *cpi) {
3822*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->twopass;
3823*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
3824*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
3825*fb1b10abSAndroid Build Coastguard Worker   const int bits_used = rc->base_frame_target;
3826*fb1b10abSAndroid Build Coastguard Worker 
3827*fb1b10abSAndroid Build Coastguard Worker   // VBR correction is done through rc->vbr_bits_off_target. Based on the
3828*fb1b10abSAndroid Build Coastguard Worker   // sign of this value, a limited % adjustment is made to the target rate
3829*fb1b10abSAndroid Build Coastguard Worker   // of subsequent frames, to try and push it back towards 0. This method
3830*fb1b10abSAndroid Build Coastguard Worker   // is designed to prevent extreme behaviour at the end of a clip
3831*fb1b10abSAndroid Build Coastguard Worker   // or group of frames.
3832*fb1b10abSAndroid Build Coastguard Worker   rc->vbr_bits_off_target += rc->base_frame_target - rc->projected_frame_size;
3833*fb1b10abSAndroid Build Coastguard Worker   twopass->bits_left = VPXMAX(twopass->bits_left - bits_used, 0);
3834*fb1b10abSAndroid Build Coastguard Worker 
3835*fb1b10abSAndroid Build Coastguard Worker   // Target vs actual bits for this arf group.
3836*fb1b10abSAndroid Build Coastguard Worker   twopass->rolling_arf_group_target_bits += rc->this_frame_target;
3837*fb1b10abSAndroid Build Coastguard Worker   twopass->rolling_arf_group_actual_bits += rc->projected_frame_size;
3838*fb1b10abSAndroid Build Coastguard Worker 
3839*fb1b10abSAndroid Build Coastguard Worker   // Calculate the pct rc error.
3840*fb1b10abSAndroid Build Coastguard Worker   if (rc->total_actual_bits) {
3841*fb1b10abSAndroid Build Coastguard Worker     rc->rate_error_estimate =
3842*fb1b10abSAndroid Build Coastguard Worker         (int)((rc->vbr_bits_off_target * 100) / rc->total_actual_bits);
3843*fb1b10abSAndroid Build Coastguard Worker     rc->rate_error_estimate = clamp(rc->rate_error_estimate, -100, 100);
3844*fb1b10abSAndroid Build Coastguard Worker   } else {
3845*fb1b10abSAndroid Build Coastguard Worker     rc->rate_error_estimate = 0;
3846*fb1b10abSAndroid Build Coastguard Worker   }
3847*fb1b10abSAndroid Build Coastguard Worker 
3848*fb1b10abSAndroid Build Coastguard Worker   if (cpi->common.frame_type != KEY_FRAME) {
3849*fb1b10abSAndroid Build Coastguard Worker     twopass->kf_group_bits -= bits_used;
3850*fb1b10abSAndroid Build Coastguard Worker     twopass->last_kfgroup_zeromotion_pct = twopass->kf_zeromotion_pct;
3851*fb1b10abSAndroid Build Coastguard Worker   }
3852*fb1b10abSAndroid Build Coastguard Worker   twopass->kf_group_bits = VPXMAX(twopass->kf_group_bits, 0);
3853*fb1b10abSAndroid Build Coastguard Worker 
3854*fb1b10abSAndroid Build Coastguard Worker   // Increment the gf group index ready for the next frame.
3855*fb1b10abSAndroid Build Coastguard Worker   ++twopass->gf_group.index;
3856*fb1b10abSAndroid Build Coastguard Worker 
3857*fb1b10abSAndroid Build Coastguard Worker   // If the rate control is drifting consider adjustment to min or maxq.
3858*fb1b10abSAndroid Build Coastguard Worker   if ((cpi->oxcf.rc_mode != VPX_Q) && !cpi->rc.is_src_frame_alt_ref) {
3859*fb1b10abSAndroid Build Coastguard Worker     const int maxq_adj_limit =
3860*fb1b10abSAndroid Build Coastguard Worker         rc->worst_quality - twopass->active_worst_quality;
3861*fb1b10abSAndroid Build Coastguard Worker     const int minq_adj_limit =
3862*fb1b10abSAndroid Build Coastguard Worker         (cpi->oxcf.rc_mode == VPX_CQ ? MINQ_ADJ_LIMIT_CQ : MINQ_ADJ_LIMIT);
3863*fb1b10abSAndroid Build Coastguard Worker     int aq_extend_min = 0;
3864*fb1b10abSAndroid Build Coastguard Worker     int aq_extend_max = 0;
3865*fb1b10abSAndroid Build Coastguard Worker 
3866*fb1b10abSAndroid Build Coastguard Worker     // Extend min or Max Q range to account for imbalance from the base
3867*fb1b10abSAndroid Build Coastguard Worker     // value when using AQ.
3868*fb1b10abSAndroid Build Coastguard Worker     if (cpi->oxcf.aq_mode != NO_AQ && cpi->oxcf.aq_mode != PSNR_AQ &&
3869*fb1b10abSAndroid Build Coastguard Worker         cpi->oxcf.aq_mode != PERCEPTUAL_AQ) {
3870*fb1b10abSAndroid Build Coastguard Worker       if (cm->seg.aq_av_offset < 0) {
3871*fb1b10abSAndroid Build Coastguard Worker         // The balance of the AQ map tends towarda lowering the average Q.
3872*fb1b10abSAndroid Build Coastguard Worker         aq_extend_min = 0;
3873*fb1b10abSAndroid Build Coastguard Worker         aq_extend_max = VPXMIN(maxq_adj_limit, -cm->seg.aq_av_offset);
3874*fb1b10abSAndroid Build Coastguard Worker       } else {
3875*fb1b10abSAndroid Build Coastguard Worker         // The balance of the AQ map tends towards raising the average Q.
3876*fb1b10abSAndroid Build Coastguard Worker         aq_extend_min = VPXMIN(minq_adj_limit, cm->seg.aq_av_offset);
3877*fb1b10abSAndroid Build Coastguard Worker         aq_extend_max = 0;
3878*fb1b10abSAndroid Build Coastguard Worker       }
3879*fb1b10abSAndroid Build Coastguard Worker     }
3880*fb1b10abSAndroid Build Coastguard Worker 
3881*fb1b10abSAndroid Build Coastguard Worker     // Undershoot.
3882*fb1b10abSAndroid Build Coastguard Worker     if (rc->rate_error_estimate > cpi->oxcf.under_shoot_pct) {
3883*fb1b10abSAndroid Build Coastguard Worker       --twopass->extend_maxq;
3884*fb1b10abSAndroid Build Coastguard Worker       if (rc->rolling_target_bits >= rc->rolling_actual_bits)
3885*fb1b10abSAndroid Build Coastguard Worker         ++twopass->extend_minq;
3886*fb1b10abSAndroid Build Coastguard Worker       // Overshoot.
3887*fb1b10abSAndroid Build Coastguard Worker     } else if (rc->rate_error_estimate < -cpi->oxcf.over_shoot_pct) {
3888*fb1b10abSAndroid Build Coastguard Worker       --twopass->extend_minq;
3889*fb1b10abSAndroid Build Coastguard Worker       if (rc->rolling_target_bits < rc->rolling_actual_bits)
3890*fb1b10abSAndroid Build Coastguard Worker         ++twopass->extend_maxq;
3891*fb1b10abSAndroid Build Coastguard Worker     } else {
3892*fb1b10abSAndroid Build Coastguard Worker       // Adjustment for extreme local overshoot.
3893*fb1b10abSAndroid Build Coastguard Worker       if (rc->projected_frame_size > (2 * rc->base_frame_target) &&
3894*fb1b10abSAndroid Build Coastguard Worker           rc->projected_frame_size > (2 * rc->avg_frame_bandwidth))
3895*fb1b10abSAndroid Build Coastguard Worker         ++twopass->extend_maxq;
3896*fb1b10abSAndroid Build Coastguard Worker 
3897*fb1b10abSAndroid Build Coastguard Worker       // Unwind undershoot or overshoot adjustment.
3898*fb1b10abSAndroid Build Coastguard Worker       if (rc->rolling_target_bits < rc->rolling_actual_bits)
3899*fb1b10abSAndroid Build Coastguard Worker         --twopass->extend_minq;
3900*fb1b10abSAndroid Build Coastguard Worker       else if (rc->rolling_target_bits > rc->rolling_actual_bits)
3901*fb1b10abSAndroid Build Coastguard Worker         --twopass->extend_maxq;
3902*fb1b10abSAndroid Build Coastguard Worker     }
3903*fb1b10abSAndroid Build Coastguard Worker 
3904*fb1b10abSAndroid Build Coastguard Worker     twopass->extend_minq =
3905*fb1b10abSAndroid Build Coastguard Worker         clamp(twopass->extend_minq, aq_extend_min, minq_adj_limit);
3906*fb1b10abSAndroid Build Coastguard Worker     twopass->extend_maxq =
3907*fb1b10abSAndroid Build Coastguard Worker         clamp(twopass->extend_maxq, aq_extend_max, maxq_adj_limit);
3908*fb1b10abSAndroid Build Coastguard Worker 
3909*fb1b10abSAndroid Build Coastguard Worker     // If there is a big and undexpected undershoot then feed the extra
3910*fb1b10abSAndroid Build Coastguard Worker     // bits back in quickly. One situation where this may happen is if a
3911*fb1b10abSAndroid Build Coastguard Worker     // frame is unexpectedly almost perfectly predicted by the ARF or GF
3912*fb1b10abSAndroid Build Coastguard Worker     // but not very well predcited by the previous frame.
3913*fb1b10abSAndroid Build Coastguard Worker     if (!frame_is_kf_gf_arf(cpi) && !cpi->rc.is_src_frame_alt_ref) {
3914*fb1b10abSAndroid Build Coastguard Worker       int fast_extra_thresh = rc->base_frame_target / HIGH_UNDERSHOOT_RATIO;
3915*fb1b10abSAndroid Build Coastguard Worker       if (rc->projected_frame_size < fast_extra_thresh) {
3916*fb1b10abSAndroid Build Coastguard Worker         rc->vbr_bits_off_target_fast +=
3917*fb1b10abSAndroid Build Coastguard Worker             fast_extra_thresh - rc->projected_frame_size;
3918*fb1b10abSAndroid Build Coastguard Worker         rc->vbr_bits_off_target_fast =
3919*fb1b10abSAndroid Build Coastguard Worker             VPXMIN(rc->vbr_bits_off_target_fast,
3920*fb1b10abSAndroid Build Coastguard Worker                    (4 * (int64_t)rc->avg_frame_bandwidth));
3921*fb1b10abSAndroid Build Coastguard Worker 
3922*fb1b10abSAndroid Build Coastguard Worker         // Fast adaptation of minQ if necessary to use up the extra bits.
3923*fb1b10abSAndroid Build Coastguard Worker         if (rc->avg_frame_bandwidth) {
3924*fb1b10abSAndroid Build Coastguard Worker           twopass->extend_minq_fast =
3925*fb1b10abSAndroid Build Coastguard Worker               (int)(rc->vbr_bits_off_target_fast * 8 / rc->avg_frame_bandwidth);
3926*fb1b10abSAndroid Build Coastguard Worker         }
3927*fb1b10abSAndroid Build Coastguard Worker         twopass->extend_minq_fast = VPXMIN(
3928*fb1b10abSAndroid Build Coastguard Worker             twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
3929*fb1b10abSAndroid Build Coastguard Worker       } else if (rc->vbr_bits_off_target_fast) {
3930*fb1b10abSAndroid Build Coastguard Worker         twopass->extend_minq_fast = VPXMIN(
3931*fb1b10abSAndroid Build Coastguard Worker             twopass->extend_minq_fast, minq_adj_limit - twopass->extend_minq);
3932*fb1b10abSAndroid Build Coastguard Worker       } else {
3933*fb1b10abSAndroid Build Coastguard Worker         twopass->extend_minq_fast = 0;
3934*fb1b10abSAndroid Build Coastguard Worker       }
3935*fb1b10abSAndroid Build Coastguard Worker     }
3936*fb1b10abSAndroid Build Coastguard Worker   }
3937*fb1b10abSAndroid Build Coastguard Worker }
3938*fb1b10abSAndroid Build Coastguard Worker 
3939*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
vp9_get_next_group_of_picture(const VP9_COMP * cpi,int * first_is_key_frame,int * use_alt_ref,int * coding_frame_count,int * first_show_idx,int * last_gop_use_alt_ref)3940*fb1b10abSAndroid Build Coastguard Worker void vp9_get_next_group_of_picture(const VP9_COMP *cpi, int *first_is_key_frame,
3941*fb1b10abSAndroid Build Coastguard Worker                                    int *use_alt_ref, int *coding_frame_count,
3942*fb1b10abSAndroid Build Coastguard Worker                                    int *first_show_idx,
3943*fb1b10abSAndroid Build Coastguard Worker                                    int *last_gop_use_alt_ref) {
3944*fb1b10abSAndroid Build Coastguard Worker   const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
3945*fb1b10abSAndroid Build Coastguard Worker   // We make a copy of rc here because we want to get information from the
3946*fb1b10abSAndroid Build Coastguard Worker   // encoder without changing its state.
3947*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): Avoid copying rc here.
3948*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL rc = cpi->rc;
3949*fb1b10abSAndroid Build Coastguard Worker   const int multi_layer_arf = 0;
3950*fb1b10abSAndroid Build Coastguard Worker   const int allow_alt_ref = 1;
3951*fb1b10abSAndroid Build Coastguard Worker   // We assume that current_video_frame is updated to the show index of the
3952*fb1b10abSAndroid Build Coastguard Worker   // frame we are about to called. Note that current_video_frame is updated at
3953*fb1b10abSAndroid Build Coastguard Worker   // the end of encode_frame_to_data_rate().
3954*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): Avoid this kind of fragile style.
3955*fb1b10abSAndroid Build Coastguard Worker   *first_show_idx = cpi->common.current_video_frame;
3956*fb1b10abSAndroid Build Coastguard Worker   *last_gop_use_alt_ref = rc.source_alt_ref_active;
3957*fb1b10abSAndroid Build Coastguard Worker 
3958*fb1b10abSAndroid Build Coastguard Worker   *first_is_key_frame = 0;
3959*fb1b10abSAndroid Build Coastguard Worker   if (rc.frames_to_key == 0) {
3960*fb1b10abSAndroid Build Coastguard Worker     rc.frames_to_key = vp9_get_frames_to_next_key(
3961*fb1b10abSAndroid Build Coastguard Worker         &cpi->oxcf, &cpi->twopass, *first_show_idx, rc.min_gf_interval);
3962*fb1b10abSAndroid Build Coastguard Worker     rc.frames_since_key = 0;
3963*fb1b10abSAndroid Build Coastguard Worker     *first_is_key_frame = 1;
3964*fb1b10abSAndroid Build Coastguard Worker   }
3965*fb1b10abSAndroid Build Coastguard Worker 
3966*fb1b10abSAndroid Build Coastguard Worker   if (gop_command->use) {
3967*fb1b10abSAndroid Build Coastguard Worker     *coding_frame_count = gop_command_coding_frame_count(gop_command);
3968*fb1b10abSAndroid Build Coastguard Worker     *use_alt_ref = gop_command->use_alt_ref;
3969*fb1b10abSAndroid Build Coastguard Worker     assert(gop_command->show_frame_count <= rc.frames_to_key);
3970*fb1b10abSAndroid Build Coastguard Worker   } else {
3971*fb1b10abSAndroid Build Coastguard Worker     *coding_frame_count = vp9_get_gop_coding_frame_count(
3972*fb1b10abSAndroid Build Coastguard Worker         &cpi->oxcf, &cpi->twopass, &cpi->frame_info, &rc, *first_show_idx,
3973*fb1b10abSAndroid Build Coastguard Worker         multi_layer_arf, allow_alt_ref, *first_is_key_frame,
3974*fb1b10abSAndroid Build Coastguard Worker         *last_gop_use_alt_ref, use_alt_ref);
3975*fb1b10abSAndroid Build Coastguard Worker   }
3976*fb1b10abSAndroid Build Coastguard Worker }
3977*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_gop_coding_frame_count(const VP9EncoderConfig * oxcf,const TWO_PASS * const twopass,const FRAME_INFO * frame_info,const RATE_CONTROL * rc,int show_idx,int multi_layer_arf,int allow_alt_ref,int first_is_key_frame,int last_gop_use_alt_ref,int * use_alt_ref)3978*fb1b10abSAndroid Build Coastguard Worker int vp9_get_gop_coding_frame_count(const VP9EncoderConfig *oxcf,
3979*fb1b10abSAndroid Build Coastguard Worker                                    const TWO_PASS *const twopass,
3980*fb1b10abSAndroid Build Coastguard Worker                                    const FRAME_INFO *frame_info,
3981*fb1b10abSAndroid Build Coastguard Worker                                    const RATE_CONTROL *rc, int show_idx,
3982*fb1b10abSAndroid Build Coastguard Worker                                    int multi_layer_arf, int allow_alt_ref,
3983*fb1b10abSAndroid Build Coastguard Worker                                    int first_is_key_frame,
3984*fb1b10abSAndroid Build Coastguard Worker                                    int last_gop_use_alt_ref, int *use_alt_ref) {
3985*fb1b10abSAndroid Build Coastguard Worker   int frame_count;
3986*fb1b10abSAndroid Build Coastguard Worker   double gop_intra_factor;
3987*fb1b10abSAndroid Build Coastguard Worker   const int arf_active_or_kf = last_gop_use_alt_ref || first_is_key_frame;
3988*fb1b10abSAndroid Build Coastguard Worker   RANGE active_gf_interval;
3989*fb1b10abSAndroid Build Coastguard Worker   int arf_layers;
3990*fb1b10abSAndroid Build Coastguard Worker   int end_of_sequence = 0;
3991*fb1b10abSAndroid Build Coastguard Worker   if (oxcf->use_simple_encode_api) {
3992*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval = get_active_gf_inverval_range_simple(
3993*fb1b10abSAndroid Build Coastguard Worker         rc->min_gf_interval, arf_active_or_kf, rc->frames_to_key);
3994*fb1b10abSAndroid Build Coastguard Worker   } else {
3995*fb1b10abSAndroid Build Coastguard Worker     active_gf_interval = get_active_gf_inverval_range(
3996*fb1b10abSAndroid Build Coastguard Worker         frame_info, rc, arf_active_or_kf, show_idx, /*active_worst_quality=*/0,
3997*fb1b10abSAndroid Build Coastguard Worker         /*last_boosted_qindex=*/0);
3998*fb1b10abSAndroid Build Coastguard Worker   }
3999*fb1b10abSAndroid Build Coastguard Worker 
4000*fb1b10abSAndroid Build Coastguard Worker   arf_layers = get_arf_layers(multi_layer_arf, oxcf->enable_auto_arf,
4001*fb1b10abSAndroid Build Coastguard Worker                               active_gf_interval.max);
4002*fb1b10abSAndroid Build Coastguard Worker   if (multi_layer_arf) {
4003*fb1b10abSAndroid Build Coastguard Worker     gop_intra_factor = 1.0 + 0.25 * arf_layers;
4004*fb1b10abSAndroid Build Coastguard Worker   } else {
4005*fb1b10abSAndroid Build Coastguard Worker     gop_intra_factor = 1.0;
4006*fb1b10abSAndroid Build Coastguard Worker   }
4007*fb1b10abSAndroid Build Coastguard Worker 
4008*fb1b10abSAndroid Build Coastguard Worker   frame_count = get_gop_coding_frame_num(
4009*fb1b10abSAndroid Build Coastguard Worker       use_alt_ref, frame_info, twopass, rc, show_idx, &active_gf_interval,
4010*fb1b10abSAndroid Build Coastguard Worker       gop_intra_factor, oxcf->lag_in_frames, &end_of_sequence);
4011*fb1b10abSAndroid Build Coastguard Worker   *use_alt_ref &= allow_alt_ref;
4012*fb1b10abSAndroid Build Coastguard Worker   return frame_count;
4013*fb1b10abSAndroid Build Coastguard Worker }
4014*fb1b10abSAndroid Build Coastguard Worker 
4015*fb1b10abSAndroid Build Coastguard Worker // Under CONFIG_RATE_CTRL, once the first_pass_info is ready, the number of
4016*fb1b10abSAndroid Build Coastguard Worker // coding frames (including show frame and alt ref) can be determined.
vp9_get_coding_frame_num(const VP9EncoderConfig * oxcf,const TWO_PASS * const twopass,const FRAME_INFO * frame_info,int multi_layer_arf,int allow_alt_ref)4017*fb1b10abSAndroid Build Coastguard Worker int vp9_get_coding_frame_num(const VP9EncoderConfig *oxcf,
4018*fb1b10abSAndroid Build Coastguard Worker                              const TWO_PASS *const twopass,
4019*fb1b10abSAndroid Build Coastguard Worker                              const FRAME_INFO *frame_info, int multi_layer_arf,
4020*fb1b10abSAndroid Build Coastguard Worker                              int allow_alt_ref) {
4021*fb1b10abSAndroid Build Coastguard Worker   const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
4022*fb1b10abSAndroid Build Coastguard Worker   int coding_frame_num = 0;
4023*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL rc;
4024*fb1b10abSAndroid Build Coastguard Worker   int gop_coding_frame_count;
4025*fb1b10abSAndroid Build Coastguard Worker   int gop_show_frames;
4026*fb1b10abSAndroid Build Coastguard Worker   int show_idx = 0;
4027*fb1b10abSAndroid Build Coastguard Worker   int last_gop_use_alt_ref = 0;
4028*fb1b10abSAndroid Build Coastguard Worker   vp9_rc_init(oxcf, 1, &rc);
4029*fb1b10abSAndroid Build Coastguard Worker 
4030*fb1b10abSAndroid Build Coastguard Worker   while (show_idx < first_pass_info->num_frames) {
4031*fb1b10abSAndroid Build Coastguard Worker     int use_alt_ref;
4032*fb1b10abSAndroid Build Coastguard Worker     int first_is_key_frame = 0;
4033*fb1b10abSAndroid Build Coastguard Worker     if (rc.frames_to_key == 0) {
4034*fb1b10abSAndroid Build Coastguard Worker       rc.frames_to_key = vp9_get_frames_to_next_key(oxcf, twopass, show_idx,
4035*fb1b10abSAndroid Build Coastguard Worker                                                     rc.min_gf_interval);
4036*fb1b10abSAndroid Build Coastguard Worker       rc.frames_since_key = 0;
4037*fb1b10abSAndroid Build Coastguard Worker       first_is_key_frame = 1;
4038*fb1b10abSAndroid Build Coastguard Worker     }
4039*fb1b10abSAndroid Build Coastguard Worker 
4040*fb1b10abSAndroid Build Coastguard Worker     gop_coding_frame_count = vp9_get_gop_coding_frame_count(
4041*fb1b10abSAndroid Build Coastguard Worker         oxcf, twopass, frame_info, &rc, show_idx, multi_layer_arf,
4042*fb1b10abSAndroid Build Coastguard Worker         allow_alt_ref, first_is_key_frame, last_gop_use_alt_ref, &use_alt_ref);
4043*fb1b10abSAndroid Build Coastguard Worker 
4044*fb1b10abSAndroid Build Coastguard Worker     rc.source_alt_ref_active = use_alt_ref;
4045*fb1b10abSAndroid Build Coastguard Worker     last_gop_use_alt_ref = use_alt_ref;
4046*fb1b10abSAndroid Build Coastguard Worker     gop_show_frames = gop_coding_frame_count - use_alt_ref;
4047*fb1b10abSAndroid Build Coastguard Worker     rc.frames_to_key -= gop_show_frames;
4048*fb1b10abSAndroid Build Coastguard Worker     rc.frames_since_key += gop_show_frames;
4049*fb1b10abSAndroid Build Coastguard Worker     show_idx += gop_show_frames;
4050*fb1b10abSAndroid Build Coastguard Worker     coding_frame_num += gop_show_frames + use_alt_ref;
4051*fb1b10abSAndroid Build Coastguard Worker   }
4052*fb1b10abSAndroid Build Coastguard Worker   return coding_frame_num;
4053*fb1b10abSAndroid Build Coastguard Worker }
4054*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_key_frame_map(const VP9EncoderConfig * oxcf,const TWO_PASS * const twopass,int * key_frame_map)4055*fb1b10abSAndroid Build Coastguard Worker void vp9_get_key_frame_map(const VP9EncoderConfig *oxcf,
4056*fb1b10abSAndroid Build Coastguard Worker                            const TWO_PASS *const twopass, int *key_frame_map) {
4057*fb1b10abSAndroid Build Coastguard Worker   const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info;
4058*fb1b10abSAndroid Build Coastguard Worker   int show_idx = 0;
4059*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL rc;
4060*fb1b10abSAndroid Build Coastguard Worker   vp9_rc_init(oxcf, 1, &rc);
4061*fb1b10abSAndroid Build Coastguard Worker 
4062*fb1b10abSAndroid Build Coastguard Worker   // key_frame_map points to an int array with size equal to
4063*fb1b10abSAndroid Build Coastguard Worker   // first_pass_info->num_frames, which is also the number of show frames in the
4064*fb1b10abSAndroid Build Coastguard Worker   // video.
4065*fb1b10abSAndroid Build Coastguard Worker   memset(key_frame_map, 0,
4066*fb1b10abSAndroid Build Coastguard Worker          sizeof(*key_frame_map) * first_pass_info->num_frames);
4067*fb1b10abSAndroid Build Coastguard Worker   while (show_idx < first_pass_info->num_frames) {
4068*fb1b10abSAndroid Build Coastguard Worker     int key_frame_group_size;
4069*fb1b10abSAndroid Build Coastguard Worker     key_frame_map[show_idx] = 1;
4070*fb1b10abSAndroid Build Coastguard Worker     key_frame_group_size =
4071*fb1b10abSAndroid Build Coastguard Worker         vp9_get_frames_to_next_key(oxcf, twopass, show_idx, rc.min_gf_interval);
4072*fb1b10abSAndroid Build Coastguard Worker     assert(key_frame_group_size > 0);
4073*fb1b10abSAndroid Build Coastguard Worker     show_idx += key_frame_group_size;
4074*fb1b10abSAndroid Build Coastguard Worker   }
4075*fb1b10abSAndroid Build Coastguard Worker   assert(show_idx == first_pass_info->num_frames);
4076*fb1b10abSAndroid Build Coastguard Worker }
4077*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RATE_CTRL
4078*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_frame_stats(const TWO_PASS * twopass)4079*fb1b10abSAndroid Build Coastguard Worker FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass) {
4080*fb1b10abSAndroid Build Coastguard Worker   return twopass->this_frame_stats;
4081*fb1b10abSAndroid Build Coastguard Worker }
vp9_get_total_stats(const TWO_PASS * twopass)4082*fb1b10abSAndroid Build Coastguard Worker FIRSTPASS_STATS vp9_get_total_stats(const TWO_PASS *twopass) {
4083*fb1b10abSAndroid Build Coastguard Worker   return twopass->total_stats;
4084*fb1b10abSAndroid Build Coastguard Worker }
4085