xref: /aosp_15_r20/external/libvpx/vp9/encoder/vp9_tpl_model.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2023 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 <math.h>
12*fb1b10abSAndroid Build Coastguard Worker 
13*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
14*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
15*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_mvref_common.h"
16*fb1b10abSAndroid Build Coastguard Worker #endif
17*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconinter.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconintra.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_scan.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_ext_ratectrl.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_firstpass.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_ratectrl.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_tpl_model.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vpx/internal/vpx_codec_internal.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_codec.h"
27*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_ext_ratectrl.h"
28*fb1b10abSAndroid Build Coastguard Worker 
init_gop_frames_rc(VP9_COMP * cpi,GF_PICTURE * gf_picture,const GF_GROUP * gf_group,int * tpl_group_frames)29*fb1b10abSAndroid Build Coastguard Worker static int init_gop_frames_rc(VP9_COMP *cpi, GF_PICTURE *gf_picture,
30*fb1b10abSAndroid Build Coastguard Worker                               const GF_GROUP *gf_group, int *tpl_group_frames) {
31*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi->common;
32*fb1b10abSAndroid Build Coastguard Worker   int frame_idx = 0;
33*fb1b10abSAndroid Build Coastguard Worker   int i;
34*fb1b10abSAndroid Build Coastguard Worker   int extend_frame_count = 0;
35*fb1b10abSAndroid Build Coastguard Worker   int pframe_qindex = cpi->tpl_stats[2].base_qindex;
36*fb1b10abSAndroid Build Coastguard Worker   int frame_gop_offset = 0;
37*fb1b10abSAndroid Build Coastguard Worker 
38*fb1b10abSAndroid Build Coastguard Worker   int added_overlay = 0;
39*fb1b10abSAndroid Build Coastguard Worker 
40*fb1b10abSAndroid Build Coastguard Worker   RefCntBuffer *frame_bufs = cm->buffer_pool->frame_bufs;
41*fb1b10abSAndroid Build Coastguard Worker   int8_t recon_frame_index[REFS_PER_FRAME + MAX_ARF_LAYERS];
42*fb1b10abSAndroid Build Coastguard Worker 
43*fb1b10abSAndroid Build Coastguard Worker   memset(recon_frame_index, -1, sizeof(recon_frame_index));
44*fb1b10abSAndroid Build Coastguard Worker 
45*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < FRAME_BUFFERS; ++i) {
46*fb1b10abSAndroid Build Coastguard Worker     if (frame_bufs[i].ref_count == 0) {
47*fb1b10abSAndroid Build Coastguard Worker       alloc_frame_mvs(cm, i);
48*fb1b10abSAndroid Build Coastguard Worker       if (vpx_realloc_frame_buffer(&frame_bufs[i].buf, cm->width, cm->height,
49*fb1b10abSAndroid Build Coastguard Worker                                    cm->subsampling_x, cm->subsampling_y,
50*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
51*fb1b10abSAndroid Build Coastguard Worker                                    cm->use_highbitdepth,
52*fb1b10abSAndroid Build Coastguard Worker #endif
53*fb1b10abSAndroid Build Coastguard Worker                                    VP9_ENC_BORDER_IN_PIXELS, cm->byte_alignment,
54*fb1b10abSAndroid Build Coastguard Worker                                    NULL, NULL, NULL))
55*fb1b10abSAndroid Build Coastguard Worker         vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
56*fb1b10abSAndroid Build Coastguard Worker                            "Failed to allocate frame buffer");
57*fb1b10abSAndroid Build Coastguard Worker 
58*fb1b10abSAndroid Build Coastguard Worker       recon_frame_index[frame_idx] = i;
59*fb1b10abSAndroid Build Coastguard Worker       ++frame_idx;
60*fb1b10abSAndroid Build Coastguard Worker 
61*fb1b10abSAndroid Build Coastguard Worker       if (frame_idx >= REFS_PER_FRAME + cpi->oxcf.enable_auto_arf) break;
62*fb1b10abSAndroid Build Coastguard Worker     }
63*fb1b10abSAndroid Build Coastguard Worker   }
64*fb1b10abSAndroid Build Coastguard Worker 
65*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < REFS_PER_FRAME + 1; ++i) {
66*fb1b10abSAndroid Build Coastguard Worker     assert(recon_frame_index[i] >= 0);
67*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_recon_frames[i] = &frame_bufs[recon_frame_index[i]].buf;
68*fb1b10abSAndroid Build Coastguard Worker   }
69*fb1b10abSAndroid Build Coastguard Worker 
70*fb1b10abSAndroid Build Coastguard Worker   *tpl_group_frames = 0;
71*fb1b10abSAndroid Build Coastguard Worker 
72*fb1b10abSAndroid Build Coastguard Worker   int ref_table[3];
73*fb1b10abSAndroid Build Coastguard Worker 
74*fb1b10abSAndroid Build Coastguard Worker   if (gf_group->index == 1 && gf_group->update_type[1] == ARF_UPDATE) {
75*fb1b10abSAndroid Build Coastguard Worker     if (gf_group->update_type[0] == KF_UPDATE) {
76*fb1b10abSAndroid Build Coastguard Worker       // This is the only frame in ref buffer. We need it to be on
77*fb1b10abSAndroid Build Coastguard Worker       // gf_picture[0].
78*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) ref_table[i] = -REFS_PER_FRAME;
79*fb1b10abSAndroid Build Coastguard Worker 
80*fb1b10abSAndroid Build Coastguard Worker       gf_picture[0].frame =
81*fb1b10abSAndroid Build Coastguard Worker           &cm->buffer_pool->frame_bufs[gf_group->update_ref_idx[0]].buf;
82*fb1b10abSAndroid Build Coastguard Worker       ref_table[gf_group->update_ref_idx[0]] = 0;
83*fb1b10abSAndroid Build Coastguard Worker 
84*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) gf_picture[0].ref_frame[i] = -REFS_PER_FRAME;
85*fb1b10abSAndroid Build Coastguard Worker       gf_picture[0].update_type = gf_group->update_type[0];
86*fb1b10abSAndroid Build Coastguard Worker     } else {
87*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < REFS_PER_FRAME; i++) {
88*fb1b10abSAndroid Build Coastguard Worker         if (cm->ref_frame_map[i] != -1) {
89*fb1b10abSAndroid Build Coastguard Worker           gf_picture[-i].frame =
90*fb1b10abSAndroid Build Coastguard Worker               &cm->buffer_pool->frame_bufs[cm->ref_frame_map[i]].buf;
91*fb1b10abSAndroid Build Coastguard Worker           ref_table[i] = -i;
92*fb1b10abSAndroid Build Coastguard Worker         } else {
93*fb1b10abSAndroid Build Coastguard Worker           ref_table[i] = -REFS_PER_FRAME;
94*fb1b10abSAndroid Build Coastguard Worker         }
95*fb1b10abSAndroid Build Coastguard Worker       }
96*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) {
97*fb1b10abSAndroid Build Coastguard Worker         gf_picture[0].ref_frame[i] = ref_table[i];
98*fb1b10abSAndroid Build Coastguard Worker       }
99*fb1b10abSAndroid Build Coastguard Worker     }
100*fb1b10abSAndroid Build Coastguard Worker     ++*tpl_group_frames;
101*fb1b10abSAndroid Build Coastguard Worker 
102*fb1b10abSAndroid Build Coastguard Worker     // Initialize base layer ARF frame
103*fb1b10abSAndroid Build Coastguard Worker     gf_picture[1].frame = cpi->Source;
104*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 3; ++i) gf_picture[1].ref_frame[i] = ref_table[i];
105*fb1b10abSAndroid Build Coastguard Worker     gf_picture[1].update_type = gf_group->update_type[1];
106*fb1b10abSAndroid Build Coastguard Worker     ref_table[gf_group->update_ref_idx[1]] = 1;
107*fb1b10abSAndroid Build Coastguard Worker 
108*fb1b10abSAndroid Build Coastguard Worker     ++*tpl_group_frames;
109*fb1b10abSAndroid Build Coastguard Worker   } else {
110*fb1b10abSAndroid Build Coastguard Worker     assert(gf_group->index == 0);
111*fb1b10abSAndroid Build Coastguard Worker     if (gf_group->update_type[0] == KF_UPDATE) {
112*fb1b10abSAndroid Build Coastguard Worker       // This is the only frame in ref buffer. We need it to be on
113*fb1b10abSAndroid Build Coastguard Worker       // gf_picture[0].
114*fb1b10abSAndroid Build Coastguard Worker       gf_picture[0].frame = cpi->Source;
115*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) gf_picture[0].ref_frame[i] = -REFS_PER_FRAME;
116*fb1b10abSAndroid Build Coastguard Worker       gf_picture[0].update_type = gf_group->update_type[0];
117*fb1b10abSAndroid Build Coastguard Worker 
118*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) ref_table[i] = -REFS_PER_FRAME;
119*fb1b10abSAndroid Build Coastguard Worker       ref_table[gf_group->update_ref_idx[0]] = 0;
120*fb1b10abSAndroid Build Coastguard Worker     } else {
121*fb1b10abSAndroid Build Coastguard Worker       // Initialize ref table
122*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < REFS_PER_FRAME; i++) {
123*fb1b10abSAndroid Build Coastguard Worker         if (cm->ref_frame_map[i] != -1) {
124*fb1b10abSAndroid Build Coastguard Worker           gf_picture[-i].frame =
125*fb1b10abSAndroid Build Coastguard Worker               &cm->buffer_pool->frame_bufs[cm->ref_frame_map[i]].buf;
126*fb1b10abSAndroid Build Coastguard Worker           ref_table[i] = -i;
127*fb1b10abSAndroid Build Coastguard Worker         } else {
128*fb1b10abSAndroid Build Coastguard Worker           ref_table[i] = -REFS_PER_FRAME;
129*fb1b10abSAndroid Build Coastguard Worker         }
130*fb1b10abSAndroid Build Coastguard Worker       }
131*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) {
132*fb1b10abSAndroid Build Coastguard Worker         gf_picture[0].ref_frame[i] = ref_table[i];
133*fb1b10abSAndroid Build Coastguard Worker       }
134*fb1b10abSAndroid Build Coastguard Worker       gf_picture[0].update_type = gf_group->update_type[0];
135*fb1b10abSAndroid Build Coastguard Worker       if (gf_group->update_type[0] != OVERLAY_UPDATE &&
136*fb1b10abSAndroid Build Coastguard Worker           gf_group->update_ref_idx[0] != -1) {
137*fb1b10abSAndroid Build Coastguard Worker         ref_table[gf_group->update_ref_idx[0]] = 0;
138*fb1b10abSAndroid Build Coastguard Worker       }
139*fb1b10abSAndroid Build Coastguard Worker     }
140*fb1b10abSAndroid Build Coastguard Worker     ++*tpl_group_frames;
141*fb1b10abSAndroid Build Coastguard Worker   }
142*fb1b10abSAndroid Build Coastguard Worker 
143*fb1b10abSAndroid Build Coastguard Worker   int has_arf =
144*fb1b10abSAndroid Build Coastguard Worker       gf_group->gf_group_size > 1 && gf_group->update_type[1] == ARF_UPDATE &&
145*fb1b10abSAndroid Build Coastguard Worker       gf_group->update_type[gf_group->gf_group_size] == OVERLAY_UPDATE;
146*fb1b10abSAndroid Build Coastguard Worker 
147*fb1b10abSAndroid Build Coastguard Worker   // Initialize P frames
148*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = *tpl_group_frames; frame_idx < MAX_ARF_GOP_SIZE;
149*fb1b10abSAndroid Build Coastguard Worker        ++frame_idx) {
150*fb1b10abSAndroid Build Coastguard Worker     if (frame_idx >= gf_group->gf_group_size && !has_arf) break;
151*fb1b10abSAndroid Build Coastguard Worker     struct lookahead_entry *buf;
152*fb1b10abSAndroid Build Coastguard Worker     frame_gop_offset = gf_group->frame_gop_index[frame_idx];
153*fb1b10abSAndroid Build Coastguard Worker     buf = vp9_lookahead_peek(cpi->lookahead, frame_gop_offset - 1);
154*fb1b10abSAndroid Build Coastguard Worker 
155*fb1b10abSAndroid Build Coastguard Worker     if (buf == NULL) break;
156*fb1b10abSAndroid Build Coastguard Worker 
157*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].frame = &buf->img;
158*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 3; ++i) {
159*fb1b10abSAndroid Build Coastguard Worker       gf_picture[frame_idx].ref_frame[i] = ref_table[i];
160*fb1b10abSAndroid Build Coastguard Worker     }
161*fb1b10abSAndroid Build Coastguard Worker 
162*fb1b10abSAndroid Build Coastguard Worker     if (gf_group->update_type[frame_idx] != OVERLAY_UPDATE &&
163*fb1b10abSAndroid Build Coastguard Worker         gf_group->update_ref_idx[frame_idx] != -1) {
164*fb1b10abSAndroid Build Coastguard Worker       ref_table[gf_group->update_ref_idx[frame_idx]] = frame_idx;
165*fb1b10abSAndroid Build Coastguard Worker     }
166*fb1b10abSAndroid Build Coastguard Worker 
167*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].update_type = gf_group->update_type[frame_idx];
168*fb1b10abSAndroid Build Coastguard Worker 
169*fb1b10abSAndroid Build Coastguard Worker     ++*tpl_group_frames;
170*fb1b10abSAndroid Build Coastguard Worker 
171*fb1b10abSAndroid Build Coastguard Worker     // The length of group of pictures is baseline_gf_interval, plus the
172*fb1b10abSAndroid Build Coastguard Worker     // beginning golden frame from last GOP, plus the last overlay frame in
173*fb1b10abSAndroid Build Coastguard Worker     // the same GOP.
174*fb1b10abSAndroid Build Coastguard Worker     if (frame_idx == gf_group->gf_group_size) {
175*fb1b10abSAndroid Build Coastguard Worker       added_overlay = 1;
176*fb1b10abSAndroid Build Coastguard Worker 
177*fb1b10abSAndroid Build Coastguard Worker       ++frame_idx;
178*fb1b10abSAndroid Build Coastguard Worker       ++frame_gop_offset;
179*fb1b10abSAndroid Build Coastguard Worker       break;
180*fb1b10abSAndroid Build Coastguard Worker     }
181*fb1b10abSAndroid Build Coastguard Worker 
182*fb1b10abSAndroid Build Coastguard Worker     if (frame_idx == gf_group->gf_group_size - 1 &&
183*fb1b10abSAndroid Build Coastguard Worker         gf_group->update_type[gf_group->gf_group_size] != OVERLAY_UPDATE) {
184*fb1b10abSAndroid Build Coastguard Worker       ++frame_idx;
185*fb1b10abSAndroid Build Coastguard Worker       ++frame_gop_offset;
186*fb1b10abSAndroid Build Coastguard Worker       break;
187*fb1b10abSAndroid Build Coastguard Worker     }
188*fb1b10abSAndroid Build Coastguard Worker   }
189*fb1b10abSAndroid Build Coastguard Worker 
190*fb1b10abSAndroid Build Coastguard Worker   int lst_index = frame_idx - 1;
191*fb1b10abSAndroid Build Coastguard Worker   // Extend two frames outside the current gf group.
192*fb1b10abSAndroid Build Coastguard Worker   for (; has_arf && frame_idx < MAX_LAG_BUFFERS && extend_frame_count < 2;
193*fb1b10abSAndroid Build Coastguard Worker        ++frame_idx) {
194*fb1b10abSAndroid Build Coastguard Worker     struct lookahead_entry *buf =
195*fb1b10abSAndroid Build Coastguard Worker         vp9_lookahead_peek(cpi->lookahead, frame_gop_offset - 1);
196*fb1b10abSAndroid Build Coastguard Worker 
197*fb1b10abSAndroid Build Coastguard Worker     if (buf == NULL) break;
198*fb1b10abSAndroid Build Coastguard Worker 
199*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame_idx].base_qindex = pframe_qindex;
200*fb1b10abSAndroid Build Coastguard Worker 
201*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].frame = &buf->img;
202*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[0] = gf_picture[lst_index].ref_frame[0];
203*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[1] = gf_picture[lst_index].ref_frame[1];
204*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[2] = gf_picture[lst_index].ref_frame[2];
205*fb1b10abSAndroid Build Coastguard Worker 
206*fb1b10abSAndroid Build Coastguard Worker     if (gf_picture[frame_idx].ref_frame[0] >
207*fb1b10abSAndroid Build Coastguard Worker             gf_picture[frame_idx].ref_frame[1] &&
208*fb1b10abSAndroid Build Coastguard Worker         gf_picture[frame_idx].ref_frame[0] >
209*fb1b10abSAndroid Build Coastguard Worker             gf_picture[frame_idx].ref_frame[2]) {
210*fb1b10abSAndroid Build Coastguard Worker       gf_picture[frame_idx].ref_frame[0] = lst_index;
211*fb1b10abSAndroid Build Coastguard Worker     } else if (gf_picture[frame_idx].ref_frame[1] >
212*fb1b10abSAndroid Build Coastguard Worker                    gf_picture[frame_idx].ref_frame[0] &&
213*fb1b10abSAndroid Build Coastguard Worker                gf_picture[frame_idx].ref_frame[1] >
214*fb1b10abSAndroid Build Coastguard Worker                    gf_picture[frame_idx].ref_frame[2]) {
215*fb1b10abSAndroid Build Coastguard Worker       gf_picture[frame_idx].ref_frame[1] = lst_index;
216*fb1b10abSAndroid Build Coastguard Worker     } else {
217*fb1b10abSAndroid Build Coastguard Worker       gf_picture[frame_idx].ref_frame[2] = lst_index;
218*fb1b10abSAndroid Build Coastguard Worker     }
219*fb1b10abSAndroid Build Coastguard Worker 
220*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].update_type = LF_UPDATE;
221*fb1b10abSAndroid Build Coastguard Worker     lst_index = frame_idx;
222*fb1b10abSAndroid Build Coastguard Worker     ++*tpl_group_frames;
223*fb1b10abSAndroid Build Coastguard Worker     ++extend_frame_count;
224*fb1b10abSAndroid Build Coastguard Worker     ++frame_gop_offset;
225*fb1b10abSAndroid Build Coastguard Worker   }
226*fb1b10abSAndroid Build Coastguard Worker 
227*fb1b10abSAndroid Build Coastguard Worker   return extend_frame_count + added_overlay;
228*fb1b10abSAndroid Build Coastguard Worker }
229*fb1b10abSAndroid Build Coastguard Worker 
init_gop_frames(VP9_COMP * cpi,GF_PICTURE * gf_picture,const GF_GROUP * gf_group,int * tpl_group_frames)230*fb1b10abSAndroid Build Coastguard Worker static int init_gop_frames(VP9_COMP *cpi, GF_PICTURE *gf_picture,
231*fb1b10abSAndroid Build Coastguard Worker                            const GF_GROUP *gf_group, int *tpl_group_frames) {
232*fb1b10abSAndroid Build Coastguard Worker   if (cpi->ext_ratectrl.ready &&
233*fb1b10abSAndroid Build Coastguard Worker       (cpi->ext_ratectrl.funcs.rc_type & VPX_RC_GOP) != 0) {
234*fb1b10abSAndroid Build Coastguard Worker     return init_gop_frames_rc(cpi, gf_picture, gf_group, tpl_group_frames);
235*fb1b10abSAndroid Build Coastguard Worker   }
236*fb1b10abSAndroid Build Coastguard Worker 
237*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi->common;
238*fb1b10abSAndroid Build Coastguard Worker   int frame_idx = 0;
239*fb1b10abSAndroid Build Coastguard Worker   int i;
240*fb1b10abSAndroid Build Coastguard Worker   int gld_index = -1;
241*fb1b10abSAndroid Build Coastguard Worker   int alt_index = -2;
242*fb1b10abSAndroid Build Coastguard Worker   int lst_index = -1;
243*fb1b10abSAndroid Build Coastguard Worker   int arf_index_stack[MAX_ARF_LAYERS];
244*fb1b10abSAndroid Build Coastguard Worker   int arf_stack_size = 0;
245*fb1b10abSAndroid Build Coastguard Worker   int extend_frame_count = 0;
246*fb1b10abSAndroid Build Coastguard Worker   int pframe_qindex = cpi->tpl_stats[2].base_qindex;
247*fb1b10abSAndroid Build Coastguard Worker   int frame_gop_offset = 0;
248*fb1b10abSAndroid Build Coastguard Worker 
249*fb1b10abSAndroid Build Coastguard Worker   RefCntBuffer *frame_bufs = cm->buffer_pool->frame_bufs;
250*fb1b10abSAndroid Build Coastguard Worker   int8_t recon_frame_index[REFS_PER_FRAME + MAX_ARF_LAYERS];
251*fb1b10abSAndroid Build Coastguard Worker 
252*fb1b10abSAndroid Build Coastguard Worker   memset(recon_frame_index, -1, sizeof(recon_frame_index));
253*fb1b10abSAndroid Build Coastguard Worker   stack_init(arf_index_stack, MAX_ARF_LAYERS);
254*fb1b10abSAndroid Build Coastguard Worker 
255*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < FRAME_BUFFERS; ++i) {
256*fb1b10abSAndroid Build Coastguard Worker     if (frame_bufs[i].ref_count == 0) {
257*fb1b10abSAndroid Build Coastguard Worker       alloc_frame_mvs(cm, i);
258*fb1b10abSAndroid Build Coastguard Worker       if (vpx_realloc_frame_buffer(&frame_bufs[i].buf, cm->width, cm->height,
259*fb1b10abSAndroid Build Coastguard Worker                                    cm->subsampling_x, cm->subsampling_y,
260*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
261*fb1b10abSAndroid Build Coastguard Worker                                    cm->use_highbitdepth,
262*fb1b10abSAndroid Build Coastguard Worker #endif
263*fb1b10abSAndroid Build Coastguard Worker                                    VP9_ENC_BORDER_IN_PIXELS, cm->byte_alignment,
264*fb1b10abSAndroid Build Coastguard Worker                                    NULL, NULL, NULL))
265*fb1b10abSAndroid Build Coastguard Worker         vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
266*fb1b10abSAndroid Build Coastguard Worker                            "Failed to allocate frame buffer");
267*fb1b10abSAndroid Build Coastguard Worker 
268*fb1b10abSAndroid Build Coastguard Worker       recon_frame_index[frame_idx] = i;
269*fb1b10abSAndroid Build Coastguard Worker       ++frame_idx;
270*fb1b10abSAndroid Build Coastguard Worker 
271*fb1b10abSAndroid Build Coastguard Worker       if (frame_idx >= REFS_PER_FRAME + cpi->oxcf.enable_auto_arf) break;
272*fb1b10abSAndroid Build Coastguard Worker     }
273*fb1b10abSAndroid Build Coastguard Worker   }
274*fb1b10abSAndroid Build Coastguard Worker 
275*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < REFS_PER_FRAME + 1; ++i) {
276*fb1b10abSAndroid Build Coastguard Worker     assert(recon_frame_index[i] >= 0);
277*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_recon_frames[i] = &frame_bufs[recon_frame_index[i]].buf;
278*fb1b10abSAndroid Build Coastguard Worker   }
279*fb1b10abSAndroid Build Coastguard Worker 
280*fb1b10abSAndroid Build Coastguard Worker   *tpl_group_frames = 0;
281*fb1b10abSAndroid Build Coastguard Worker 
282*fb1b10abSAndroid Build Coastguard Worker   // Initialize Golden reference frame.
283*fb1b10abSAndroid Build Coastguard Worker   gf_picture[0].frame = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
284*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < 3; ++i) gf_picture[0].ref_frame[i] = -REFS_PER_FRAME;
285*fb1b10abSAndroid Build Coastguard Worker   gf_picture[0].update_type = gf_group->update_type[0];
286*fb1b10abSAndroid Build Coastguard Worker   gld_index = 0;
287*fb1b10abSAndroid Build Coastguard Worker   ++*tpl_group_frames;
288*fb1b10abSAndroid Build Coastguard Worker 
289*fb1b10abSAndroid Build Coastguard Worker   gf_picture[-1].frame = get_ref_frame_buffer(cpi, LAST_FRAME);
290*fb1b10abSAndroid Build Coastguard Worker   gf_picture[-2].frame = get_ref_frame_buffer(cpi, ALTREF_FRAME);
291*fb1b10abSAndroid Build Coastguard Worker 
292*fb1b10abSAndroid Build Coastguard Worker   // Initialize base layer ARF frame
293*fb1b10abSAndroid Build Coastguard Worker   gf_picture[1].frame = cpi->Source;
294*fb1b10abSAndroid Build Coastguard Worker   gf_picture[1].ref_frame[0] = gld_index;
295*fb1b10abSAndroid Build Coastguard Worker   gf_picture[1].ref_frame[1] = lst_index;
296*fb1b10abSAndroid Build Coastguard Worker   gf_picture[1].ref_frame[2] = alt_index;
297*fb1b10abSAndroid Build Coastguard Worker   gf_picture[1].update_type = gf_group->update_type[1];
298*fb1b10abSAndroid Build Coastguard Worker   alt_index = 1;
299*fb1b10abSAndroid Build Coastguard Worker   ++*tpl_group_frames;
300*fb1b10abSAndroid Build Coastguard Worker 
301*fb1b10abSAndroid Build Coastguard Worker   // Initialize P frames
302*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = 2; frame_idx < MAX_ARF_GOP_SIZE; ++frame_idx) {
303*fb1b10abSAndroid Build Coastguard Worker     struct lookahead_entry *buf;
304*fb1b10abSAndroid Build Coastguard Worker     frame_gop_offset = gf_group->frame_gop_index[frame_idx];
305*fb1b10abSAndroid Build Coastguard Worker     buf = vp9_lookahead_peek(cpi->lookahead, frame_gop_offset - 1);
306*fb1b10abSAndroid Build Coastguard Worker 
307*fb1b10abSAndroid Build Coastguard Worker     if (buf == NULL) break;
308*fb1b10abSAndroid Build Coastguard Worker 
309*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].frame = &buf->img;
310*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[0] = gld_index;
311*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[1] = lst_index;
312*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[2] = alt_index;
313*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].update_type = gf_group->update_type[frame_idx];
314*fb1b10abSAndroid Build Coastguard Worker 
315*fb1b10abSAndroid Build Coastguard Worker     switch (gf_group->update_type[frame_idx]) {
316*fb1b10abSAndroid Build Coastguard Worker       case ARF_UPDATE:
317*fb1b10abSAndroid Build Coastguard Worker         stack_push(arf_index_stack, alt_index, arf_stack_size);
318*fb1b10abSAndroid Build Coastguard Worker         ++arf_stack_size;
319*fb1b10abSAndroid Build Coastguard Worker         alt_index = frame_idx;
320*fb1b10abSAndroid Build Coastguard Worker         break;
321*fb1b10abSAndroid Build Coastguard Worker       case LF_UPDATE: lst_index = frame_idx; break;
322*fb1b10abSAndroid Build Coastguard Worker       case OVERLAY_UPDATE:
323*fb1b10abSAndroid Build Coastguard Worker         gld_index = frame_idx;
324*fb1b10abSAndroid Build Coastguard Worker         alt_index = stack_pop(arf_index_stack, arf_stack_size);
325*fb1b10abSAndroid Build Coastguard Worker         --arf_stack_size;
326*fb1b10abSAndroid Build Coastguard Worker         break;
327*fb1b10abSAndroid Build Coastguard Worker       case USE_BUF_FRAME:
328*fb1b10abSAndroid Build Coastguard Worker         lst_index = alt_index;
329*fb1b10abSAndroid Build Coastguard Worker         alt_index = stack_pop(arf_index_stack, arf_stack_size);
330*fb1b10abSAndroid Build Coastguard Worker         --arf_stack_size;
331*fb1b10abSAndroid Build Coastguard Worker         break;
332*fb1b10abSAndroid Build Coastguard Worker       default: break;
333*fb1b10abSAndroid Build Coastguard Worker     }
334*fb1b10abSAndroid Build Coastguard Worker 
335*fb1b10abSAndroid Build Coastguard Worker     ++*tpl_group_frames;
336*fb1b10abSAndroid Build Coastguard Worker 
337*fb1b10abSAndroid Build Coastguard Worker     // The length of group of pictures is baseline_gf_interval, plus the
338*fb1b10abSAndroid Build Coastguard Worker     // beginning golden frame from last GOP, plus the last overlay frame in
339*fb1b10abSAndroid Build Coastguard Worker     // the same GOP.
340*fb1b10abSAndroid Build Coastguard Worker     if (frame_idx == gf_group->gf_group_size) break;
341*fb1b10abSAndroid Build Coastguard Worker   }
342*fb1b10abSAndroid Build Coastguard Worker 
343*fb1b10abSAndroid Build Coastguard Worker   alt_index = -1;
344*fb1b10abSAndroid Build Coastguard Worker   ++frame_idx;
345*fb1b10abSAndroid Build Coastguard Worker   ++frame_gop_offset;
346*fb1b10abSAndroid Build Coastguard Worker 
347*fb1b10abSAndroid Build Coastguard Worker   // Extend two frames outside the current gf group.
348*fb1b10abSAndroid Build Coastguard Worker   for (; frame_idx < MAX_LAG_BUFFERS && extend_frame_count < 2; ++frame_idx) {
349*fb1b10abSAndroid Build Coastguard Worker     struct lookahead_entry *buf =
350*fb1b10abSAndroid Build Coastguard Worker         vp9_lookahead_peek(cpi->lookahead, frame_gop_offset - 1);
351*fb1b10abSAndroid Build Coastguard Worker 
352*fb1b10abSAndroid Build Coastguard Worker     if (buf == NULL) break;
353*fb1b10abSAndroid Build Coastguard Worker 
354*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame_idx].base_qindex = pframe_qindex;
355*fb1b10abSAndroid Build Coastguard Worker 
356*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].frame = &buf->img;
357*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[0] = gld_index;
358*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[1] = lst_index;
359*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].ref_frame[2] = alt_index;
360*fb1b10abSAndroid Build Coastguard Worker     gf_picture[frame_idx].update_type = LF_UPDATE;
361*fb1b10abSAndroid Build Coastguard Worker     lst_index = frame_idx;
362*fb1b10abSAndroid Build Coastguard Worker     ++*tpl_group_frames;
363*fb1b10abSAndroid Build Coastguard Worker     ++extend_frame_count;
364*fb1b10abSAndroid Build Coastguard Worker     ++frame_gop_offset;
365*fb1b10abSAndroid Build Coastguard Worker   }
366*fb1b10abSAndroid Build Coastguard Worker 
367*fb1b10abSAndroid Build Coastguard Worker   return extend_frame_count;
368*fb1b10abSAndroid Build Coastguard Worker }
369*fb1b10abSAndroid Build Coastguard Worker 
init_tpl_stats(VP9_COMP * cpi)370*fb1b10abSAndroid Build Coastguard Worker static void init_tpl_stats(VP9_COMP *cpi) {
371*fb1b10abSAndroid Build Coastguard Worker   int frame_idx;
372*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = 0; frame_idx < MAX_ARF_GOP_SIZE; ++frame_idx) {
373*fb1b10abSAndroid Build Coastguard Worker     TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx];
374*fb1b10abSAndroid Build Coastguard Worker     memset(tpl_frame->tpl_stats_ptr, 0,
375*fb1b10abSAndroid Build Coastguard Worker            tpl_frame->height * tpl_frame->width *
376*fb1b10abSAndroid Build Coastguard Worker                sizeof(*tpl_frame->tpl_stats_ptr));
377*fb1b10abSAndroid Build Coastguard Worker     tpl_frame->is_valid = 0;
378*fb1b10abSAndroid Build Coastguard Worker   }
379*fb1b10abSAndroid Build Coastguard Worker }
380*fb1b10abSAndroid Build Coastguard Worker 
free_tpl_frame_stats_list(VpxTplGopStats * tpl_gop_stats)381*fb1b10abSAndroid Build Coastguard Worker static void free_tpl_frame_stats_list(VpxTplGopStats *tpl_gop_stats) {
382*fb1b10abSAndroid Build Coastguard Worker   int frame_idx;
383*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = 0; frame_idx < tpl_gop_stats->size; ++frame_idx) {
384*fb1b10abSAndroid Build Coastguard Worker     vpx_free(tpl_gop_stats->frame_stats_list[frame_idx].block_stats_list);
385*fb1b10abSAndroid Build Coastguard Worker   }
386*fb1b10abSAndroid Build Coastguard Worker   vpx_free(tpl_gop_stats->frame_stats_list);
387*fb1b10abSAndroid Build Coastguard Worker }
388*fb1b10abSAndroid Build Coastguard Worker 
init_tpl_stats_before_propagation(struct vpx_internal_error_info * error_info,VpxTplGopStats * tpl_gop_stats,TplDepFrame * tpl_stats,int tpl_gop_frames,int frame_width,int frame_height)389*fb1b10abSAndroid Build Coastguard Worker static void init_tpl_stats_before_propagation(
390*fb1b10abSAndroid Build Coastguard Worker     struct vpx_internal_error_info *error_info, VpxTplGopStats *tpl_gop_stats,
391*fb1b10abSAndroid Build Coastguard Worker     TplDepFrame *tpl_stats, int tpl_gop_frames, int frame_width,
392*fb1b10abSAndroid Build Coastguard Worker     int frame_height) {
393*fb1b10abSAndroid Build Coastguard Worker   int frame_idx;
394*fb1b10abSAndroid Build Coastguard Worker   free_tpl_frame_stats_list(tpl_gop_stats);
395*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(
396*fb1b10abSAndroid Build Coastguard Worker       error_info, tpl_gop_stats->frame_stats_list,
397*fb1b10abSAndroid Build Coastguard Worker       vpx_calloc(tpl_gop_frames, sizeof(*tpl_gop_stats->frame_stats_list)));
398*fb1b10abSAndroid Build Coastguard Worker   tpl_gop_stats->size = tpl_gop_frames;
399*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = 0; frame_idx < tpl_gop_frames; ++frame_idx) {
400*fb1b10abSAndroid Build Coastguard Worker     const int mi_rows = tpl_stats[frame_idx].mi_rows;
401*fb1b10abSAndroid Build Coastguard Worker     const int mi_cols = tpl_stats[frame_idx].mi_cols;
402*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(
403*fb1b10abSAndroid Build Coastguard Worker         error_info, tpl_gop_stats->frame_stats_list[frame_idx].block_stats_list,
404*fb1b10abSAndroid Build Coastguard Worker         vpx_calloc(
405*fb1b10abSAndroid Build Coastguard Worker             mi_rows * mi_cols,
406*fb1b10abSAndroid Build Coastguard Worker             sizeof(
407*fb1b10abSAndroid Build Coastguard Worker                 *tpl_gop_stats->frame_stats_list[frame_idx].block_stats_list)));
408*fb1b10abSAndroid Build Coastguard Worker     tpl_gop_stats->frame_stats_list[frame_idx].num_blocks = mi_rows * mi_cols;
409*fb1b10abSAndroid Build Coastguard Worker     tpl_gop_stats->frame_stats_list[frame_idx].frame_width = frame_width;
410*fb1b10abSAndroid Build Coastguard Worker     tpl_gop_stats->frame_stats_list[frame_idx].frame_height = frame_height;
411*fb1b10abSAndroid Build Coastguard Worker   }
412*fb1b10abSAndroid Build Coastguard Worker }
413*fb1b10abSAndroid Build Coastguard Worker 
414*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
full_pixel_motion_search(VP9_COMP * cpi,ThreadData * td,MotionField * motion_field,int frame_idx,uint8_t * cur_frame_buf,uint8_t * ref_frame_buf,int stride,BLOCK_SIZE bsize,int mi_row,int mi_col,MV * mv)415*fb1b10abSAndroid Build Coastguard Worker static uint32_t full_pixel_motion_search(VP9_COMP *cpi, ThreadData *td,
416*fb1b10abSAndroid Build Coastguard Worker                                          MotionField *motion_field,
417*fb1b10abSAndroid Build Coastguard Worker                                          int frame_idx, uint8_t *cur_frame_buf,
418*fb1b10abSAndroid Build Coastguard Worker                                          uint8_t *ref_frame_buf, int stride,
419*fb1b10abSAndroid Build Coastguard Worker                                          BLOCK_SIZE bsize, int mi_row,
420*fb1b10abSAndroid Build Coastguard Worker                                          int mi_col, MV *mv) {
421*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = &td->mb;
422*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
423*fb1b10abSAndroid Build Coastguard Worker   MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv;
424*fb1b10abSAndroid Build Coastguard Worker   int step_param;
425*fb1b10abSAndroid Build Coastguard Worker   uint32_t bestsme = UINT_MAX;
426*fb1b10abSAndroid Build Coastguard Worker   const MvLimits tmp_mv_limits = x->mv_limits;
427*fb1b10abSAndroid Build Coastguard Worker   // lambda is used to adjust the importance of motion vector consistency.
428*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): Figure out lambda's proper value.
429*fb1b10abSAndroid Build Coastguard Worker   const int lambda = cpi->tpl_stats[frame_idx].lambda;
430*fb1b10abSAndroid Build Coastguard Worker   int_mv nb_full_mvs[NB_MVS_NUM];
431*fb1b10abSAndroid Build Coastguard Worker   int nb_full_mv_num;
432*fb1b10abSAndroid Build Coastguard Worker 
433*fb1b10abSAndroid Build Coastguard Worker   MV best_ref_mv1 = { 0, 0 };
434*fb1b10abSAndroid Build Coastguard Worker   MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
435*fb1b10abSAndroid Build Coastguard Worker 
436*fb1b10abSAndroid Build Coastguard Worker   best_ref_mv1_full.col = best_ref_mv1.col >> 3;
437*fb1b10abSAndroid Build Coastguard Worker   best_ref_mv1_full.row = best_ref_mv1.row >> 3;
438*fb1b10abSAndroid Build Coastguard Worker 
439*fb1b10abSAndroid Build Coastguard Worker   // Setup frame pointers
440*fb1b10abSAndroid Build Coastguard Worker   x->plane[0].src.buf = cur_frame_buf;
441*fb1b10abSAndroid Build Coastguard Worker   x->plane[0].src.stride = stride;
442*fb1b10abSAndroid Build Coastguard Worker   xd->plane[0].pre[0].buf = ref_frame_buf;
443*fb1b10abSAndroid Build Coastguard Worker   xd->plane[0].pre[0].stride = stride;
444*fb1b10abSAndroid Build Coastguard Worker 
445*fb1b10abSAndroid Build Coastguard Worker   step_param = mv_sf->reduce_first_step_size;
446*fb1b10abSAndroid Build Coastguard Worker   step_param = VPXMIN(step_param, MAX_MVSEARCH_STEPS - 2);
447*fb1b10abSAndroid Build Coastguard Worker 
448*fb1b10abSAndroid Build Coastguard Worker   vp9_set_mv_search_range(&x->mv_limits, &best_ref_mv1);
449*fb1b10abSAndroid Build Coastguard Worker 
450*fb1b10abSAndroid Build Coastguard Worker   nb_full_mv_num =
451*fb1b10abSAndroid Build Coastguard Worker       vp9_prepare_nb_full_mvs(motion_field, mi_row, mi_col, nb_full_mvs);
452*fb1b10abSAndroid Build Coastguard Worker   vp9_full_pixel_diamond_new(cpi, x, bsize, &best_ref_mv1_full, step_param,
453*fb1b10abSAndroid Build Coastguard Worker                              lambda, 1, nb_full_mvs, nb_full_mv_num, mv);
454*fb1b10abSAndroid Build Coastguard Worker 
455*fb1b10abSAndroid Build Coastguard Worker   /* restore UMV window */
456*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits = tmp_mv_limits;
457*fb1b10abSAndroid Build Coastguard Worker 
458*fb1b10abSAndroid Build Coastguard Worker   return bestsme;
459*fb1b10abSAndroid Build Coastguard Worker }
460*fb1b10abSAndroid Build Coastguard Worker 
sub_pixel_motion_search(VP9_COMP * cpi,ThreadData * td,uint8_t * cur_frame_buf,uint8_t * ref_frame_buf,int stride,BLOCK_SIZE bsize,MV * mv)461*fb1b10abSAndroid Build Coastguard Worker static uint32_t sub_pixel_motion_search(VP9_COMP *cpi, ThreadData *td,
462*fb1b10abSAndroid Build Coastguard Worker                                         uint8_t *cur_frame_buf,
463*fb1b10abSAndroid Build Coastguard Worker                                         uint8_t *ref_frame_buf, int stride,
464*fb1b10abSAndroid Build Coastguard Worker                                         BLOCK_SIZE bsize, MV *mv) {
465*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = &td->mb;
466*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
467*fb1b10abSAndroid Build Coastguard Worker   MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv;
468*fb1b10abSAndroid Build Coastguard Worker   uint32_t bestsme = UINT_MAX;
469*fb1b10abSAndroid Build Coastguard Worker   uint32_t distortion;
470*fb1b10abSAndroid Build Coastguard Worker   uint32_t sse;
471*fb1b10abSAndroid Build Coastguard Worker   int cost_list[5];
472*fb1b10abSAndroid Build Coastguard Worker 
473*fb1b10abSAndroid Build Coastguard Worker   MV best_ref_mv1 = { 0, 0 };
474*fb1b10abSAndroid Build Coastguard Worker 
475*fb1b10abSAndroid Build Coastguard Worker   // Setup frame pointers
476*fb1b10abSAndroid Build Coastguard Worker   x->plane[0].src.buf = cur_frame_buf;
477*fb1b10abSAndroid Build Coastguard Worker   x->plane[0].src.stride = stride;
478*fb1b10abSAndroid Build Coastguard Worker   xd->plane[0].pre[0].buf = ref_frame_buf;
479*fb1b10abSAndroid Build Coastguard Worker   xd->plane[0].pre[0].stride = stride;
480*fb1b10abSAndroid Build Coastguard Worker 
481*fb1b10abSAndroid Build Coastguard Worker   // TODO(yunqing): may use higher tap interp filter than 2 taps.
482*fb1b10abSAndroid Build Coastguard Worker   // Ignore mv costing by sending NULL pointer instead of cost array
483*fb1b10abSAndroid Build Coastguard Worker   bestsme = cpi->find_fractional_mv_step(
484*fb1b10abSAndroid Build Coastguard Worker       x, mv, &best_ref_mv1, cpi->common.allow_high_precision_mv, x->errorperbit,
485*fb1b10abSAndroid Build Coastguard Worker       &cpi->fn_ptr[bsize], 0, mv_sf->subpel_search_level,
486*fb1b10abSAndroid Build Coastguard Worker       cond_cost_list(cpi, cost_list), NULL, NULL, &distortion, &sse, NULL, 0, 0,
487*fb1b10abSAndroid Build Coastguard Worker       USE_2_TAPS);
488*fb1b10abSAndroid Build Coastguard Worker 
489*fb1b10abSAndroid Build Coastguard Worker   return bestsme;
490*fb1b10abSAndroid Build Coastguard Worker }
491*fb1b10abSAndroid Build Coastguard Worker 
492*fb1b10abSAndroid Build Coastguard Worker #else  // CONFIG_NON_GREEDY_MV
motion_compensated_prediction(VP9_COMP * cpi,ThreadData * td,uint8_t * cur_frame_buf,uint8_t * ref_frame_buf,int stride,BLOCK_SIZE bsize,MV * mv)493*fb1b10abSAndroid Build Coastguard Worker static uint32_t motion_compensated_prediction(VP9_COMP *cpi, ThreadData *td,
494*fb1b10abSAndroid Build Coastguard Worker                                               uint8_t *cur_frame_buf,
495*fb1b10abSAndroid Build Coastguard Worker                                               uint8_t *ref_frame_buf,
496*fb1b10abSAndroid Build Coastguard Worker                                               int stride, BLOCK_SIZE bsize,
497*fb1b10abSAndroid Build Coastguard Worker                                               MV *mv) {
498*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *const x = &td->mb;
499*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
500*fb1b10abSAndroid Build Coastguard Worker   MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv;
501*fb1b10abSAndroid Build Coastguard Worker   const SEARCH_METHODS search_method = NSTEP;
502*fb1b10abSAndroid Build Coastguard Worker   int step_param;
503*fb1b10abSAndroid Build Coastguard Worker   int sadpb = x->sadperbit16;
504*fb1b10abSAndroid Build Coastguard Worker   uint32_t bestsme = UINT_MAX;
505*fb1b10abSAndroid Build Coastguard Worker   uint32_t distortion;
506*fb1b10abSAndroid Build Coastguard Worker   uint32_t sse;
507*fb1b10abSAndroid Build Coastguard Worker   int cost_list[5];
508*fb1b10abSAndroid Build Coastguard Worker   const MvLimits tmp_mv_limits = x->mv_limits;
509*fb1b10abSAndroid Build Coastguard Worker 
510*fb1b10abSAndroid Build Coastguard Worker   MV best_ref_mv1 = { 0, 0 };
511*fb1b10abSAndroid Build Coastguard Worker   MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
512*fb1b10abSAndroid Build Coastguard Worker 
513*fb1b10abSAndroid Build Coastguard Worker   best_ref_mv1_full.col = best_ref_mv1.col >> 3;
514*fb1b10abSAndroid Build Coastguard Worker   best_ref_mv1_full.row = best_ref_mv1.row >> 3;
515*fb1b10abSAndroid Build Coastguard Worker 
516*fb1b10abSAndroid Build Coastguard Worker   // Setup frame pointers
517*fb1b10abSAndroid Build Coastguard Worker   x->plane[0].src.buf = cur_frame_buf;
518*fb1b10abSAndroid Build Coastguard Worker   x->plane[0].src.stride = stride;
519*fb1b10abSAndroid Build Coastguard Worker   xd->plane[0].pre[0].buf = ref_frame_buf;
520*fb1b10abSAndroid Build Coastguard Worker   xd->plane[0].pre[0].stride = stride;
521*fb1b10abSAndroid Build Coastguard Worker 
522*fb1b10abSAndroid Build Coastguard Worker   step_param = mv_sf->reduce_first_step_size;
523*fb1b10abSAndroid Build Coastguard Worker   step_param = VPXMIN(step_param, MAX_MVSEARCH_STEPS - 2);
524*fb1b10abSAndroid Build Coastguard Worker 
525*fb1b10abSAndroid Build Coastguard Worker   vp9_set_mv_search_range(&x->mv_limits, &best_ref_mv1);
526*fb1b10abSAndroid Build Coastguard Worker 
527*fb1b10abSAndroid Build Coastguard Worker   vp9_full_pixel_search(cpi, x, bsize, &best_ref_mv1_full, step_param,
528*fb1b10abSAndroid Build Coastguard Worker                         search_method, sadpb, cond_cost_list(cpi, cost_list),
529*fb1b10abSAndroid Build Coastguard Worker                         &best_ref_mv1, mv, 0, 0);
530*fb1b10abSAndroid Build Coastguard Worker 
531*fb1b10abSAndroid Build Coastguard Worker   /* restore UMV window */
532*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits = tmp_mv_limits;
533*fb1b10abSAndroid Build Coastguard Worker 
534*fb1b10abSAndroid Build Coastguard Worker   // TODO(yunqing): may use higher tap interp filter than 2 taps.
535*fb1b10abSAndroid Build Coastguard Worker   // Ignore mv costing by sending NULL pointer instead of cost array
536*fb1b10abSAndroid Build Coastguard Worker   bestsme = cpi->find_fractional_mv_step(
537*fb1b10abSAndroid Build Coastguard Worker       x, mv, &best_ref_mv1, cpi->common.allow_high_precision_mv, x->errorperbit,
538*fb1b10abSAndroid Build Coastguard Worker       &cpi->fn_ptr[bsize], 0, mv_sf->subpel_search_level,
539*fb1b10abSAndroid Build Coastguard Worker       cond_cost_list(cpi, cost_list), NULL, NULL, &distortion, &sse, NULL, 0, 0,
540*fb1b10abSAndroid Build Coastguard Worker       USE_2_TAPS);
541*fb1b10abSAndroid Build Coastguard Worker 
542*fb1b10abSAndroid Build Coastguard Worker   return bestsme;
543*fb1b10abSAndroid Build Coastguard Worker }
544*fb1b10abSAndroid Build Coastguard Worker #endif
545*fb1b10abSAndroid Build Coastguard Worker 
get_overlap_area(int grid_pos_row,int grid_pos_col,int ref_pos_row,int ref_pos_col,int block,BLOCK_SIZE bsize)546*fb1b10abSAndroid Build Coastguard Worker static int get_overlap_area(int grid_pos_row, int grid_pos_col, int ref_pos_row,
547*fb1b10abSAndroid Build Coastguard Worker                             int ref_pos_col, int block, BLOCK_SIZE bsize) {
548*fb1b10abSAndroid Build Coastguard Worker   int width = 0, height = 0;
549*fb1b10abSAndroid Build Coastguard Worker   int bw = 4 << b_width_log2_lookup[bsize];
550*fb1b10abSAndroid Build Coastguard Worker   int bh = 4 << b_height_log2_lookup[bsize];
551*fb1b10abSAndroid Build Coastguard Worker 
552*fb1b10abSAndroid Build Coastguard Worker   switch (block) {
553*fb1b10abSAndroid Build Coastguard Worker     case 0:
554*fb1b10abSAndroid Build Coastguard Worker       width = grid_pos_col + bw - ref_pos_col;
555*fb1b10abSAndroid Build Coastguard Worker       height = grid_pos_row + bh - ref_pos_row;
556*fb1b10abSAndroid Build Coastguard Worker       break;
557*fb1b10abSAndroid Build Coastguard Worker     case 1:
558*fb1b10abSAndroid Build Coastguard Worker       width = ref_pos_col + bw - grid_pos_col;
559*fb1b10abSAndroid Build Coastguard Worker       height = grid_pos_row + bh - ref_pos_row;
560*fb1b10abSAndroid Build Coastguard Worker       break;
561*fb1b10abSAndroid Build Coastguard Worker     case 2:
562*fb1b10abSAndroid Build Coastguard Worker       width = grid_pos_col + bw - ref_pos_col;
563*fb1b10abSAndroid Build Coastguard Worker       height = ref_pos_row + bh - grid_pos_row;
564*fb1b10abSAndroid Build Coastguard Worker       break;
565*fb1b10abSAndroid Build Coastguard Worker     case 3:
566*fb1b10abSAndroid Build Coastguard Worker       width = ref_pos_col + bw - grid_pos_col;
567*fb1b10abSAndroid Build Coastguard Worker       height = ref_pos_row + bh - grid_pos_row;
568*fb1b10abSAndroid Build Coastguard Worker       break;
569*fb1b10abSAndroid Build Coastguard Worker     default: assert(0);
570*fb1b10abSAndroid Build Coastguard Worker   }
571*fb1b10abSAndroid Build Coastguard Worker 
572*fb1b10abSAndroid Build Coastguard Worker   return width * height;
573*fb1b10abSAndroid Build Coastguard Worker }
574*fb1b10abSAndroid Build Coastguard Worker 
round_floor(int ref_pos,int bsize_pix)575*fb1b10abSAndroid Build Coastguard Worker static int round_floor(int ref_pos, int bsize_pix) {
576*fb1b10abSAndroid Build Coastguard Worker   int round;
577*fb1b10abSAndroid Build Coastguard Worker   if (ref_pos < 0)
578*fb1b10abSAndroid Build Coastguard Worker     round = -(1 + (-ref_pos - 1) / bsize_pix);
579*fb1b10abSAndroid Build Coastguard Worker   else
580*fb1b10abSAndroid Build Coastguard Worker     round = ref_pos / bsize_pix;
581*fb1b10abSAndroid Build Coastguard Worker 
582*fb1b10abSAndroid Build Coastguard Worker   return round;
583*fb1b10abSAndroid Build Coastguard Worker }
584*fb1b10abSAndroid Build Coastguard Worker 
tpl_model_store(TplDepStats * tpl_stats,int mi_row,int mi_col,BLOCK_SIZE bsize,int stride)585*fb1b10abSAndroid Build Coastguard Worker static void tpl_model_store(TplDepStats *tpl_stats, int mi_row, int mi_col,
586*fb1b10abSAndroid Build Coastguard Worker                             BLOCK_SIZE bsize, int stride) {
587*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
588*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
589*fb1b10abSAndroid Build Coastguard Worker   const TplDepStats *src_stats = &tpl_stats[mi_row * stride + mi_col];
590*fb1b10abSAndroid Build Coastguard Worker   int idx, idy;
591*fb1b10abSAndroid Build Coastguard Worker 
592*fb1b10abSAndroid Build Coastguard Worker   for (idy = 0; idy < mi_height; ++idy) {
593*fb1b10abSAndroid Build Coastguard Worker     for (idx = 0; idx < mi_width; ++idx) {
594*fb1b10abSAndroid Build Coastguard Worker       TplDepStats *tpl_ptr = &tpl_stats[(mi_row + idy) * stride + mi_col + idx];
595*fb1b10abSAndroid Build Coastguard Worker       const int64_t mc_flow = tpl_ptr->mc_flow;
596*fb1b10abSAndroid Build Coastguard Worker       const int64_t mc_ref_cost = tpl_ptr->mc_ref_cost;
597*fb1b10abSAndroid Build Coastguard Worker       *tpl_ptr = *src_stats;
598*fb1b10abSAndroid Build Coastguard Worker       tpl_ptr->mc_flow = mc_flow;
599*fb1b10abSAndroid Build Coastguard Worker       tpl_ptr->mc_ref_cost = mc_ref_cost;
600*fb1b10abSAndroid Build Coastguard Worker       tpl_ptr->mc_dep_cost = tpl_ptr->intra_cost + tpl_ptr->mc_flow;
601*fb1b10abSAndroid Build Coastguard Worker     }
602*fb1b10abSAndroid Build Coastguard Worker   }
603*fb1b10abSAndroid Build Coastguard Worker }
604*fb1b10abSAndroid Build Coastguard Worker 
tpl_store_before_propagation(VpxTplBlockStats * tpl_block_stats,TplDepStats * tpl_stats,int mi_row,int mi_col,BLOCK_SIZE bsize,int src_stride,int64_t recon_error,int64_t rate_cost,int ref_frame_idx,int mi_rows,int mi_cols)605*fb1b10abSAndroid Build Coastguard Worker static void tpl_store_before_propagation(VpxTplBlockStats *tpl_block_stats,
606*fb1b10abSAndroid Build Coastguard Worker                                          TplDepStats *tpl_stats, int mi_row,
607*fb1b10abSAndroid Build Coastguard Worker                                          int mi_col, BLOCK_SIZE bsize,
608*fb1b10abSAndroid Build Coastguard Worker                                          int src_stride, int64_t recon_error,
609*fb1b10abSAndroid Build Coastguard Worker                                          int64_t rate_cost, int ref_frame_idx,
610*fb1b10abSAndroid Build Coastguard Worker                                          int mi_rows, int mi_cols) {
611*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
612*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
613*fb1b10abSAndroid Build Coastguard Worker   const TplDepStats *src_stats = &tpl_stats[mi_row * src_stride + mi_col];
614*fb1b10abSAndroid Build Coastguard Worker   int idx, idy;
615*fb1b10abSAndroid Build Coastguard Worker 
616*fb1b10abSAndroid Build Coastguard Worker   for (idy = 0; idy < mi_height; ++idy) {
617*fb1b10abSAndroid Build Coastguard Worker     for (idx = 0; idx < mi_width; ++idx) {
618*fb1b10abSAndroid Build Coastguard Worker       if (mi_row + idy >= mi_rows || mi_col + idx >= mi_cols) continue;
619*fb1b10abSAndroid Build Coastguard Worker       VpxTplBlockStats *tpl_block_stats_ptr =
620*fb1b10abSAndroid Build Coastguard Worker           &tpl_block_stats[(mi_row + idy) * mi_cols + mi_col + idx];
621*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->row = mi_row * 8 + idy * 8;
622*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->col = mi_col * 8 + idx * 8;
623*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->inter_cost = src_stats->inter_cost;
624*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->intra_cost = src_stats->intra_cost;
625*fb1b10abSAndroid Build Coastguard Worker       // inter/intra_cost here is calculated with SATD which should be close
626*fb1b10abSAndroid Build Coastguard Worker       // enough to be used as inter/intra_pred_error
627*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->inter_pred_err = src_stats->inter_cost;
628*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->intra_pred_err = src_stats->intra_cost;
629*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->srcrf_dist = recon_error << TPL_DEP_COST_SCALE_LOG2;
630*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->srcrf_rate = rate_cost << TPL_DEP_COST_SCALE_LOG2;
631*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->mv_r = src_stats->mv.as_mv.row;
632*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->mv_c = src_stats->mv.as_mv.col;
633*fb1b10abSAndroid Build Coastguard Worker       tpl_block_stats_ptr->ref_frame_index = ref_frame_idx;
634*fb1b10abSAndroid Build Coastguard Worker     }
635*fb1b10abSAndroid Build Coastguard Worker   }
636*fb1b10abSAndroid Build Coastguard Worker }
637*fb1b10abSAndroid Build Coastguard Worker 
tpl_model_update_b(TplDepFrame * tpl_frame,TplDepStats * tpl_stats,int mi_row,int mi_col,const BLOCK_SIZE bsize)638*fb1b10abSAndroid Build Coastguard Worker static void tpl_model_update_b(TplDepFrame *tpl_frame, TplDepStats *tpl_stats,
639*fb1b10abSAndroid Build Coastguard Worker                                int mi_row, int mi_col, const BLOCK_SIZE bsize) {
640*fb1b10abSAndroid Build Coastguard Worker   if (tpl_stats->ref_frame_index < 0) return;
641*fb1b10abSAndroid Build Coastguard Worker 
642*fb1b10abSAndroid Build Coastguard Worker   TplDepFrame *ref_tpl_frame = &tpl_frame[tpl_stats->ref_frame_index];
643*fb1b10abSAndroid Build Coastguard Worker   TplDepStats *ref_stats = ref_tpl_frame->tpl_stats_ptr;
644*fb1b10abSAndroid Build Coastguard Worker   MV mv = tpl_stats->mv.as_mv;
645*fb1b10abSAndroid Build Coastguard Worker   int mv_row = mv.row >> 3;
646*fb1b10abSAndroid Build Coastguard Worker   int mv_col = mv.col >> 3;
647*fb1b10abSAndroid Build Coastguard Worker 
648*fb1b10abSAndroid Build Coastguard Worker   int ref_pos_row = mi_row * MI_SIZE + mv_row;
649*fb1b10abSAndroid Build Coastguard Worker   int ref_pos_col = mi_col * MI_SIZE + mv_col;
650*fb1b10abSAndroid Build Coastguard Worker 
651*fb1b10abSAndroid Build Coastguard Worker   const int bw = 4 << b_width_log2_lookup[bsize];
652*fb1b10abSAndroid Build Coastguard Worker   const int bh = 4 << b_height_log2_lookup[bsize];
653*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
654*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
655*fb1b10abSAndroid Build Coastguard Worker   const int pix_num = bw * bh;
656*fb1b10abSAndroid Build Coastguard Worker 
657*fb1b10abSAndroid Build Coastguard Worker   // top-left on grid block location in pixel
658*fb1b10abSAndroid Build Coastguard Worker   int grid_pos_row_base = round_floor(ref_pos_row, bh) * bh;
659*fb1b10abSAndroid Build Coastguard Worker   int grid_pos_col_base = round_floor(ref_pos_col, bw) * bw;
660*fb1b10abSAndroid Build Coastguard Worker   int block;
661*fb1b10abSAndroid Build Coastguard Worker 
662*fb1b10abSAndroid Build Coastguard Worker   for (block = 0; block < 4; ++block) {
663*fb1b10abSAndroid Build Coastguard Worker     int grid_pos_row = grid_pos_row_base + bh * (block >> 1);
664*fb1b10abSAndroid Build Coastguard Worker     int grid_pos_col = grid_pos_col_base + bw * (block & 0x01);
665*fb1b10abSAndroid Build Coastguard Worker 
666*fb1b10abSAndroid Build Coastguard Worker     if (grid_pos_row >= 0 && grid_pos_row < ref_tpl_frame->mi_rows * MI_SIZE &&
667*fb1b10abSAndroid Build Coastguard Worker         grid_pos_col >= 0 && grid_pos_col < ref_tpl_frame->mi_cols * MI_SIZE) {
668*fb1b10abSAndroid Build Coastguard Worker       int overlap_area = get_overlap_area(
669*fb1b10abSAndroid Build Coastguard Worker           grid_pos_row, grid_pos_col, ref_pos_row, ref_pos_col, block, bsize);
670*fb1b10abSAndroid Build Coastguard Worker       int ref_mi_row = round_floor(grid_pos_row, bh) * mi_height;
671*fb1b10abSAndroid Build Coastguard Worker       int ref_mi_col = round_floor(grid_pos_col, bw) * mi_width;
672*fb1b10abSAndroid Build Coastguard Worker 
673*fb1b10abSAndroid Build Coastguard Worker       int64_t mc_flow = tpl_stats->mc_dep_cost -
674*fb1b10abSAndroid Build Coastguard Worker                         (tpl_stats->mc_dep_cost * tpl_stats->inter_cost) /
675*fb1b10abSAndroid Build Coastguard Worker                             tpl_stats->intra_cost;
676*fb1b10abSAndroid Build Coastguard Worker 
677*fb1b10abSAndroid Build Coastguard Worker       int idx, idy;
678*fb1b10abSAndroid Build Coastguard Worker 
679*fb1b10abSAndroid Build Coastguard Worker       for (idy = 0; idy < mi_height; ++idy) {
680*fb1b10abSAndroid Build Coastguard Worker         for (idx = 0; idx < mi_width; ++idx) {
681*fb1b10abSAndroid Build Coastguard Worker           TplDepStats *des_stats =
682*fb1b10abSAndroid Build Coastguard Worker               &ref_stats[(ref_mi_row + idy) * ref_tpl_frame->stride +
683*fb1b10abSAndroid Build Coastguard Worker                          (ref_mi_col + idx)];
684*fb1b10abSAndroid Build Coastguard Worker 
685*fb1b10abSAndroid Build Coastguard Worker           des_stats->mc_flow += (mc_flow * overlap_area) / pix_num;
686*fb1b10abSAndroid Build Coastguard Worker           des_stats->mc_ref_cost +=
687*fb1b10abSAndroid Build Coastguard Worker               ((tpl_stats->intra_cost - tpl_stats->inter_cost) * overlap_area) /
688*fb1b10abSAndroid Build Coastguard Worker               pix_num;
689*fb1b10abSAndroid Build Coastguard Worker           assert(overlap_area >= 0);
690*fb1b10abSAndroid Build Coastguard Worker         }
691*fb1b10abSAndroid Build Coastguard Worker       }
692*fb1b10abSAndroid Build Coastguard Worker     }
693*fb1b10abSAndroid Build Coastguard Worker   }
694*fb1b10abSAndroid Build Coastguard Worker }
695*fb1b10abSAndroid Build Coastguard Worker 
tpl_model_update(TplDepFrame * tpl_frame,TplDepStats * tpl_stats,int mi_row,int mi_col,const BLOCK_SIZE bsize)696*fb1b10abSAndroid Build Coastguard Worker static void tpl_model_update(TplDepFrame *tpl_frame, TplDepStats *tpl_stats,
697*fb1b10abSAndroid Build Coastguard Worker                              int mi_row, int mi_col, const BLOCK_SIZE bsize) {
698*fb1b10abSAndroid Build Coastguard Worker   int idx, idy;
699*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
700*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
701*fb1b10abSAndroid Build Coastguard Worker 
702*fb1b10abSAndroid Build Coastguard Worker   for (idy = 0; idy < mi_height; ++idy) {
703*fb1b10abSAndroid Build Coastguard Worker     for (idx = 0; idx < mi_width; ++idx) {
704*fb1b10abSAndroid Build Coastguard Worker       TplDepStats *tpl_ptr =
705*fb1b10abSAndroid Build Coastguard Worker           &tpl_stats[(mi_row + idy) * tpl_frame->stride + (mi_col + idx)];
706*fb1b10abSAndroid Build Coastguard Worker       tpl_model_update_b(tpl_frame, tpl_ptr, mi_row + idy, mi_col + idx,
707*fb1b10abSAndroid Build Coastguard Worker                          BLOCK_8X8);
708*fb1b10abSAndroid Build Coastguard Worker     }
709*fb1b10abSAndroid Build Coastguard Worker   }
710*fb1b10abSAndroid Build Coastguard Worker }
711*fb1b10abSAndroid Build Coastguard Worker 
get_quantize_error(MACROBLOCK * x,int plane,tran_low_t * coeff,tran_low_t * qcoeff,tran_low_t * dqcoeff,TX_SIZE tx_size,int64_t * recon_error,int64_t * sse,uint16_t * eob)712*fb1b10abSAndroid Build Coastguard Worker static void get_quantize_error(MACROBLOCK *x, int plane, tran_low_t *coeff,
713*fb1b10abSAndroid Build Coastguard Worker                                tran_low_t *qcoeff, tran_low_t *dqcoeff,
714*fb1b10abSAndroid Build Coastguard Worker                                TX_SIZE tx_size, int64_t *recon_error,
715*fb1b10abSAndroid Build Coastguard Worker                                int64_t *sse, uint16_t *eob) {
716*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *const xd = &x->e_mbd;
717*fb1b10abSAndroid Build Coastguard Worker   const struct macroblock_plane *const p = &x->plane[plane];
718*fb1b10abSAndroid Build Coastguard Worker   const struct macroblockd_plane *const pd = &xd->plane[plane];
719*fb1b10abSAndroid Build Coastguard Worker   const ScanOrder *const scan_order = &vp9_default_scan_orders[tx_size];
720*fb1b10abSAndroid Build Coastguard Worker   int pix_num = 1 << num_pels_log2_lookup[txsize_to_bsize[tx_size]];
721*fb1b10abSAndroid Build Coastguard Worker   const int shift = tx_size == TX_32X32 ? 0 : 2;
722*fb1b10abSAndroid Build Coastguard Worker 
723*fb1b10abSAndroid Build Coastguard Worker   // skip block condition should be handled before this is called.
724*fb1b10abSAndroid Build Coastguard Worker   assert(!x->skip_block);
725*fb1b10abSAndroid Build Coastguard Worker 
726*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
727*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
728*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_quantize_fp_32x32(coeff, pix_num, p, qcoeff, dqcoeff,
729*fb1b10abSAndroid Build Coastguard Worker                                  pd->dequant, eob, scan_order);
730*fb1b10abSAndroid Build Coastguard Worker   } else {
731*fb1b10abSAndroid Build Coastguard Worker     vp9_quantize_fp_32x32(coeff, pix_num, p, qcoeff, dqcoeff, pd->dequant, eob,
732*fb1b10abSAndroid Build Coastguard Worker                           scan_order);
733*fb1b10abSAndroid Build Coastguard Worker   }
734*fb1b10abSAndroid Build Coastguard Worker #else
735*fb1b10abSAndroid Build Coastguard Worker   vp9_quantize_fp_32x32(coeff, pix_num, p, qcoeff, dqcoeff, pd->dequant, eob,
736*fb1b10abSAndroid Build Coastguard Worker                         scan_order);
737*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
738*fb1b10abSAndroid Build Coastguard Worker 
739*fb1b10abSAndroid Build Coastguard Worker   *recon_error = vp9_block_error(coeff, dqcoeff, pix_num, sse) >> shift;
740*fb1b10abSAndroid Build Coastguard Worker   *recon_error = VPXMAX(*recon_error, 1);
741*fb1b10abSAndroid Build Coastguard Worker 
742*fb1b10abSAndroid Build Coastguard Worker   *sse = (*sse) >> shift;
743*fb1b10abSAndroid Build Coastguard Worker   *sse = VPXMAX(*sse, 1);
744*fb1b10abSAndroid Build Coastguard Worker }
745*fb1b10abSAndroid Build Coastguard Worker 
746*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
vp9_highbd_wht_fwd_txfm(int16_t * src_diff,int bw,tran_low_t * coeff,TX_SIZE tx_size)747*fb1b10abSAndroid Build Coastguard Worker void vp9_highbd_wht_fwd_txfm(int16_t *src_diff, int bw, tran_low_t *coeff,
748*fb1b10abSAndroid Build Coastguard Worker                              TX_SIZE tx_size) {
749*fb1b10abSAndroid Build Coastguard Worker   // TODO(sdeng): Implement SIMD based high bit-depth Hadamard transforms.
750*fb1b10abSAndroid Build Coastguard Worker   switch (tx_size) {
751*fb1b10abSAndroid Build Coastguard Worker     case TX_8X8: vpx_highbd_hadamard_8x8(src_diff, bw, coeff); break;
752*fb1b10abSAndroid Build Coastguard Worker     case TX_16X16: vpx_highbd_hadamard_16x16(src_diff, bw, coeff); break;
753*fb1b10abSAndroid Build Coastguard Worker     case TX_32X32: vpx_highbd_hadamard_32x32(src_diff, bw, coeff); break;
754*fb1b10abSAndroid Build Coastguard Worker     default: assert(0);
755*fb1b10abSAndroid Build Coastguard Worker   }
756*fb1b10abSAndroid Build Coastguard Worker }
757*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
758*fb1b10abSAndroid Build Coastguard Worker 
vp9_wht_fwd_txfm(int16_t * src_diff,int bw,tran_low_t * coeff,TX_SIZE tx_size)759*fb1b10abSAndroid Build Coastguard Worker void vp9_wht_fwd_txfm(int16_t *src_diff, int bw, tran_low_t *coeff,
760*fb1b10abSAndroid Build Coastguard Worker                       TX_SIZE tx_size) {
761*fb1b10abSAndroid Build Coastguard Worker   switch (tx_size) {
762*fb1b10abSAndroid Build Coastguard Worker     case TX_8X8: vpx_hadamard_8x8(src_diff, bw, coeff); break;
763*fb1b10abSAndroid Build Coastguard Worker     case TX_16X16: vpx_hadamard_16x16(src_diff, bw, coeff); break;
764*fb1b10abSAndroid Build Coastguard Worker     case TX_32X32: vpx_hadamard_32x32(src_diff, bw, coeff); break;
765*fb1b10abSAndroid Build Coastguard Worker     default: assert(0);
766*fb1b10abSAndroid Build Coastguard Worker   }
767*fb1b10abSAndroid Build Coastguard Worker }
768*fb1b10abSAndroid Build Coastguard Worker 
set_mv_limits(const VP9_COMMON * cm,MACROBLOCK * x,int mi_row,int mi_col)769*fb1b10abSAndroid Build Coastguard Worker static void set_mv_limits(const VP9_COMMON *cm, MACROBLOCK *x, int mi_row,
770*fb1b10abSAndroid Build Coastguard Worker                           int mi_col) {
771*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits.row_min = -((mi_row * MI_SIZE) + (17 - 2 * VP9_INTERP_EXTEND));
772*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits.row_max =
773*fb1b10abSAndroid Build Coastguard Worker       (cm->mi_rows - 1 - mi_row) * MI_SIZE + (17 - 2 * VP9_INTERP_EXTEND);
774*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits.col_min = -((mi_col * MI_SIZE) + (17 - 2 * VP9_INTERP_EXTEND));
775*fb1b10abSAndroid Build Coastguard Worker   x->mv_limits.col_max =
776*fb1b10abSAndroid Build Coastguard Worker       ((cm->mi_cols - 1 - mi_col) * MI_SIZE) + (17 - 2 * VP9_INTERP_EXTEND);
777*fb1b10abSAndroid Build Coastguard Worker }
778*fb1b10abSAndroid Build Coastguard Worker 
rate_estimator(const tran_low_t * qcoeff,int eob,TX_SIZE tx_size)779*fb1b10abSAndroid Build Coastguard Worker static int rate_estimator(const tran_low_t *qcoeff, int eob, TX_SIZE tx_size) {
780*fb1b10abSAndroid Build Coastguard Worker   const ScanOrder *const scan_order = &vp9_scan_orders[tx_size][DCT_DCT];
781*fb1b10abSAndroid Build Coastguard Worker   int rate_cost = 1;
782*fb1b10abSAndroid Build Coastguard Worker   int idx;
783*fb1b10abSAndroid Build Coastguard Worker   assert((1 << num_pels_log2_lookup[txsize_to_bsize[tx_size]]) >= eob);
784*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < eob; ++idx) {
785*fb1b10abSAndroid Build Coastguard Worker     unsigned int abs_level = abs(qcoeff[scan_order->scan[idx]]);
786*fb1b10abSAndroid Build Coastguard Worker     rate_cost += get_msb(abs_level + 1) + 1 + (abs_level > 0);
787*fb1b10abSAndroid Build Coastguard Worker   }
788*fb1b10abSAndroid Build Coastguard Worker 
789*fb1b10abSAndroid Build Coastguard Worker   return (rate_cost << VP9_PROB_COST_SHIFT);
790*fb1b10abSAndroid Build Coastguard Worker }
791*fb1b10abSAndroid Build Coastguard Worker 
mode_estimation(VP9_COMP * cpi,MACROBLOCK * x,MACROBLOCKD * xd,struct scale_factors * sf,GF_PICTURE * gf_picture,int frame_idx,TplDepFrame * tpl_frame,int16_t * src_diff,tran_low_t * coeff,tran_low_t * qcoeff,tran_low_t * dqcoeff,int mi_row,int mi_col,BLOCK_SIZE bsize,TX_SIZE tx_size,YV12_BUFFER_CONFIG * ref_frame[],uint8_t * predictor,int64_t * recon_error,int64_t * rate_cost,int64_t * sse,int * ref_frame_idx)792*fb1b10abSAndroid Build Coastguard Worker static void mode_estimation(VP9_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
793*fb1b10abSAndroid Build Coastguard Worker                             struct scale_factors *sf, GF_PICTURE *gf_picture,
794*fb1b10abSAndroid Build Coastguard Worker                             int frame_idx, TplDepFrame *tpl_frame,
795*fb1b10abSAndroid Build Coastguard Worker                             int16_t *src_diff, tran_low_t *coeff,
796*fb1b10abSAndroid Build Coastguard Worker                             tran_low_t *qcoeff, tran_low_t *dqcoeff, int mi_row,
797*fb1b10abSAndroid Build Coastguard Worker                             int mi_col, BLOCK_SIZE bsize, TX_SIZE tx_size,
798*fb1b10abSAndroid Build Coastguard Worker                             YV12_BUFFER_CONFIG *ref_frame[], uint8_t *predictor,
799*fb1b10abSAndroid Build Coastguard Worker                             int64_t *recon_error, int64_t *rate_cost,
800*fb1b10abSAndroid Build Coastguard Worker                             int64_t *sse, int *ref_frame_idx) {
801*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi->common;
802*fb1b10abSAndroid Build Coastguard Worker   ThreadData *td = &cpi->td;
803*fb1b10abSAndroid Build Coastguard Worker 
804*fb1b10abSAndroid Build Coastguard Worker   const int bw = 4 << b_width_log2_lookup[bsize];
805*fb1b10abSAndroid Build Coastguard Worker   const int bh = 4 << b_height_log2_lookup[bsize];
806*fb1b10abSAndroid Build Coastguard Worker   const int pix_num = bw * bh;
807*fb1b10abSAndroid Build Coastguard Worker   int best_rf_idx = -1;
808*fb1b10abSAndroid Build Coastguard Worker   int_mv best_mv;
809*fb1b10abSAndroid Build Coastguard Worker   int64_t best_inter_cost = INT64_MAX;
810*fb1b10abSAndroid Build Coastguard Worker   int64_t inter_cost;
811*fb1b10abSAndroid Build Coastguard Worker   int rf_idx;
812*fb1b10abSAndroid Build Coastguard Worker   const InterpKernel *const kernel = vp9_filter_kernels[EIGHTTAP];
813*fb1b10abSAndroid Build Coastguard Worker 
814*fb1b10abSAndroid Build Coastguard Worker   int64_t best_intra_cost = INT64_MAX;
815*fb1b10abSAndroid Build Coastguard Worker   int64_t intra_cost;
816*fb1b10abSAndroid Build Coastguard Worker   PREDICTION_MODE mode;
817*fb1b10abSAndroid Build Coastguard Worker   int mb_y_offset = mi_row * MI_SIZE * xd->cur_buf->y_stride + mi_col * MI_SIZE;
818*fb1b10abSAndroid Build Coastguard Worker   MODE_INFO mi_above, mi_left;
819*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
820*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
821*fb1b10abSAndroid Build Coastguard Worker   TplDepStats *tpl_stats =
822*fb1b10abSAndroid Build Coastguard Worker       &tpl_frame->tpl_stats_ptr[mi_row * tpl_frame->stride + mi_col];
823*fb1b10abSAndroid Build Coastguard Worker 
824*fb1b10abSAndroid Build Coastguard Worker   xd->mb_to_top_edge = -((mi_row * MI_SIZE) * 8);
825*fb1b10abSAndroid Build Coastguard Worker   xd->mb_to_bottom_edge = ((cm->mi_rows - 1 - mi_row) * MI_SIZE) * 8;
826*fb1b10abSAndroid Build Coastguard Worker   xd->mb_to_left_edge = -((mi_col * MI_SIZE) * 8);
827*fb1b10abSAndroid Build Coastguard Worker   xd->mb_to_right_edge = ((cm->mi_cols - 1 - mi_col) * MI_SIZE) * 8;
828*fb1b10abSAndroid Build Coastguard Worker   xd->above_mi = (mi_row > 0) ? &mi_above : NULL;
829*fb1b10abSAndroid Build Coastguard Worker   xd->left_mi = (mi_col > 0) ? &mi_left : NULL;
830*fb1b10abSAndroid Build Coastguard Worker 
831*fb1b10abSAndroid Build Coastguard Worker   // Intra prediction search
832*fb1b10abSAndroid Build Coastguard Worker   for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
833*fb1b10abSAndroid Build Coastguard Worker     uint8_t *src, *dst;
834*fb1b10abSAndroid Build Coastguard Worker     int src_stride, dst_stride;
835*fb1b10abSAndroid Build Coastguard Worker 
836*fb1b10abSAndroid Build Coastguard Worker     src = xd->cur_buf->y_buffer + mb_y_offset;
837*fb1b10abSAndroid Build Coastguard Worker     src_stride = xd->cur_buf->y_stride;
838*fb1b10abSAndroid Build Coastguard Worker 
839*fb1b10abSAndroid Build Coastguard Worker     dst = &predictor[0];
840*fb1b10abSAndroid Build Coastguard Worker     dst_stride = bw;
841*fb1b10abSAndroid Build Coastguard Worker 
842*fb1b10abSAndroid Build Coastguard Worker     xd->mi[0]->sb_type = bsize;
843*fb1b10abSAndroid Build Coastguard Worker     xd->mi[0]->ref_frame[0] = INTRA_FRAME;
844*fb1b10abSAndroid Build Coastguard Worker 
845*fb1b10abSAndroid Build Coastguard Worker     vp9_predict_intra_block(xd, b_width_log2_lookup[bsize], tx_size, mode, src,
846*fb1b10abSAndroid Build Coastguard Worker                             src_stride, dst, dst_stride, 0, 0, 0);
847*fb1b10abSAndroid Build Coastguard Worker 
848*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
849*fb1b10abSAndroid Build Coastguard Worker     if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
850*fb1b10abSAndroid Build Coastguard Worker       vpx_highbd_subtract_block(bh, bw, src_diff, bw, src, src_stride, dst,
851*fb1b10abSAndroid Build Coastguard Worker                                 dst_stride, xd->bd);
852*fb1b10abSAndroid Build Coastguard Worker       vp9_highbd_wht_fwd_txfm(src_diff, bw, coeff, tx_size);
853*fb1b10abSAndroid Build Coastguard Worker       intra_cost = vpx_highbd_satd(coeff, pix_num);
854*fb1b10abSAndroid Build Coastguard Worker     } else {
855*fb1b10abSAndroid Build Coastguard Worker       vpx_subtract_block(bh, bw, src_diff, bw, src, src_stride, dst,
856*fb1b10abSAndroid Build Coastguard Worker                          dst_stride);
857*fb1b10abSAndroid Build Coastguard Worker       vp9_wht_fwd_txfm(src_diff, bw, coeff, tx_size);
858*fb1b10abSAndroid Build Coastguard Worker       intra_cost = vpx_satd(coeff, pix_num);
859*fb1b10abSAndroid Build Coastguard Worker     }
860*fb1b10abSAndroid Build Coastguard Worker #else
861*fb1b10abSAndroid Build Coastguard Worker     vpx_subtract_block(bh, bw, src_diff, bw, src, src_stride, dst, dst_stride);
862*fb1b10abSAndroid Build Coastguard Worker     vp9_wht_fwd_txfm(src_diff, bw, coeff, tx_size);
863*fb1b10abSAndroid Build Coastguard Worker     intra_cost = vpx_satd(coeff, pix_num);
864*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
865*fb1b10abSAndroid Build Coastguard Worker 
866*fb1b10abSAndroid Build Coastguard Worker     if (intra_cost < best_intra_cost) best_intra_cost = intra_cost;
867*fb1b10abSAndroid Build Coastguard Worker   }
868*fb1b10abSAndroid Build Coastguard Worker 
869*fb1b10abSAndroid Build Coastguard Worker   // Motion compensated prediction
870*fb1b10abSAndroid Build Coastguard Worker   best_mv.as_int = 0;
871*fb1b10abSAndroid Build Coastguard Worker 
872*fb1b10abSAndroid Build Coastguard Worker   set_mv_limits(cm, x, mi_row, mi_col);
873*fb1b10abSAndroid Build Coastguard Worker 
874*fb1b10abSAndroid Build Coastguard Worker   for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
875*fb1b10abSAndroid Build Coastguard Worker     int_mv mv;
876*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
877*fb1b10abSAndroid Build Coastguard Worker     MotionField *motion_field;
878*fb1b10abSAndroid Build Coastguard Worker #endif
879*fb1b10abSAndroid Build Coastguard Worker     if (ref_frame[rf_idx] == NULL) continue;
880*fb1b10abSAndroid Build Coastguard Worker 
881*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
882*fb1b10abSAndroid Build Coastguard Worker     (void)td;
883*fb1b10abSAndroid Build Coastguard Worker     motion_field = vp9_motion_field_info_get_motion_field(
884*fb1b10abSAndroid Build Coastguard Worker         &cpi->motion_field_info, frame_idx, rf_idx, bsize);
885*fb1b10abSAndroid Build Coastguard Worker     mv = vp9_motion_field_mi_get_mv(motion_field, mi_row, mi_col);
886*fb1b10abSAndroid Build Coastguard Worker #else
887*fb1b10abSAndroid Build Coastguard Worker     motion_compensated_prediction(cpi, td, xd->cur_buf->y_buffer + mb_y_offset,
888*fb1b10abSAndroid Build Coastguard Worker                                   ref_frame[rf_idx]->y_buffer + mb_y_offset,
889*fb1b10abSAndroid Build Coastguard Worker                                   xd->cur_buf->y_stride, bsize, &mv.as_mv);
890*fb1b10abSAndroid Build Coastguard Worker #endif
891*fb1b10abSAndroid Build Coastguard Worker 
892*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
893*fb1b10abSAndroid Build Coastguard Worker     if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
894*fb1b10abSAndroid Build Coastguard Worker       vp9_highbd_build_inter_predictor(
895*fb1b10abSAndroid Build Coastguard Worker           CONVERT_TO_SHORTPTR(ref_frame[rf_idx]->y_buffer + mb_y_offset),
896*fb1b10abSAndroid Build Coastguard Worker           ref_frame[rf_idx]->y_stride, CONVERT_TO_SHORTPTR(&predictor[0]), bw,
897*fb1b10abSAndroid Build Coastguard Worker           &mv.as_mv, sf, bw, bh, 0, kernel, MV_PRECISION_Q3, mi_col * MI_SIZE,
898*fb1b10abSAndroid Build Coastguard Worker           mi_row * MI_SIZE, xd->bd);
899*fb1b10abSAndroid Build Coastguard Worker       vpx_highbd_subtract_block(
900*fb1b10abSAndroid Build Coastguard Worker           bh, bw, src_diff, bw, xd->cur_buf->y_buffer + mb_y_offset,
901*fb1b10abSAndroid Build Coastguard Worker           xd->cur_buf->y_stride, &predictor[0], bw, xd->bd);
902*fb1b10abSAndroid Build Coastguard Worker       vp9_highbd_wht_fwd_txfm(src_diff, bw, coeff, tx_size);
903*fb1b10abSAndroid Build Coastguard Worker       inter_cost = vpx_highbd_satd(coeff, pix_num);
904*fb1b10abSAndroid Build Coastguard Worker     } else {
905*fb1b10abSAndroid Build Coastguard Worker       vp9_build_inter_predictor(
906*fb1b10abSAndroid Build Coastguard Worker           ref_frame[rf_idx]->y_buffer + mb_y_offset,
907*fb1b10abSAndroid Build Coastguard Worker           ref_frame[rf_idx]->y_stride, &predictor[0], bw, &mv.as_mv, sf, bw, bh,
908*fb1b10abSAndroid Build Coastguard Worker           0, kernel, MV_PRECISION_Q3, mi_col * MI_SIZE, mi_row * MI_SIZE);
909*fb1b10abSAndroid Build Coastguard Worker       vpx_subtract_block(bh, bw, src_diff, bw,
910*fb1b10abSAndroid Build Coastguard Worker                          xd->cur_buf->y_buffer + mb_y_offset,
911*fb1b10abSAndroid Build Coastguard Worker                          xd->cur_buf->y_stride, &predictor[0], bw);
912*fb1b10abSAndroid Build Coastguard Worker       vp9_wht_fwd_txfm(src_diff, bw, coeff, tx_size);
913*fb1b10abSAndroid Build Coastguard Worker       inter_cost = vpx_satd(coeff, pix_num);
914*fb1b10abSAndroid Build Coastguard Worker     }
915*fb1b10abSAndroid Build Coastguard Worker #else
916*fb1b10abSAndroid Build Coastguard Worker     vp9_build_inter_predictor(ref_frame[rf_idx]->y_buffer + mb_y_offset,
917*fb1b10abSAndroid Build Coastguard Worker                               ref_frame[rf_idx]->y_stride, &predictor[0], bw,
918*fb1b10abSAndroid Build Coastguard Worker                               &mv.as_mv, sf, bw, bh, 0, kernel, MV_PRECISION_Q3,
919*fb1b10abSAndroid Build Coastguard Worker                               mi_col * MI_SIZE, mi_row * MI_SIZE);
920*fb1b10abSAndroid Build Coastguard Worker     vpx_subtract_block(bh, bw, src_diff, bw,
921*fb1b10abSAndroid Build Coastguard Worker                        xd->cur_buf->y_buffer + mb_y_offset,
922*fb1b10abSAndroid Build Coastguard Worker                        xd->cur_buf->y_stride, &predictor[0], bw);
923*fb1b10abSAndroid Build Coastguard Worker     vp9_wht_fwd_txfm(src_diff, bw, coeff, tx_size);
924*fb1b10abSAndroid Build Coastguard Worker     inter_cost = vpx_satd(coeff, pix_num);
925*fb1b10abSAndroid Build Coastguard Worker #endif
926*fb1b10abSAndroid Build Coastguard Worker 
927*fb1b10abSAndroid Build Coastguard Worker     if (inter_cost < best_inter_cost) {
928*fb1b10abSAndroid Build Coastguard Worker       uint16_t eob = 0;
929*fb1b10abSAndroid Build Coastguard Worker       best_rf_idx = rf_idx;
930*fb1b10abSAndroid Build Coastguard Worker       best_inter_cost = inter_cost;
931*fb1b10abSAndroid Build Coastguard Worker       best_mv.as_int = mv.as_int;
932*fb1b10abSAndroid Build Coastguard Worker       // Since best_inter_cost is initialized as INT64_MAX, recon_error and
933*fb1b10abSAndroid Build Coastguard Worker       // rate_cost will be calculated with the best reference frame.
934*fb1b10abSAndroid Build Coastguard Worker       get_quantize_error(x, 0, coeff, qcoeff, dqcoeff, tx_size, recon_error,
935*fb1b10abSAndroid Build Coastguard Worker                          sse, &eob);
936*fb1b10abSAndroid Build Coastguard Worker       *rate_cost = rate_estimator(qcoeff, eob, tx_size);
937*fb1b10abSAndroid Build Coastguard Worker     }
938*fb1b10abSAndroid Build Coastguard Worker   }
939*fb1b10abSAndroid Build Coastguard Worker   best_intra_cost = VPXMAX(best_intra_cost, 1);
940*fb1b10abSAndroid Build Coastguard Worker   best_inter_cost = VPXMIN(best_intra_cost, best_inter_cost);
941*fb1b10abSAndroid Build Coastguard Worker   tpl_stats->inter_cost = VPXMAX(
942*fb1b10abSAndroid Build Coastguard Worker       1, (best_inter_cost << TPL_DEP_COST_SCALE_LOG2) / (mi_height * mi_width));
943*fb1b10abSAndroid Build Coastguard Worker   tpl_stats->intra_cost = VPXMAX(
944*fb1b10abSAndroid Build Coastguard Worker       1, (best_intra_cost << TPL_DEP_COST_SCALE_LOG2) / (mi_height * mi_width));
945*fb1b10abSAndroid Build Coastguard Worker   if (best_rf_idx >= 0) {
946*fb1b10abSAndroid Build Coastguard Worker     tpl_stats->ref_frame_index = gf_picture[frame_idx].ref_frame[best_rf_idx];
947*fb1b10abSAndroid Build Coastguard Worker   }
948*fb1b10abSAndroid Build Coastguard Worker   tpl_stats->mv.as_int = best_mv.as_int;
949*fb1b10abSAndroid Build Coastguard Worker   *ref_frame_idx = best_rf_idx;
950*fb1b10abSAndroid Build Coastguard Worker }
951*fb1b10abSAndroid Build Coastguard Worker 
952*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
get_block_src_pred_buf(MACROBLOCKD * xd,GF_PICTURE * gf_picture,int frame_idx,int rf_idx,int mi_row,int mi_col,struct buf_2d * src,struct buf_2d * pre)953*fb1b10abSAndroid Build Coastguard Worker static int get_block_src_pred_buf(MACROBLOCKD *xd, GF_PICTURE *gf_picture,
954*fb1b10abSAndroid Build Coastguard Worker                                   int frame_idx, int rf_idx, int mi_row,
955*fb1b10abSAndroid Build Coastguard Worker                                   int mi_col, struct buf_2d *src,
956*fb1b10abSAndroid Build Coastguard Worker                                   struct buf_2d *pre) {
957*fb1b10abSAndroid Build Coastguard Worker   const int mb_y_offset =
958*fb1b10abSAndroid Build Coastguard Worker       mi_row * MI_SIZE * xd->cur_buf->y_stride + mi_col * MI_SIZE;
959*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *ref_frame = NULL;
960*fb1b10abSAndroid Build Coastguard Worker   int ref_frame_idx = gf_picture[frame_idx].ref_frame[rf_idx];
961*fb1b10abSAndroid Build Coastguard Worker   if (ref_frame_idx != -1) {
962*fb1b10abSAndroid Build Coastguard Worker     ref_frame = gf_picture[ref_frame_idx].frame;
963*fb1b10abSAndroid Build Coastguard Worker     src->buf = xd->cur_buf->y_buffer + mb_y_offset;
964*fb1b10abSAndroid Build Coastguard Worker     src->stride = xd->cur_buf->y_stride;
965*fb1b10abSAndroid Build Coastguard Worker     pre->buf = ref_frame->y_buffer + mb_y_offset;
966*fb1b10abSAndroid Build Coastguard Worker     pre->stride = ref_frame->y_stride;
967*fb1b10abSAndroid Build Coastguard Worker     assert(src->stride == pre->stride);
968*fb1b10abSAndroid Build Coastguard Worker     return 1;
969*fb1b10abSAndroid Build Coastguard Worker   } else {
970*fb1b10abSAndroid Build Coastguard Worker     printf("invalid ref_frame_idx");
971*fb1b10abSAndroid Build Coastguard Worker     assert(ref_frame_idx != -1);
972*fb1b10abSAndroid Build Coastguard Worker     return 0;
973*fb1b10abSAndroid Build Coastguard Worker   }
974*fb1b10abSAndroid Build Coastguard Worker }
975*fb1b10abSAndroid Build Coastguard Worker 
976*fb1b10abSAndroid Build Coastguard Worker #define kMvPreCheckLines 5
977*fb1b10abSAndroid Build Coastguard Worker #define kMvPreCheckSize 15
978*fb1b10abSAndroid Build Coastguard Worker 
979*fb1b10abSAndroid Build Coastguard Worker #define MV_REF_POS_NUM 3
980*fb1b10abSAndroid Build Coastguard Worker POSITION mv_ref_pos[MV_REF_POS_NUM] = {
981*fb1b10abSAndroid Build Coastguard Worker   { -1, 0 },
982*fb1b10abSAndroid Build Coastguard Worker   { 0, -1 },
983*fb1b10abSAndroid Build Coastguard Worker   { -1, -1 },
984*fb1b10abSAndroid Build Coastguard Worker };
985*fb1b10abSAndroid Build Coastguard Worker 
get_select_mv(VP9_COMP * cpi,TplDepFrame * tpl_frame,int mi_row,int mi_col)986*fb1b10abSAndroid Build Coastguard Worker static int_mv *get_select_mv(VP9_COMP *cpi, TplDepFrame *tpl_frame, int mi_row,
987*fb1b10abSAndroid Build Coastguard Worker                              int mi_col) {
988*fb1b10abSAndroid Build Coastguard Worker   return &cpi->select_mv_arr[mi_row * tpl_frame->stride + mi_col];
989*fb1b10abSAndroid Build Coastguard Worker }
990*fb1b10abSAndroid Build Coastguard Worker 
find_ref_mv(int mv_mode,VP9_COMP * cpi,TplDepFrame * tpl_frame,BLOCK_SIZE bsize,int mi_row,int mi_col)991*fb1b10abSAndroid Build Coastguard Worker static int_mv find_ref_mv(int mv_mode, VP9_COMP *cpi, TplDepFrame *tpl_frame,
992*fb1b10abSAndroid Build Coastguard Worker                           BLOCK_SIZE bsize, int mi_row, int mi_col) {
993*fb1b10abSAndroid Build Coastguard Worker   int i;
994*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
995*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
996*fb1b10abSAndroid Build Coastguard Worker   int_mv nearest_mv, near_mv, invalid_mv;
997*fb1b10abSAndroid Build Coastguard Worker   nearest_mv.as_int = INVALID_MV;
998*fb1b10abSAndroid Build Coastguard Worker   near_mv.as_int = INVALID_MV;
999*fb1b10abSAndroid Build Coastguard Worker   invalid_mv.as_int = INVALID_MV;
1000*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < MV_REF_POS_NUM; ++i) {
1001*fb1b10abSAndroid Build Coastguard Worker     int nb_row = mi_row + mv_ref_pos[i].row * mi_height;
1002*fb1b10abSAndroid Build Coastguard Worker     int nb_col = mi_col + mv_ref_pos[i].col * mi_width;
1003*fb1b10abSAndroid Build Coastguard Worker     assert(mv_ref_pos[i].row <= 0);
1004*fb1b10abSAndroid Build Coastguard Worker     assert(mv_ref_pos[i].col <= 0);
1005*fb1b10abSAndroid Build Coastguard Worker     if (nb_row >= 0 && nb_col >= 0) {
1006*fb1b10abSAndroid Build Coastguard Worker       if (nearest_mv.as_int == INVALID_MV) {
1007*fb1b10abSAndroid Build Coastguard Worker         nearest_mv = *get_select_mv(cpi, tpl_frame, nb_row, nb_col);
1008*fb1b10abSAndroid Build Coastguard Worker       } else {
1009*fb1b10abSAndroid Build Coastguard Worker         int_mv mv = *get_select_mv(cpi, tpl_frame, nb_row, nb_col);
1010*fb1b10abSAndroid Build Coastguard Worker         if (mv.as_int == nearest_mv.as_int) {
1011*fb1b10abSAndroid Build Coastguard Worker           continue;
1012*fb1b10abSAndroid Build Coastguard Worker         } else {
1013*fb1b10abSAndroid Build Coastguard Worker           near_mv = mv;
1014*fb1b10abSAndroid Build Coastguard Worker           break;
1015*fb1b10abSAndroid Build Coastguard Worker         }
1016*fb1b10abSAndroid Build Coastguard Worker       }
1017*fb1b10abSAndroid Build Coastguard Worker     }
1018*fb1b10abSAndroid Build Coastguard Worker   }
1019*fb1b10abSAndroid Build Coastguard Worker   if (nearest_mv.as_int == INVALID_MV) {
1020*fb1b10abSAndroid Build Coastguard Worker     nearest_mv.as_mv.row = 0;
1021*fb1b10abSAndroid Build Coastguard Worker     nearest_mv.as_mv.col = 0;
1022*fb1b10abSAndroid Build Coastguard Worker   }
1023*fb1b10abSAndroid Build Coastguard Worker   if (near_mv.as_int == INVALID_MV) {
1024*fb1b10abSAndroid Build Coastguard Worker     near_mv.as_mv.row = 0;
1025*fb1b10abSAndroid Build Coastguard Worker     near_mv.as_mv.col = 0;
1026*fb1b10abSAndroid Build Coastguard Worker   }
1027*fb1b10abSAndroid Build Coastguard Worker   if (mv_mode == NEAREST_MV_MODE) {
1028*fb1b10abSAndroid Build Coastguard Worker     return nearest_mv;
1029*fb1b10abSAndroid Build Coastguard Worker   }
1030*fb1b10abSAndroid Build Coastguard Worker   if (mv_mode == NEAR_MV_MODE) {
1031*fb1b10abSAndroid Build Coastguard Worker     return near_mv;
1032*fb1b10abSAndroid Build Coastguard Worker   }
1033*fb1b10abSAndroid Build Coastguard Worker   assert(0);
1034*fb1b10abSAndroid Build Coastguard Worker   return invalid_mv;
1035*fb1b10abSAndroid Build Coastguard Worker }
1036*fb1b10abSAndroid Build Coastguard Worker 
get_mv_from_mv_mode(int mv_mode,VP9_COMP * cpi,MotionField * motion_field,TplDepFrame * tpl_frame,BLOCK_SIZE bsize,int mi_row,int mi_col)1037*fb1b10abSAndroid Build Coastguard Worker static int_mv get_mv_from_mv_mode(int mv_mode, VP9_COMP *cpi,
1038*fb1b10abSAndroid Build Coastguard Worker                                   MotionField *motion_field,
1039*fb1b10abSAndroid Build Coastguard Worker                                   TplDepFrame *tpl_frame, BLOCK_SIZE bsize,
1040*fb1b10abSAndroid Build Coastguard Worker                                   int mi_row, int mi_col) {
1041*fb1b10abSAndroid Build Coastguard Worker   int_mv mv;
1042*fb1b10abSAndroid Build Coastguard Worker   switch (mv_mode) {
1043*fb1b10abSAndroid Build Coastguard Worker     case ZERO_MV_MODE:
1044*fb1b10abSAndroid Build Coastguard Worker       mv.as_mv.row = 0;
1045*fb1b10abSAndroid Build Coastguard Worker       mv.as_mv.col = 0;
1046*fb1b10abSAndroid Build Coastguard Worker       break;
1047*fb1b10abSAndroid Build Coastguard Worker     case NEW_MV_MODE:
1048*fb1b10abSAndroid Build Coastguard Worker       mv = vp9_motion_field_mi_get_mv(motion_field, mi_row, mi_col);
1049*fb1b10abSAndroid Build Coastguard Worker       break;
1050*fb1b10abSAndroid Build Coastguard Worker     case NEAREST_MV_MODE:
1051*fb1b10abSAndroid Build Coastguard Worker       mv = find_ref_mv(mv_mode, cpi, tpl_frame, bsize, mi_row, mi_col);
1052*fb1b10abSAndroid Build Coastguard Worker       break;
1053*fb1b10abSAndroid Build Coastguard Worker     case NEAR_MV_MODE:
1054*fb1b10abSAndroid Build Coastguard Worker       mv = find_ref_mv(mv_mode, cpi, tpl_frame, bsize, mi_row, mi_col);
1055*fb1b10abSAndroid Build Coastguard Worker       break;
1056*fb1b10abSAndroid Build Coastguard Worker     default:
1057*fb1b10abSAndroid Build Coastguard Worker       mv.as_int = INVALID_MV;
1058*fb1b10abSAndroid Build Coastguard Worker       assert(0);
1059*fb1b10abSAndroid Build Coastguard Worker       break;
1060*fb1b10abSAndroid Build Coastguard Worker   }
1061*fb1b10abSAndroid Build Coastguard Worker   return mv;
1062*fb1b10abSAndroid Build Coastguard Worker }
1063*fb1b10abSAndroid Build Coastguard Worker 
get_mv_dist(int mv_mode,VP9_COMP * cpi,MACROBLOCKD * xd,GF_PICTURE * gf_picture,MotionField * motion_field,int frame_idx,TplDepFrame * tpl_frame,int rf_idx,BLOCK_SIZE bsize,int mi_row,int mi_col,int_mv * mv)1064*fb1b10abSAndroid Build Coastguard Worker static double get_mv_dist(int mv_mode, VP9_COMP *cpi, MACROBLOCKD *xd,
1065*fb1b10abSAndroid Build Coastguard Worker                           GF_PICTURE *gf_picture, MotionField *motion_field,
1066*fb1b10abSAndroid Build Coastguard Worker                           int frame_idx, TplDepFrame *tpl_frame, int rf_idx,
1067*fb1b10abSAndroid Build Coastguard Worker                           BLOCK_SIZE bsize, int mi_row, int mi_col,
1068*fb1b10abSAndroid Build Coastguard Worker                           int_mv *mv) {
1069*fb1b10abSAndroid Build Coastguard Worker   uint32_t sse;
1070*fb1b10abSAndroid Build Coastguard Worker   struct buf_2d src;
1071*fb1b10abSAndroid Build Coastguard Worker   struct buf_2d pre;
1072*fb1b10abSAndroid Build Coastguard Worker   MV full_mv;
1073*fb1b10abSAndroid Build Coastguard Worker   *mv = get_mv_from_mv_mode(mv_mode, cpi, motion_field, tpl_frame, bsize,
1074*fb1b10abSAndroid Build Coastguard Worker                             mi_row, mi_col);
1075*fb1b10abSAndroid Build Coastguard Worker   full_mv = get_full_mv(&mv->as_mv);
1076*fb1b10abSAndroid Build Coastguard Worker   if (get_block_src_pred_buf(xd, gf_picture, frame_idx, rf_idx, mi_row, mi_col,
1077*fb1b10abSAndroid Build Coastguard Worker                              &src, &pre)) {
1078*fb1b10abSAndroid Build Coastguard Worker     // TODO(angiebird): Consider subpixel when computing the sse.
1079*fb1b10abSAndroid Build Coastguard Worker     cpi->fn_ptr[bsize].vf(src.buf, src.stride, get_buf_from_mv(&pre, &full_mv),
1080*fb1b10abSAndroid Build Coastguard Worker                           pre.stride, &sse);
1081*fb1b10abSAndroid Build Coastguard Worker     return (double)(sse << VP9_DIST_SCALE_LOG2);
1082*fb1b10abSAndroid Build Coastguard Worker   } else {
1083*fb1b10abSAndroid Build Coastguard Worker     assert(0);
1084*fb1b10abSAndroid Build Coastguard Worker     return 0;
1085*fb1b10abSAndroid Build Coastguard Worker   }
1086*fb1b10abSAndroid Build Coastguard Worker }
1087*fb1b10abSAndroid Build Coastguard Worker 
get_mv_mode_cost(int mv_mode)1088*fb1b10abSAndroid Build Coastguard Worker static int get_mv_mode_cost(int mv_mode) {
1089*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): The probabilities are roughly inferred from
1090*fb1b10abSAndroid Build Coastguard Worker   // default_inter_mode_probs. Check if there is a better way to set the
1091*fb1b10abSAndroid Build Coastguard Worker   // probabilities.
1092*fb1b10abSAndroid Build Coastguard Worker   const int zero_mv_prob = 16;
1093*fb1b10abSAndroid Build Coastguard Worker   const int new_mv_prob = 24 * 1;
1094*fb1b10abSAndroid Build Coastguard Worker   const int ref_mv_prob = 256 - zero_mv_prob - new_mv_prob;
1095*fb1b10abSAndroid Build Coastguard Worker   assert(zero_mv_prob + new_mv_prob + ref_mv_prob == 256);
1096*fb1b10abSAndroid Build Coastguard Worker   switch (mv_mode) {
1097*fb1b10abSAndroid Build Coastguard Worker     case ZERO_MV_MODE: return vp9_prob_cost[zero_mv_prob]; break;
1098*fb1b10abSAndroid Build Coastguard Worker     case NEW_MV_MODE: return vp9_prob_cost[new_mv_prob]; break;
1099*fb1b10abSAndroid Build Coastguard Worker     case NEAREST_MV_MODE: return vp9_prob_cost[ref_mv_prob]; break;
1100*fb1b10abSAndroid Build Coastguard Worker     case NEAR_MV_MODE: return vp9_prob_cost[ref_mv_prob]; break;
1101*fb1b10abSAndroid Build Coastguard Worker     default: assert(0); return -1;
1102*fb1b10abSAndroid Build Coastguard Worker   }
1103*fb1b10abSAndroid Build Coastguard Worker }
1104*fb1b10abSAndroid Build Coastguard Worker 
get_mv_diff_cost(MV * new_mv,MV * ref_mv)1105*fb1b10abSAndroid Build Coastguard Worker static INLINE double get_mv_diff_cost(MV *new_mv, MV *ref_mv) {
1106*fb1b10abSAndroid Build Coastguard Worker   double mv_diff_cost = log2(1 + abs(new_mv->row - ref_mv->row)) +
1107*fb1b10abSAndroid Build Coastguard Worker                         log2(1 + abs(new_mv->col - ref_mv->col));
1108*fb1b10abSAndroid Build Coastguard Worker   mv_diff_cost *= (1 << VP9_PROB_COST_SHIFT);
1109*fb1b10abSAndroid Build Coastguard Worker   return mv_diff_cost;
1110*fb1b10abSAndroid Build Coastguard Worker }
get_mv_cost(int mv_mode,VP9_COMP * cpi,MotionField * motion_field,TplDepFrame * tpl_frame,BLOCK_SIZE bsize,int mi_row,int mi_col)1111*fb1b10abSAndroid Build Coastguard Worker static double get_mv_cost(int mv_mode, VP9_COMP *cpi, MotionField *motion_field,
1112*fb1b10abSAndroid Build Coastguard Worker                           TplDepFrame *tpl_frame, BLOCK_SIZE bsize, int mi_row,
1113*fb1b10abSAndroid Build Coastguard Worker                           int mi_col) {
1114*fb1b10abSAndroid Build Coastguard Worker   double mv_cost = get_mv_mode_cost(mv_mode);
1115*fb1b10abSAndroid Build Coastguard Worker   if (mv_mode == NEW_MV_MODE) {
1116*fb1b10abSAndroid Build Coastguard Worker     MV new_mv = get_mv_from_mv_mode(mv_mode, cpi, motion_field, tpl_frame,
1117*fb1b10abSAndroid Build Coastguard Worker                                     bsize, mi_row, mi_col)
1118*fb1b10abSAndroid Build Coastguard Worker                     .as_mv;
1119*fb1b10abSAndroid Build Coastguard Worker     MV nearest_mv = get_mv_from_mv_mode(NEAREST_MV_MODE, cpi, motion_field,
1120*fb1b10abSAndroid Build Coastguard Worker                                         tpl_frame, bsize, mi_row, mi_col)
1121*fb1b10abSAndroid Build Coastguard Worker                         .as_mv;
1122*fb1b10abSAndroid Build Coastguard Worker     MV near_mv = get_mv_from_mv_mode(NEAR_MV_MODE, cpi, motion_field, tpl_frame,
1123*fb1b10abSAndroid Build Coastguard Worker                                      bsize, mi_row, mi_col)
1124*fb1b10abSAndroid Build Coastguard Worker                      .as_mv;
1125*fb1b10abSAndroid Build Coastguard Worker     double nearest_cost = get_mv_diff_cost(&new_mv, &nearest_mv);
1126*fb1b10abSAndroid Build Coastguard Worker     double near_cost = get_mv_diff_cost(&new_mv, &near_mv);
1127*fb1b10abSAndroid Build Coastguard Worker     mv_cost += nearest_cost < near_cost ? nearest_cost : near_cost;
1128*fb1b10abSAndroid Build Coastguard Worker   }
1129*fb1b10abSAndroid Build Coastguard Worker   return mv_cost;
1130*fb1b10abSAndroid Build Coastguard Worker }
1131*fb1b10abSAndroid Build Coastguard Worker 
eval_mv_mode(int mv_mode,VP9_COMP * cpi,MACROBLOCK * x,GF_PICTURE * gf_picture,MotionField * motion_field,int frame_idx,TplDepFrame * tpl_frame,int rf_idx,BLOCK_SIZE bsize,int mi_row,int mi_col,int_mv * mv)1132*fb1b10abSAndroid Build Coastguard Worker static double eval_mv_mode(int mv_mode, VP9_COMP *cpi, MACROBLOCK *x,
1133*fb1b10abSAndroid Build Coastguard Worker                            GF_PICTURE *gf_picture, MotionField *motion_field,
1134*fb1b10abSAndroid Build Coastguard Worker                            int frame_idx, TplDepFrame *tpl_frame, int rf_idx,
1135*fb1b10abSAndroid Build Coastguard Worker                            BLOCK_SIZE bsize, int mi_row, int mi_col,
1136*fb1b10abSAndroid Build Coastguard Worker                            int_mv *mv) {
1137*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
1138*fb1b10abSAndroid Build Coastguard Worker   double mv_dist =
1139*fb1b10abSAndroid Build Coastguard Worker       get_mv_dist(mv_mode, cpi, xd, gf_picture, motion_field, frame_idx,
1140*fb1b10abSAndroid Build Coastguard Worker                   tpl_frame, rf_idx, bsize, mi_row, mi_col, mv);
1141*fb1b10abSAndroid Build Coastguard Worker   double mv_cost =
1142*fb1b10abSAndroid Build Coastguard Worker       get_mv_cost(mv_mode, cpi, motion_field, tpl_frame, bsize, mi_row, mi_col);
1143*fb1b10abSAndroid Build Coastguard Worker   double mult = 180;
1144*fb1b10abSAndroid Build Coastguard Worker 
1145*fb1b10abSAndroid Build Coastguard Worker   return mv_cost + mult * log2f(1 + mv_dist);
1146*fb1b10abSAndroid Build Coastguard Worker }
1147*fb1b10abSAndroid Build Coastguard Worker 
find_best_ref_mv_mode(VP9_COMP * cpi,MACROBLOCK * x,GF_PICTURE * gf_picture,MotionField * motion_field,int frame_idx,TplDepFrame * tpl_frame,int rf_idx,BLOCK_SIZE bsize,int mi_row,int mi_col,double * rd,int_mv * mv)1148*fb1b10abSAndroid Build Coastguard Worker static int find_best_ref_mv_mode(VP9_COMP *cpi, MACROBLOCK *x,
1149*fb1b10abSAndroid Build Coastguard Worker                                  GF_PICTURE *gf_picture,
1150*fb1b10abSAndroid Build Coastguard Worker                                  MotionField *motion_field, int frame_idx,
1151*fb1b10abSAndroid Build Coastguard Worker                                  TplDepFrame *tpl_frame, int rf_idx,
1152*fb1b10abSAndroid Build Coastguard Worker                                  BLOCK_SIZE bsize, int mi_row, int mi_col,
1153*fb1b10abSAndroid Build Coastguard Worker                                  double *rd, int_mv *mv) {
1154*fb1b10abSAndroid Build Coastguard Worker   int best_mv_mode = ZERO_MV_MODE;
1155*fb1b10abSAndroid Build Coastguard Worker   int update = 0;
1156*fb1b10abSAndroid Build Coastguard Worker   int mv_mode;
1157*fb1b10abSAndroid Build Coastguard Worker   *rd = 0;
1158*fb1b10abSAndroid Build Coastguard Worker   for (mv_mode = 0; mv_mode < MAX_MV_MODE; ++mv_mode) {
1159*fb1b10abSAndroid Build Coastguard Worker     double this_rd;
1160*fb1b10abSAndroid Build Coastguard Worker     int_mv this_mv;
1161*fb1b10abSAndroid Build Coastguard Worker     if (mv_mode == NEW_MV_MODE) {
1162*fb1b10abSAndroid Build Coastguard Worker       continue;
1163*fb1b10abSAndroid Build Coastguard Worker     }
1164*fb1b10abSAndroid Build Coastguard Worker     this_rd = eval_mv_mode(mv_mode, cpi, x, gf_picture, motion_field, frame_idx,
1165*fb1b10abSAndroid Build Coastguard Worker                            tpl_frame, rf_idx, bsize, mi_row, mi_col, &this_mv);
1166*fb1b10abSAndroid Build Coastguard Worker     if (update == 0) {
1167*fb1b10abSAndroid Build Coastguard Worker       *rd = this_rd;
1168*fb1b10abSAndroid Build Coastguard Worker       *mv = this_mv;
1169*fb1b10abSAndroid Build Coastguard Worker       best_mv_mode = mv_mode;
1170*fb1b10abSAndroid Build Coastguard Worker       update = 1;
1171*fb1b10abSAndroid Build Coastguard Worker     } else {
1172*fb1b10abSAndroid Build Coastguard Worker       if (this_rd < *rd) {
1173*fb1b10abSAndroid Build Coastguard Worker         *rd = this_rd;
1174*fb1b10abSAndroid Build Coastguard Worker         *mv = this_mv;
1175*fb1b10abSAndroid Build Coastguard Worker         best_mv_mode = mv_mode;
1176*fb1b10abSAndroid Build Coastguard Worker       }
1177*fb1b10abSAndroid Build Coastguard Worker     }
1178*fb1b10abSAndroid Build Coastguard Worker   }
1179*fb1b10abSAndroid Build Coastguard Worker   return best_mv_mode;
1180*fb1b10abSAndroid Build Coastguard Worker }
1181*fb1b10abSAndroid Build Coastguard Worker 
predict_mv_mode(VP9_COMP * cpi,MACROBLOCK * x,GF_PICTURE * gf_picture,MotionField * motion_field,int frame_idx,TplDepFrame * tpl_frame,int rf_idx,BLOCK_SIZE bsize,int mi_row,int mi_col)1182*fb1b10abSAndroid Build Coastguard Worker static void predict_mv_mode(VP9_COMP *cpi, MACROBLOCK *x,
1183*fb1b10abSAndroid Build Coastguard Worker                             GF_PICTURE *gf_picture, MotionField *motion_field,
1184*fb1b10abSAndroid Build Coastguard Worker                             int frame_idx, TplDepFrame *tpl_frame, int rf_idx,
1185*fb1b10abSAndroid Build Coastguard Worker                             BLOCK_SIZE bsize, int mi_row, int mi_col) {
1186*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
1187*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
1188*fb1b10abSAndroid Build Coastguard Worker   int tmp_mv_mode_arr[kMvPreCheckSize];
1189*fb1b10abSAndroid Build Coastguard Worker   int *mv_mode_arr = tpl_frame->mv_mode_arr[rf_idx];
1190*fb1b10abSAndroid Build Coastguard Worker   double *rd_diff_arr = tpl_frame->rd_diff_arr[rf_idx];
1191*fb1b10abSAndroid Build Coastguard Worker   int_mv *select_mv_arr = cpi->select_mv_arr;
1192*fb1b10abSAndroid Build Coastguard Worker   int_mv tmp_select_mv_arr[kMvPreCheckSize];
1193*fb1b10abSAndroid Build Coastguard Worker   int stride = tpl_frame->stride;
1194*fb1b10abSAndroid Build Coastguard Worker   double new_mv_rd = 0;
1195*fb1b10abSAndroid Build Coastguard Worker   double no_new_mv_rd = 0;
1196*fb1b10abSAndroid Build Coastguard Worker   double this_new_mv_rd = 0;
1197*fb1b10abSAndroid Build Coastguard Worker   double this_no_new_mv_rd = 0;
1198*fb1b10abSAndroid Build Coastguard Worker   int idx;
1199*fb1b10abSAndroid Build Coastguard Worker   int tmp_idx;
1200*fb1b10abSAndroid Build Coastguard Worker   assert(kMvPreCheckSize == (kMvPreCheckLines * (kMvPreCheckLines + 1)) >> 1);
1201*fb1b10abSAndroid Build Coastguard Worker 
1202*fb1b10abSAndroid Build Coastguard Worker   // no new mv
1203*fb1b10abSAndroid Build Coastguard Worker   // diagonal scan order
1204*fb1b10abSAndroid Build Coastguard Worker   tmp_idx = 0;
1205*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < kMvPreCheckLines; ++idx) {
1206*fb1b10abSAndroid Build Coastguard Worker     int r;
1207*fb1b10abSAndroid Build Coastguard Worker     for (r = 0; r <= idx; ++r) {
1208*fb1b10abSAndroid Build Coastguard Worker       int c = idx - r;
1209*fb1b10abSAndroid Build Coastguard Worker       int nb_row = mi_row + r * mi_height;
1210*fb1b10abSAndroid Build Coastguard Worker       int nb_col = mi_col + c * mi_width;
1211*fb1b10abSAndroid Build Coastguard Worker       if (nb_row < tpl_frame->mi_rows && nb_col < tpl_frame->mi_cols) {
1212*fb1b10abSAndroid Build Coastguard Worker         double this_rd;
1213*fb1b10abSAndroid Build Coastguard Worker         int_mv *mv = &select_mv_arr[nb_row * stride + nb_col];
1214*fb1b10abSAndroid Build Coastguard Worker         mv_mode_arr[nb_row * stride + nb_col] = find_best_ref_mv_mode(
1215*fb1b10abSAndroid Build Coastguard Worker             cpi, x, gf_picture, motion_field, frame_idx, tpl_frame, rf_idx,
1216*fb1b10abSAndroid Build Coastguard Worker             bsize, nb_row, nb_col, &this_rd, mv);
1217*fb1b10abSAndroid Build Coastguard Worker         if (r == 0 && c == 0) {
1218*fb1b10abSAndroid Build Coastguard Worker           this_no_new_mv_rd = this_rd;
1219*fb1b10abSAndroid Build Coastguard Worker         }
1220*fb1b10abSAndroid Build Coastguard Worker         no_new_mv_rd += this_rd;
1221*fb1b10abSAndroid Build Coastguard Worker         tmp_mv_mode_arr[tmp_idx] = mv_mode_arr[nb_row * stride + nb_col];
1222*fb1b10abSAndroid Build Coastguard Worker         tmp_select_mv_arr[tmp_idx] = select_mv_arr[nb_row * stride + nb_col];
1223*fb1b10abSAndroid Build Coastguard Worker         ++tmp_idx;
1224*fb1b10abSAndroid Build Coastguard Worker       }
1225*fb1b10abSAndroid Build Coastguard Worker     }
1226*fb1b10abSAndroid Build Coastguard Worker   }
1227*fb1b10abSAndroid Build Coastguard Worker 
1228*fb1b10abSAndroid Build Coastguard Worker   // new mv
1229*fb1b10abSAndroid Build Coastguard Worker   mv_mode_arr[mi_row * stride + mi_col] = NEW_MV_MODE;
1230*fb1b10abSAndroid Build Coastguard Worker   this_new_mv_rd = eval_mv_mode(
1231*fb1b10abSAndroid Build Coastguard Worker       NEW_MV_MODE, cpi, x, gf_picture, motion_field, frame_idx, tpl_frame,
1232*fb1b10abSAndroid Build Coastguard Worker       rf_idx, bsize, mi_row, mi_col, &select_mv_arr[mi_row * stride + mi_col]);
1233*fb1b10abSAndroid Build Coastguard Worker   new_mv_rd = this_new_mv_rd;
1234*fb1b10abSAndroid Build Coastguard Worker   // We start from idx = 1 because idx = 0 is evaluated as NEW_MV_MODE
1235*fb1b10abSAndroid Build Coastguard Worker   // beforehand.
1236*fb1b10abSAndroid Build Coastguard Worker   for (idx = 1; idx < kMvPreCheckLines; ++idx) {
1237*fb1b10abSAndroid Build Coastguard Worker     int r;
1238*fb1b10abSAndroid Build Coastguard Worker     for (r = 0; r <= idx; ++r) {
1239*fb1b10abSAndroid Build Coastguard Worker       int c = idx - r;
1240*fb1b10abSAndroid Build Coastguard Worker       int nb_row = mi_row + r * mi_height;
1241*fb1b10abSAndroid Build Coastguard Worker       int nb_col = mi_col + c * mi_width;
1242*fb1b10abSAndroid Build Coastguard Worker       if (nb_row < tpl_frame->mi_rows && nb_col < tpl_frame->mi_cols) {
1243*fb1b10abSAndroid Build Coastguard Worker         double this_rd;
1244*fb1b10abSAndroid Build Coastguard Worker         int_mv *mv = &select_mv_arr[nb_row * stride + nb_col];
1245*fb1b10abSAndroid Build Coastguard Worker         mv_mode_arr[nb_row * stride + nb_col] = find_best_ref_mv_mode(
1246*fb1b10abSAndroid Build Coastguard Worker             cpi, x, gf_picture, motion_field, frame_idx, tpl_frame, rf_idx,
1247*fb1b10abSAndroid Build Coastguard Worker             bsize, nb_row, nb_col, &this_rd, mv);
1248*fb1b10abSAndroid Build Coastguard Worker         new_mv_rd += this_rd;
1249*fb1b10abSAndroid Build Coastguard Worker       }
1250*fb1b10abSAndroid Build Coastguard Worker     }
1251*fb1b10abSAndroid Build Coastguard Worker   }
1252*fb1b10abSAndroid Build Coastguard Worker 
1253*fb1b10abSAndroid Build Coastguard Worker   // update best_mv_mode
1254*fb1b10abSAndroid Build Coastguard Worker   tmp_idx = 0;
1255*fb1b10abSAndroid Build Coastguard Worker   if (no_new_mv_rd < new_mv_rd) {
1256*fb1b10abSAndroid Build Coastguard Worker     for (idx = 0; idx < kMvPreCheckLines; ++idx) {
1257*fb1b10abSAndroid Build Coastguard Worker       int r;
1258*fb1b10abSAndroid Build Coastguard Worker       for (r = 0; r <= idx; ++r) {
1259*fb1b10abSAndroid Build Coastguard Worker         int c = idx - r;
1260*fb1b10abSAndroid Build Coastguard Worker         int nb_row = mi_row + r * mi_height;
1261*fb1b10abSAndroid Build Coastguard Worker         int nb_col = mi_col + c * mi_width;
1262*fb1b10abSAndroid Build Coastguard Worker         if (nb_row < tpl_frame->mi_rows && nb_col < tpl_frame->mi_cols) {
1263*fb1b10abSAndroid Build Coastguard Worker           mv_mode_arr[nb_row * stride + nb_col] = tmp_mv_mode_arr[tmp_idx];
1264*fb1b10abSAndroid Build Coastguard Worker           select_mv_arr[nb_row * stride + nb_col] = tmp_select_mv_arr[tmp_idx];
1265*fb1b10abSAndroid Build Coastguard Worker           ++tmp_idx;
1266*fb1b10abSAndroid Build Coastguard Worker         }
1267*fb1b10abSAndroid Build Coastguard Worker       }
1268*fb1b10abSAndroid Build Coastguard Worker     }
1269*fb1b10abSAndroid Build Coastguard Worker     rd_diff_arr[mi_row * stride + mi_col] = 0;
1270*fb1b10abSAndroid Build Coastguard Worker   } else {
1271*fb1b10abSAndroid Build Coastguard Worker     rd_diff_arr[mi_row * stride + mi_col] =
1272*fb1b10abSAndroid Build Coastguard Worker         (no_new_mv_rd - this_no_new_mv_rd) - (new_mv_rd - this_new_mv_rd);
1273*fb1b10abSAndroid Build Coastguard Worker   }
1274*fb1b10abSAndroid Build Coastguard Worker }
1275*fb1b10abSAndroid Build Coastguard Worker 
predict_mv_mode_arr(VP9_COMP * cpi,MACROBLOCK * x,GF_PICTURE * gf_picture,MotionField * motion_field,int frame_idx,TplDepFrame * tpl_frame,int rf_idx,BLOCK_SIZE bsize)1276*fb1b10abSAndroid Build Coastguard Worker static void predict_mv_mode_arr(VP9_COMP *cpi, MACROBLOCK *x,
1277*fb1b10abSAndroid Build Coastguard Worker                                 GF_PICTURE *gf_picture,
1278*fb1b10abSAndroid Build Coastguard Worker                                 MotionField *motion_field, int frame_idx,
1279*fb1b10abSAndroid Build Coastguard Worker                                 TplDepFrame *tpl_frame, int rf_idx,
1280*fb1b10abSAndroid Build Coastguard Worker                                 BLOCK_SIZE bsize) {
1281*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
1282*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
1283*fb1b10abSAndroid Build Coastguard Worker   const int unit_rows = tpl_frame->mi_rows / mi_height;
1284*fb1b10abSAndroid Build Coastguard Worker   const int unit_cols = tpl_frame->mi_cols / mi_width;
1285*fb1b10abSAndroid Build Coastguard Worker   const int max_diagonal_lines = unit_rows + unit_cols - 1;
1286*fb1b10abSAndroid Build Coastguard Worker   int idx;
1287*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < max_diagonal_lines; ++idx) {
1288*fb1b10abSAndroid Build Coastguard Worker     int r;
1289*fb1b10abSAndroid Build Coastguard Worker     for (r = VPXMAX(idx - unit_cols + 1, 0); r <= VPXMIN(idx, unit_rows - 1);
1290*fb1b10abSAndroid Build Coastguard Worker          ++r) {
1291*fb1b10abSAndroid Build Coastguard Worker       int c = idx - r;
1292*fb1b10abSAndroid Build Coastguard Worker       int mi_row = r * mi_height;
1293*fb1b10abSAndroid Build Coastguard Worker       int mi_col = c * mi_width;
1294*fb1b10abSAndroid Build Coastguard Worker       assert(c >= 0 && c < unit_cols);
1295*fb1b10abSAndroid Build Coastguard Worker       assert(mi_row >= 0 && mi_row < tpl_frame->mi_rows);
1296*fb1b10abSAndroid Build Coastguard Worker       assert(mi_col >= 0 && mi_col < tpl_frame->mi_cols);
1297*fb1b10abSAndroid Build Coastguard Worker       predict_mv_mode(cpi, x, gf_picture, motion_field, frame_idx, tpl_frame,
1298*fb1b10abSAndroid Build Coastguard Worker                       rf_idx, bsize, mi_row, mi_col);
1299*fb1b10abSAndroid Build Coastguard Worker     }
1300*fb1b10abSAndroid Build Coastguard Worker   }
1301*fb1b10abSAndroid Build Coastguard Worker }
1302*fb1b10abSAndroid Build Coastguard Worker 
do_motion_search(VP9_COMP * cpi,ThreadData * td,MotionField * motion_field,int frame_idx,YV12_BUFFER_CONFIG * ref_frame,BLOCK_SIZE bsize,int mi_row,int mi_col)1303*fb1b10abSAndroid Build Coastguard Worker static void do_motion_search(VP9_COMP *cpi, ThreadData *td,
1304*fb1b10abSAndroid Build Coastguard Worker                              MotionField *motion_field, int frame_idx,
1305*fb1b10abSAndroid Build Coastguard Worker                              YV12_BUFFER_CONFIG *ref_frame, BLOCK_SIZE bsize,
1306*fb1b10abSAndroid Build Coastguard Worker                              int mi_row, int mi_col) {
1307*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi->common;
1308*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *x = &td->mb;
1309*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
1310*fb1b10abSAndroid Build Coastguard Worker   const int mb_y_offset =
1311*fb1b10abSAndroid Build Coastguard Worker       mi_row * MI_SIZE * xd->cur_buf->y_stride + mi_col * MI_SIZE;
1312*fb1b10abSAndroid Build Coastguard Worker   assert(ref_frame != NULL);
1313*fb1b10abSAndroid Build Coastguard Worker   set_mv_limits(cm, x, mi_row, mi_col);
1314*fb1b10abSAndroid Build Coastguard Worker   {
1315*fb1b10abSAndroid Build Coastguard Worker     int_mv mv = vp9_motion_field_mi_get_mv(motion_field, mi_row, mi_col);
1316*fb1b10abSAndroid Build Coastguard Worker     uint8_t *cur_frame_buf = xd->cur_buf->y_buffer + mb_y_offset;
1317*fb1b10abSAndroid Build Coastguard Worker     uint8_t *ref_frame_buf = ref_frame->y_buffer + mb_y_offset;
1318*fb1b10abSAndroid Build Coastguard Worker     const int stride = xd->cur_buf->y_stride;
1319*fb1b10abSAndroid Build Coastguard Worker     full_pixel_motion_search(cpi, td, motion_field, frame_idx, cur_frame_buf,
1320*fb1b10abSAndroid Build Coastguard Worker                              ref_frame_buf, stride, bsize, mi_row, mi_col,
1321*fb1b10abSAndroid Build Coastguard Worker                              &mv.as_mv);
1322*fb1b10abSAndroid Build Coastguard Worker     sub_pixel_motion_search(cpi, td, cur_frame_buf, ref_frame_buf, stride,
1323*fb1b10abSAndroid Build Coastguard Worker                             bsize, &mv.as_mv);
1324*fb1b10abSAndroid Build Coastguard Worker     vp9_motion_field_mi_set_mv(motion_field, mi_row, mi_col, mv);
1325*fb1b10abSAndroid Build Coastguard Worker   }
1326*fb1b10abSAndroid Build Coastguard Worker }
1327*fb1b10abSAndroid Build Coastguard Worker 
build_motion_field(VP9_COMP * cpi,int frame_idx,YV12_BUFFER_CONFIG * ref_frame[MAX_INTER_REF_FRAMES],BLOCK_SIZE bsize)1328*fb1b10abSAndroid Build Coastguard Worker static void build_motion_field(
1329*fb1b10abSAndroid Build Coastguard Worker     VP9_COMP *cpi, int frame_idx,
1330*fb1b10abSAndroid Build Coastguard Worker     YV12_BUFFER_CONFIG *ref_frame[MAX_INTER_REF_FRAMES], BLOCK_SIZE bsize) {
1331*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi->common;
1332*fb1b10abSAndroid Build Coastguard Worker   ThreadData *td = &cpi->td;
1333*fb1b10abSAndroid Build Coastguard Worker   TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx];
1334*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
1335*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
1336*fb1b10abSAndroid Build Coastguard Worker   const int pw = num_4x4_blocks_wide_lookup[bsize] << 2;
1337*fb1b10abSAndroid Build Coastguard Worker   const int ph = num_4x4_blocks_high_lookup[bsize] << 2;
1338*fb1b10abSAndroid Build Coastguard Worker   int mi_row, mi_col;
1339*fb1b10abSAndroid Build Coastguard Worker   int rf_idx;
1340*fb1b10abSAndroid Build Coastguard Worker 
1341*fb1b10abSAndroid Build Coastguard Worker   tpl_frame->lambda = (pw * ph) >> 2;
1342*fb1b10abSAndroid Build Coastguard Worker   assert(pw * ph == tpl_frame->lambda << 2);
1343*fb1b10abSAndroid Build Coastguard Worker 
1344*fb1b10abSAndroid Build Coastguard Worker   for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
1345*fb1b10abSAndroid Build Coastguard Worker     MotionField *motion_field = vp9_motion_field_info_get_motion_field(
1346*fb1b10abSAndroid Build Coastguard Worker         &cpi->motion_field_info, frame_idx, rf_idx, bsize);
1347*fb1b10abSAndroid Build Coastguard Worker     if (ref_frame[rf_idx] == NULL) {
1348*fb1b10abSAndroid Build Coastguard Worker       continue;
1349*fb1b10abSAndroid Build Coastguard Worker     }
1350*fb1b10abSAndroid Build Coastguard Worker     vp9_motion_field_reset_mvs(motion_field);
1351*fb1b10abSAndroid Build Coastguard Worker     for (mi_row = 0; mi_row < cm->mi_rows; mi_row += mi_height) {
1352*fb1b10abSAndroid Build Coastguard Worker       for (mi_col = 0; mi_col < cm->mi_cols; mi_col += mi_width) {
1353*fb1b10abSAndroid Build Coastguard Worker         do_motion_search(cpi, td, motion_field, frame_idx, ref_frame[rf_idx],
1354*fb1b10abSAndroid Build Coastguard Worker                          bsize, mi_row, mi_col);
1355*fb1b10abSAndroid Build Coastguard Worker       }
1356*fb1b10abSAndroid Build Coastguard Worker     }
1357*fb1b10abSAndroid Build Coastguard Worker   }
1358*fb1b10abSAndroid Build Coastguard Worker }
1359*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_NON_GREEDY_MV
1360*fb1b10abSAndroid Build Coastguard Worker 
mc_flow_dispenser(VP9_COMP * cpi,GF_PICTURE * gf_picture,int frame_idx,BLOCK_SIZE bsize)1361*fb1b10abSAndroid Build Coastguard Worker static void mc_flow_dispenser(VP9_COMP *cpi, GF_PICTURE *gf_picture,
1362*fb1b10abSAndroid Build Coastguard Worker                               int frame_idx, BLOCK_SIZE bsize) {
1363*fb1b10abSAndroid Build Coastguard Worker   TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx];
1364*fb1b10abSAndroid Build Coastguard Worker   VpxTplFrameStats *tpl_frame_stats_before_propagation =
1365*fb1b10abSAndroid Build Coastguard Worker       &cpi->tpl_gop_stats.frame_stats_list[frame_idx];
1366*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *this_frame = gf_picture[frame_idx].frame;
1367*fb1b10abSAndroid Build Coastguard Worker   YV12_BUFFER_CONFIG *ref_frame[MAX_INTER_REF_FRAMES] = { NULL, NULL, NULL };
1368*fb1b10abSAndroid Build Coastguard Worker 
1369*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi->common;
1370*fb1b10abSAndroid Build Coastguard Worker   struct scale_factors sf;
1371*fb1b10abSAndroid Build Coastguard Worker   int rdmult, idx;
1372*fb1b10abSAndroid Build Coastguard Worker   ThreadData *td = &cpi->td;
1373*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCK *x = &td->mb;
1374*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
1375*fb1b10abSAndroid Build Coastguard Worker   int mi_row, mi_col;
1376*fb1b10abSAndroid Build Coastguard Worker 
1377*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1378*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint16_t, predictor16[32 * 32 * 3]);
1379*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint8_t, predictor8[32 * 32 * 3]);
1380*fb1b10abSAndroid Build Coastguard Worker   uint8_t *predictor;
1381*fb1b10abSAndroid Build Coastguard Worker #else
1382*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint8_t, predictor[32 * 32 * 3]);
1383*fb1b10abSAndroid Build Coastguard Worker #endif
1384*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, int16_t, src_diff[32 * 32]);
1385*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, tran_low_t, coeff[32 * 32]);
1386*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, tran_low_t, qcoeff[32 * 32]);
1387*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, tran_low_t, dqcoeff[32 * 32]);
1388*fb1b10abSAndroid Build Coastguard Worker 
1389*fb1b10abSAndroid Build Coastguard Worker   const TX_SIZE tx_size = max_txsize_lookup[bsize];
1390*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[bsize];
1391*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[bsize];
1392*fb1b10abSAndroid Build Coastguard Worker 
1393*fb1b10abSAndroid Build Coastguard Worker   tpl_frame_stats_before_propagation->frame_width = cm->width;
1394*fb1b10abSAndroid Build Coastguard Worker   tpl_frame_stats_before_propagation->frame_height = cm->height;
1395*fb1b10abSAndroid Build Coastguard Worker   // Setup scaling factor
1396*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1397*fb1b10abSAndroid Build Coastguard Worker   vp9_setup_scale_factors_for_frame(
1398*fb1b10abSAndroid Build Coastguard Worker       &sf, this_frame->y_crop_width, this_frame->y_crop_height,
1399*fb1b10abSAndroid Build Coastguard Worker       this_frame->y_crop_width, this_frame->y_crop_height,
1400*fb1b10abSAndroid Build Coastguard Worker       cpi->common.use_highbitdepth);
1401*fb1b10abSAndroid Build Coastguard Worker 
1402*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
1403*fb1b10abSAndroid Build Coastguard Worker     predictor = CONVERT_TO_BYTEPTR(predictor16);
1404*fb1b10abSAndroid Build Coastguard Worker   else
1405*fb1b10abSAndroid Build Coastguard Worker     predictor = predictor8;
1406*fb1b10abSAndroid Build Coastguard Worker #else
1407*fb1b10abSAndroid Build Coastguard Worker   vp9_setup_scale_factors_for_frame(
1408*fb1b10abSAndroid Build Coastguard Worker       &sf, this_frame->y_crop_width, this_frame->y_crop_height,
1409*fb1b10abSAndroid Build Coastguard Worker       this_frame->y_crop_width, this_frame->y_crop_height);
1410*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
1411*fb1b10abSAndroid Build Coastguard Worker 
1412*fb1b10abSAndroid Build Coastguard Worker   // Prepare reference frame pointers. If any reference frame slot is
1413*fb1b10abSAndroid Build Coastguard Worker   // unavailable, the pointer will be set to Null.
1414*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < MAX_INTER_REF_FRAMES; ++idx) {
1415*fb1b10abSAndroid Build Coastguard Worker     int rf_idx = gf_picture[frame_idx].ref_frame[idx];
1416*fb1b10abSAndroid Build Coastguard Worker     if (rf_idx != -REFS_PER_FRAME) ref_frame[idx] = gf_picture[rf_idx].frame;
1417*fb1b10abSAndroid Build Coastguard Worker   }
1418*fb1b10abSAndroid Build Coastguard Worker 
1419*fb1b10abSAndroid Build Coastguard Worker   xd->mi = cm->mi_grid_visible;
1420*fb1b10abSAndroid Build Coastguard Worker   xd->mi[0] = cm->mi;
1421*fb1b10abSAndroid Build Coastguard Worker   xd->cur_buf = this_frame;
1422*fb1b10abSAndroid Build Coastguard Worker 
1423*fb1b10abSAndroid Build Coastguard Worker   // Get rd multiplier set up.
1424*fb1b10abSAndroid Build Coastguard Worker   rdmult = vp9_compute_rd_mult_based_on_qindex(cpi, tpl_frame->base_qindex);
1425*fb1b10abSAndroid Build Coastguard Worker   set_error_per_bit(&cpi->td.mb, rdmult);
1426*fb1b10abSAndroid Build Coastguard Worker   vp9_initialize_me_consts(cpi, &cpi->td.mb, tpl_frame->base_qindex);
1427*fb1b10abSAndroid Build Coastguard Worker 
1428*fb1b10abSAndroid Build Coastguard Worker   tpl_frame->is_valid = 1;
1429*fb1b10abSAndroid Build Coastguard Worker 
1430*fb1b10abSAndroid Build Coastguard Worker   cm->base_qindex = tpl_frame->base_qindex;
1431*fb1b10abSAndroid Build Coastguard Worker   vp9_frame_init_quantizer(cpi);
1432*fb1b10abSAndroid Build Coastguard Worker 
1433*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
1434*fb1b10abSAndroid Build Coastguard Worker   {
1435*fb1b10abSAndroid Build Coastguard Worker     int square_block_idx;
1436*fb1b10abSAndroid Build Coastguard Worker     int rf_idx;
1437*fb1b10abSAndroid Build Coastguard Worker     for (square_block_idx = 0; square_block_idx < SQUARE_BLOCK_SIZES;
1438*fb1b10abSAndroid Build Coastguard Worker          ++square_block_idx) {
1439*fb1b10abSAndroid Build Coastguard Worker       BLOCK_SIZE square_bsize = square_block_idx_to_bsize(square_block_idx);
1440*fb1b10abSAndroid Build Coastguard Worker       build_motion_field(cpi, frame_idx, ref_frame, square_bsize);
1441*fb1b10abSAndroid Build Coastguard Worker     }
1442*fb1b10abSAndroid Build Coastguard Worker     for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
1443*fb1b10abSAndroid Build Coastguard Worker       int ref_frame_idx = gf_picture[frame_idx].ref_frame[rf_idx];
1444*fb1b10abSAndroid Build Coastguard Worker       if (ref_frame_idx != -1) {
1445*fb1b10abSAndroid Build Coastguard Worker         MotionField *motion_field = vp9_motion_field_info_get_motion_field(
1446*fb1b10abSAndroid Build Coastguard Worker             &cpi->motion_field_info, frame_idx, rf_idx, bsize);
1447*fb1b10abSAndroid Build Coastguard Worker         predict_mv_mode_arr(cpi, x, gf_picture, motion_field, frame_idx,
1448*fb1b10abSAndroid Build Coastguard Worker                             tpl_frame, rf_idx, bsize);
1449*fb1b10abSAndroid Build Coastguard Worker       }
1450*fb1b10abSAndroid Build Coastguard Worker     }
1451*fb1b10abSAndroid Build Coastguard Worker   }
1452*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_NON_GREEDY_MV
1453*fb1b10abSAndroid Build Coastguard Worker 
1454*fb1b10abSAndroid Build Coastguard Worker   for (mi_row = 0; mi_row < cm->mi_rows; mi_row += mi_height) {
1455*fb1b10abSAndroid Build Coastguard Worker     for (mi_col = 0; mi_col < cm->mi_cols; mi_col += mi_width) {
1456*fb1b10abSAndroid Build Coastguard Worker       int64_t recon_error = 0;
1457*fb1b10abSAndroid Build Coastguard Worker       int64_t rate_cost = 0;
1458*fb1b10abSAndroid Build Coastguard Worker       int64_t sse = 0;
1459*fb1b10abSAndroid Build Coastguard Worker       // Ref frame index in the ref frame buffer.
1460*fb1b10abSAndroid Build Coastguard Worker       int ref_frame_idx = -1;
1461*fb1b10abSAndroid Build Coastguard Worker       mode_estimation(cpi, x, xd, &sf, gf_picture, frame_idx, tpl_frame,
1462*fb1b10abSAndroid Build Coastguard Worker                       src_diff, coeff, qcoeff, dqcoeff, mi_row, mi_col, bsize,
1463*fb1b10abSAndroid Build Coastguard Worker                       tx_size, ref_frame, predictor, &recon_error, &rate_cost,
1464*fb1b10abSAndroid Build Coastguard Worker                       &sse, &ref_frame_idx);
1465*fb1b10abSAndroid Build Coastguard Worker       // Motion flow dependency dispenser.
1466*fb1b10abSAndroid Build Coastguard Worker       tpl_model_store(tpl_frame->tpl_stats_ptr, mi_row, mi_col, bsize,
1467*fb1b10abSAndroid Build Coastguard Worker                       tpl_frame->stride);
1468*fb1b10abSAndroid Build Coastguard Worker 
1469*fb1b10abSAndroid Build Coastguard Worker       tpl_store_before_propagation(
1470*fb1b10abSAndroid Build Coastguard Worker           tpl_frame_stats_before_propagation->block_stats_list,
1471*fb1b10abSAndroid Build Coastguard Worker           tpl_frame->tpl_stats_ptr, mi_row, mi_col, bsize, tpl_frame->stride,
1472*fb1b10abSAndroid Build Coastguard Worker           recon_error, rate_cost, ref_frame_idx, tpl_frame->mi_rows,
1473*fb1b10abSAndroid Build Coastguard Worker           tpl_frame->mi_cols);
1474*fb1b10abSAndroid Build Coastguard Worker 
1475*fb1b10abSAndroid Build Coastguard Worker       tpl_model_update(cpi->tpl_stats, tpl_frame->tpl_stats_ptr, mi_row, mi_col,
1476*fb1b10abSAndroid Build Coastguard Worker                        bsize);
1477*fb1b10abSAndroid Build Coastguard Worker     }
1478*fb1b10abSAndroid Build Coastguard Worker   }
1479*fb1b10abSAndroid Build Coastguard Worker }
1480*fb1b10abSAndroid Build Coastguard Worker 
trim_tpl_stats(struct vpx_internal_error_info * error_info,VpxTplGopStats * tpl_gop_stats,int extra_frames)1481*fb1b10abSAndroid Build Coastguard Worker static void trim_tpl_stats(struct vpx_internal_error_info *error_info,
1482*fb1b10abSAndroid Build Coastguard Worker                            VpxTplGopStats *tpl_gop_stats, int extra_frames) {
1483*fb1b10abSAndroid Build Coastguard Worker   int i;
1484*fb1b10abSAndroid Build Coastguard Worker   VpxTplFrameStats *new_frame_stats;
1485*fb1b10abSAndroid Build Coastguard Worker   const int new_size = tpl_gop_stats->size - extra_frames;
1486*fb1b10abSAndroid Build Coastguard Worker   if (tpl_gop_stats->size <= extra_frames)
1487*fb1b10abSAndroid Build Coastguard Worker     vpx_internal_error(
1488*fb1b10abSAndroid Build Coastguard Worker         error_info, VPX_CODEC_ERROR,
1489*fb1b10abSAndroid Build Coastguard Worker         "The number of frames in VpxTplGopStats is fewer than expected.");
1490*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(error_info, new_frame_stats,
1491*fb1b10abSAndroid Build Coastguard Worker                   vpx_calloc(new_size, sizeof(*new_frame_stats)));
1492*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < new_size; i++) {
1493*fb1b10abSAndroid Build Coastguard Worker     VpxTplFrameStats *frame_stats = &tpl_gop_stats->frame_stats_list[i];
1494*fb1b10abSAndroid Build Coastguard Worker     const int num_blocks = frame_stats->num_blocks;
1495*fb1b10abSAndroid Build Coastguard Worker     new_frame_stats[i].num_blocks = frame_stats->num_blocks;
1496*fb1b10abSAndroid Build Coastguard Worker     new_frame_stats[i].frame_width = frame_stats->frame_width;
1497*fb1b10abSAndroid Build Coastguard Worker     new_frame_stats[i].frame_height = frame_stats->frame_height;
1498*fb1b10abSAndroid Build Coastguard Worker     new_frame_stats[i].num_blocks = num_blocks;
1499*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(
1500*fb1b10abSAndroid Build Coastguard Worker         error_info, new_frame_stats[i].block_stats_list,
1501*fb1b10abSAndroid Build Coastguard Worker         vpx_calloc(num_blocks, sizeof(*new_frame_stats[i].block_stats_list)));
1502*fb1b10abSAndroid Build Coastguard Worker     memcpy(new_frame_stats[i].block_stats_list, frame_stats->block_stats_list,
1503*fb1b10abSAndroid Build Coastguard Worker            num_blocks * sizeof(*new_frame_stats[i].block_stats_list));
1504*fb1b10abSAndroid Build Coastguard Worker   }
1505*fb1b10abSAndroid Build Coastguard Worker   free_tpl_frame_stats_list(tpl_gop_stats);
1506*fb1b10abSAndroid Build Coastguard Worker   tpl_gop_stats->size = new_size;
1507*fb1b10abSAndroid Build Coastguard Worker   tpl_gop_stats->frame_stats_list = new_frame_stats;
1508*fb1b10abSAndroid Build Coastguard Worker }
1509*fb1b10abSAndroid Build Coastguard Worker 
1510*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
1511*fb1b10abSAndroid Build Coastguard Worker #define DUMP_TPL_STATS 0
1512*fb1b10abSAndroid Build Coastguard Worker #if DUMP_TPL_STATS
dump_buf(uint8_t * buf,int stride,int row,int col,int h,int w)1513*fb1b10abSAndroid Build Coastguard Worker static void dump_buf(uint8_t *buf, int stride, int row, int col, int h, int w) {
1514*fb1b10abSAndroid Build Coastguard Worker   int i, j;
1515*fb1b10abSAndroid Build Coastguard Worker   printf("%d %d\n", h, w);
1516*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < h; ++i) {
1517*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < w; ++j) {
1518*fb1b10abSAndroid Build Coastguard Worker       printf("%d ", buf[(row + i) * stride + col + j]);
1519*fb1b10abSAndroid Build Coastguard Worker     }
1520*fb1b10abSAndroid Build Coastguard Worker   }
1521*fb1b10abSAndroid Build Coastguard Worker   printf("\n");
1522*fb1b10abSAndroid Build Coastguard Worker }
1523*fb1b10abSAndroid Build Coastguard Worker 
dump_frame_buf(const YV12_BUFFER_CONFIG * frame_buf)1524*fb1b10abSAndroid Build Coastguard Worker static void dump_frame_buf(const YV12_BUFFER_CONFIG *frame_buf) {
1525*fb1b10abSAndroid Build Coastguard Worker   dump_buf(frame_buf->y_buffer, frame_buf->y_stride, 0, 0, frame_buf->y_height,
1526*fb1b10abSAndroid Build Coastguard Worker            frame_buf->y_width);
1527*fb1b10abSAndroid Build Coastguard Worker   dump_buf(frame_buf->u_buffer, frame_buf->uv_stride, 0, 0,
1528*fb1b10abSAndroid Build Coastguard Worker            frame_buf->uv_height, frame_buf->uv_width);
1529*fb1b10abSAndroid Build Coastguard Worker   dump_buf(frame_buf->v_buffer, frame_buf->uv_stride, 0, 0,
1530*fb1b10abSAndroid Build Coastguard Worker            frame_buf->uv_height, frame_buf->uv_width);
1531*fb1b10abSAndroid Build Coastguard Worker }
1532*fb1b10abSAndroid Build Coastguard Worker 
dump_tpl_stats(const VP9_COMP * cpi,int tpl_group_frames,const GF_GROUP * gf_group,const GF_PICTURE * gf_picture,BLOCK_SIZE bsize)1533*fb1b10abSAndroid Build Coastguard Worker static void dump_tpl_stats(const VP9_COMP *cpi, int tpl_group_frames,
1534*fb1b10abSAndroid Build Coastguard Worker                            const GF_GROUP *gf_group,
1535*fb1b10abSAndroid Build Coastguard Worker                            const GF_PICTURE *gf_picture, BLOCK_SIZE bsize) {
1536*fb1b10abSAndroid Build Coastguard Worker   int frame_idx;
1537*fb1b10abSAndroid Build Coastguard Worker   const VP9_COMMON *cm = &cpi->common;
1538*fb1b10abSAndroid Build Coastguard Worker   int rf_idx;
1539*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = 1; frame_idx < tpl_group_frames; ++frame_idx) {
1540*fb1b10abSAndroid Build Coastguard Worker     for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
1541*fb1b10abSAndroid Build Coastguard Worker       const TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx];
1542*fb1b10abSAndroid Build Coastguard Worker       int mi_row, mi_col;
1543*fb1b10abSAndroid Build Coastguard Worker       int ref_frame_idx;
1544*fb1b10abSAndroid Build Coastguard Worker       const int mi_height = num_8x8_blocks_high_lookup[bsize];
1545*fb1b10abSAndroid Build Coastguard Worker       const int mi_width = num_8x8_blocks_wide_lookup[bsize];
1546*fb1b10abSAndroid Build Coastguard Worker       ref_frame_idx = gf_picture[frame_idx].ref_frame[rf_idx];
1547*fb1b10abSAndroid Build Coastguard Worker       if (ref_frame_idx != -1) {
1548*fb1b10abSAndroid Build Coastguard Worker         YV12_BUFFER_CONFIG *ref_frame_buf = gf_picture[ref_frame_idx].frame;
1549*fb1b10abSAndroid Build Coastguard Worker         const int gf_frame_offset = gf_group->frame_gop_index[frame_idx];
1550*fb1b10abSAndroid Build Coastguard Worker         const int ref_gf_frame_offset =
1551*fb1b10abSAndroid Build Coastguard Worker             gf_group->frame_gop_index[ref_frame_idx];
1552*fb1b10abSAndroid Build Coastguard Worker         printf("=\n");
1553*fb1b10abSAndroid Build Coastguard Worker         printf(
1554*fb1b10abSAndroid Build Coastguard Worker             "frame_idx %d mi_rows %d mi_cols %d bsize %d ref_frame_idx %d "
1555*fb1b10abSAndroid Build Coastguard Worker             "rf_idx %d gf_frame_offset %d ref_gf_frame_offset %d\n",
1556*fb1b10abSAndroid Build Coastguard Worker             frame_idx, cm->mi_rows, cm->mi_cols, mi_width * MI_SIZE,
1557*fb1b10abSAndroid Build Coastguard Worker             ref_frame_idx, rf_idx, gf_frame_offset, ref_gf_frame_offset);
1558*fb1b10abSAndroid Build Coastguard Worker         for (mi_row = 0; mi_row < cm->mi_rows; ++mi_row) {
1559*fb1b10abSAndroid Build Coastguard Worker           for (mi_col = 0; mi_col < cm->mi_cols; ++mi_col) {
1560*fb1b10abSAndroid Build Coastguard Worker             if ((mi_row % mi_height) == 0 && (mi_col % mi_width) == 0) {
1561*fb1b10abSAndroid Build Coastguard Worker               int_mv mv = vp9_motion_field_info_get_mv(&cpi->motion_field_info,
1562*fb1b10abSAndroid Build Coastguard Worker                                                        frame_idx, rf_idx, bsize,
1563*fb1b10abSAndroid Build Coastguard Worker                                                        mi_row, mi_col);
1564*fb1b10abSAndroid Build Coastguard Worker               printf("%d %d %d %d\n", mi_row, mi_col, mv.as_mv.row,
1565*fb1b10abSAndroid Build Coastguard Worker                      mv.as_mv.col);
1566*fb1b10abSAndroid Build Coastguard Worker             }
1567*fb1b10abSAndroid Build Coastguard Worker           }
1568*fb1b10abSAndroid Build Coastguard Worker         }
1569*fb1b10abSAndroid Build Coastguard Worker         for (mi_row = 0; mi_row < cm->mi_rows; ++mi_row) {
1570*fb1b10abSAndroid Build Coastguard Worker           for (mi_col = 0; mi_col < cm->mi_cols; ++mi_col) {
1571*fb1b10abSAndroid Build Coastguard Worker             if ((mi_row % mi_height) == 0 && (mi_col % mi_width) == 0) {
1572*fb1b10abSAndroid Build Coastguard Worker               const TplDepStats *tpl_ptr =
1573*fb1b10abSAndroid Build Coastguard Worker                   &tpl_frame
1574*fb1b10abSAndroid Build Coastguard Worker                        ->tpl_stats_ptr[mi_row * tpl_frame->stride + mi_col];
1575*fb1b10abSAndroid Build Coastguard Worker               printf("%f ", tpl_ptr->feature_score);
1576*fb1b10abSAndroid Build Coastguard Worker             }
1577*fb1b10abSAndroid Build Coastguard Worker           }
1578*fb1b10abSAndroid Build Coastguard Worker         }
1579*fb1b10abSAndroid Build Coastguard Worker         printf("\n");
1580*fb1b10abSAndroid Build Coastguard Worker 
1581*fb1b10abSAndroid Build Coastguard Worker         for (mi_row = 0; mi_row < cm->mi_rows; mi_row += mi_height) {
1582*fb1b10abSAndroid Build Coastguard Worker           for (mi_col = 0; mi_col < cm->mi_cols; mi_col += mi_width) {
1583*fb1b10abSAndroid Build Coastguard Worker             const int mv_mode =
1584*fb1b10abSAndroid Build Coastguard Worker                 tpl_frame
1585*fb1b10abSAndroid Build Coastguard Worker                     ->mv_mode_arr[rf_idx][mi_row * tpl_frame->stride + mi_col];
1586*fb1b10abSAndroid Build Coastguard Worker             printf("%d ", mv_mode);
1587*fb1b10abSAndroid Build Coastguard Worker           }
1588*fb1b10abSAndroid Build Coastguard Worker         }
1589*fb1b10abSAndroid Build Coastguard Worker         printf("\n");
1590*fb1b10abSAndroid Build Coastguard Worker 
1591*fb1b10abSAndroid Build Coastguard Worker         dump_frame_buf(gf_picture[frame_idx].frame);
1592*fb1b10abSAndroid Build Coastguard Worker         dump_frame_buf(ref_frame_buf);
1593*fb1b10abSAndroid Build Coastguard Worker       }
1594*fb1b10abSAndroid Build Coastguard Worker     }
1595*fb1b10abSAndroid Build Coastguard Worker   }
1596*fb1b10abSAndroid Build Coastguard Worker }
1597*fb1b10abSAndroid Build Coastguard Worker #endif  // DUMP_TPL_STATS
1598*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_NON_GREEDY_MV
1599*fb1b10abSAndroid Build Coastguard Worker 
vp9_init_tpl_buffer(VP9_COMP * cpi)1600*fb1b10abSAndroid Build Coastguard Worker void vp9_init_tpl_buffer(VP9_COMP *cpi) {
1601*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi->common;
1602*fb1b10abSAndroid Build Coastguard Worker   int frame;
1603*fb1b10abSAndroid Build Coastguard Worker 
1604*fb1b10abSAndroid Build Coastguard Worker   const int mi_cols = mi_cols_aligned_to_sb(cm->mi_cols);
1605*fb1b10abSAndroid Build Coastguard Worker   const int mi_rows = mi_cols_aligned_to_sb(cm->mi_rows);
1606*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
1607*fb1b10abSAndroid Build Coastguard Worker   int rf_idx;
1608*fb1b10abSAndroid Build Coastguard Worker 
1609*fb1b10abSAndroid Build Coastguard Worker   vpx_free(cpi->select_mv_arr);
1610*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(
1611*fb1b10abSAndroid Build Coastguard Worker       &cm->error, cpi->select_mv_arr,
1612*fb1b10abSAndroid Build Coastguard Worker       vpx_calloc(mi_rows * mi_cols * 4, sizeof(*cpi->select_mv_arr)));
1613*fb1b10abSAndroid Build Coastguard Worker #endif
1614*fb1b10abSAndroid Build Coastguard Worker 
1615*fb1b10abSAndroid Build Coastguard Worker   // TODO(jingning): Reduce the actual memory use for tpl model build up.
1616*fb1b10abSAndroid Build Coastguard Worker   for (frame = 0; frame < MAX_ARF_GOP_SIZE; ++frame) {
1617*fb1b10abSAndroid Build Coastguard Worker     if (cpi->tpl_stats[frame].width >= mi_cols &&
1618*fb1b10abSAndroid Build Coastguard Worker         cpi->tpl_stats[frame].height >= mi_rows &&
1619*fb1b10abSAndroid Build Coastguard Worker         cpi->tpl_stats[frame].tpl_stats_ptr)
1620*fb1b10abSAndroid Build Coastguard Worker       continue;
1621*fb1b10abSAndroid Build Coastguard Worker 
1622*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
1623*fb1b10abSAndroid Build Coastguard Worker     for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
1624*fb1b10abSAndroid Build Coastguard Worker       vpx_free(cpi->tpl_stats[frame].mv_mode_arr[rf_idx]);
1625*fb1b10abSAndroid Build Coastguard Worker       CHECK_MEM_ERROR(
1626*fb1b10abSAndroid Build Coastguard Worker           &cm->error, cpi->tpl_stats[frame].mv_mode_arr[rf_idx],
1627*fb1b10abSAndroid Build Coastguard Worker           vpx_calloc(mi_rows * mi_cols * 4,
1628*fb1b10abSAndroid Build Coastguard Worker                      sizeof(*cpi->tpl_stats[frame].mv_mode_arr[rf_idx])));
1629*fb1b10abSAndroid Build Coastguard Worker       vpx_free(cpi->tpl_stats[frame].rd_diff_arr[rf_idx]);
1630*fb1b10abSAndroid Build Coastguard Worker       CHECK_MEM_ERROR(
1631*fb1b10abSAndroid Build Coastguard Worker           &cm->error, cpi->tpl_stats[frame].rd_diff_arr[rf_idx],
1632*fb1b10abSAndroid Build Coastguard Worker           vpx_calloc(mi_rows * mi_cols * 4,
1633*fb1b10abSAndroid Build Coastguard Worker                      sizeof(*cpi->tpl_stats[frame].rd_diff_arr[rf_idx])));
1634*fb1b10abSAndroid Build Coastguard Worker     }
1635*fb1b10abSAndroid Build Coastguard Worker #endif
1636*fb1b10abSAndroid Build Coastguard Worker     vpx_free(cpi->tpl_stats[frame].tpl_stats_ptr);
1637*fb1b10abSAndroid Build Coastguard Worker     CHECK_MEM_ERROR(&cm->error, cpi->tpl_stats[frame].tpl_stats_ptr,
1638*fb1b10abSAndroid Build Coastguard Worker                     vpx_calloc(mi_rows * mi_cols,
1639*fb1b10abSAndroid Build Coastguard Worker                                sizeof(*cpi->tpl_stats[frame].tpl_stats_ptr)));
1640*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame].is_valid = 0;
1641*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame].width = mi_cols;
1642*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame].height = mi_rows;
1643*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame].stride = mi_cols;
1644*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame].mi_rows = cm->mi_rows;
1645*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame].mi_cols = cm->mi_cols;
1646*fb1b10abSAndroid Build Coastguard Worker   }
1647*fb1b10abSAndroid Build Coastguard Worker 
1648*fb1b10abSAndroid Build Coastguard Worker   for (frame = 0; frame < REF_FRAMES; ++frame) {
1649*fb1b10abSAndroid Build Coastguard Worker     cpi->enc_frame_buf[frame].mem_valid = 0;
1650*fb1b10abSAndroid Build Coastguard Worker     cpi->enc_frame_buf[frame].released = 1;
1651*fb1b10abSAndroid Build Coastguard Worker   }
1652*fb1b10abSAndroid Build Coastguard Worker }
1653*fb1b10abSAndroid Build Coastguard Worker 
vp9_free_tpl_buffer(VP9_COMP * cpi)1654*fb1b10abSAndroid Build Coastguard Worker void vp9_free_tpl_buffer(VP9_COMP *cpi) {
1655*fb1b10abSAndroid Build Coastguard Worker   int frame;
1656*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
1657*fb1b10abSAndroid Build Coastguard Worker   vp9_free_motion_field_info(&cpi->motion_field_info);
1658*fb1b10abSAndroid Build Coastguard Worker   vpx_free(cpi->select_mv_arr);
1659*fb1b10abSAndroid Build Coastguard Worker #endif
1660*fb1b10abSAndroid Build Coastguard Worker   for (frame = 0; frame < MAX_ARF_GOP_SIZE; ++frame) {
1661*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
1662*fb1b10abSAndroid Build Coastguard Worker     int rf_idx;
1663*fb1b10abSAndroid Build Coastguard Worker     for (rf_idx = 0; rf_idx < MAX_INTER_REF_FRAMES; ++rf_idx) {
1664*fb1b10abSAndroid Build Coastguard Worker       vpx_free(cpi->tpl_stats[frame].mv_mode_arr[rf_idx]);
1665*fb1b10abSAndroid Build Coastguard Worker       vpx_free(cpi->tpl_stats[frame].rd_diff_arr[rf_idx]);
1666*fb1b10abSAndroid Build Coastguard Worker     }
1667*fb1b10abSAndroid Build Coastguard Worker #endif
1668*fb1b10abSAndroid Build Coastguard Worker     vpx_free(cpi->tpl_stats[frame].tpl_stats_ptr);
1669*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats[frame].is_valid = 0;
1670*fb1b10abSAndroid Build Coastguard Worker   }
1671*fb1b10abSAndroid Build Coastguard Worker   free_tpl_frame_stats_list(&cpi->tpl_gop_stats);
1672*fb1b10abSAndroid Build Coastguard Worker }
1673*fb1b10abSAndroid Build Coastguard Worker 
1674*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
accumulate_frame_tpl_stats(VP9_COMP * cpi)1675*fb1b10abSAndroid Build Coastguard Worker static void accumulate_frame_tpl_stats(VP9_COMP *cpi) {
1676*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
1677*fb1b10abSAndroid Build Coastguard Worker   const GF_GROUP *gf_group = &cpi->twopass.gf_group;
1678*fb1b10abSAndroid Build Coastguard Worker   int show_frame_count = 0;
1679*fb1b10abSAndroid Build Coastguard Worker   int frame_idx;
1680*fb1b10abSAndroid Build Coastguard Worker   // Accumulate tpl stats for each frame in the current group of picture.
1681*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = 1; frame_idx < gf_group->gf_group_size; ++frame_idx) {
1682*fb1b10abSAndroid Build Coastguard Worker     TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx];
1683*fb1b10abSAndroid Build Coastguard Worker     TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
1684*fb1b10abSAndroid Build Coastguard Worker     const int tpl_stride = tpl_frame->stride;
1685*fb1b10abSAndroid Build Coastguard Worker     int64_t intra_cost_base = 0;
1686*fb1b10abSAndroid Build Coastguard Worker     int64_t inter_cost_base = 0;
1687*fb1b10abSAndroid Build Coastguard Worker     int64_t mc_dep_cost_base = 0;
1688*fb1b10abSAndroid Build Coastguard Worker     int64_t mc_ref_cost_base = 0;
1689*fb1b10abSAndroid Build Coastguard Worker     int64_t mc_flow_base = 0;
1690*fb1b10abSAndroid Build Coastguard Worker     int row, col;
1691*fb1b10abSAndroid Build Coastguard Worker 
1692*fb1b10abSAndroid Build Coastguard Worker     if (!tpl_frame->is_valid) continue;
1693*fb1b10abSAndroid Build Coastguard Worker 
1694*fb1b10abSAndroid Build Coastguard Worker     for (row = 0; row < cm->mi_rows && tpl_frame->is_valid; ++row) {
1695*fb1b10abSAndroid Build Coastguard Worker       for (col = 0; col < cm->mi_cols; ++col) {
1696*fb1b10abSAndroid Build Coastguard Worker         TplDepStats *this_stats = &tpl_stats[row * tpl_stride + col];
1697*fb1b10abSAndroid Build Coastguard Worker         intra_cost_base += this_stats->intra_cost;
1698*fb1b10abSAndroid Build Coastguard Worker         inter_cost_base += this_stats->inter_cost;
1699*fb1b10abSAndroid Build Coastguard Worker         mc_dep_cost_base += this_stats->mc_dep_cost;
1700*fb1b10abSAndroid Build Coastguard Worker         mc_ref_cost_base += this_stats->mc_ref_cost;
1701*fb1b10abSAndroid Build Coastguard Worker         mc_flow_base += this_stats->mc_flow;
1702*fb1b10abSAndroid Build Coastguard Worker       }
1703*fb1b10abSAndroid Build Coastguard Worker     }
1704*fb1b10abSAndroid Build Coastguard Worker 
1705*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats_info[show_frame_count].intra_cost = intra_cost_base;
1706*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats_info[show_frame_count].inter_cost = inter_cost_base;
1707*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats_info[show_frame_count].mc_dep_cost = mc_dep_cost_base;
1708*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats_info[show_frame_count].mc_ref_cost = mc_ref_cost_base;
1709*fb1b10abSAndroid Build Coastguard Worker     cpi->tpl_stats_info[show_frame_count].mc_flow = mc_flow_base;
1710*fb1b10abSAndroid Build Coastguard Worker 
1711*fb1b10abSAndroid Build Coastguard Worker     ++show_frame_count;
1712*fb1b10abSAndroid Build Coastguard Worker   }
1713*fb1b10abSAndroid Build Coastguard Worker }
1714*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RATE_CTRL
1715*fb1b10abSAndroid Build Coastguard Worker 
vp9_estimate_tpl_qp_gop(VP9_COMP * cpi)1716*fb1b10abSAndroid Build Coastguard Worker void vp9_estimate_tpl_qp_gop(VP9_COMP *cpi) {
1717*fb1b10abSAndroid Build Coastguard Worker   int gop_length = cpi->twopass.gf_group.gf_group_size;
1718*fb1b10abSAndroid Build Coastguard Worker   int bottom_index, top_index;
1719*fb1b10abSAndroid Build Coastguard Worker   int idx;
1720*fb1b10abSAndroid Build Coastguard Worker   const int gf_index = cpi->twopass.gf_group.index;
1721*fb1b10abSAndroid Build Coastguard Worker   const int is_src_frame_alt_ref = cpi->rc.is_src_frame_alt_ref;
1722*fb1b10abSAndroid Build Coastguard Worker   const int refresh_frame_context = cpi->common.refresh_frame_context;
1723*fb1b10abSAndroid Build Coastguard Worker 
1724*fb1b10abSAndroid Build Coastguard Worker   for (idx = gf_index; idx <= gop_length; ++idx) {
1725*fb1b10abSAndroid Build Coastguard Worker     TplDepFrame *tpl_frame = &cpi->tpl_stats[idx];
1726*fb1b10abSAndroid Build Coastguard Worker     int target_rate = cpi->twopass.gf_group.bit_allocation[idx];
1727*fb1b10abSAndroid Build Coastguard Worker     cpi->twopass.gf_group.index = idx;
1728*fb1b10abSAndroid Build Coastguard Worker     vp9_rc_set_frame_target(cpi, target_rate);
1729*fb1b10abSAndroid Build Coastguard Worker     vp9_configure_buffer_updates(cpi, idx);
1730*fb1b10abSAndroid Build Coastguard Worker     if (cpi->ext_ratectrl.ready &&
1731*fb1b10abSAndroid Build Coastguard Worker         (cpi->ext_ratectrl.funcs.rc_type & VPX_RC_QP) != 0 &&
1732*fb1b10abSAndroid Build Coastguard Worker         cpi->ext_ratectrl.funcs.get_encodeframe_decision != NULL) {
1733*fb1b10abSAndroid Build Coastguard Worker       VP9_COMMON *cm = &cpi->common;
1734*fb1b10abSAndroid Build Coastguard Worker       vpx_codec_err_t codec_status;
1735*fb1b10abSAndroid Build Coastguard Worker       const GF_GROUP *gf_group = &cpi->twopass.gf_group;
1736*fb1b10abSAndroid Build Coastguard Worker       vpx_rc_encodeframe_decision_t encode_frame_decision;
1737*fb1b10abSAndroid Build Coastguard Worker       if (idx == gop_length) break;
1738*fb1b10abSAndroid Build Coastguard Worker       codec_status = vp9_extrc_get_encodeframe_decision(
1739*fb1b10abSAndroid Build Coastguard Worker           &cpi->ext_ratectrl, gf_group->index, &encode_frame_decision);
1740*fb1b10abSAndroid Build Coastguard Worker       if (codec_status != VPX_CODEC_OK) {
1741*fb1b10abSAndroid Build Coastguard Worker         vpx_internal_error(&cm->error, codec_status,
1742*fb1b10abSAndroid Build Coastguard Worker                            "vp9_extrc_get_encodeframe_decision() failed");
1743*fb1b10abSAndroid Build Coastguard Worker       }
1744*fb1b10abSAndroid Build Coastguard Worker       tpl_frame->base_qindex = encode_frame_decision.q_index;
1745*fb1b10abSAndroid Build Coastguard Worker     } else {
1746*fb1b10abSAndroid Build Coastguard Worker       tpl_frame->base_qindex = vp9_rc_pick_q_and_bounds_two_pass(
1747*fb1b10abSAndroid Build Coastguard Worker           cpi, &bottom_index, &top_index, idx);
1748*fb1b10abSAndroid Build Coastguard Worker       tpl_frame->base_qindex = VPXMAX(tpl_frame->base_qindex, 1);
1749*fb1b10abSAndroid Build Coastguard Worker     }
1750*fb1b10abSAndroid Build Coastguard Worker   }
1751*fb1b10abSAndroid Build Coastguard Worker   // Reset the actual index and frame update
1752*fb1b10abSAndroid Build Coastguard Worker   cpi->twopass.gf_group.index = gf_index;
1753*fb1b10abSAndroid Build Coastguard Worker   cpi->rc.is_src_frame_alt_ref = is_src_frame_alt_ref;
1754*fb1b10abSAndroid Build Coastguard Worker   cpi->common.refresh_frame_context = refresh_frame_context;
1755*fb1b10abSAndroid Build Coastguard Worker   vp9_configure_buffer_updates(cpi, gf_index);
1756*fb1b10abSAndroid Build Coastguard Worker }
1757*fb1b10abSAndroid Build Coastguard Worker 
vp9_setup_tpl_stats(VP9_COMP * cpi)1758*fb1b10abSAndroid Build Coastguard Worker void vp9_setup_tpl_stats(VP9_COMP *cpi) {
1759*fb1b10abSAndroid Build Coastguard Worker   GF_PICTURE gf_picture_buf[MAX_ARF_GOP_SIZE + REFS_PER_FRAME];
1760*fb1b10abSAndroid Build Coastguard Worker   GF_PICTURE *gf_picture = &gf_picture_buf[REFS_PER_FRAME];
1761*fb1b10abSAndroid Build Coastguard Worker   const GF_GROUP *gf_group = &cpi->twopass.gf_group;
1762*fb1b10abSAndroid Build Coastguard Worker   int tpl_group_frames = 0;
1763*fb1b10abSAndroid Build Coastguard Worker   int frame_idx;
1764*fb1b10abSAndroid Build Coastguard Worker   int extended_frame_count;
1765*fb1b10abSAndroid Build Coastguard Worker   cpi->tpl_bsize = BLOCK_32X32;
1766*fb1b10abSAndroid Build Coastguard Worker 
1767*fb1b10abSAndroid Build Coastguard Worker   memset(gf_picture_buf, 0, sizeof(gf_picture_buf));
1768*fb1b10abSAndroid Build Coastguard Worker   extended_frame_count =
1769*fb1b10abSAndroid Build Coastguard Worker       init_gop_frames(cpi, gf_picture, gf_group, &tpl_group_frames);
1770*fb1b10abSAndroid Build Coastguard Worker 
1771*fb1b10abSAndroid Build Coastguard Worker   init_tpl_stats(cpi);
1772*fb1b10abSAndroid Build Coastguard Worker 
1773*fb1b10abSAndroid Build Coastguard Worker   init_tpl_stats_before_propagation(&cpi->common.error, &cpi->tpl_gop_stats,
1774*fb1b10abSAndroid Build Coastguard Worker                                     cpi->tpl_stats, tpl_group_frames,
1775*fb1b10abSAndroid Build Coastguard Worker                                     cpi->common.width, cpi->common.height);
1776*fb1b10abSAndroid Build Coastguard Worker 
1777*fb1b10abSAndroid Build Coastguard Worker   // Backward propagation from tpl_group_frames to 1.
1778*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = tpl_group_frames - 1; frame_idx > 0; --frame_idx) {
1779*fb1b10abSAndroid Build Coastguard Worker     if (gf_picture[frame_idx].update_type == USE_BUF_FRAME) continue;
1780*fb1b10abSAndroid Build Coastguard Worker     mc_flow_dispenser(cpi, gf_picture, frame_idx, cpi->tpl_bsize);
1781*fb1b10abSAndroid Build Coastguard Worker   }
1782*fb1b10abSAndroid Build Coastguard Worker 
1783*fb1b10abSAndroid Build Coastguard Worker   if (cpi->ext_ratectrl.ready &&
1784*fb1b10abSAndroid Build Coastguard Worker       cpi->ext_ratectrl.funcs.send_tpl_gop_stats != NULL) {
1785*fb1b10abSAndroid Build Coastguard Worker     // Intra search on key frame
1786*fb1b10abSAndroid Build Coastguard Worker     if (gf_picture[0].update_type != OVERLAY_UPDATE) {
1787*fb1b10abSAndroid Build Coastguard Worker       mc_flow_dispenser(cpi, gf_picture, 0, cpi->tpl_bsize);
1788*fb1b10abSAndroid Build Coastguard Worker     }
1789*fb1b10abSAndroid Build Coastguard Worker     // TPL stats has extra frames from next GOP. Trim those extra frames for
1790*fb1b10abSAndroid Build Coastguard Worker     // Qmode.
1791*fb1b10abSAndroid Build Coastguard Worker     trim_tpl_stats(&cpi->common.error, &cpi->tpl_gop_stats,
1792*fb1b10abSAndroid Build Coastguard Worker                    extended_frame_count);
1793*fb1b10abSAndroid Build Coastguard Worker     const vpx_codec_err_t codec_status =
1794*fb1b10abSAndroid Build Coastguard Worker         vp9_extrc_send_tpl_stats(&cpi->ext_ratectrl, &cpi->tpl_gop_stats);
1795*fb1b10abSAndroid Build Coastguard Worker     if (codec_status != VPX_CODEC_OK) {
1796*fb1b10abSAndroid Build Coastguard Worker       vpx_internal_error(&cpi->common.error, codec_status,
1797*fb1b10abSAndroid Build Coastguard Worker                          "vp9_extrc_send_tpl_stats() failed");
1798*fb1b10abSAndroid Build Coastguard Worker     }
1799*fb1b10abSAndroid Build Coastguard Worker   }
1800*fb1b10abSAndroid Build Coastguard Worker 
1801*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
1802*fb1b10abSAndroid Build Coastguard Worker   cpi->tpl_ready = 1;
1803*fb1b10abSAndroid Build Coastguard Worker #if DUMP_TPL_STATS
1804*fb1b10abSAndroid Build Coastguard Worker   dump_tpl_stats(cpi, tpl_group_frames, gf_group, gf_picture, cpi->tpl_bsize);
1805*fb1b10abSAndroid Build Coastguard Worker #endif  // DUMP_TPL_STATS
1806*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_NON_GREEDY_MV
1807*fb1b10abSAndroid Build Coastguard Worker 
1808*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_RATE_CTRL
1809*fb1b10abSAndroid Build Coastguard Worker   if (cpi->oxcf.use_simple_encode_api) {
1810*fb1b10abSAndroid Build Coastguard Worker     accumulate_frame_tpl_stats(cpi);
1811*fb1b10abSAndroid Build Coastguard Worker   }
1812*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_RATE_CTRL
1813*fb1b10abSAndroid Build Coastguard Worker }
1814