xref: /aosp_15_r20/external/libaom/av1/encoder/gop_structure.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2019, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include <stdint.h>
13*77c1e3ccSAndroid Build Coastguard Worker 
14*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/blockd.h"
15*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h"
16*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_scale_rtcd.h"
17*77c1e3ccSAndroid Build Coastguard Worker 
18*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_codec.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_encoder.h"
20*77c1e3ccSAndroid Build Coastguard Worker 
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/av1_common_int.h"
22*77c1e3ccSAndroid Build Coastguard Worker 
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/firstpass.h"
25*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/gop_structure.h"
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/pass2_strategy.h"
27*77c1e3ccSAndroid Build Coastguard Worker 
28*77c1e3ccSAndroid Build Coastguard Worker // This function sets gf_group->frame_parallel_level for LF_UPDATE frames based
29*77c1e3ccSAndroid Build Coastguard Worker // on the value of parallel_frame_count.
set_frame_parallel_level(int * frame_parallel_level,int * parallel_frame_count,int max_parallel_frames)30*77c1e3ccSAndroid Build Coastguard Worker static void set_frame_parallel_level(int *frame_parallel_level,
31*77c1e3ccSAndroid Build Coastguard Worker                                      int *parallel_frame_count,
32*77c1e3ccSAndroid Build Coastguard Worker                                      int max_parallel_frames) {
33*77c1e3ccSAndroid Build Coastguard Worker   assert(*parallel_frame_count > 0);
34*77c1e3ccSAndroid Build Coastguard Worker   // parallel_frame_count > 1 indicates subsequent frame(s) in the current
35*77c1e3ccSAndroid Build Coastguard Worker   // parallel encode set.
36*77c1e3ccSAndroid Build Coastguard Worker   *frame_parallel_level = 1 + (*parallel_frame_count > 1);
37*77c1e3ccSAndroid Build Coastguard Worker   // Update the count of no. of parallel frames.
38*77c1e3ccSAndroid Build Coastguard Worker   (*parallel_frame_count)++;
39*77c1e3ccSAndroid Build Coastguard Worker   if (*parallel_frame_count > max_parallel_frames) *parallel_frame_count = 1;
40*77c1e3ccSAndroid Build Coastguard Worker }
41*77c1e3ccSAndroid Build Coastguard Worker 
42*77c1e3ccSAndroid Build Coastguard Worker // This function sets gf_group->src_offset based on frame_parallel_level.
43*77c1e3ccSAndroid Build Coastguard Worker // Outputs are gf_group->src_offset and first_frame_index
set_src_offset(GF_GROUP * const gf_group,int * first_frame_index,int cur_frame_idx,int frame_ind)44*77c1e3ccSAndroid Build Coastguard Worker static void set_src_offset(GF_GROUP *const gf_group, int *first_frame_index,
45*77c1e3ccSAndroid Build Coastguard Worker                            int cur_frame_idx, int frame_ind) {
46*77c1e3ccSAndroid Build Coastguard Worker   if (gf_group->frame_parallel_level[frame_ind] > 0) {
47*77c1e3ccSAndroid Build Coastguard Worker     if (gf_group->frame_parallel_level[frame_ind] == 1) {
48*77c1e3ccSAndroid Build Coastguard Worker       *first_frame_index = cur_frame_idx;
49*77c1e3ccSAndroid Build Coastguard Worker     }
50*77c1e3ccSAndroid Build Coastguard Worker 
51*77c1e3ccSAndroid Build Coastguard Worker     // Obtain the offset of the frame at frame_ind in the lookahead queue by
52*77c1e3ccSAndroid Build Coastguard Worker     // subtracting the display order hints of the current frame from the display
53*77c1e3ccSAndroid Build Coastguard Worker     // order hint of the first frame in parallel encoding set (at
54*77c1e3ccSAndroid Build Coastguard Worker     // first_frame_index).
55*77c1e3ccSAndroid Build Coastguard Worker     gf_group->src_offset[frame_ind] =
56*77c1e3ccSAndroid Build Coastguard Worker         (cur_frame_idx + gf_group->arf_src_offset[frame_ind]) -
57*77c1e3ccSAndroid Build Coastguard Worker         *first_frame_index;
58*77c1e3ccSAndroid Build Coastguard Worker   }
59*77c1e3ccSAndroid Build Coastguard Worker }
60*77c1e3ccSAndroid Build Coastguard Worker 
61*77c1e3ccSAndroid Build Coastguard Worker // Sets the GF_GROUP params for LF_UPDATE frames.
set_params_for_leaf_frames(const TWO_PASS * twopass,const TWO_PASS_FRAME * twopass_frame,const PRIMARY_RATE_CONTROL * p_rc,FRAME_INFO * frame_info,GF_GROUP * const gf_group,int * cur_frame_idx,int * frame_ind,int * parallel_frame_count,int max_parallel_frames,int do_frame_parallel_encode,int * first_frame_index,int * cur_disp_index,int layer_depth,int start,int end)62*77c1e3ccSAndroid Build Coastguard Worker static inline void set_params_for_leaf_frames(
63*77c1e3ccSAndroid Build Coastguard Worker     const TWO_PASS *twopass, const TWO_PASS_FRAME *twopass_frame,
64*77c1e3ccSAndroid Build Coastguard Worker     const PRIMARY_RATE_CONTROL *p_rc, FRAME_INFO *frame_info,
65*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, int *cur_frame_idx, int *frame_ind,
66*77c1e3ccSAndroid Build Coastguard Worker     int *parallel_frame_count, int max_parallel_frames,
67*77c1e3ccSAndroid Build Coastguard Worker     int do_frame_parallel_encode, int *first_frame_index, int *cur_disp_index,
68*77c1e3ccSAndroid Build Coastguard Worker     int layer_depth, int start, int end) {
69*77c1e3ccSAndroid Build Coastguard Worker   gf_group->update_type[*frame_ind] = LF_UPDATE;
70*77c1e3ccSAndroid Build Coastguard Worker   gf_group->arf_src_offset[*frame_ind] = 0;
71*77c1e3ccSAndroid Build Coastguard Worker   gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
72*77c1e3ccSAndroid Build Coastguard Worker   gf_group->layer_depth[*frame_ind] = MAX_ARF_LAYERS;
73*77c1e3ccSAndroid Build Coastguard Worker   gf_group->frame_type[*frame_ind] = INTER_FRAME;
74*77c1e3ccSAndroid Build Coastguard Worker   gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
75*77c1e3ccSAndroid Build Coastguard Worker   gf_group->max_layer_depth = AOMMAX(gf_group->max_layer_depth, layer_depth);
76*77c1e3ccSAndroid Build Coastguard Worker   gf_group->display_idx[*frame_ind] = (*cur_disp_index);
77*77c1e3ccSAndroid Build Coastguard Worker   gf_group->arf_boost[*frame_ind] =
78*77c1e3ccSAndroid Build Coastguard Worker       av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, start,
79*77c1e3ccSAndroid Build Coastguard Worker                          end - start, 0, NULL, NULL, 0);
80*77c1e3ccSAndroid Build Coastguard Worker   ++(*cur_disp_index);
81*77c1e3ccSAndroid Build Coastguard Worker 
82*77c1e3ccSAndroid Build Coastguard Worker   // Set the level of parallelism for the LF_UPDATE frame.
83*77c1e3ccSAndroid Build Coastguard Worker   if (do_frame_parallel_encode) {
84*77c1e3ccSAndroid Build Coastguard Worker     set_frame_parallel_level(&gf_group->frame_parallel_level[*frame_ind],
85*77c1e3ccSAndroid Build Coastguard Worker                              parallel_frame_count, max_parallel_frames);
86*77c1e3ccSAndroid Build Coastguard Worker     // Set LF_UPDATE frames as non-reference frames.
87*77c1e3ccSAndroid Build Coastguard Worker     gf_group->is_frame_non_ref[*frame_ind] = true;
88*77c1e3ccSAndroid Build Coastguard Worker   }
89*77c1e3ccSAndroid Build Coastguard Worker   set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind);
90*77c1e3ccSAndroid Build Coastguard Worker 
91*77c1e3ccSAndroid Build Coastguard Worker   ++(*frame_ind);
92*77c1e3ccSAndroid Build Coastguard Worker   ++(*cur_frame_idx);
93*77c1e3ccSAndroid Build Coastguard Worker }
94*77c1e3ccSAndroid Build Coastguard Worker 
95*77c1e3ccSAndroid Build Coastguard Worker // Sets the GF_GROUP params for INTNL_OVERLAY_UPDATE frames.
set_params_for_intnl_overlay_frames(GF_GROUP * const gf_group,int * cur_frame_idx,int * frame_ind,int * first_frame_index,int * cur_disp_index,int layer_depth)96*77c1e3ccSAndroid Build Coastguard Worker static inline void set_params_for_intnl_overlay_frames(
97*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, int *cur_frame_idx, int *frame_ind,
98*77c1e3ccSAndroid Build Coastguard Worker     int *first_frame_index, int *cur_disp_index, int layer_depth) {
99*77c1e3ccSAndroid Build Coastguard Worker   gf_group->update_type[*frame_ind] = INTNL_OVERLAY_UPDATE;
100*77c1e3ccSAndroid Build Coastguard Worker   gf_group->arf_src_offset[*frame_ind] = 0;
101*77c1e3ccSAndroid Build Coastguard Worker   gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
102*77c1e3ccSAndroid Build Coastguard Worker   gf_group->layer_depth[*frame_ind] = layer_depth;
103*77c1e3ccSAndroid Build Coastguard Worker   gf_group->frame_type[*frame_ind] = INTER_FRAME;
104*77c1e3ccSAndroid Build Coastguard Worker   gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
105*77c1e3ccSAndroid Build Coastguard Worker   gf_group->display_idx[*frame_ind] = (*cur_disp_index);
106*77c1e3ccSAndroid Build Coastguard Worker   ++(*cur_disp_index);
107*77c1e3ccSAndroid Build Coastguard Worker 
108*77c1e3ccSAndroid Build Coastguard Worker   set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind);
109*77c1e3ccSAndroid Build Coastguard Worker   ++(*frame_ind);
110*77c1e3ccSAndroid Build Coastguard Worker   ++(*cur_frame_idx);
111*77c1e3ccSAndroid Build Coastguard Worker }
112*77c1e3ccSAndroid Build Coastguard Worker 
113*77c1e3ccSAndroid Build Coastguard Worker // Sets the GF_GROUP params for INTNL_ARF_UPDATE frames.
set_params_for_internal_arfs(const TWO_PASS * twopass,const TWO_PASS_FRAME * twopass_frame,const PRIMARY_RATE_CONTROL * p_rc,FRAME_INFO * frame_info,GF_GROUP * const gf_group,int * cur_frame_idx,int * frame_ind,int * parallel_frame_count,int max_parallel_frames,int do_frame_parallel_encode,int * first_frame_index,int depth_thr,int * cur_disp_idx,int layer_depth,int arf_src_offset,int offset,int f_frames,int b_frames)114*77c1e3ccSAndroid Build Coastguard Worker static inline void set_params_for_internal_arfs(
115*77c1e3ccSAndroid Build Coastguard Worker     const TWO_PASS *twopass, const TWO_PASS_FRAME *twopass_frame,
116*77c1e3ccSAndroid Build Coastguard Worker     const PRIMARY_RATE_CONTROL *p_rc, FRAME_INFO *frame_info,
117*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, int *cur_frame_idx, int *frame_ind,
118*77c1e3ccSAndroid Build Coastguard Worker     int *parallel_frame_count, int max_parallel_frames,
119*77c1e3ccSAndroid Build Coastguard Worker     int do_frame_parallel_encode, int *first_frame_index, int depth_thr,
120*77c1e3ccSAndroid Build Coastguard Worker     int *cur_disp_idx, int layer_depth, int arf_src_offset, int offset,
121*77c1e3ccSAndroid Build Coastguard Worker     int f_frames, int b_frames) {
122*77c1e3ccSAndroid Build Coastguard Worker   gf_group->update_type[*frame_ind] = INTNL_ARF_UPDATE;
123*77c1e3ccSAndroid Build Coastguard Worker   gf_group->arf_src_offset[*frame_ind] = arf_src_offset;
124*77c1e3ccSAndroid Build Coastguard Worker   gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
125*77c1e3ccSAndroid Build Coastguard Worker   gf_group->layer_depth[*frame_ind] = layer_depth;
126*77c1e3ccSAndroid Build Coastguard Worker   gf_group->frame_type[*frame_ind] = INTER_FRAME;
127*77c1e3ccSAndroid Build Coastguard Worker   gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
128*77c1e3ccSAndroid Build Coastguard Worker   gf_group->display_idx[*frame_ind] =
129*77c1e3ccSAndroid Build Coastguard Worker       (*cur_disp_idx) + gf_group->arf_src_offset[*frame_ind];
130*77c1e3ccSAndroid Build Coastguard Worker   gf_group->arf_boost[*frame_ind] =
131*77c1e3ccSAndroid Build Coastguard Worker       av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, offset,
132*77c1e3ccSAndroid Build Coastguard Worker                          f_frames, b_frames, NULL, NULL, 0);
133*77c1e3ccSAndroid Build Coastguard Worker 
134*77c1e3ccSAndroid Build Coastguard Worker   if (do_frame_parallel_encode) {
135*77c1e3ccSAndroid Build Coastguard Worker     if (depth_thr != INT_MAX) {
136*77c1e3ccSAndroid Build Coastguard Worker       assert(depth_thr == 3 || depth_thr == 4);
137*77c1e3ccSAndroid Build Coastguard Worker       assert(IMPLIES(depth_thr == 3, layer_depth == 4));
138*77c1e3ccSAndroid Build Coastguard Worker       assert(IMPLIES(depth_thr == 4, layer_depth == 5));
139*77c1e3ccSAndroid Build Coastguard Worker       // Set frame_parallel_level of the first frame in the given layer to 1.
140*77c1e3ccSAndroid Build Coastguard Worker       if (gf_group->layer_depth[(*frame_ind) - 1] != layer_depth) {
141*77c1e3ccSAndroid Build Coastguard Worker         gf_group->frame_parallel_level[*frame_ind] = 1;
142*77c1e3ccSAndroid Build Coastguard Worker       } else {
143*77c1e3ccSAndroid Build Coastguard Worker         // Set frame_parallel_level of the consecutive frame in the same given
144*77c1e3ccSAndroid Build Coastguard Worker         // layer to 2.
145*77c1e3ccSAndroid Build Coastguard Worker         assert(gf_group->frame_parallel_level[(*frame_ind) - 1] == 1);
146*77c1e3ccSAndroid Build Coastguard Worker         gf_group->frame_parallel_level[*frame_ind] = 2;
147*77c1e3ccSAndroid Build Coastguard Worker         // Store the display order hints of the past 2 INTNL_ARF_UPDATE
148*77c1e3ccSAndroid Build Coastguard Worker         // frames which would not have been displayed at the time of the encode
149*77c1e3ccSAndroid Build Coastguard Worker         // of current frame.
150*77c1e3ccSAndroid Build Coastguard Worker         gf_group->skip_frame_refresh[*frame_ind][0] =
151*77c1e3ccSAndroid Build Coastguard Worker             gf_group->display_idx[(*frame_ind) - 1];
152*77c1e3ccSAndroid Build Coastguard Worker         gf_group->skip_frame_refresh[*frame_ind][1] =
153*77c1e3ccSAndroid Build Coastguard Worker             gf_group->display_idx[(*frame_ind) - 2];
154*77c1e3ccSAndroid Build Coastguard Worker         // Set the display_idx of frame_parallel_level 1 frame in
155*77c1e3ccSAndroid Build Coastguard Worker         // gf_group->skip_frame_as_ref.
156*77c1e3ccSAndroid Build Coastguard Worker         gf_group->skip_frame_as_ref[*frame_ind] =
157*77c1e3ccSAndroid Build Coastguard Worker             gf_group->display_idx[(*frame_ind) - 1];
158*77c1e3ccSAndroid Build Coastguard Worker       }
159*77c1e3ccSAndroid Build Coastguard Worker     }
160*77c1e3ccSAndroid Build Coastguard Worker     // If max_parallel_frames is not exceeded and if the frame will not be
161*77c1e3ccSAndroid Build Coastguard Worker     // temporally filtered, encode the next internal ARF frame in parallel.
162*77c1e3ccSAndroid Build Coastguard Worker     if (*parallel_frame_count > 1 &&
163*77c1e3ccSAndroid Build Coastguard Worker         *parallel_frame_count <= max_parallel_frames) {
164*77c1e3ccSAndroid Build Coastguard Worker       if (gf_group->arf_src_offset[*frame_ind] < TF_LOOKAHEAD_IDX_THR)
165*77c1e3ccSAndroid Build Coastguard Worker         gf_group->frame_parallel_level[*frame_ind] = 2;
166*77c1e3ccSAndroid Build Coastguard Worker       *parallel_frame_count = 1;
167*77c1e3ccSAndroid Build Coastguard Worker     }
168*77c1e3ccSAndroid Build Coastguard Worker   }
169*77c1e3ccSAndroid Build Coastguard Worker   set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind);
170*77c1e3ccSAndroid Build Coastguard Worker   ++(*frame_ind);
171*77c1e3ccSAndroid Build Coastguard Worker }
172*77c1e3ccSAndroid Build Coastguard Worker 
173*77c1e3ccSAndroid Build Coastguard Worker // Set parameters for frames between 'start' and 'end' (excluding both).
set_multi_layer_params_for_fp(const TWO_PASS * twopass,const TWO_PASS_FRAME * twopass_frame,GF_GROUP * const gf_group,const PRIMARY_RATE_CONTROL * p_rc,RATE_CONTROL * rc,FRAME_INFO * frame_info,int start,int end,int * cur_frame_idx,int * frame_ind,int * parallel_frame_count,int max_parallel_frames,int do_frame_parallel_encode,int * first_frame_index,int depth_thr,int * cur_disp_idx,int layer_depth)174*77c1e3ccSAndroid Build Coastguard Worker static void set_multi_layer_params_for_fp(
175*77c1e3ccSAndroid Build Coastguard Worker     const TWO_PASS *twopass, const TWO_PASS_FRAME *twopass_frame,
176*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, const PRIMARY_RATE_CONTROL *p_rc,
177*77c1e3ccSAndroid Build Coastguard Worker     RATE_CONTROL *rc, FRAME_INFO *frame_info, int start, int end,
178*77c1e3ccSAndroid Build Coastguard Worker     int *cur_frame_idx, int *frame_ind, int *parallel_frame_count,
179*77c1e3ccSAndroid Build Coastguard Worker     int max_parallel_frames, int do_frame_parallel_encode,
180*77c1e3ccSAndroid Build Coastguard Worker     int *first_frame_index, int depth_thr, int *cur_disp_idx, int layer_depth) {
181*77c1e3ccSAndroid Build Coastguard Worker   const int num_frames_to_process = end - start;
182*77c1e3ccSAndroid Build Coastguard Worker 
183*77c1e3ccSAndroid Build Coastguard Worker   // Either we are at the last level of the pyramid, or we don't have enough
184*77c1e3ccSAndroid Build Coastguard Worker   // frames between 'l' and 'r' to create one more level.
185*77c1e3ccSAndroid Build Coastguard Worker   if (layer_depth > gf_group->max_layer_depth_allowed ||
186*77c1e3ccSAndroid Build Coastguard Worker       num_frames_to_process < 3) {
187*77c1e3ccSAndroid Build Coastguard Worker     // Leaf nodes.
188*77c1e3ccSAndroid Build Coastguard Worker     while (start < end) {
189*77c1e3ccSAndroid Build Coastguard Worker       set_params_for_leaf_frames(twopass, twopass_frame, p_rc, frame_info,
190*77c1e3ccSAndroid Build Coastguard Worker                                  gf_group, cur_frame_idx, frame_ind,
191*77c1e3ccSAndroid Build Coastguard Worker                                  parallel_frame_count, max_parallel_frames,
192*77c1e3ccSAndroid Build Coastguard Worker                                  do_frame_parallel_encode, first_frame_index,
193*77c1e3ccSAndroid Build Coastguard Worker                                  cur_disp_idx, layer_depth, start, end);
194*77c1e3ccSAndroid Build Coastguard Worker       ++start;
195*77c1e3ccSAndroid Build Coastguard Worker     }
196*77c1e3ccSAndroid Build Coastguard Worker   } else {
197*77c1e3ccSAndroid Build Coastguard Worker     const int m = (start + end - 1) / 2;
198*77c1e3ccSAndroid Build Coastguard Worker 
199*77c1e3ccSAndroid Build Coastguard Worker     // Internal ARF.
200*77c1e3ccSAndroid Build Coastguard Worker     int arf_src_offset = m - start;
201*77c1e3ccSAndroid Build Coastguard Worker     set_params_for_internal_arfs(
202*77c1e3ccSAndroid Build Coastguard Worker         twopass, twopass_frame, p_rc, frame_info, gf_group, cur_frame_idx,
203*77c1e3ccSAndroid Build Coastguard Worker         frame_ind, parallel_frame_count, max_parallel_frames,
204*77c1e3ccSAndroid Build Coastguard Worker         do_frame_parallel_encode, first_frame_index, INT_MAX, cur_disp_idx,
205*77c1e3ccSAndroid Build Coastguard Worker         layer_depth, arf_src_offset, m, end - m, m - start);
206*77c1e3ccSAndroid Build Coastguard Worker 
207*77c1e3ccSAndroid Build Coastguard Worker     // If encode reordering is enabled, configure the multi-layers accordingly
208*77c1e3ccSAndroid Build Coastguard Worker     // and return. For e.g., the encode order for gf-interval 16 after
209*77c1e3ccSAndroid Build Coastguard Worker     // reordering would be 0-> 16-> 8-> 4-> 2-> 6-> 1-> 3-> 5-> 7-> 12-> 10->
210*77c1e3ccSAndroid Build Coastguard Worker     // 14-> 9-> 11-> 13-> 15.
211*77c1e3ccSAndroid Build Coastguard Worker     if (layer_depth >= depth_thr) {
212*77c1e3ccSAndroid Build Coastguard Worker       int m1 = (m + start - 1) / 2;
213*77c1e3ccSAndroid Build Coastguard Worker       int m2 = (m + 1 + end) / 2;
214*77c1e3ccSAndroid Build Coastguard Worker       int arf_src_offsets[2] = { m1 - start, m2 - start };
215*77c1e3ccSAndroid Build Coastguard Worker       // Parameters to compute arf_boost.
216*77c1e3ccSAndroid Build Coastguard Worker       int offset[2] = { m1, m2 };
217*77c1e3ccSAndroid Build Coastguard Worker       int f_frames[2] = { m - m1, end - m2 };
218*77c1e3ccSAndroid Build Coastguard Worker       int b_frames[2] = { m1 - start, m2 - (m + 1) };
219*77c1e3ccSAndroid Build Coastguard Worker 
220*77c1e3ccSAndroid Build Coastguard Worker       // Set GF_GROUP params for INTNL_ARF_UPDATE frames which are reordered.
221*77c1e3ccSAndroid Build Coastguard Worker       for (int i = 0; i < 2; i++) {
222*77c1e3ccSAndroid Build Coastguard Worker         set_params_for_internal_arfs(
223*77c1e3ccSAndroid Build Coastguard Worker             twopass, twopass_frame, p_rc, frame_info, gf_group, cur_frame_idx,
224*77c1e3ccSAndroid Build Coastguard Worker             frame_ind, parallel_frame_count, max_parallel_frames,
225*77c1e3ccSAndroid Build Coastguard Worker             do_frame_parallel_encode, first_frame_index, depth_thr,
226*77c1e3ccSAndroid Build Coastguard Worker             cur_disp_idx, layer_depth + 1, arf_src_offsets[i], offset[i],
227*77c1e3ccSAndroid Build Coastguard Worker             f_frames[i], b_frames[i]);
228*77c1e3ccSAndroid Build Coastguard Worker       }
229*77c1e3ccSAndroid Build Coastguard Worker 
230*77c1e3ccSAndroid Build Coastguard Worker       // Initialize the start and end indices to configure LF_UPDATE frames.
231*77c1e3ccSAndroid Build Coastguard Worker       int start_idx[4] = { start, m1 + 1, m + 1, end - 1 };
232*77c1e3ccSAndroid Build Coastguard Worker       int end_idx[4] = { m1, m, m2, end };
233*77c1e3ccSAndroid Build Coastguard Worker       int layer_depth_for_intnl_overlay[4] = { layer_depth + 1, layer_depth,
234*77c1e3ccSAndroid Build Coastguard Worker                                                layer_depth + 1, INVALID_IDX };
235*77c1e3ccSAndroid Build Coastguard Worker 
236*77c1e3ccSAndroid Build Coastguard Worker       // Set GF_GROUP params for the rest of LF_UPDATE and INTNL_OVERLAY_UPDATE
237*77c1e3ccSAndroid Build Coastguard Worker       // frames after reordering.
238*77c1e3ccSAndroid Build Coastguard Worker       for (int i = 0; i < 4; i++) {
239*77c1e3ccSAndroid Build Coastguard Worker         set_multi_layer_params_for_fp(
240*77c1e3ccSAndroid Build Coastguard Worker             twopass, twopass_frame, gf_group, p_rc, rc, frame_info,
241*77c1e3ccSAndroid Build Coastguard Worker             start_idx[i], end_idx[i], cur_frame_idx, frame_ind,
242*77c1e3ccSAndroid Build Coastguard Worker             parallel_frame_count, max_parallel_frames, do_frame_parallel_encode,
243*77c1e3ccSAndroid Build Coastguard Worker             first_frame_index, depth_thr, cur_disp_idx, layer_depth + 2);
244*77c1e3ccSAndroid Build Coastguard Worker         if (layer_depth_for_intnl_overlay[i] != INVALID_IDX)
245*77c1e3ccSAndroid Build Coastguard Worker           set_params_for_intnl_overlay_frames(
246*77c1e3ccSAndroid Build Coastguard Worker               gf_group, cur_frame_idx, frame_ind, first_frame_index,
247*77c1e3ccSAndroid Build Coastguard Worker               cur_disp_idx, layer_depth_for_intnl_overlay[i]);
248*77c1e3ccSAndroid Build Coastguard Worker       }
249*77c1e3ccSAndroid Build Coastguard Worker       return;
250*77c1e3ccSAndroid Build Coastguard Worker     }
251*77c1e3ccSAndroid Build Coastguard Worker 
252*77c1e3ccSAndroid Build Coastguard Worker     // Frames displayed before this internal ARF.
253*77c1e3ccSAndroid Build Coastguard Worker     set_multi_layer_params_for_fp(
254*77c1e3ccSAndroid Build Coastguard Worker         twopass, twopass_frame, gf_group, p_rc, rc, frame_info, start, m,
255*77c1e3ccSAndroid Build Coastguard Worker         cur_frame_idx, frame_ind, parallel_frame_count, max_parallel_frames,
256*77c1e3ccSAndroid Build Coastguard Worker         do_frame_parallel_encode, first_frame_index, depth_thr, cur_disp_idx,
257*77c1e3ccSAndroid Build Coastguard Worker         layer_depth + 1);
258*77c1e3ccSAndroid Build Coastguard Worker 
259*77c1e3ccSAndroid Build Coastguard Worker     // Overlay for internal ARF.
260*77c1e3ccSAndroid Build Coastguard Worker     set_params_for_intnl_overlay_frames(gf_group, cur_frame_idx, frame_ind,
261*77c1e3ccSAndroid Build Coastguard Worker                                         first_frame_index, cur_disp_idx,
262*77c1e3ccSAndroid Build Coastguard Worker                                         layer_depth);
263*77c1e3ccSAndroid Build Coastguard Worker 
264*77c1e3ccSAndroid Build Coastguard Worker     // Frames displayed after this internal ARF.
265*77c1e3ccSAndroid Build Coastguard Worker     set_multi_layer_params_for_fp(
266*77c1e3ccSAndroid Build Coastguard Worker         twopass, twopass_frame, gf_group, p_rc, rc, frame_info, m + 1, end,
267*77c1e3ccSAndroid Build Coastguard Worker         cur_frame_idx, frame_ind, parallel_frame_count, max_parallel_frames,
268*77c1e3ccSAndroid Build Coastguard Worker         do_frame_parallel_encode, first_frame_index, depth_thr, cur_disp_idx,
269*77c1e3ccSAndroid Build Coastguard Worker         layer_depth + 1);
270*77c1e3ccSAndroid Build Coastguard Worker   }
271*77c1e3ccSAndroid Build Coastguard Worker }
272*77c1e3ccSAndroid Build Coastguard Worker 
273*77c1e3ccSAndroid Build Coastguard Worker // Structure for bookkeeping start, end and display indices to configure
274*77c1e3ccSAndroid Build Coastguard Worker // INTNL_ARF_UPDATE frames.
275*77c1e3ccSAndroid Build Coastguard Worker typedef struct {
276*77c1e3ccSAndroid Build Coastguard Worker   int start;
277*77c1e3ccSAndroid Build Coastguard Worker   int end;
278*77c1e3ccSAndroid Build Coastguard Worker   int display_index;
279*77c1e3ccSAndroid Build Coastguard Worker } FRAME_REORDER_INFO;
280*77c1e3ccSAndroid Build Coastguard Worker 
281*77c1e3ccSAndroid Build Coastguard Worker // Updates the stats required to configure the GF_GROUP.
fill_arf_frame_stats(FRAME_REORDER_INFO * arf_frame_stats,int arf_frame_index,int display_idx,int start,int end)282*77c1e3ccSAndroid Build Coastguard Worker static inline void fill_arf_frame_stats(FRAME_REORDER_INFO *arf_frame_stats,
283*77c1e3ccSAndroid Build Coastguard Worker                                         int arf_frame_index, int display_idx,
284*77c1e3ccSAndroid Build Coastguard Worker                                         int start, int end) {
285*77c1e3ccSAndroid Build Coastguard Worker   arf_frame_stats[arf_frame_index].start = start;
286*77c1e3ccSAndroid Build Coastguard Worker   arf_frame_stats[arf_frame_index].end = end;
287*77c1e3ccSAndroid Build Coastguard Worker   arf_frame_stats[arf_frame_index].display_index = display_idx;
288*77c1e3ccSAndroid Build Coastguard Worker }
289*77c1e3ccSAndroid Build Coastguard Worker 
290*77c1e3ccSAndroid Build Coastguard Worker // Sets GF_GROUP params for INTNL_ARF_UPDATE frames. Also populates
291*77c1e3ccSAndroid Build Coastguard Worker // doh_gf_index_map and arf_frame_stats.
set_params_for_internal_arfs_in_gf14(GF_GROUP * const gf_group,FRAME_REORDER_INFO * arf_frame_stats,int * cur_frame_idx,int * cur_disp_idx,int * frame_ind,int * count_arf_frames,int * doh_gf_index_map,int start,int end,int layer_depth,int layer_with_parallel_encodes)292*77c1e3ccSAndroid Build Coastguard Worker static inline void set_params_for_internal_arfs_in_gf14(
293*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, FRAME_REORDER_INFO *arf_frame_stats,
294*77c1e3ccSAndroid Build Coastguard Worker     int *cur_frame_idx, int *cur_disp_idx, int *frame_ind,
295*77c1e3ccSAndroid Build Coastguard Worker     int *count_arf_frames, int *doh_gf_index_map, int start, int end,
296*77c1e3ccSAndroid Build Coastguard Worker     int layer_depth, int layer_with_parallel_encodes) {
297*77c1e3ccSAndroid Build Coastguard Worker   int index = (start + end - 1) / 2;
298*77c1e3ccSAndroid Build Coastguard Worker   gf_group->update_type[*frame_ind] = INTNL_ARF_UPDATE;
299*77c1e3ccSAndroid Build Coastguard Worker   gf_group->arf_src_offset[*frame_ind] = index - 1;
300*77c1e3ccSAndroid Build Coastguard Worker   gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
301*77c1e3ccSAndroid Build Coastguard Worker   gf_group->layer_depth[*frame_ind] = layer_depth;
302*77c1e3ccSAndroid Build Coastguard Worker   gf_group->frame_type[*frame_ind] = INTER_FRAME;
303*77c1e3ccSAndroid Build Coastguard Worker   gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
304*77c1e3ccSAndroid Build Coastguard Worker   gf_group->display_idx[*frame_ind] =
305*77c1e3ccSAndroid Build Coastguard Worker       (*cur_disp_idx) + gf_group->arf_src_offset[*frame_ind];
306*77c1e3ccSAndroid Build Coastguard Worker 
307*77c1e3ccSAndroid Build Coastguard Worker   // Update the display index of the current frame with its gf index.
308*77c1e3ccSAndroid Build Coastguard Worker   doh_gf_index_map[index] = *frame_ind;
309*77c1e3ccSAndroid Build Coastguard Worker   if (layer_with_parallel_encodes) {
310*77c1e3ccSAndroid Build Coastguard Worker     assert(layer_depth == 4);
311*77c1e3ccSAndroid Build Coastguard Worker     // Set frame_parallel_level of the first frame in the given layer depth
312*77c1e3ccSAndroid Build Coastguard Worker     // to 1.
313*77c1e3ccSAndroid Build Coastguard Worker     if (gf_group->layer_depth[(*frame_ind) - 1] != layer_depth) {
314*77c1e3ccSAndroid Build Coastguard Worker       gf_group->frame_parallel_level[*frame_ind] = 1;
315*77c1e3ccSAndroid Build Coastguard Worker     } else {
316*77c1e3ccSAndroid Build Coastguard Worker       // Set frame_parallel_level of the consecutive frame in the same given
317*77c1e3ccSAndroid Build Coastguard Worker       // layer depth to 2.
318*77c1e3ccSAndroid Build Coastguard Worker       assert(gf_group->frame_parallel_level[(*frame_ind) - 1] == 1);
319*77c1e3ccSAndroid Build Coastguard Worker       gf_group->frame_parallel_level[*frame_ind] = 2;
320*77c1e3ccSAndroid Build Coastguard Worker       // Set the display_idx of frame_parallel_level 1 frame in
321*77c1e3ccSAndroid Build Coastguard Worker       // gf_group->skip_frame_as_ref.
322*77c1e3ccSAndroid Build Coastguard Worker       gf_group->skip_frame_as_ref[*frame_ind] =
323*77c1e3ccSAndroid Build Coastguard Worker           gf_group->display_idx[(*frame_ind) - 1];
324*77c1e3ccSAndroid Build Coastguard Worker     }
325*77c1e3ccSAndroid Build Coastguard Worker   }
326*77c1e3ccSAndroid Build Coastguard Worker   ++(*frame_ind);
327*77c1e3ccSAndroid Build Coastguard Worker 
328*77c1e3ccSAndroid Build Coastguard Worker   // Update arf_frame_stats.
329*77c1e3ccSAndroid Build Coastguard Worker   fill_arf_frame_stats(arf_frame_stats, *count_arf_frames, index, start, end);
330*77c1e3ccSAndroid Build Coastguard Worker   ++(*count_arf_frames);
331*77c1e3ccSAndroid Build Coastguard Worker }
332*77c1e3ccSAndroid Build Coastguard Worker 
333*77c1e3ccSAndroid Build Coastguard Worker // Sets GF_GROUP params for all INTNL_ARF_UPDATE frames in the given layer
334*77c1e3ccSAndroid Build Coastguard Worker // dpeth.
set_params_for_cur_layer_frames(GF_GROUP * const gf_group,FRAME_REORDER_INFO * arf_frame_stats,int * cur_frame_idx,int * cur_disp_idx,int * frame_ind,int * count_arf_frames,int * doh_gf_index_map,int num_dir,int node_start,int node_end,int layer_depth)335*77c1e3ccSAndroid Build Coastguard Worker static inline void set_params_for_cur_layer_frames(
336*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, FRAME_REORDER_INFO *arf_frame_stats,
337*77c1e3ccSAndroid Build Coastguard Worker     int *cur_frame_idx, int *cur_disp_idx, int *frame_ind,
338*77c1e3ccSAndroid Build Coastguard Worker     int *count_arf_frames, int *doh_gf_index_map, int num_dir, int node_start,
339*77c1e3ccSAndroid Build Coastguard Worker     int node_end, int layer_depth) {
340*77c1e3ccSAndroid Build Coastguard Worker   assert(num_dir < 3);
341*77c1e3ccSAndroid Build Coastguard Worker   int start, end;
342*77c1e3ccSAndroid Build Coastguard Worker   // Iterate through the nodes in the previous layer depth.
343*77c1e3ccSAndroid Build Coastguard Worker   for (int i = node_start; i < node_end; i++) {
344*77c1e3ccSAndroid Build Coastguard Worker     // For each node, check if a frame can be coded as INTNL_ARF_UPDATE frame on
345*77c1e3ccSAndroid Build Coastguard Worker     // either direction.
346*77c1e3ccSAndroid Build Coastguard Worker     for (int dir = 0; dir < num_dir; dir++) {
347*77c1e3ccSAndroid Build Coastguard Worker       // Checks for a frame to the left of current node.
348*77c1e3ccSAndroid Build Coastguard Worker       if (dir == 0) {
349*77c1e3ccSAndroid Build Coastguard Worker         start = arf_frame_stats[i].start;
350*77c1e3ccSAndroid Build Coastguard Worker         end = arf_frame_stats[i].display_index;
351*77c1e3ccSAndroid Build Coastguard Worker       } else {
352*77c1e3ccSAndroid Build Coastguard Worker         // Checks for a frame to the right of current node.
353*77c1e3ccSAndroid Build Coastguard Worker         start = arf_frame_stats[i].display_index + 1;
354*77c1e3ccSAndroid Build Coastguard Worker         end = arf_frame_stats[i].end;
355*77c1e3ccSAndroid Build Coastguard Worker       }
356*77c1e3ccSAndroid Build Coastguard Worker       const int num_frames_to_process = end - start;
357*77c1e3ccSAndroid Build Coastguard Worker       // Checks if a frame can be coded as INTNL_ARF_UPDATE frame. If
358*77c1e3ccSAndroid Build Coastguard Worker       // num_frames_to_process is less than 3, then there are not enough frames
359*77c1e3ccSAndroid Build Coastguard Worker       // between 'start' and 'end' to create another level.
360*77c1e3ccSAndroid Build Coastguard Worker       if (num_frames_to_process >= 3) {
361*77c1e3ccSAndroid Build Coastguard Worker         // Flag to indicate the lower layer depths for which parallel encoding
362*77c1e3ccSAndroid Build Coastguard Worker         // is enabled. Currently enabled for layer 4 frames.
363*77c1e3ccSAndroid Build Coastguard Worker         int layer_with_parallel_encodes = layer_depth == 4;
364*77c1e3ccSAndroid Build Coastguard Worker         set_params_for_internal_arfs_in_gf14(
365*77c1e3ccSAndroid Build Coastguard Worker             gf_group, arf_frame_stats, cur_frame_idx, cur_disp_idx, frame_ind,
366*77c1e3ccSAndroid Build Coastguard Worker             count_arf_frames, doh_gf_index_map, start, end, layer_depth,
367*77c1e3ccSAndroid Build Coastguard Worker             layer_with_parallel_encodes);
368*77c1e3ccSAndroid Build Coastguard Worker       }
369*77c1e3ccSAndroid Build Coastguard Worker     }
370*77c1e3ccSAndroid Build Coastguard Worker   }
371*77c1e3ccSAndroid Build Coastguard Worker }
372*77c1e3ccSAndroid Build Coastguard Worker 
373*77c1e3ccSAndroid Build Coastguard Worker // Configures multi-layers of the GF_GROUP when consecutive encode of frames in
374*77c1e3ccSAndroid Build Coastguard Worker // the same layer depth is enbaled.
set_multi_layer_params_for_gf14(const TWO_PASS * twopass,const TWO_PASS_FRAME * twopass_frame,const PRIMARY_RATE_CONTROL * p_rc,FRAME_INFO * frame_info,GF_GROUP * const gf_group,FRAME_REORDER_INFO * arf_frame_stats,int * cur_frame_idx,int * frame_ind,int * count_arf_frames,int * doh_gf_index_map,int * parallel_frame_count,int * first_frame_index,int * cur_disp_index,int gf_interval,int layer_depth,int max_parallel_frames)375*77c1e3ccSAndroid Build Coastguard Worker static inline void set_multi_layer_params_for_gf14(
376*77c1e3ccSAndroid Build Coastguard Worker     const TWO_PASS *twopass, const TWO_PASS_FRAME *twopass_frame,
377*77c1e3ccSAndroid Build Coastguard Worker     const PRIMARY_RATE_CONTROL *p_rc, FRAME_INFO *frame_info,
378*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, FRAME_REORDER_INFO *arf_frame_stats,
379*77c1e3ccSAndroid Build Coastguard Worker     int *cur_frame_idx, int *frame_ind, int *count_arf_frames,
380*77c1e3ccSAndroid Build Coastguard Worker     int *doh_gf_index_map, int *parallel_frame_count, int *first_frame_index,
381*77c1e3ccSAndroid Build Coastguard Worker     int *cur_disp_index, int gf_interval, int layer_depth,
382*77c1e3ccSAndroid Build Coastguard Worker     int max_parallel_frames) {
383*77c1e3ccSAndroid Build Coastguard Worker   assert(layer_depth == 2);
384*77c1e3ccSAndroid Build Coastguard Worker   assert(gf_group->max_layer_depth_allowed >= 4);
385*77c1e3ccSAndroid Build Coastguard Worker   int layer, node_start, node_end = 0;
386*77c1e3ccSAndroid Build Coastguard Worker   // Maximum layer depth excluding LF_UPDATE frames is 4 since applicable only
387*77c1e3ccSAndroid Build Coastguard Worker   // for gf-interval 14.
388*77c1e3ccSAndroid Build Coastguard Worker   const int max_layer_depth = 4;
389*77c1e3ccSAndroid Build Coastguard Worker   // Iterate through each layer depth starting from 2 till 'max_layer_depth'.
390*77c1e3ccSAndroid Build Coastguard Worker   for (layer = layer_depth; layer <= max_layer_depth; layer++) {
391*77c1e3ccSAndroid Build Coastguard Worker     // 'node_start' and 'node_end' indicate the number of nodes from the
392*77c1e3ccSAndroid Build Coastguard Worker     // previous layer depth to be considered. It also corresponds to the indices
393*77c1e3ccSAndroid Build Coastguard Worker     // of arf_frame_stats.
394*77c1e3ccSAndroid Build Coastguard Worker     node_start = node_end;
395*77c1e3ccSAndroid Build Coastguard Worker     node_end = (*count_arf_frames);
396*77c1e3ccSAndroid Build Coastguard Worker     // 'num_dir' indicates the number of directions to traverse w.r.t. a given
397*77c1e3ccSAndroid Build Coastguard Worker     // node in order to choose an INTNL_ARF_UPDATE frame. Layer depth 2 would
398*77c1e3ccSAndroid Build Coastguard Worker     // have only one frame and hence needs to traverse only in the left
399*77c1e3ccSAndroid Build Coastguard Worker     // direction w.r.t the node in the previous layer.
400*77c1e3ccSAndroid Build Coastguard Worker     int num_dir = layer == 2 ? 1 : 2;
401*77c1e3ccSAndroid Build Coastguard Worker     set_params_for_cur_layer_frames(gf_group, arf_frame_stats, cur_frame_idx,
402*77c1e3ccSAndroid Build Coastguard Worker                                     cur_disp_index, frame_ind, count_arf_frames,
403*77c1e3ccSAndroid Build Coastguard Worker                                     doh_gf_index_map, num_dir, node_start,
404*77c1e3ccSAndroid Build Coastguard Worker                                     node_end, layer);
405*77c1e3ccSAndroid Build Coastguard Worker   }
406*77c1e3ccSAndroid Build Coastguard Worker 
407*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 1; i < gf_interval; i++) {
408*77c1e3ccSAndroid Build Coastguard Worker     // Since doh_gf_index_map is already populated for all INTNL_ARF_UPDATE
409*77c1e3ccSAndroid Build Coastguard Worker     // frames in the GF_GROUP, any frame with INVALID_IDX would correspond to an
410*77c1e3ccSAndroid Build Coastguard Worker     // LF_UPDATE frame.
411*77c1e3ccSAndroid Build Coastguard Worker     if (doh_gf_index_map[i] == INVALID_IDX) {
412*77c1e3ccSAndroid Build Coastguard Worker       // LF_UPDATE frames.
413*77c1e3ccSAndroid Build Coastguard Worker       // TODO(Remya): Correct start and end parameters passed to
414*77c1e3ccSAndroid Build Coastguard Worker       // set_params_for_leaf_frames() once encode reordering for gf-interval 14
415*77c1e3ccSAndroid Build Coastguard Worker       // is enbaled for parallel encode of lower layer frames.
416*77c1e3ccSAndroid Build Coastguard Worker       set_params_for_leaf_frames(
417*77c1e3ccSAndroid Build Coastguard Worker           twopass, twopass_frame, p_rc, frame_info, gf_group, cur_frame_idx,
418*77c1e3ccSAndroid Build Coastguard Worker           frame_ind, parallel_frame_count, max_parallel_frames, 1,
419*77c1e3ccSAndroid Build Coastguard Worker           first_frame_index, cur_disp_index, layer, 0, 0);
420*77c1e3ccSAndroid Build Coastguard Worker     } else {
421*77c1e3ccSAndroid Build Coastguard Worker       // In order to obtain the layer depths of INTNL_OVERLAY_UPDATE frames, get
422*77c1e3ccSAndroid Build Coastguard Worker       // the gf index of corresponding INTNL_ARF_UPDATE frames.
423*77c1e3ccSAndroid Build Coastguard Worker       int intnl_arf_index = doh_gf_index_map[i];
424*77c1e3ccSAndroid Build Coastguard Worker       int ld = gf_group->layer_depth[intnl_arf_index];
425*77c1e3ccSAndroid Build Coastguard Worker       set_params_for_intnl_overlay_frames(gf_group, cur_frame_idx, frame_ind,
426*77c1e3ccSAndroid Build Coastguard Worker                                           first_frame_index, cur_disp_index,
427*77c1e3ccSAndroid Build Coastguard Worker                                           ld);
428*77c1e3ccSAndroid Build Coastguard Worker     }
429*77c1e3ccSAndroid Build Coastguard Worker   }
430*77c1e3ccSAndroid Build Coastguard Worker }
431*77c1e3ccSAndroid Build Coastguard Worker 
432*77c1e3ccSAndroid Build Coastguard Worker // Set parameters for frames between 'start' and 'end' (excluding both).
set_multi_layer_params(const TWO_PASS * twopass,const TWO_PASS_FRAME * twopass_frame,GF_GROUP * const gf_group,const PRIMARY_RATE_CONTROL * p_rc,RATE_CONTROL * rc,FRAME_INFO * frame_info,int start,int end,int * cur_frame_idx,int * frame_ind,int * parallel_frame_count,int max_parallel_frames,int do_frame_parallel_encode,int * first_frame_index,int * cur_disp_idx,int layer_depth)433*77c1e3ccSAndroid Build Coastguard Worker static void set_multi_layer_params(
434*77c1e3ccSAndroid Build Coastguard Worker     const TWO_PASS *twopass, const TWO_PASS_FRAME *twopass_frame,
435*77c1e3ccSAndroid Build Coastguard Worker     GF_GROUP *const gf_group, const PRIMARY_RATE_CONTROL *p_rc,
436*77c1e3ccSAndroid Build Coastguard Worker     RATE_CONTROL *rc, FRAME_INFO *frame_info, int start, int end,
437*77c1e3ccSAndroid Build Coastguard Worker     int *cur_frame_idx, int *frame_ind, int *parallel_frame_count,
438*77c1e3ccSAndroid Build Coastguard Worker     int max_parallel_frames, int do_frame_parallel_encode,
439*77c1e3ccSAndroid Build Coastguard Worker     int *first_frame_index, int *cur_disp_idx, int layer_depth) {
440*77c1e3ccSAndroid Build Coastguard Worker   const int num_frames_to_process = end - start;
441*77c1e3ccSAndroid Build Coastguard Worker 
442*77c1e3ccSAndroid Build Coastguard Worker   // Either we are at the last level of the pyramid, or we don't have enough
443*77c1e3ccSAndroid Build Coastguard Worker   // frames between 'l' and 'r' to create one more level.
444*77c1e3ccSAndroid Build Coastguard Worker   if (layer_depth > gf_group->max_layer_depth_allowed ||
445*77c1e3ccSAndroid Build Coastguard Worker       num_frames_to_process < 3) {
446*77c1e3ccSAndroid Build Coastguard Worker     // Leaf nodes.
447*77c1e3ccSAndroid Build Coastguard Worker     while (start < end) {
448*77c1e3ccSAndroid Build Coastguard Worker       gf_group->update_type[*frame_ind] = LF_UPDATE;
449*77c1e3ccSAndroid Build Coastguard Worker       gf_group->arf_src_offset[*frame_ind] = 0;
450*77c1e3ccSAndroid Build Coastguard Worker       gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
451*77c1e3ccSAndroid Build Coastguard Worker       gf_group->display_idx[*frame_ind] = *cur_disp_idx;
452*77c1e3ccSAndroid Build Coastguard Worker       gf_group->layer_depth[*frame_ind] = MAX_ARF_LAYERS;
453*77c1e3ccSAndroid Build Coastguard Worker       gf_group->arf_boost[*frame_ind] =
454*77c1e3ccSAndroid Build Coastguard Worker           av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, start,
455*77c1e3ccSAndroid Build Coastguard Worker                              end - start, 0, NULL, NULL, 0);
456*77c1e3ccSAndroid Build Coastguard Worker       gf_group->frame_type[*frame_ind] = INTER_FRAME;
457*77c1e3ccSAndroid Build Coastguard Worker       gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
458*77c1e3ccSAndroid Build Coastguard Worker       gf_group->max_layer_depth =
459*77c1e3ccSAndroid Build Coastguard Worker           AOMMAX(gf_group->max_layer_depth, layer_depth);
460*77c1e3ccSAndroid Build Coastguard Worker       // Set the level of parallelism for the LF_UPDATE frame.
461*77c1e3ccSAndroid Build Coastguard Worker       if (do_frame_parallel_encode) {
462*77c1e3ccSAndroid Build Coastguard Worker         set_frame_parallel_level(&gf_group->frame_parallel_level[*frame_ind],
463*77c1e3ccSAndroid Build Coastguard Worker                                  parallel_frame_count, max_parallel_frames);
464*77c1e3ccSAndroid Build Coastguard Worker         // Set LF_UPDATE frames as non-reference frames.
465*77c1e3ccSAndroid Build Coastguard Worker         gf_group->is_frame_non_ref[*frame_ind] = true;
466*77c1e3ccSAndroid Build Coastguard Worker       }
467*77c1e3ccSAndroid Build Coastguard Worker       set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind);
468*77c1e3ccSAndroid Build Coastguard Worker       ++(*frame_ind);
469*77c1e3ccSAndroid Build Coastguard Worker       ++(*cur_frame_idx);
470*77c1e3ccSAndroid Build Coastguard Worker       ++(*cur_disp_idx);
471*77c1e3ccSAndroid Build Coastguard Worker       ++start;
472*77c1e3ccSAndroid Build Coastguard Worker     }
473*77c1e3ccSAndroid Build Coastguard Worker   } else {
474*77c1e3ccSAndroid Build Coastguard Worker     const int m = (start + end - 1) / 2;
475*77c1e3ccSAndroid Build Coastguard Worker 
476*77c1e3ccSAndroid Build Coastguard Worker     // Internal ARF.
477*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[*frame_ind] = INTNL_ARF_UPDATE;
478*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_src_offset[*frame_ind] = m - start;
479*77c1e3ccSAndroid Build Coastguard Worker     gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
480*77c1e3ccSAndroid Build Coastguard Worker     gf_group->display_idx[*frame_ind] =
481*77c1e3ccSAndroid Build Coastguard Worker         *cur_disp_idx + gf_group->arf_src_offset[*frame_ind];
482*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[*frame_ind] = layer_depth;
483*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[*frame_ind] = INTER_FRAME;
484*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
485*77c1e3ccSAndroid Build Coastguard Worker 
486*77c1e3ccSAndroid Build Coastguard Worker     if (do_frame_parallel_encode) {
487*77c1e3ccSAndroid Build Coastguard Worker       // If max_parallel_frames is not exceeded and if the frame will not be
488*77c1e3ccSAndroid Build Coastguard Worker       // temporally filtered, encode the next internal ARF frame in parallel.
489*77c1e3ccSAndroid Build Coastguard Worker       if (*parallel_frame_count > 1 &&
490*77c1e3ccSAndroid Build Coastguard Worker           *parallel_frame_count <= max_parallel_frames) {
491*77c1e3ccSAndroid Build Coastguard Worker         if (gf_group->arf_src_offset[*frame_ind] < TF_LOOKAHEAD_IDX_THR)
492*77c1e3ccSAndroid Build Coastguard Worker           gf_group->frame_parallel_level[*frame_ind] = 2;
493*77c1e3ccSAndroid Build Coastguard Worker         *parallel_frame_count = 1;
494*77c1e3ccSAndroid Build Coastguard Worker       }
495*77c1e3ccSAndroid Build Coastguard Worker     }
496*77c1e3ccSAndroid Build Coastguard Worker     set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind);
497*77c1e3ccSAndroid Build Coastguard Worker 
498*77c1e3ccSAndroid Build Coastguard Worker     // Get the boost factor for intermediate ARF frames.
499*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_boost[*frame_ind] =
500*77c1e3ccSAndroid Build Coastguard Worker         av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, m, end - m,
501*77c1e3ccSAndroid Build Coastguard Worker                            m - start, NULL, NULL, 0);
502*77c1e3ccSAndroid Build Coastguard Worker     ++(*frame_ind);
503*77c1e3ccSAndroid Build Coastguard Worker 
504*77c1e3ccSAndroid Build Coastguard Worker     // Frames displayed before this internal ARF.
505*77c1e3ccSAndroid Build Coastguard Worker     set_multi_layer_params(twopass, twopass_frame, gf_group, p_rc, rc,
506*77c1e3ccSAndroid Build Coastguard Worker                            frame_info, start, m, cur_frame_idx, frame_ind,
507*77c1e3ccSAndroid Build Coastguard Worker                            parallel_frame_count, max_parallel_frames,
508*77c1e3ccSAndroid Build Coastguard Worker                            do_frame_parallel_encode, first_frame_index,
509*77c1e3ccSAndroid Build Coastguard Worker                            cur_disp_idx, layer_depth + 1);
510*77c1e3ccSAndroid Build Coastguard Worker 
511*77c1e3ccSAndroid Build Coastguard Worker     // Overlay for internal ARF.
512*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[*frame_ind] = INTNL_OVERLAY_UPDATE;
513*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_src_offset[*frame_ind] = 0;
514*77c1e3ccSAndroid Build Coastguard Worker     gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx;
515*77c1e3ccSAndroid Build Coastguard Worker     gf_group->display_idx[*frame_ind] = *cur_disp_idx;
516*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_boost[*frame_ind] = 0;
517*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[*frame_ind] = layer_depth;
518*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[*frame_ind] = INTER_FRAME;
519*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE;
520*77c1e3ccSAndroid Build Coastguard Worker 
521*77c1e3ccSAndroid Build Coastguard Worker     set_src_offset(gf_group, first_frame_index, *cur_frame_idx, *frame_ind);
522*77c1e3ccSAndroid Build Coastguard Worker     ++(*frame_ind);
523*77c1e3ccSAndroid Build Coastguard Worker     ++(*cur_frame_idx);
524*77c1e3ccSAndroid Build Coastguard Worker     ++(*cur_disp_idx);
525*77c1e3ccSAndroid Build Coastguard Worker 
526*77c1e3ccSAndroid Build Coastguard Worker     // Frames displayed after this internal ARF.
527*77c1e3ccSAndroid Build Coastguard Worker     set_multi_layer_params(twopass, twopass_frame, gf_group, p_rc, rc,
528*77c1e3ccSAndroid Build Coastguard Worker                            frame_info, m + 1, end, cur_frame_idx, frame_ind,
529*77c1e3ccSAndroid Build Coastguard Worker                            parallel_frame_count, max_parallel_frames,
530*77c1e3ccSAndroid Build Coastguard Worker                            do_frame_parallel_encode, first_frame_index,
531*77c1e3ccSAndroid Build Coastguard Worker                            cur_disp_idx, layer_depth + 1);
532*77c1e3ccSAndroid Build Coastguard Worker   }
533*77c1e3ccSAndroid Build Coastguard Worker }
534*77c1e3ccSAndroid Build Coastguard Worker 
construct_multi_layer_gf_structure(AV1_COMP * cpi,TWO_PASS * twopass,GF_GROUP * const gf_group,RATE_CONTROL * rc,FRAME_INFO * const frame_info,int baseline_gf_interval,FRAME_UPDATE_TYPE first_frame_update_type)535*77c1e3ccSAndroid Build Coastguard Worker static int construct_multi_layer_gf_structure(
536*77c1e3ccSAndroid Build Coastguard Worker     AV1_COMP *cpi, TWO_PASS *twopass, GF_GROUP *const gf_group,
537*77c1e3ccSAndroid Build Coastguard Worker     RATE_CONTROL *rc, FRAME_INFO *const frame_info, int baseline_gf_interval,
538*77c1e3ccSAndroid Build Coastguard Worker     FRAME_UPDATE_TYPE first_frame_update_type) {
539*77c1e3ccSAndroid Build Coastguard Worker   PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
540*77c1e3ccSAndroid Build Coastguard Worker   // TODO(angiebird): Why do we need "-1" here?
541*77c1e3ccSAndroid Build Coastguard Worker   const int gf_interval = baseline_gf_interval - 1;
542*77c1e3ccSAndroid Build Coastguard Worker   int frame_index = 0;
543*77c1e3ccSAndroid Build Coastguard Worker   int cur_frame_index = 0;
544*77c1e3ccSAndroid Build Coastguard Worker 
545*77c1e3ccSAndroid Build Coastguard Worker   // Set the display order hint for the first frame in the GF_GROUP.
546*77c1e3ccSAndroid Build Coastguard Worker   int cur_disp_index = (first_frame_update_type == KF_UPDATE)
547*77c1e3ccSAndroid Build Coastguard Worker                            ? 0
548*77c1e3ccSAndroid Build Coastguard Worker                            : cpi->common.current_frame.frame_number;
549*77c1e3ccSAndroid Build Coastguard Worker 
550*77c1e3ccSAndroid Build Coastguard Worker   // Initialize gf_group->frame_parallel_level, gf_group->is_frame_non_ref,
551*77c1e3ccSAndroid Build Coastguard Worker   // gf_group->src_offset and gf_group->is_frame_dropped with 0.
552*77c1e3ccSAndroid Build Coastguard Worker   memset(gf_group->frame_parallel_level, 0,
553*77c1e3ccSAndroid Build Coastguard Worker          sizeof(gf_group->frame_parallel_level));
554*77c1e3ccSAndroid Build Coastguard Worker   memset(gf_group->is_frame_non_ref, 0, sizeof(gf_group->is_frame_non_ref));
555*77c1e3ccSAndroid Build Coastguard Worker   memset(gf_group->src_offset, 0, sizeof(gf_group->src_offset));
556*77c1e3ccSAndroid Build Coastguard Worker   memset(gf_group->is_frame_dropped, 0, sizeof(gf_group->is_frame_dropped));
557*77c1e3ccSAndroid Build Coastguard Worker   // Initialize gf_group->skip_frame_refresh and gf_group->skip_frame_as_ref
558*77c1e3ccSAndroid Build Coastguard Worker   // with INVALID_IDX.
559*77c1e3ccSAndroid Build Coastguard Worker   memset(gf_group->skip_frame_refresh, INVALID_IDX,
560*77c1e3ccSAndroid Build Coastguard Worker          sizeof(gf_group->skip_frame_refresh));
561*77c1e3ccSAndroid Build Coastguard Worker   memset(gf_group->skip_frame_as_ref, INVALID_IDX,
562*77c1e3ccSAndroid Build Coastguard Worker          sizeof(gf_group->skip_frame_as_ref));
563*77c1e3ccSAndroid Build Coastguard Worker 
564*77c1e3ccSAndroid Build Coastguard Worker   int kf_decomp = cpi->oxcf.kf_cfg.enable_keyframe_filtering > 1;
565*77c1e3ccSAndroid Build Coastguard Worker   // This is a patch that fixes https://crbug.com/aomedia/3163
566*77c1e3ccSAndroid Build Coastguard Worker   // enable_keyframe_filtering > 1 will introduce an extra overlay frame at
567*77c1e3ccSAndroid Build Coastguard Worker   // key frame location. However when
568*77c1e3ccSAndroid Build Coastguard Worker   // baseline_gf_interval == MAX_STATIC_GF_GROUP_LENGTH, we can't
569*77c1e3ccSAndroid Build Coastguard Worker   // afford to have an extra overlay frame. Otherwise, the gf_group->size will
570*77c1e3ccSAndroid Build Coastguard Worker   // become MAX_STATIC_GF_GROUP_LENGTH + 1, which causes memory error.
571*77c1e3ccSAndroid Build Coastguard Worker   // A cheap solution is to turn of kf_decomp here.
572*77c1e3ccSAndroid Build Coastguard Worker   // TODO(angiebird): Find a systematic way to solve this issue.
573*77c1e3ccSAndroid Build Coastguard Worker   if (baseline_gf_interval == MAX_STATIC_GF_GROUP_LENGTH) {
574*77c1e3ccSAndroid Build Coastguard Worker     kf_decomp = 0;
575*77c1e3ccSAndroid Build Coastguard Worker   }
576*77c1e3ccSAndroid Build Coastguard Worker   if (first_frame_update_type == KF_UPDATE) {
577*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[frame_index] = kf_decomp ? ARF_UPDATE : KF_UPDATE;
578*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_src_offset[frame_index] = 0;
579*77c1e3ccSAndroid Build Coastguard Worker     gf_group->cur_frame_idx[frame_index] = cur_frame_index;
580*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[frame_index] = 0;
581*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[frame_index] = KEY_FRAME;
582*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[frame_index] = REFBUF_RESET;
583*77c1e3ccSAndroid Build Coastguard Worker     gf_group->max_layer_depth = 0;
584*77c1e3ccSAndroid Build Coastguard Worker     gf_group->display_idx[frame_index] = cur_disp_index;
585*77c1e3ccSAndroid Build Coastguard Worker     if (!kf_decomp) cur_disp_index++;
586*77c1e3ccSAndroid Build Coastguard Worker     ++frame_index;
587*77c1e3ccSAndroid Build Coastguard Worker 
588*77c1e3ccSAndroid Build Coastguard Worker     if (kf_decomp) {
589*77c1e3ccSAndroid Build Coastguard Worker       gf_group->update_type[frame_index] = OVERLAY_UPDATE;
590*77c1e3ccSAndroid Build Coastguard Worker       gf_group->arf_src_offset[frame_index] = 0;
591*77c1e3ccSAndroid Build Coastguard Worker       gf_group->cur_frame_idx[frame_index] = cur_frame_index;
592*77c1e3ccSAndroid Build Coastguard Worker       gf_group->layer_depth[frame_index] = 0;
593*77c1e3ccSAndroid Build Coastguard Worker       gf_group->frame_type[frame_index] = INTER_FRAME;
594*77c1e3ccSAndroid Build Coastguard Worker       gf_group->refbuf_state[frame_index] = REFBUF_UPDATE;
595*77c1e3ccSAndroid Build Coastguard Worker       gf_group->max_layer_depth = 0;
596*77c1e3ccSAndroid Build Coastguard Worker       gf_group->display_idx[frame_index] = cur_disp_index;
597*77c1e3ccSAndroid Build Coastguard Worker       cur_disp_index++;
598*77c1e3ccSAndroid Build Coastguard Worker       ++frame_index;
599*77c1e3ccSAndroid Build Coastguard Worker     }
600*77c1e3ccSAndroid Build Coastguard Worker     cur_frame_index++;
601*77c1e3ccSAndroid Build Coastguard Worker   }
602*77c1e3ccSAndroid Build Coastguard Worker 
603*77c1e3ccSAndroid Build Coastguard Worker   if (first_frame_update_type == GF_UPDATE) {
604*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[frame_index] = GF_UPDATE;
605*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_src_offset[frame_index] = 0;
606*77c1e3ccSAndroid Build Coastguard Worker     gf_group->cur_frame_idx[frame_index] = cur_frame_index;
607*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[frame_index] = 0;
608*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[frame_index] = INTER_FRAME;
609*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[frame_index] = REFBUF_UPDATE;
610*77c1e3ccSAndroid Build Coastguard Worker     gf_group->max_layer_depth = 0;
611*77c1e3ccSAndroid Build Coastguard Worker     gf_group->display_idx[frame_index] = cur_disp_index;
612*77c1e3ccSAndroid Build Coastguard Worker     cur_disp_index++;
613*77c1e3ccSAndroid Build Coastguard Worker     ++frame_index;
614*77c1e3ccSAndroid Build Coastguard Worker     ++cur_frame_index;
615*77c1e3ccSAndroid Build Coastguard Worker   }
616*77c1e3ccSAndroid Build Coastguard Worker 
617*77c1e3ccSAndroid Build Coastguard Worker   // ALTREF.
618*77c1e3ccSAndroid Build Coastguard Worker   const int use_altref = gf_group->max_layer_depth_allowed > 0;
619*77c1e3ccSAndroid Build Coastguard Worker   int is_fwd_kf = rc->frames_to_fwd_kf == gf_interval;
620*77c1e3ccSAndroid Build Coastguard Worker 
621*77c1e3ccSAndroid Build Coastguard Worker   if (use_altref) {
622*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[frame_index] = ARF_UPDATE;
623*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_src_offset[frame_index] = gf_interval - cur_frame_index;
624*77c1e3ccSAndroid Build Coastguard Worker     gf_group->cur_frame_idx[frame_index] = cur_frame_index;
625*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[frame_index] = 1;
626*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_boost[frame_index] = cpi->ppi->p_rc.gfu_boost;
627*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[frame_index] = is_fwd_kf ? KEY_FRAME : INTER_FRAME;
628*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[frame_index] = REFBUF_UPDATE;
629*77c1e3ccSAndroid Build Coastguard Worker     gf_group->max_layer_depth = 1;
630*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_index = frame_index;
631*77c1e3ccSAndroid Build Coastguard Worker     gf_group->display_idx[frame_index] =
632*77c1e3ccSAndroid Build Coastguard Worker         cur_disp_index + gf_group->arf_src_offset[frame_index];
633*77c1e3ccSAndroid Build Coastguard Worker     ++frame_index;
634*77c1e3ccSAndroid Build Coastguard Worker   } else {
635*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_index = -1;
636*77c1e3ccSAndroid Build Coastguard Worker   }
637*77c1e3ccSAndroid Build Coastguard Worker 
638*77c1e3ccSAndroid Build Coastguard Worker   // Flag to indicate if multi-layer configuration is complete.
639*77c1e3ccSAndroid Build Coastguard Worker   int is_multi_layer_configured = 0;
640*77c1e3ccSAndroid Build Coastguard Worker 
641*77c1e3ccSAndroid Build Coastguard Worker   // Running count of no. of frames that is part of a given parallel
642*77c1e3ccSAndroid Build Coastguard Worker   // encode set in a gf_group. Value of 1 indicates no parallel encode.
643*77c1e3ccSAndroid Build Coastguard Worker   int parallel_frame_count = 1;
644*77c1e3ccSAndroid Build Coastguard Worker   // Enable parallel encode of frames if gf_group has a multi-layer pyramid
645*77c1e3ccSAndroid Build Coastguard Worker   // structure with minimum 4 layers.
646*77c1e3ccSAndroid Build Coastguard Worker   int do_frame_parallel_encode = (cpi->ppi->num_fp_contexts > 1 && use_altref &&
647*77c1e3ccSAndroid Build Coastguard Worker                                   gf_group->max_layer_depth_allowed >= 4);
648*77c1e3ccSAndroid Build Coastguard Worker 
649*77c1e3ccSAndroid Build Coastguard Worker   int first_frame_index = cur_frame_index;
650*77c1e3ccSAndroid Build Coastguard Worker   if (do_frame_parallel_encode) {
651*77c1e3ccSAndroid Build Coastguard Worker     // construct_multi_layer_gf_structure() takes the input parameter
652*77c1e3ccSAndroid Build Coastguard Worker     // 'gf_interval' as p_rc->baseline_gf_interval - 1 . Below code computes the
653*77c1e3ccSAndroid Build Coastguard Worker     // actual GF_GROUP length by compensating for this offset.
654*77c1e3ccSAndroid Build Coastguard Worker     int actual_gf_length = ((first_frame_update_type == KF_UPDATE) ||
655*77c1e3ccSAndroid Build Coastguard Worker                             (first_frame_update_type == GF_UPDATE))
656*77c1e3ccSAndroid Build Coastguard Worker                                ? gf_interval
657*77c1e3ccSAndroid Build Coastguard Worker                                : gf_interval + 1;
658*77c1e3ccSAndroid Build Coastguard Worker 
659*77c1e3ccSAndroid Build Coastguard Worker     // In order to facilitate parallel encoding of frames in lower layer depths,
660*77c1e3ccSAndroid Build Coastguard Worker     // encode reordering is done. Currently encode reordering is enabled only
661*77c1e3ccSAndroid Build Coastguard Worker     // for gf-intervals 16 and 32. NOTE: Since the buffer holding the
662*77c1e3ccSAndroid Build Coastguard Worker     // reference frames is of size 8 (ref_frame_map[REF_FRAMES]), there is a
663*77c1e3ccSAndroid Build Coastguard Worker     // limitation on the number of hidden frames possible at any given point and
664*77c1e3ccSAndroid Build Coastguard Worker     // hence the reordering is enabled only for gf-intervals 16 and 32.
665*77c1e3ccSAndroid Build Coastguard Worker     // Disabling encode reordering for gf-interval 14 since some cross-frame
666*77c1e3ccSAndroid Build Coastguard Worker     // dependencies related to temporal filtering for FPMT is currently not
667*77c1e3ccSAndroid Build Coastguard Worker     // handled.
668*77c1e3ccSAndroid Build Coastguard Worker     int disable_gf14_reorder = 1;
669*77c1e3ccSAndroid Build Coastguard Worker     if (actual_gf_length == 14 && !disable_gf14_reorder) {
670*77c1e3ccSAndroid Build Coastguard Worker       // This array holds the gf index of INTNL_ARF_UPDATE frames in the slot
671*77c1e3ccSAndroid Build Coastguard Worker       // corresponding to their display order hint. This is used while
672*77c1e3ccSAndroid Build Coastguard Worker       // configuring the LF_UPDATE frames and INTNL_OVERLAY_UPDATE frames.
673*77c1e3ccSAndroid Build Coastguard Worker       int doh_gf_index_map[FIXED_GF_INTERVAL];
674*77c1e3ccSAndroid Build Coastguard Worker       // Initialize doh_gf_index_map with INVALID_IDX.
675*77c1e3ccSAndroid Build Coastguard Worker       memset(&doh_gf_index_map[0], INVALID_IDX,
676*77c1e3ccSAndroid Build Coastguard Worker              (sizeof(doh_gf_index_map[0]) * FIXED_GF_INTERVAL));
677*77c1e3ccSAndroid Build Coastguard Worker 
678*77c1e3ccSAndroid Build Coastguard Worker       FRAME_REORDER_INFO arf_frame_stats[REF_FRAMES - 1];
679*77c1e3ccSAndroid Build Coastguard Worker       // Store the stats corresponding to layer 1 frame.
680*77c1e3ccSAndroid Build Coastguard Worker       fill_arf_frame_stats(arf_frame_stats, 0, actual_gf_length, 1,
681*77c1e3ccSAndroid Build Coastguard Worker                            actual_gf_length);
682*77c1e3ccSAndroid Build Coastguard Worker       int count_arf_frames = 1;
683*77c1e3ccSAndroid Build Coastguard Worker 
684*77c1e3ccSAndroid Build Coastguard Worker       // Sets multi-layer params for gf-interval 14 to consecutively encode
685*77c1e3ccSAndroid Build Coastguard Worker       // frames in the same layer depth, i.e., encode order would be 0-> 14->
686*77c1e3ccSAndroid Build Coastguard Worker       // 7-> 3-> 10-> 5-> 12-> 1-> 2-> 4-> 6-> 8-> 9-> 11-> 13.
687*77c1e3ccSAndroid Build Coastguard Worker       // TODO(Remya): Set GF_GROUP param 'arf_boost' for all frames.
688*77c1e3ccSAndroid Build Coastguard Worker       set_multi_layer_params_for_gf14(
689*77c1e3ccSAndroid Build Coastguard Worker           twopass, &cpi->twopass_frame, p_rc, frame_info, gf_group,
690*77c1e3ccSAndroid Build Coastguard Worker           arf_frame_stats, &cur_frame_index, &frame_index, &count_arf_frames,
691*77c1e3ccSAndroid Build Coastguard Worker           doh_gf_index_map, &parallel_frame_count, &first_frame_index,
692*77c1e3ccSAndroid Build Coastguard Worker           &cur_disp_index, actual_gf_length, use_altref + 1,
693*77c1e3ccSAndroid Build Coastguard Worker           cpi->ppi->num_fp_contexts);
694*77c1e3ccSAndroid Build Coastguard Worker 
695*77c1e3ccSAndroid Build Coastguard Worker       // Set gf_group->skip_frame_refresh.
696*77c1e3ccSAndroid Build Coastguard Worker       for (int i = 0; i < actual_gf_length; i++) {
697*77c1e3ccSAndroid Build Coastguard Worker         int count = 0;
698*77c1e3ccSAndroid Build Coastguard Worker         if (gf_group->update_type[i] == INTNL_ARF_UPDATE) {
699*77c1e3ccSAndroid Build Coastguard Worker           for (int j = 0; j < i; j++) {
700*77c1e3ccSAndroid Build Coastguard Worker             // Store the display order hint of the frames which would not
701*77c1e3ccSAndroid Build Coastguard Worker             // have been displayed at the encode call of frame 'i'.
702*77c1e3ccSAndroid Build Coastguard Worker             if ((gf_group->display_idx[j] < gf_group->display_idx[i]) &&
703*77c1e3ccSAndroid Build Coastguard Worker                 gf_group->update_type[j] == INTNL_ARF_UPDATE) {
704*77c1e3ccSAndroid Build Coastguard Worker               gf_group->skip_frame_refresh[i][count++] =
705*77c1e3ccSAndroid Build Coastguard Worker                   gf_group->display_idx[j];
706*77c1e3ccSAndroid Build Coastguard Worker             }
707*77c1e3ccSAndroid Build Coastguard Worker           }
708*77c1e3ccSAndroid Build Coastguard Worker         }
709*77c1e3ccSAndroid Build Coastguard Worker       }
710*77c1e3ccSAndroid Build Coastguard Worker     } else {
711*77c1e3ccSAndroid Build Coastguard Worker       // Set layer depth threshold for reordering as per the gf length.
712*77c1e3ccSAndroid Build Coastguard Worker       int depth_thr = (actual_gf_length == 16)   ? 3
713*77c1e3ccSAndroid Build Coastguard Worker                       : (actual_gf_length == 32) ? 4
714*77c1e3ccSAndroid Build Coastguard Worker                                                  : INT_MAX;
715*77c1e3ccSAndroid Build Coastguard Worker 
716*77c1e3ccSAndroid Build Coastguard Worker       set_multi_layer_params_for_fp(
717*77c1e3ccSAndroid Build Coastguard Worker           twopass, &cpi->twopass_frame, gf_group, p_rc, rc, frame_info,
718*77c1e3ccSAndroid Build Coastguard Worker           cur_frame_index, gf_interval, &cur_frame_index, &frame_index,
719*77c1e3ccSAndroid Build Coastguard Worker           &parallel_frame_count, cpi->ppi->num_fp_contexts,
720*77c1e3ccSAndroid Build Coastguard Worker           do_frame_parallel_encode, &first_frame_index, depth_thr,
721*77c1e3ccSAndroid Build Coastguard Worker           &cur_disp_index, use_altref + 1);
722*77c1e3ccSAndroid Build Coastguard Worker     }
723*77c1e3ccSAndroid Build Coastguard Worker     is_multi_layer_configured = 1;
724*77c1e3ccSAndroid Build Coastguard Worker   }
725*77c1e3ccSAndroid Build Coastguard Worker 
726*77c1e3ccSAndroid Build Coastguard Worker   // Rest of the frames.
727*77c1e3ccSAndroid Build Coastguard Worker   if (!is_multi_layer_configured)
728*77c1e3ccSAndroid Build Coastguard Worker     set_multi_layer_params(twopass, &cpi->twopass_frame, gf_group, p_rc, rc,
729*77c1e3ccSAndroid Build Coastguard Worker                            frame_info, cur_frame_index, gf_interval,
730*77c1e3ccSAndroid Build Coastguard Worker                            &cur_frame_index, &frame_index,
731*77c1e3ccSAndroid Build Coastguard Worker                            &parallel_frame_count, cpi->ppi->num_fp_contexts,
732*77c1e3ccSAndroid Build Coastguard Worker                            do_frame_parallel_encode, &first_frame_index,
733*77c1e3ccSAndroid Build Coastguard Worker                            &cur_disp_index, use_altref + 1);
734*77c1e3ccSAndroid Build Coastguard Worker 
735*77c1e3ccSAndroid Build Coastguard Worker   if (use_altref) {
736*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[frame_index] = OVERLAY_UPDATE;
737*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_src_offset[frame_index] = 0;
738*77c1e3ccSAndroid Build Coastguard Worker     gf_group->cur_frame_idx[frame_index] = cur_frame_index;
739*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[frame_index] = MAX_ARF_LAYERS;
740*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_boost[frame_index] = NORMAL_BOOST;
741*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[frame_index] = INTER_FRAME;
742*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[frame_index] =
743*77c1e3ccSAndroid Build Coastguard Worker         is_fwd_kf ? REFBUF_RESET : REFBUF_UPDATE;
744*77c1e3ccSAndroid Build Coastguard Worker     gf_group->display_idx[frame_index] = cur_disp_index;
745*77c1e3ccSAndroid Build Coastguard Worker     ++frame_index;
746*77c1e3ccSAndroid Build Coastguard Worker   } else {
747*77c1e3ccSAndroid Build Coastguard Worker     for (; cur_frame_index <= gf_interval; ++cur_frame_index) {
748*77c1e3ccSAndroid Build Coastguard Worker       gf_group->update_type[frame_index] = LF_UPDATE;
749*77c1e3ccSAndroid Build Coastguard Worker       gf_group->arf_src_offset[frame_index] = 0;
750*77c1e3ccSAndroid Build Coastguard Worker       gf_group->cur_frame_idx[frame_index] = cur_frame_index;
751*77c1e3ccSAndroid Build Coastguard Worker       gf_group->layer_depth[frame_index] = MAX_ARF_LAYERS;
752*77c1e3ccSAndroid Build Coastguard Worker       gf_group->arf_boost[frame_index] = NORMAL_BOOST;
753*77c1e3ccSAndroid Build Coastguard Worker       gf_group->frame_type[frame_index] = INTER_FRAME;
754*77c1e3ccSAndroid Build Coastguard Worker       gf_group->refbuf_state[frame_index] = REFBUF_UPDATE;
755*77c1e3ccSAndroid Build Coastguard Worker       gf_group->max_layer_depth = AOMMAX(gf_group->max_layer_depth, 2);
756*77c1e3ccSAndroid Build Coastguard Worker       set_src_offset(gf_group, &first_frame_index, cur_frame_index,
757*77c1e3ccSAndroid Build Coastguard Worker                      frame_index);
758*77c1e3ccSAndroid Build Coastguard Worker       gf_group->display_idx[frame_index] = cur_disp_index;
759*77c1e3ccSAndroid Build Coastguard Worker       cur_disp_index++;
760*77c1e3ccSAndroid Build Coastguard Worker       ++frame_index;
761*77c1e3ccSAndroid Build Coastguard Worker     }
762*77c1e3ccSAndroid Build Coastguard Worker   }
763*77c1e3ccSAndroid Build Coastguard Worker   if (do_frame_parallel_encode) {
764*77c1e3ccSAndroid Build Coastguard Worker     // Iterate through the gf_group and reset frame_parallel_level to 0 in case
765*77c1e3ccSAndroid Build Coastguard Worker     // a frame is marked as frame_parallel_level 1 with no subsequent
766*77c1e3ccSAndroid Build Coastguard Worker     // frame_parallel_level 2 frame(s).
767*77c1e3ccSAndroid Build Coastguard Worker     int level1_frame_idx = INT_MAX;
768*77c1e3ccSAndroid Build Coastguard Worker     int level2_frame_count = 0;
769*77c1e3ccSAndroid Build Coastguard Worker     for (int frame_idx = 0; frame_idx < frame_index; frame_idx++) {
770*77c1e3ccSAndroid Build Coastguard Worker       if (gf_group->frame_parallel_level[frame_idx] == 1) {
771*77c1e3ccSAndroid Build Coastguard Worker         // Set frame_parallel_level to 0 if only one frame is present in a
772*77c1e3ccSAndroid Build Coastguard Worker         // parallel encode set.
773*77c1e3ccSAndroid Build Coastguard Worker         if (level1_frame_idx != INT_MAX && !level2_frame_count)
774*77c1e3ccSAndroid Build Coastguard Worker           gf_group->frame_parallel_level[level1_frame_idx] = 0;
775*77c1e3ccSAndroid Build Coastguard Worker         // Book-keep frame_idx of frame_parallel_level 1 frame and reset the
776*77c1e3ccSAndroid Build Coastguard Worker         // count of frame_parallel_level 2 frames in the corresponding parallel
777*77c1e3ccSAndroid Build Coastguard Worker         // encode set.
778*77c1e3ccSAndroid Build Coastguard Worker         level1_frame_idx = frame_idx;
779*77c1e3ccSAndroid Build Coastguard Worker         level2_frame_count = 0;
780*77c1e3ccSAndroid Build Coastguard Worker       }
781*77c1e3ccSAndroid Build Coastguard Worker       if (gf_group->frame_parallel_level[frame_idx] == 2) level2_frame_count++;
782*77c1e3ccSAndroid Build Coastguard Worker     }
783*77c1e3ccSAndroid Build Coastguard Worker     // If frame_parallel_level is set to 1 for the last LF_UPDATE
784*77c1e3ccSAndroid Build Coastguard Worker     // frame in the gf_group, reset it to zero since there are no subsequent
785*77c1e3ccSAndroid Build Coastguard Worker     // frames in the gf_group.
786*77c1e3ccSAndroid Build Coastguard Worker     if (gf_group->frame_parallel_level[frame_index - 2] == 1) {
787*77c1e3ccSAndroid Build Coastguard Worker       assert(gf_group->update_type[frame_index - 2] == LF_UPDATE);
788*77c1e3ccSAndroid Build Coastguard Worker       gf_group->frame_parallel_level[frame_index - 2] = 0;
789*77c1e3ccSAndroid Build Coastguard Worker     }
790*77c1e3ccSAndroid Build Coastguard Worker   }
791*77c1e3ccSAndroid Build Coastguard Worker 
792*77c1e3ccSAndroid Build Coastguard Worker   for (int gf_idx = frame_index; gf_idx < MAX_STATIC_GF_GROUP_LENGTH;
793*77c1e3ccSAndroid Build Coastguard Worker        ++gf_idx) {
794*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[gf_idx] = LF_UPDATE;
795*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_src_offset[gf_idx] = 0;
796*77c1e3ccSAndroid Build Coastguard Worker     gf_group->cur_frame_idx[gf_idx] = gf_idx;
797*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[gf_idx] = MAX_ARF_LAYERS;
798*77c1e3ccSAndroid Build Coastguard Worker     gf_group->arf_boost[gf_idx] = NORMAL_BOOST;
799*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[gf_idx] = INTER_FRAME;
800*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[gf_idx] = REFBUF_UPDATE;
801*77c1e3ccSAndroid Build Coastguard Worker     gf_group->max_layer_depth = AOMMAX(gf_group->max_layer_depth, 2);
802*77c1e3ccSAndroid Build Coastguard Worker   }
803*77c1e3ccSAndroid Build Coastguard Worker 
804*77c1e3ccSAndroid Build Coastguard Worker   return frame_index;
805*77c1e3ccSAndroid Build Coastguard Worker }
806*77c1e3ccSAndroid Build Coastguard Worker 
set_ld_layer_depth(GF_GROUP * gf_group,int gop_length)807*77c1e3ccSAndroid Build Coastguard Worker static void set_ld_layer_depth(GF_GROUP *gf_group, int gop_length) {
808*77c1e3ccSAndroid Build Coastguard Worker   int log_gop_length = 0;
809*77c1e3ccSAndroid Build Coastguard Worker   while ((1 << log_gop_length) < gop_length) {
810*77c1e3ccSAndroid Build Coastguard Worker     ++log_gop_length;
811*77c1e3ccSAndroid Build Coastguard Worker   }
812*77c1e3ccSAndroid Build Coastguard Worker 
813*77c1e3ccSAndroid Build Coastguard Worker   for (int gf_index = 0; gf_index < gf_group->size; ++gf_index) {
814*77c1e3ccSAndroid Build Coastguard Worker     int count = 0;
815*77c1e3ccSAndroid Build Coastguard Worker     // Find the trailing zeros
816*77c1e3ccSAndroid Build Coastguard Worker     for (; count < MAX_ARF_LAYERS; ++count) {
817*77c1e3ccSAndroid Build Coastguard Worker       if ((gf_index >> count) & 0x01) break;
818*77c1e3ccSAndroid Build Coastguard Worker     }
819*77c1e3ccSAndroid Build Coastguard Worker     gf_group->layer_depth[gf_index] = AOMMAX(log_gop_length - count, 0);
820*77c1e3ccSAndroid Build Coastguard Worker   }
821*77c1e3ccSAndroid Build Coastguard Worker   gf_group->max_layer_depth = AOMMIN(log_gop_length, MAX_ARF_LAYERS);
822*77c1e3ccSAndroid Build Coastguard Worker }
823*77c1e3ccSAndroid Build Coastguard Worker 
av1_gop_setup_structure(AV1_COMP * cpi)824*77c1e3ccSAndroid Build Coastguard Worker void av1_gop_setup_structure(AV1_COMP *cpi) {
825*77c1e3ccSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi->rc;
826*77c1e3ccSAndroid Build Coastguard Worker   PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
827*77c1e3ccSAndroid Build Coastguard Worker   GF_GROUP *const gf_group = &cpi->ppi->gf_group;
828*77c1e3ccSAndroid Build Coastguard Worker   TWO_PASS *const twopass = &cpi->ppi->twopass;
829*77c1e3ccSAndroid Build Coastguard Worker   FRAME_INFO *const frame_info = &cpi->frame_info;
830*77c1e3ccSAndroid Build Coastguard Worker   const int key_frame = rc->frames_since_key == 0;
831*77c1e3ccSAndroid Build Coastguard Worker   FRAME_UPDATE_TYPE first_frame_update_type = ARF_UPDATE;
832*77c1e3ccSAndroid Build Coastguard Worker 
833*77c1e3ccSAndroid Build Coastguard Worker   if (key_frame) {
834*77c1e3ccSAndroid Build Coastguard Worker     first_frame_update_type = KF_UPDATE;
835*77c1e3ccSAndroid Build Coastguard Worker     if (cpi->oxcf.kf_max_pyr_height != -1) {
836*77c1e3ccSAndroid Build Coastguard Worker       gf_group->max_layer_depth_allowed = AOMMIN(
837*77c1e3ccSAndroid Build Coastguard Worker           cpi->oxcf.kf_max_pyr_height, gf_group->max_layer_depth_allowed);
838*77c1e3ccSAndroid Build Coastguard Worker     }
839*77c1e3ccSAndroid Build Coastguard Worker   } else if (!cpi->ppi->gf_state.arf_gf_boost_lst) {
840*77c1e3ccSAndroid Build Coastguard Worker     first_frame_update_type = GF_UPDATE;
841*77c1e3ccSAndroid Build Coastguard Worker   }
842*77c1e3ccSAndroid Build Coastguard Worker 
843*77c1e3ccSAndroid Build Coastguard Worker   gf_group->size = construct_multi_layer_gf_structure(
844*77c1e3ccSAndroid Build Coastguard Worker       cpi, twopass, gf_group, rc, frame_info, p_rc->baseline_gf_interval,
845*77c1e3ccSAndroid Build Coastguard Worker       first_frame_update_type);
846*77c1e3ccSAndroid Build Coastguard Worker 
847*77c1e3ccSAndroid Build Coastguard Worker   if (gf_group->max_layer_depth_allowed == 0)
848*77c1e3ccSAndroid Build Coastguard Worker     set_ld_layer_depth(gf_group, p_rc->baseline_gf_interval);
849*77c1e3ccSAndroid Build Coastguard Worker }
850*77c1e3ccSAndroid Build Coastguard Worker 
av1_gop_check_forward_keyframe(const GF_GROUP * gf_group,int gf_frame_index)851*77c1e3ccSAndroid Build Coastguard Worker int av1_gop_check_forward_keyframe(const GF_GROUP *gf_group,
852*77c1e3ccSAndroid Build Coastguard Worker                                    int gf_frame_index) {
853*77c1e3ccSAndroid Build Coastguard Worker   return gf_group->frame_type[gf_frame_index] == KEY_FRAME &&
854*77c1e3ccSAndroid Build Coastguard Worker          gf_group->refbuf_state[gf_frame_index] == REFBUF_UPDATE;
855*77c1e3ccSAndroid Build Coastguard Worker }
856*77c1e3ccSAndroid Build Coastguard Worker 
av1_gop_is_second_arf(const GF_GROUP * gf_group,int gf_frame_index)857*77c1e3ccSAndroid Build Coastguard Worker int av1_gop_is_second_arf(const GF_GROUP *gf_group, int gf_frame_index) {
858*77c1e3ccSAndroid Build Coastguard Worker   const int arf_src_offset = gf_group->arf_src_offset[gf_frame_index];
859*77c1e3ccSAndroid Build Coastguard Worker   // TODO(angiebird): when gf_group->size == 32, it's possble to
860*77c1e3ccSAndroid Build Coastguard Worker   // have "two" second arf. Check if this is acceptable.
861*77c1e3ccSAndroid Build Coastguard Worker   if (gf_group->update_type[gf_frame_index] == INTNL_ARF_UPDATE &&
862*77c1e3ccSAndroid Build Coastguard Worker       arf_src_offset >= TF_LOOKAHEAD_IDX_THR) {
863*77c1e3ccSAndroid Build Coastguard Worker     return 1;
864*77c1e3ccSAndroid Build Coastguard Worker   }
865*77c1e3ccSAndroid Build Coastguard Worker   return 0;
866*77c1e3ccSAndroid Build Coastguard Worker }
867