1*495ae853SAndroid Build Coastguard Worker /******************************************************************************
2*495ae853SAndroid Build Coastguard Worker *
3*495ae853SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
4*495ae853SAndroid Build Coastguard Worker *
5*495ae853SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*495ae853SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*495ae853SAndroid Build Coastguard Worker * You may obtain a copy of the License at:
8*495ae853SAndroid Build Coastguard Worker *
9*495ae853SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*495ae853SAndroid Build Coastguard Worker *
11*495ae853SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*495ae853SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*495ae853SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*495ae853SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*495ae853SAndroid Build Coastguard Worker * limitations under the License.
16*495ae853SAndroid Build Coastguard Worker *
17*495ae853SAndroid Build Coastguard Worker *****************************************************************************
18*495ae853SAndroid Build Coastguard Worker * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*495ae853SAndroid Build Coastguard Worker */
20*495ae853SAndroid Build Coastguard Worker /**
21*495ae853SAndroid Build Coastguard Worker *******************************************************************************
22*495ae853SAndroid Build Coastguard Worker * @file
23*495ae853SAndroid Build Coastguard Worker * ime.c
24*495ae853SAndroid Build Coastguard Worker *
25*495ae853SAndroid Build Coastguard Worker * @brief
26*495ae853SAndroid Build Coastguard Worker * This file contains functions needed for computing motion vectors of a
27*495ae853SAndroid Build Coastguard Worker * 16x16 block
28*495ae853SAndroid Build Coastguard Worker *
29*495ae853SAndroid Build Coastguard Worker * @author
30*495ae853SAndroid Build Coastguard Worker * Ittiam
31*495ae853SAndroid Build Coastguard Worker *
32*495ae853SAndroid Build Coastguard Worker * @par List of Functions:
33*495ae853SAndroid Build Coastguard Worker * - ime_diamond_search_16x16
34*495ae853SAndroid Build Coastguard Worker * - ime_evaluate_init_srchposn_16x16
35*495ae853SAndroid Build Coastguard Worker * - ime_full_pel_motion_estimation_16x16
36*495ae853SAndroid Build Coastguard Worker * - ime_sub_pel_motion_estimation_16x16
37*495ae853SAndroid Build Coastguard Worker * - ime_compute_skip_cost
38*495ae853SAndroid Build Coastguard Worker *
39*495ae853SAndroid Build Coastguard Worker * @remarks
40*495ae853SAndroid Build Coastguard Worker * None
41*495ae853SAndroid Build Coastguard Worker *
42*495ae853SAndroid Build Coastguard Worker *******************************************************************************
43*495ae853SAndroid Build Coastguard Worker */
44*495ae853SAndroid Build Coastguard Worker
45*495ae853SAndroid Build Coastguard Worker /*****************************************************************************/
46*495ae853SAndroid Build Coastguard Worker /* File Includes */
47*495ae853SAndroid Build Coastguard Worker /*****************************************************************************/
48*495ae853SAndroid Build Coastguard Worker
49*495ae853SAndroid Build Coastguard Worker /* System include files */
50*495ae853SAndroid Build Coastguard Worker #include <stdio.h>
51*495ae853SAndroid Build Coastguard Worker #include <assert.h>
52*495ae853SAndroid Build Coastguard Worker #include <limits.h>
53*495ae853SAndroid Build Coastguard Worker #include <string.h>
54*495ae853SAndroid Build Coastguard Worker
55*495ae853SAndroid Build Coastguard Worker /* User include files */
56*495ae853SAndroid Build Coastguard Worker #include "ime_typedefs.h"
57*495ae853SAndroid Build Coastguard Worker #include "ime_distortion_metrics.h"
58*495ae853SAndroid Build Coastguard Worker #include "ime_defs.h"
59*495ae853SAndroid Build Coastguard Worker #include "ime_structs.h"
60*495ae853SAndroid Build Coastguard Worker #include "ime.h"
61*495ae853SAndroid Build Coastguard Worker #include "ime_macros.h"
62*495ae853SAndroid Build Coastguard Worker #include "ime_statistics.h"
63*495ae853SAndroid Build Coastguard Worker
64*495ae853SAndroid Build Coastguard Worker /**
65*495ae853SAndroid Build Coastguard Worker *******************************************************************************
66*495ae853SAndroid Build Coastguard Worker *
67*495ae853SAndroid Build Coastguard Worker * @brief Diamond Search
68*495ae853SAndroid Build Coastguard Worker *
69*495ae853SAndroid Build Coastguard Worker * @par Description:
70*495ae853SAndroid Build Coastguard Worker * This function computes the sad at vertices of several layers of diamond grid
71*495ae853SAndroid Build Coastguard Worker * at a time. The number of layers of diamond grid that would be evaluated is
72*495ae853SAndroid Build Coastguard Worker * configurable.The function computes the sad at vertices of a diamond grid. If
73*495ae853SAndroid Build Coastguard Worker * the sad at the center of the diamond grid is lesser than the sad at any other
74*495ae853SAndroid Build Coastguard Worker * point of the diamond grid, the function marks the candidate Mb partition as
75*495ae853SAndroid Build Coastguard Worker * mv.
76*495ae853SAndroid Build Coastguard Worker *
77*495ae853SAndroid Build Coastguard Worker * @param[in] ps_me_ctxt
78*495ae853SAndroid Build Coastguard Worker * pointer to me context
79*495ae853SAndroid Build Coastguard Worker *
80*495ae853SAndroid Build Coastguard Worker * @param[in] i4_reflist
81*495ae853SAndroid Build Coastguard Worker * ref list
82*495ae853SAndroid Build Coastguard Worker *
83*495ae853SAndroid Build Coastguard Worker * @returns mv pair & corresponding distortion and cost
84*495ae853SAndroid Build Coastguard Worker *
85*495ae853SAndroid Build Coastguard Worker * @remarks Diamond Srch, radius is 1
86*495ae853SAndroid Build Coastguard Worker *
87*495ae853SAndroid Build Coastguard Worker *******************************************************************************
88*495ae853SAndroid Build Coastguard Worker */
ime_diamond_search_16x16(me_ctxt_t * ps_me_ctxt,WORD32 i4_reflist)89*495ae853SAndroid Build Coastguard Worker void ime_diamond_search_16x16(me_ctxt_t *ps_me_ctxt, WORD32 i4_reflist)
90*495ae853SAndroid Build Coastguard Worker {
91*495ae853SAndroid Build Coastguard Worker /* MB partition info */
92*495ae853SAndroid Build Coastguard Worker mb_part_ctxt *ps_mb_part = &ps_me_ctxt->as_mb_part[i4_reflist];
93*495ae853SAndroid Build Coastguard Worker
94*495ae853SAndroid Build Coastguard Worker /* lagrange parameter */
95*495ae853SAndroid Build Coastguard Worker UWORD32 u4_lambda_motion = ps_me_ctxt->u4_lambda_motion;
96*495ae853SAndroid Build Coastguard Worker
97*495ae853SAndroid Build Coastguard Worker /* srch range*/
98*495ae853SAndroid Build Coastguard Worker WORD32 i4_srch_range_n = ps_me_ctxt->i4_srch_range_n;
99*495ae853SAndroid Build Coastguard Worker WORD32 i4_srch_range_s = ps_me_ctxt->i4_srch_range_s;
100*495ae853SAndroid Build Coastguard Worker WORD32 i4_srch_range_e = ps_me_ctxt->i4_srch_range_e;
101*495ae853SAndroid Build Coastguard Worker WORD32 i4_srch_range_w = ps_me_ctxt->i4_srch_range_w;
102*495ae853SAndroid Build Coastguard Worker
103*495ae853SAndroid Build Coastguard Worker /* enabled fast sad computation */
104*495ae853SAndroid Build Coastguard Worker // UWORD32 u4_enable_fast_sad = ps_me_ctxt->u4_enable_fast_sad;
105*495ae853SAndroid Build Coastguard Worker
106*495ae853SAndroid Build Coastguard Worker /* pointer to src macro block */
107*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_curr_mb = ps_me_ctxt->pu1_src_buf_luma;
108*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb = ps_me_ctxt->apu1_ref_buf_luma[i4_reflist];
109*495ae853SAndroid Build Coastguard Worker
110*495ae853SAndroid Build Coastguard Worker /* strides */
111*495ae853SAndroid Build Coastguard Worker WORD32 i4_src_strd = ps_me_ctxt->i4_src_strd;
112*495ae853SAndroid Build Coastguard Worker WORD32 i4_ref_strd = ps_me_ctxt->i4_rec_strd;
113*495ae853SAndroid Build Coastguard Worker
114*495ae853SAndroid Build Coastguard Worker /* least cost */
115*495ae853SAndroid Build Coastguard Worker WORD32 i4_cost_least = ps_mb_part->i4_mb_cost;
116*495ae853SAndroid Build Coastguard Worker
117*495ae853SAndroid Build Coastguard Worker /* least sad */
118*495ae853SAndroid Build Coastguard Worker WORD32 i4_distortion_least = ps_mb_part->i4_mb_distortion;
119*495ae853SAndroid Build Coastguard Worker
120*495ae853SAndroid Build Coastguard Worker /* mv pair */
121*495ae853SAndroid Build Coastguard Worker WORD16 i2_mvx, i2_mvy;
122*495ae853SAndroid Build Coastguard Worker
123*495ae853SAndroid Build Coastguard Worker /* mv bits */
124*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_mv_bits = ps_me_ctxt->pu1_mv_bits;
125*495ae853SAndroid Build Coastguard Worker
126*495ae853SAndroid Build Coastguard Worker /* temp var */
127*495ae853SAndroid Build Coastguard Worker WORD32 i4_cost[4];
128*495ae853SAndroid Build Coastguard Worker WORD32 i4_sad[4];
129*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref;
130*495ae853SAndroid Build Coastguard Worker WORD16 i2_mv_u_x, i2_mv_u_y;
131*495ae853SAndroid Build Coastguard Worker
132*495ae853SAndroid Build Coastguard Worker /* Diamond search Iteration Max Cnt */
133*495ae853SAndroid Build Coastguard Worker UWORD32 u4_num_layers = ps_me_ctxt->u4_num_layers;
134*495ae853SAndroid Build Coastguard Worker
135*495ae853SAndroid Build Coastguard Worker /* temp var */
136*495ae853SAndroid Build Coastguard Worker // UWORD8 u1_prev_jump = NONE;
137*495ae853SAndroid Build Coastguard Worker // UWORD8 u1_curr_jump = NONE;
138*495ae853SAndroid Build Coastguard Worker // UWORD8 u1_next_jump;
139*495ae853SAndroid Build Coastguard Worker // WORD32 mask_arr[5] = {15, 13, 14, 7, 11};
140*495ae853SAndroid Build Coastguard Worker // WORD32 mask;
141*495ae853SAndroid Build Coastguard Worker // UWORD8 *apu1_ref[4];
142*495ae853SAndroid Build Coastguard Worker // WORD32 i, cnt;
143*495ae853SAndroid Build Coastguard Worker // WORD32 dia[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
144*495ae853SAndroid Build Coastguard Worker
145*495ae853SAndroid Build Coastguard Worker /* mv with best sad during initial evaluation */
146*495ae853SAndroid Build Coastguard Worker i2_mvx = ps_mb_part->s_mv_curr.i2_mvx;
147*495ae853SAndroid Build Coastguard Worker i2_mvy = ps_mb_part->s_mv_curr.i2_mvy;
148*495ae853SAndroid Build Coastguard Worker
149*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = i2_mvx;
150*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = i2_mvy;
151*495ae853SAndroid Build Coastguard Worker
152*495ae853SAndroid Build Coastguard Worker while (u4_num_layers)
153*495ae853SAndroid Build Coastguard Worker {
154*495ae853SAndroid Build Coastguard Worker /* FIXME : is this the write way to check for out of bounds ? */
155*495ae853SAndroid Build Coastguard Worker if ( (i2_mvx - 1 < i4_srch_range_w) ||
156*495ae853SAndroid Build Coastguard Worker (i2_mvx + 1 > i4_srch_range_e) ||
157*495ae853SAndroid Build Coastguard Worker (i2_mvy - 1 < i4_srch_range_n) ||
158*495ae853SAndroid Build Coastguard Worker (i2_mvy + 1 > i4_srch_range_s) )
159*495ae853SAndroid Build Coastguard Worker {
160*495ae853SAndroid Build Coastguard Worker break;
161*495ae853SAndroid Build Coastguard Worker }
162*495ae853SAndroid Build Coastguard Worker
163*495ae853SAndroid Build Coastguard Worker pu1_ref = pu1_ref_mb + i2_mvx + (i2_mvy * i4_ref_strd);
164*495ae853SAndroid Build Coastguard Worker
165*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->pf_ime_compute_sad4_diamond(pu1_ref,
166*495ae853SAndroid Build Coastguard Worker pu1_curr_mb,
167*495ae853SAndroid Build Coastguard Worker i4_ref_strd,
168*495ae853SAndroid Build Coastguard Worker i4_src_strd,
169*495ae853SAndroid Build Coastguard Worker i4_sad);
170*495ae853SAndroid Build Coastguard Worker
171*495ae853SAndroid Build Coastguard Worker DEBUG_SAD_HISTOGRAM_ADD(i4_sad[0], 2);
172*495ae853SAndroid Build Coastguard Worker DEBUG_SAD_HISTOGRAM_ADD(i4_sad[1], 2);
173*495ae853SAndroid Build Coastguard Worker DEBUG_SAD_HISTOGRAM_ADD(i4_sad[2], 2);
174*495ae853SAndroid Build Coastguard Worker DEBUG_SAD_HISTOGRAM_ADD(i4_sad[3], 2);
175*495ae853SAndroid Build Coastguard Worker
176*495ae853SAndroid Build Coastguard Worker /* compute cost */
177*495ae853SAndroid Build Coastguard Worker i4_cost[0] = i4_sad[0] + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ ((i2_mvx - 1) << 2) - ps_mb_part->s_mv_pred.i2_mvx]
178*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[(i2_mvy << 2) - ps_mb_part->s_mv_pred.i2_mvy] ));
179*495ae853SAndroid Build Coastguard Worker i4_cost[1] = i4_sad[1] + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ ((i2_mvx + 1) << 2) - ps_mb_part->s_mv_pred.i2_mvx]
180*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[(i2_mvy << 2) - ps_mb_part->s_mv_pred.i2_mvy] ));
181*495ae853SAndroid Build Coastguard Worker i4_cost[2] = i4_sad[2] + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ (i2_mvx << 2) - ps_mb_part->s_mv_pred.i2_mvx]
182*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[((i2_mvy - 1) << 2) - ps_mb_part->s_mv_pred.i2_mvy] ));
183*495ae853SAndroid Build Coastguard Worker i4_cost[3] = i4_sad[3] + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ (i2_mvx << 2) - ps_mb_part->s_mv_pred.i2_mvx]
184*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[((i2_mvy + 1) << 2) - ps_mb_part->s_mv_pred.i2_mvy] ));
185*495ae853SAndroid Build Coastguard Worker
186*495ae853SAndroid Build Coastguard Worker
187*495ae853SAndroid Build Coastguard Worker if (i4_cost_least > i4_cost[0])
188*495ae853SAndroid Build Coastguard Worker {
189*495ae853SAndroid Build Coastguard Worker i4_cost_least = i4_cost[0];
190*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_sad[0];
191*495ae853SAndroid Build Coastguard Worker
192*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = (i2_mvx - 1);
193*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = i2_mvy;
194*495ae853SAndroid Build Coastguard Worker }
195*495ae853SAndroid Build Coastguard Worker
196*495ae853SAndroid Build Coastguard Worker if (i4_cost_least > i4_cost[1])
197*495ae853SAndroid Build Coastguard Worker {
198*495ae853SAndroid Build Coastguard Worker i4_cost_least = i4_cost[1];
199*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_sad[1];
200*495ae853SAndroid Build Coastguard Worker
201*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = (i2_mvx + 1);
202*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = i2_mvy;
203*495ae853SAndroid Build Coastguard Worker }
204*495ae853SAndroid Build Coastguard Worker
205*495ae853SAndroid Build Coastguard Worker if (i4_cost_least > i4_cost[2])
206*495ae853SAndroid Build Coastguard Worker {
207*495ae853SAndroid Build Coastguard Worker i4_cost_least = i4_cost[2];
208*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_sad[2];
209*495ae853SAndroid Build Coastguard Worker
210*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = i2_mvx;
211*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = i2_mvy - 1;
212*495ae853SAndroid Build Coastguard Worker }
213*495ae853SAndroid Build Coastguard Worker
214*495ae853SAndroid Build Coastguard Worker if (i4_cost_least > i4_cost[3])
215*495ae853SAndroid Build Coastguard Worker {
216*495ae853SAndroid Build Coastguard Worker i4_cost_least = i4_cost[3];
217*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_sad[3];
218*495ae853SAndroid Build Coastguard Worker
219*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = i2_mvx;
220*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = i2_mvy + 1;
221*495ae853SAndroid Build Coastguard Worker }
222*495ae853SAndroid Build Coastguard Worker
223*495ae853SAndroid Build Coastguard Worker if( (i2_mv_u_x == i2_mvx) && (i2_mv_u_y == i2_mvy))
224*495ae853SAndroid Build Coastguard Worker {
225*495ae853SAndroid Build Coastguard Worker ps_mb_part->u4_exit = 1;
226*495ae853SAndroid Build Coastguard Worker break;
227*495ae853SAndroid Build Coastguard Worker }
228*495ae853SAndroid Build Coastguard Worker else
229*495ae853SAndroid Build Coastguard Worker {
230*495ae853SAndroid Build Coastguard Worker i2_mvx = i2_mv_u_x;
231*495ae853SAndroid Build Coastguard Worker i2_mvy = i2_mv_u_y;
232*495ae853SAndroid Build Coastguard Worker }
233*495ae853SAndroid Build Coastguard Worker u4_num_layers--;
234*495ae853SAndroid Build Coastguard Worker }
235*495ae853SAndroid Build Coastguard Worker
236*495ae853SAndroid Build Coastguard Worker if (i4_cost_least < ps_mb_part->i4_mb_cost)
237*495ae853SAndroid Build Coastguard Worker {
238*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_mb_cost = i4_cost_least;
239*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_mb_distortion = i4_distortion_least;
240*495ae853SAndroid Build Coastguard Worker ps_mb_part->s_mv_curr.i2_mvx = i2_mvx;
241*495ae853SAndroid Build Coastguard Worker ps_mb_part->s_mv_curr.i2_mvy = i2_mvy;
242*495ae853SAndroid Build Coastguard Worker }
243*495ae853SAndroid Build Coastguard Worker
244*495ae853SAndroid Build Coastguard Worker }
245*495ae853SAndroid Build Coastguard Worker
246*495ae853SAndroid Build Coastguard Worker
247*495ae853SAndroid Build Coastguard Worker /**
248*495ae853SAndroid Build Coastguard Worker *******************************************************************************
249*495ae853SAndroid Build Coastguard Worker *
250*495ae853SAndroid Build Coastguard Worker * @brief This function computes the best motion vector among the tentative mv
251*495ae853SAndroid Build Coastguard Worker * candidates chosen.
252*495ae853SAndroid Build Coastguard Worker *
253*495ae853SAndroid Build Coastguard Worker * @par Description:
254*495ae853SAndroid Build Coastguard Worker * This function determines the position in the search window at which the motion
255*495ae853SAndroid Build Coastguard Worker * estimation should begin in order to minimise the number of search iterations.
256*495ae853SAndroid Build Coastguard Worker *
257*495ae853SAndroid Build Coastguard Worker * @param[in] ps_me_ctxt
258*495ae853SAndroid Build Coastguard Worker * pointer to me context
259*495ae853SAndroid Build Coastguard Worker *
260*495ae853SAndroid Build Coastguard Worker * @param[in] i4_reflist
261*495ae853SAndroid Build Coastguard Worker * ref list
262*495ae853SAndroid Build Coastguard Worker *
263*495ae853SAndroid Build Coastguard Worker * @returns mv pair & corresponding distortion and cost
264*495ae853SAndroid Build Coastguard Worker *
265*495ae853SAndroid Build Coastguard Worker * @remarks none
266*495ae853SAndroid Build Coastguard Worker *
267*495ae853SAndroid Build Coastguard Worker *******************************************************************************
268*495ae853SAndroid Build Coastguard Worker */
269*495ae853SAndroid Build Coastguard Worker
ime_evaluate_init_srchposn_16x16(me_ctxt_t * ps_me_ctxt,WORD32 i4_reflist)270*495ae853SAndroid Build Coastguard Worker void ime_evaluate_init_srchposn_16x16
271*495ae853SAndroid Build Coastguard Worker (
272*495ae853SAndroid Build Coastguard Worker me_ctxt_t *ps_me_ctxt,
273*495ae853SAndroid Build Coastguard Worker WORD32 i4_reflist
274*495ae853SAndroid Build Coastguard Worker )
275*495ae853SAndroid Build Coastguard Worker {
276*495ae853SAndroid Build Coastguard Worker UWORD32 u4_lambda_motion = ps_me_ctxt->u4_lambda_motion;
277*495ae853SAndroid Build Coastguard Worker
278*495ae853SAndroid Build Coastguard Worker /* candidate mv cnt */
279*495ae853SAndroid Build Coastguard Worker UWORD32 u4_num_candidates = ps_me_ctxt->u4_num_candidates[i4_reflist];
280*495ae853SAndroid Build Coastguard Worker
281*495ae853SAndroid Build Coastguard Worker /* list of candidate mvs */
282*495ae853SAndroid Build Coastguard Worker ime_mv_t *ps_mv_list = ps_me_ctxt->as_mv_init_search[i4_reflist];
283*495ae853SAndroid Build Coastguard Worker
284*495ae853SAndroid Build Coastguard Worker /* pointer to src macro block */
285*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_curr_mb = ps_me_ctxt->pu1_src_buf_luma;
286*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb = ps_me_ctxt->apu1_ref_buf_luma[i4_reflist];
287*495ae853SAndroid Build Coastguard Worker
288*495ae853SAndroid Build Coastguard Worker /* strides */
289*495ae853SAndroid Build Coastguard Worker WORD32 i4_src_strd = ps_me_ctxt->i4_src_strd;
290*495ae853SAndroid Build Coastguard Worker WORD32 i4_ref_strd = ps_me_ctxt->i4_rec_strd;
291*495ae853SAndroid Build Coastguard Worker
292*495ae853SAndroid Build Coastguard Worker /* enabled fast sad computation */
293*495ae853SAndroid Build Coastguard Worker UWORD32 u4_enable_fast_sad = ps_me_ctxt->u4_enable_fast_sad;
294*495ae853SAndroid Build Coastguard Worker
295*495ae853SAndroid Build Coastguard Worker /* SAD(distortion metric) of an 8x8 block */
296*495ae853SAndroid Build Coastguard Worker WORD32 i4_mb_distortion;
297*495ae853SAndroid Build Coastguard Worker
298*495ae853SAndroid Build Coastguard Worker /* cost = distortion + u4_lambda_motion * rate */
299*495ae853SAndroid Build Coastguard Worker WORD32 i4_mb_cost, i4_mb_cost_least = INT_MAX, i4_distortion_least = INT_MAX;
300*495ae853SAndroid Build Coastguard Worker
301*495ae853SAndroid Build Coastguard Worker /* mb partitions info */
302*495ae853SAndroid Build Coastguard Worker mb_part_ctxt *ps_mb_part = &(ps_me_ctxt->as_mb_part[i4_reflist]);
303*495ae853SAndroid Build Coastguard Worker
304*495ae853SAndroid Build Coastguard Worker /* mv bits */
305*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_mv_bits = ps_me_ctxt->pu1_mv_bits;
306*495ae853SAndroid Build Coastguard Worker
307*495ae853SAndroid Build Coastguard Worker /* temp var */
308*495ae853SAndroid Build Coastguard Worker UWORD32 i, j;
309*495ae853SAndroid Build Coastguard Worker WORD32 i4_srch_pos_idx = 0;
310*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref = NULL;
311*495ae853SAndroid Build Coastguard Worker
312*495ae853SAndroid Build Coastguard Worker /* Carry out a search using each of the motion vector pairs identified above as predictors. */
313*495ae853SAndroid Build Coastguard Worker /* TODO : Just like Skip, Do we need to add any bias to zero mv as well */
314*495ae853SAndroid Build Coastguard Worker for(i = 0; i < u4_num_candidates; i++)
315*495ae853SAndroid Build Coastguard Worker {
316*495ae853SAndroid Build Coastguard Worker /* compute sad */
317*495ae853SAndroid Build Coastguard Worker WORD32 c_sad = 1;
318*495ae853SAndroid Build Coastguard Worker
319*495ae853SAndroid Build Coastguard Worker for(j = 0; j < i; j++ )
320*495ae853SAndroid Build Coastguard Worker {
321*495ae853SAndroid Build Coastguard Worker if ( (ps_mv_list[i].i2_mvx == ps_mv_list[j].i2_mvx) &&
322*495ae853SAndroid Build Coastguard Worker (ps_mv_list[i].i2_mvy == ps_mv_list[j].i2_mvy) )
323*495ae853SAndroid Build Coastguard Worker {
324*495ae853SAndroid Build Coastguard Worker c_sad = 0;
325*495ae853SAndroid Build Coastguard Worker break;
326*495ae853SAndroid Build Coastguard Worker }
327*495ae853SAndroid Build Coastguard Worker }
328*495ae853SAndroid Build Coastguard Worker if(c_sad)
329*495ae853SAndroid Build Coastguard Worker {
330*495ae853SAndroid Build Coastguard Worker /* adjust ref pointer */
331*495ae853SAndroid Build Coastguard Worker pu1_ref = pu1_ref_mb + ps_mv_list[i].i2_mvx + (ps_mv_list[i].i2_mvy * i4_ref_strd);
332*495ae853SAndroid Build Coastguard Worker
333*495ae853SAndroid Build Coastguard Worker /* compute distortion */
334*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->pf_ime_compute_sad_16x16[u4_enable_fast_sad](pu1_curr_mb, pu1_ref, i4_src_strd, i4_ref_strd, i4_mb_cost_least, &i4_mb_distortion);
335*495ae853SAndroid Build Coastguard Worker
336*495ae853SAndroid Build Coastguard Worker DEBUG_SAD_HISTOGRAM_ADD(i4_mb_distortion, 3);
337*495ae853SAndroid Build Coastguard Worker
338*495ae853SAndroid Build Coastguard Worker /* compute cost */
339*495ae853SAndroid Build Coastguard Worker i4_mb_cost = i4_mb_distortion + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ (ps_mv_list[i].i2_mvx << 2) - ps_mb_part->s_mv_pred.i2_mvx]
340*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[(ps_mv_list[i].i2_mvy << 2) - ps_mb_part->s_mv_pred.i2_mvy] ));
341*495ae853SAndroid Build Coastguard Worker
342*495ae853SAndroid Build Coastguard Worker if (i4_mb_cost < i4_mb_cost_least)
343*495ae853SAndroid Build Coastguard Worker {
344*495ae853SAndroid Build Coastguard Worker i4_mb_cost_least = i4_mb_cost;
345*495ae853SAndroid Build Coastguard Worker
346*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_mb_distortion;
347*495ae853SAndroid Build Coastguard Worker
348*495ae853SAndroid Build Coastguard Worker i4_srch_pos_idx = i;
349*495ae853SAndroid Build Coastguard Worker }
350*495ae853SAndroid Build Coastguard Worker }
351*495ae853SAndroid Build Coastguard Worker }
352*495ae853SAndroid Build Coastguard Worker
353*495ae853SAndroid Build Coastguard Worker if (i4_mb_cost_least < ps_mb_part->i4_mb_cost)
354*495ae853SAndroid Build Coastguard Worker {
355*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_srch_pos_idx = i4_srch_pos_idx;
356*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_mb_cost = i4_mb_cost_least;
357*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_mb_distortion = i4_distortion_least;
358*495ae853SAndroid Build Coastguard Worker ps_mb_part->s_mv_curr.i2_mvx = ps_mv_list[i4_srch_pos_idx].i2_mvx;
359*495ae853SAndroid Build Coastguard Worker ps_mb_part->s_mv_curr.i2_mvy = ps_mv_list[i4_srch_pos_idx].i2_mvy;
360*495ae853SAndroid Build Coastguard Worker }
361*495ae853SAndroid Build Coastguard Worker }
362*495ae853SAndroid Build Coastguard Worker
363*495ae853SAndroid Build Coastguard Worker /**
364*495ae853SAndroid Build Coastguard Worker *******************************************************************************
365*495ae853SAndroid Build Coastguard Worker *
366*495ae853SAndroid Build Coastguard Worker * @brief Searches for the best matching full pixel predictor within the search
367*495ae853SAndroid Build Coastguard Worker * range
368*495ae853SAndroid Build Coastguard Worker *
369*495ae853SAndroid Build Coastguard Worker * @par Description:
370*495ae853SAndroid Build Coastguard Worker * For a given algorithm (diamond, Hex, nStep, ...) chosen, it searches for the
371*495ae853SAndroid Build Coastguard Worker * best matching full pixel predictor within the search range
372*495ae853SAndroid Build Coastguard Worker *
373*495ae853SAndroid Build Coastguard Worker * @param[in] ps_me_ctxt
374*495ae853SAndroid Build Coastguard Worker * pointer to me context
375*495ae853SAndroid Build Coastguard Worker *
376*495ae853SAndroid Build Coastguard Worker * @param[in] i4_reflist
377*495ae853SAndroid Build Coastguard Worker * ref list
378*495ae853SAndroid Build Coastguard Worker *
379*495ae853SAndroid Build Coastguard Worker * @returns mv pair & corresponding distortion and cost
380*495ae853SAndroid Build Coastguard Worker *
381*495ae853SAndroid Build Coastguard Worker * @remarks none
382*495ae853SAndroid Build Coastguard Worker *
383*495ae853SAndroid Build Coastguard Worker *******************************************************************************
384*495ae853SAndroid Build Coastguard Worker */
ime_full_pel_motion_estimation_16x16(me_ctxt_t * ps_me_ctxt,WORD32 i4_ref_list)385*495ae853SAndroid Build Coastguard Worker void ime_full_pel_motion_estimation_16x16
386*495ae853SAndroid Build Coastguard Worker (
387*495ae853SAndroid Build Coastguard Worker me_ctxt_t *ps_me_ctxt,
388*495ae853SAndroid Build Coastguard Worker WORD32 i4_ref_list
389*495ae853SAndroid Build Coastguard Worker )
390*495ae853SAndroid Build Coastguard Worker {
391*495ae853SAndroid Build Coastguard Worker /* mb part info */
392*495ae853SAndroid Build Coastguard Worker mb_part_ctxt *ps_mb_part = &ps_me_ctxt->as_mb_part[i4_ref_list];
393*495ae853SAndroid Build Coastguard Worker
394*495ae853SAndroid Build Coastguard Worker /******************************************************************/
395*495ae853SAndroid Build Coastguard Worker /* Modify Search range about initial candidate instead of zero mv */
396*495ae853SAndroid Build Coastguard Worker /******************************************************************/
397*495ae853SAndroid Build Coastguard Worker /*
398*495ae853SAndroid Build Coastguard Worker * FIXME: The motion vectors in a way can become unbounded. It may so happen that
399*495ae853SAndroid Build Coastguard Worker * MV might exceed the limit of the profile configured.
400*495ae853SAndroid Build Coastguard Worker */
401*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_srch_range_w = MAX(ps_me_ctxt->i4_srch_range_w,
402*495ae853SAndroid Build Coastguard Worker -ps_me_ctxt->ai2_srch_boundaries[0] + ps_mb_part->s_mv_curr.i2_mvx);
403*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_srch_range_e = MIN(ps_me_ctxt->i4_srch_range_e,
404*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->ai2_srch_boundaries[0] + ps_mb_part->s_mv_curr.i2_mvx);
405*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_srch_range_n = MAX(ps_me_ctxt->i4_srch_range_n,
406*495ae853SAndroid Build Coastguard Worker -ps_me_ctxt->ai2_srch_boundaries[1] + ps_mb_part->s_mv_curr.i2_mvy);
407*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_srch_range_s = MIN(ps_me_ctxt->i4_srch_range_s,
408*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->ai2_srch_boundaries[1] + ps_mb_part->s_mv_curr.i2_mvy);
409*495ae853SAndroid Build Coastguard Worker
410*495ae853SAndroid Build Coastguard Worker /************************************************************/
411*495ae853SAndroid Build Coastguard Worker /* Traverse about best initial candidate for mv */
412*495ae853SAndroid Build Coastguard Worker /************************************************************/
413*495ae853SAndroid Build Coastguard Worker
414*495ae853SAndroid Build Coastguard Worker switch (ps_me_ctxt->u4_me_speed_preset)
415*495ae853SAndroid Build Coastguard Worker {
416*495ae853SAndroid Build Coastguard Worker case DMND_SRCH:
417*495ae853SAndroid Build Coastguard Worker ime_diamond_search_16x16(ps_me_ctxt, i4_ref_list);
418*495ae853SAndroid Build Coastguard Worker break;
419*495ae853SAndroid Build Coastguard Worker default:
420*495ae853SAndroid Build Coastguard Worker assert(0);
421*495ae853SAndroid Build Coastguard Worker break;
422*495ae853SAndroid Build Coastguard Worker }
423*495ae853SAndroid Build Coastguard Worker }
424*495ae853SAndroid Build Coastguard Worker
425*495ae853SAndroid Build Coastguard Worker /**
426*495ae853SAndroid Build Coastguard Worker *******************************************************************************
427*495ae853SAndroid Build Coastguard Worker *
428*495ae853SAndroid Build Coastguard Worker * @brief Searches for the best matching sub pixel predictor within the search
429*495ae853SAndroid Build Coastguard Worker * range
430*495ae853SAndroid Build Coastguard Worker *
431*495ae853SAndroid Build Coastguard Worker * @par Description:
432*495ae853SAndroid Build Coastguard Worker * This function begins by searching across all sub pixel sample points
433*495ae853SAndroid Build Coastguard Worker * around the full pel motion vector. The vector with least cost is chosen as
434*495ae853SAndroid Build Coastguard Worker * the mv for the current mb.
435*495ae853SAndroid Build Coastguard Worker *
436*495ae853SAndroid Build Coastguard Worker * @param[in] ps_me_ctxt
437*495ae853SAndroid Build Coastguard Worker * pointer to me context
438*495ae853SAndroid Build Coastguard Worker *
439*495ae853SAndroid Build Coastguard Worker * @param[in] i4_reflist
440*495ae853SAndroid Build Coastguard Worker * ref list
441*495ae853SAndroid Build Coastguard Worker *
442*495ae853SAndroid Build Coastguard Worker * @returns mv pair & corresponding distortion and cost
443*495ae853SAndroid Build Coastguard Worker *
444*495ae853SAndroid Build Coastguard Worker * @remarks none
445*495ae853SAndroid Build Coastguard Worker *
446*495ae853SAndroid Build Coastguard Worker *******************************************************************************
447*495ae853SAndroid Build Coastguard Worker */
ime_sub_pel_motion_estimation_16x16(me_ctxt_t * ps_me_ctxt,WORD32 i4_reflist)448*495ae853SAndroid Build Coastguard Worker void ime_sub_pel_motion_estimation_16x16
449*495ae853SAndroid Build Coastguard Worker (
450*495ae853SAndroid Build Coastguard Worker me_ctxt_t *ps_me_ctxt,
451*495ae853SAndroid Build Coastguard Worker WORD32 i4_reflist
452*495ae853SAndroid Build Coastguard Worker )
453*495ae853SAndroid Build Coastguard Worker {
454*495ae853SAndroid Build Coastguard Worker /* pointers to src & ref macro block */
455*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_curr_mb = ps_me_ctxt->pu1_src_buf_luma;
456*495ae853SAndroid Build Coastguard Worker
457*495ae853SAndroid Build Coastguard Worker /* pointers to ref. half pel planes */
458*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb_half_x;
459*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb_half_y;
460*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb_half_xy;
461*495ae853SAndroid Build Coastguard Worker
462*495ae853SAndroid Build Coastguard Worker /* pointers to ref. half pel planes */
463*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb_half_x_temp;
464*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb_half_y_temp;
465*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref_mb_half_xy_temp;
466*495ae853SAndroid Build Coastguard Worker
467*495ae853SAndroid Build Coastguard Worker /* strides */
468*495ae853SAndroid Build Coastguard Worker WORD32 i4_src_strd = ps_me_ctxt->i4_src_strd;
469*495ae853SAndroid Build Coastguard Worker
470*495ae853SAndroid Build Coastguard Worker WORD32 i4_ref_strd = ps_me_ctxt->u4_subpel_buf_strd;
471*495ae853SAndroid Build Coastguard Worker
472*495ae853SAndroid Build Coastguard Worker /* mb partitions info */
473*495ae853SAndroid Build Coastguard Worker mb_part_ctxt *ps_mb_part = &ps_me_ctxt->as_mb_part[i4_reflist];
474*495ae853SAndroid Build Coastguard Worker
475*495ae853SAndroid Build Coastguard Worker /* SAD(distortion metric) of an mb */
476*495ae853SAndroid Build Coastguard Worker WORD32 i4_mb_distortion;
477*495ae853SAndroid Build Coastguard Worker WORD32 i4_distortion_least = ps_mb_part->i4_mb_distortion;
478*495ae853SAndroid Build Coastguard Worker
479*495ae853SAndroid Build Coastguard Worker /* cost = distortion + u4_lambda_motion * rate */
480*495ae853SAndroid Build Coastguard Worker WORD32 i4_mb_cost;
481*495ae853SAndroid Build Coastguard Worker WORD32 i4_mb_cost_least = ps_mb_part->i4_mb_cost;
482*495ae853SAndroid Build Coastguard Worker
483*495ae853SAndroid Build Coastguard Worker /*Best half pel buffer*/
484*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_best_hpel_buf = NULL;
485*495ae853SAndroid Build Coastguard Worker
486*495ae853SAndroid Build Coastguard Worker /* mv bits */
487*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_mv_bits = ps_me_ctxt->pu1_mv_bits;
488*495ae853SAndroid Build Coastguard Worker
489*495ae853SAndroid Build Coastguard Worker /* Motion vectors in full-pel units */
490*495ae853SAndroid Build Coastguard Worker WORD16 mv_x, mv_y;
491*495ae853SAndroid Build Coastguard Worker
492*495ae853SAndroid Build Coastguard Worker /* lambda - lagrange constant */
493*495ae853SAndroid Build Coastguard Worker UWORD32 u4_lambda_motion = ps_me_ctxt->u4_lambda_motion;
494*495ae853SAndroid Build Coastguard Worker
495*495ae853SAndroid Build Coastguard Worker /* Flags to check if half pel points needs to be evaluated */
496*495ae853SAndroid Build Coastguard Worker /**************************************/
497*495ae853SAndroid Build Coastguard Worker /* 1 bit for each half pel candidate */
498*495ae853SAndroid Build Coastguard Worker /* bit 0 - half x = 1, half y = 0 */
499*495ae853SAndroid Build Coastguard Worker /* bit 1 - half x = -1, half y = 0 */
500*495ae853SAndroid Build Coastguard Worker /* bit 2 - half x = 0, half y = 1 */
501*495ae853SAndroid Build Coastguard Worker /* bit 3 - half x = 0, half y = -1 */
502*495ae853SAndroid Build Coastguard Worker /* bit 4 - half x = 1, half y = 1 */
503*495ae853SAndroid Build Coastguard Worker /* bit 5 - half x = -1, half y = 1 */
504*495ae853SAndroid Build Coastguard Worker /* bit 6 - half x = 1, half y = -1 */
505*495ae853SAndroid Build Coastguard Worker /* bit 7 - half x = -1, half y = -1 */
506*495ae853SAndroid Build Coastguard Worker /**************************************/
507*495ae853SAndroid Build Coastguard Worker /* temp var */
508*495ae853SAndroid Build Coastguard Worker WORD16 i2_mv_u_x, i2_mv_u_y;
509*495ae853SAndroid Build Coastguard Worker WORD32 i, j;
510*495ae853SAndroid Build Coastguard Worker WORD32 ai4_sad[8];
511*495ae853SAndroid Build Coastguard Worker
512*495ae853SAndroid Build Coastguard Worker WORD32 i4_srch_pos_idx = ps_mb_part->i4_srch_pos_idx;
513*495ae853SAndroid Build Coastguard Worker
514*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = ps_mb_part->s_mv_curr.i2_mvx;
515*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = ps_mb_part->s_mv_curr.i2_mvy;
516*495ae853SAndroid Build Coastguard Worker
517*495ae853SAndroid Build Coastguard Worker /************************************************************/
518*495ae853SAndroid Build Coastguard Worker /* Evaluate half pel */
519*495ae853SAndroid Build Coastguard Worker /************************************************************/
520*495ae853SAndroid Build Coastguard Worker mv_x = ps_mb_part->s_mv_curr.i2_mvx >> 2;
521*495ae853SAndroid Build Coastguard Worker mv_y = ps_mb_part->s_mv_curr.i2_mvy >> 2;
522*495ae853SAndroid Build Coastguard Worker
523*495ae853SAndroid Build Coastguard Worker
524*495ae853SAndroid Build Coastguard Worker /**************************************************************/
525*495ae853SAndroid Build Coastguard Worker /* ps_me_ctxt->pu1_half_x points to the half pel pixel on the */
526*495ae853SAndroid Build Coastguard Worker /* left side of full pel */
527*495ae853SAndroid Build Coastguard Worker /* ps_me_ctxt->pu1_half_y points to the half pel pixel on the */
528*495ae853SAndroid Build Coastguard Worker /* top side of full pel */
529*495ae853SAndroid Build Coastguard Worker /* ps_me_ctxt->pu1_half_xy points to the half pel pixel */
530*495ae853SAndroid Build Coastguard Worker /* on the top left side of full pel */
531*495ae853SAndroid Build Coastguard Worker /* for the function pf_ime_sub_pel_compute_sad_16x16 the */
532*495ae853SAndroid Build Coastguard Worker /* default postions are */
533*495ae853SAndroid Build Coastguard Worker /* ps_me_ctxt->pu1_half_x = right halp_pel */
534*495ae853SAndroid Build Coastguard Worker /* ps_me_ctxt->pu1_half_y = bottom halp_pel */
535*495ae853SAndroid Build Coastguard Worker /* ps_me_ctxt->pu1_half_xy = bottom right halp_pel */
536*495ae853SAndroid Build Coastguard Worker /* Hence corresponding adjustments made here */
537*495ae853SAndroid Build Coastguard Worker /**************************************************************/
538*495ae853SAndroid Build Coastguard Worker
539*495ae853SAndroid Build Coastguard Worker pu1_ref_mb_half_x_temp = pu1_ref_mb_half_x = ps_me_ctxt->apu1_subpel_buffs[0] + 1;
540*495ae853SAndroid Build Coastguard Worker pu1_ref_mb_half_y_temp = pu1_ref_mb_half_y = ps_me_ctxt->apu1_subpel_buffs[1] + 1 + i4_ref_strd;
541*495ae853SAndroid Build Coastguard Worker pu1_ref_mb_half_xy_temp = pu1_ref_mb_half_xy = ps_me_ctxt->apu1_subpel_buffs[2] + 1 + i4_ref_strd;
542*495ae853SAndroid Build Coastguard Worker
543*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->pf_ime_sub_pel_compute_sad_16x16(pu1_curr_mb, pu1_ref_mb_half_x,
544*495ae853SAndroid Build Coastguard Worker pu1_ref_mb_half_y,
545*495ae853SAndroid Build Coastguard Worker pu1_ref_mb_half_xy,
546*495ae853SAndroid Build Coastguard Worker i4_src_strd, i4_ref_strd,
547*495ae853SAndroid Build Coastguard Worker ai4_sad);
548*495ae853SAndroid Build Coastguard Worker
549*495ae853SAndroid Build Coastguard Worker /* Half x plane */
550*495ae853SAndroid Build Coastguard Worker for(i = 0; i < 2; i++)
551*495ae853SAndroid Build Coastguard Worker {
552*495ae853SAndroid Build Coastguard Worker WORD32 mv_x_tmp = (mv_x << 2) + 2;
553*495ae853SAndroid Build Coastguard Worker WORD32 mv_y_tmp = (mv_y << 2);
554*495ae853SAndroid Build Coastguard Worker
555*495ae853SAndroid Build Coastguard Worker mv_x_tmp -= (i * 4);
556*495ae853SAndroid Build Coastguard Worker
557*495ae853SAndroid Build Coastguard Worker i4_mb_distortion = ai4_sad[i];
558*495ae853SAndroid Build Coastguard Worker
559*495ae853SAndroid Build Coastguard Worker /* compute cost */
560*495ae853SAndroid Build Coastguard Worker i4_mb_cost = i4_mb_distortion + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ mv_x_tmp - ps_mb_part->s_mv_pred.i2_mvx]
561*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[mv_y_tmp - ps_mb_part->s_mv_pred.i2_mvy] ));
562*495ae853SAndroid Build Coastguard Worker
563*495ae853SAndroid Build Coastguard Worker if (i4_mb_cost < i4_mb_cost_least)
564*495ae853SAndroid Build Coastguard Worker {
565*495ae853SAndroid Build Coastguard Worker i4_mb_cost_least = i4_mb_cost;
566*495ae853SAndroid Build Coastguard Worker
567*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_mb_distortion;
568*495ae853SAndroid Build Coastguard Worker
569*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = mv_x_tmp;
570*495ae853SAndroid Build Coastguard Worker
571*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = mv_y_tmp;
572*495ae853SAndroid Build Coastguard Worker
573*495ae853SAndroid Build Coastguard Worker #ifndef HP_PL /*choosing whether left or right half_x*/
574*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->apu1_subpel_buffs[0] = pu1_ref_mb_half_x_temp - i;
575*495ae853SAndroid Build Coastguard Worker pu1_best_hpel_buf = pu1_ref_mb_half_x_temp - i;
576*495ae853SAndroid Build Coastguard Worker
577*495ae853SAndroid Build Coastguard Worker i4_srch_pos_idx = 0;
578*495ae853SAndroid Build Coastguard Worker #endif
579*495ae853SAndroid Build Coastguard Worker }
580*495ae853SAndroid Build Coastguard Worker
581*495ae853SAndroid Build Coastguard Worker }
582*495ae853SAndroid Build Coastguard Worker
583*495ae853SAndroid Build Coastguard Worker /* Half y plane */
584*495ae853SAndroid Build Coastguard Worker for(i = 0; i < 2; i++)
585*495ae853SAndroid Build Coastguard Worker {
586*495ae853SAndroid Build Coastguard Worker WORD32 mv_x_tmp = (mv_x << 2);
587*495ae853SAndroid Build Coastguard Worker WORD32 mv_y_tmp = (mv_y << 2) + 2;
588*495ae853SAndroid Build Coastguard Worker
589*495ae853SAndroid Build Coastguard Worker mv_y_tmp -= (i * 4);
590*495ae853SAndroid Build Coastguard Worker
591*495ae853SAndroid Build Coastguard Worker i4_mb_distortion = ai4_sad[2 + i];
592*495ae853SAndroid Build Coastguard Worker
593*495ae853SAndroid Build Coastguard Worker /* compute cost */
594*495ae853SAndroid Build Coastguard Worker i4_mb_cost = i4_mb_distortion + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ mv_x_tmp - ps_mb_part->s_mv_pred.i2_mvx]
595*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[mv_y_tmp - ps_mb_part->s_mv_pred.i2_mvy] ));
596*495ae853SAndroid Build Coastguard Worker
597*495ae853SAndroid Build Coastguard Worker if (i4_mb_cost < i4_mb_cost_least)
598*495ae853SAndroid Build Coastguard Worker {
599*495ae853SAndroid Build Coastguard Worker i4_mb_cost_least = i4_mb_cost;
600*495ae853SAndroid Build Coastguard Worker
601*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_mb_distortion;
602*495ae853SAndroid Build Coastguard Worker
603*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = mv_x_tmp;
604*495ae853SAndroid Build Coastguard Worker
605*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = mv_y_tmp;
606*495ae853SAndroid Build Coastguard Worker
607*495ae853SAndroid Build Coastguard Worker #ifndef HP_PL/*choosing whether top or bottom half_y*/
608*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->apu1_subpel_buffs[1] = pu1_ref_mb_half_y_temp - i*(i4_ref_strd);
609*495ae853SAndroid Build Coastguard Worker pu1_best_hpel_buf = pu1_ref_mb_half_y_temp - i*(i4_ref_strd);
610*495ae853SAndroid Build Coastguard Worker
611*495ae853SAndroid Build Coastguard Worker i4_srch_pos_idx = 1;
612*495ae853SAndroid Build Coastguard Worker #endif
613*495ae853SAndroid Build Coastguard Worker }
614*495ae853SAndroid Build Coastguard Worker
615*495ae853SAndroid Build Coastguard Worker }
616*495ae853SAndroid Build Coastguard Worker
617*495ae853SAndroid Build Coastguard Worker /* Half xy plane */
618*495ae853SAndroid Build Coastguard Worker for(j = 0; j < 2; j++)
619*495ae853SAndroid Build Coastguard Worker {
620*495ae853SAndroid Build Coastguard Worker for(i = 0; i < 2; i++)
621*495ae853SAndroid Build Coastguard Worker {
622*495ae853SAndroid Build Coastguard Worker WORD32 mv_x_tmp = (mv_x << 2) + 2;
623*495ae853SAndroid Build Coastguard Worker WORD32 mv_y_tmp = (mv_y << 2) + 2;
624*495ae853SAndroid Build Coastguard Worker
625*495ae853SAndroid Build Coastguard Worker mv_x_tmp -= (i * 4);
626*495ae853SAndroid Build Coastguard Worker mv_y_tmp -= (j * 4);
627*495ae853SAndroid Build Coastguard Worker
628*495ae853SAndroid Build Coastguard Worker i4_mb_distortion = ai4_sad[4 + i + 2 * j];
629*495ae853SAndroid Build Coastguard Worker
630*495ae853SAndroid Build Coastguard Worker /* compute cost */
631*495ae853SAndroid Build Coastguard Worker i4_mb_cost = i4_mb_distortion + (WORD32)(u4_lambda_motion * ( pu1_mv_bits[ mv_x_tmp - ps_mb_part->s_mv_pred.i2_mvx]
632*495ae853SAndroid Build Coastguard Worker + pu1_mv_bits[mv_y_tmp - ps_mb_part->s_mv_pred.i2_mvy] ));
633*495ae853SAndroid Build Coastguard Worker
634*495ae853SAndroid Build Coastguard Worker if (i4_mb_cost < i4_mb_cost_least)
635*495ae853SAndroid Build Coastguard Worker {
636*495ae853SAndroid Build Coastguard Worker i4_mb_cost_least = i4_mb_cost;
637*495ae853SAndroid Build Coastguard Worker
638*495ae853SAndroid Build Coastguard Worker i4_distortion_least = i4_mb_distortion;
639*495ae853SAndroid Build Coastguard Worker
640*495ae853SAndroid Build Coastguard Worker i2_mv_u_x = mv_x_tmp;
641*495ae853SAndroid Build Coastguard Worker
642*495ae853SAndroid Build Coastguard Worker i2_mv_u_y = mv_y_tmp;
643*495ae853SAndroid Build Coastguard Worker
644*495ae853SAndroid Build Coastguard Worker #ifndef HP_PL /*choosing between four half_xy */
645*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->apu1_subpel_buffs[2] = pu1_ref_mb_half_xy_temp - j*(i4_ref_strd) - i;
646*495ae853SAndroid Build Coastguard Worker pu1_best_hpel_buf = pu1_ref_mb_half_xy_temp - j*(i4_ref_strd) - i;
647*495ae853SAndroid Build Coastguard Worker
648*495ae853SAndroid Build Coastguard Worker i4_srch_pos_idx = 2;
649*495ae853SAndroid Build Coastguard Worker #endif
650*495ae853SAndroid Build Coastguard Worker }
651*495ae853SAndroid Build Coastguard Worker
652*495ae853SAndroid Build Coastguard Worker }
653*495ae853SAndroid Build Coastguard Worker }
654*495ae853SAndroid Build Coastguard Worker
655*495ae853SAndroid Build Coastguard Worker if (i4_mb_cost_least < ps_mb_part->i4_mb_cost)
656*495ae853SAndroid Build Coastguard Worker {
657*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_mb_cost = i4_mb_cost_least;
658*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_mb_distortion = i4_distortion_least;
659*495ae853SAndroid Build Coastguard Worker ps_mb_part->s_mv_curr.i2_mvx = i2_mv_u_x;
660*495ae853SAndroid Build Coastguard Worker ps_mb_part->s_mv_curr.i2_mvy = i2_mv_u_y;
661*495ae853SAndroid Build Coastguard Worker ps_mb_part->pu1_best_hpel_buf = pu1_best_hpel_buf;
662*495ae853SAndroid Build Coastguard Worker ps_mb_part->i4_srch_pos_idx = i4_srch_pos_idx;
663*495ae853SAndroid Build Coastguard Worker }
664*495ae853SAndroid Build Coastguard Worker }
665*495ae853SAndroid Build Coastguard Worker
666*495ae853SAndroid Build Coastguard Worker /**
667*495ae853SAndroid Build Coastguard Worker *******************************************************************************
668*495ae853SAndroid Build Coastguard Worker *
669*495ae853SAndroid Build Coastguard Worker * @brief This function computes cost of skip macroblocks
670*495ae853SAndroid Build Coastguard Worker *
671*495ae853SAndroid Build Coastguard Worker * @par Description:
672*495ae853SAndroid Build Coastguard Worker *
673*495ae853SAndroid Build Coastguard Worker * @param[in] ps_me_ctxt
674*495ae853SAndroid Build Coastguard Worker * pointer to me ctxt
675*495ae853SAndroid Build Coastguard Worker *
676*495ae853SAndroid Build Coastguard Worker *
677*495ae853SAndroid Build Coastguard Worker * @returns none
678*495ae853SAndroid Build Coastguard Worker *
679*495ae853SAndroid Build Coastguard Worker * @remarks
680*495ae853SAndroid Build Coastguard Worker * NOTE: while computing the skip cost, do not enable early exit from compute
681*495ae853SAndroid Build Coastguard Worker * sad function because, a negative bias gets added later
682*495ae853SAndroid Build Coastguard Worker * Note that the last ME candidate in me ctxt is taken as skip motion vector
683*495ae853SAndroid Build Coastguard Worker *
684*495ae853SAndroid Build Coastguard Worker *******************************************************************************
685*495ae853SAndroid Build Coastguard Worker */
ime_compute_skip_cost(me_ctxt_t * ps_me_ctxt,ime_mv_t * ps_skip_mv,mb_part_ctxt * ps_smb_part_info,UWORD32 u4_use_stat_sad,WORD32 i4_reflist,WORD32 i4_is_slice_type_b)686*495ae853SAndroid Build Coastguard Worker void ime_compute_skip_cost
687*495ae853SAndroid Build Coastguard Worker (
688*495ae853SAndroid Build Coastguard Worker me_ctxt_t *ps_me_ctxt,
689*495ae853SAndroid Build Coastguard Worker ime_mv_t *ps_skip_mv,
690*495ae853SAndroid Build Coastguard Worker mb_part_ctxt *ps_smb_part_info,
691*495ae853SAndroid Build Coastguard Worker UWORD32 u4_use_stat_sad,
692*495ae853SAndroid Build Coastguard Worker WORD32 i4_reflist,
693*495ae853SAndroid Build Coastguard Worker WORD32 i4_is_slice_type_b
694*495ae853SAndroid Build Coastguard Worker )
695*495ae853SAndroid Build Coastguard Worker {
696*495ae853SAndroid Build Coastguard Worker
697*495ae853SAndroid Build Coastguard Worker /* SAD(distortion metric) of an mb */
698*495ae853SAndroid Build Coastguard Worker WORD32 i4_mb_distortion;
699*495ae853SAndroid Build Coastguard Worker
700*495ae853SAndroid Build Coastguard Worker /* cost = distortion + u4_lambda_motion * rate */
701*495ae853SAndroid Build Coastguard Worker WORD32 i4_mb_cost;
702*495ae853SAndroid Build Coastguard Worker
703*495ae853SAndroid Build Coastguard Worker /* temp var */
704*495ae853SAndroid Build Coastguard Worker UWORD8 *pu1_ref = NULL;
705*495ae853SAndroid Build Coastguard Worker
706*495ae853SAndroid Build Coastguard Worker ime_mv_t s_skip_mv;
707*495ae853SAndroid Build Coastguard Worker
708*495ae853SAndroid Build Coastguard Worker s_skip_mv.i2_mvx = (ps_skip_mv->i2_mvx +2)>>2;
709*495ae853SAndroid Build Coastguard Worker s_skip_mv.i2_mvy = (ps_skip_mv->i2_mvy +2)>>2;
710*495ae853SAndroid Build Coastguard Worker
711*495ae853SAndroid Build Coastguard Worker /* Check if the skip mv is out of bounds or subpel */
712*495ae853SAndroid Build Coastguard Worker {
713*495ae853SAndroid Build Coastguard Worker /* skip mv */
714*495ae853SAndroid Build Coastguard Worker ime_mv_t s_clip_skip_mv;
715*495ae853SAndroid Build Coastguard Worker
716*495ae853SAndroid Build Coastguard Worker s_clip_skip_mv.i2_mvx = CLIP3(ps_me_ctxt->i4_srch_range_w, ps_me_ctxt->i4_srch_range_e, s_skip_mv.i2_mvx);
717*495ae853SAndroid Build Coastguard Worker s_clip_skip_mv.i2_mvy = CLIP3(ps_me_ctxt->i4_srch_range_n, ps_me_ctxt->i4_srch_range_s, s_skip_mv.i2_mvy);
718*495ae853SAndroid Build Coastguard Worker
719*495ae853SAndroid Build Coastguard Worker if ((s_clip_skip_mv.i2_mvx != s_skip_mv.i2_mvx) ||
720*495ae853SAndroid Build Coastguard Worker (s_clip_skip_mv.i2_mvy != s_skip_mv.i2_mvy) ||
721*495ae853SAndroid Build Coastguard Worker (ps_skip_mv->i2_mvx & 0x3) ||
722*495ae853SAndroid Build Coastguard Worker (ps_skip_mv->i2_mvy & 0x3))
723*495ae853SAndroid Build Coastguard Worker {
724*495ae853SAndroid Build Coastguard Worker return ;
725*495ae853SAndroid Build Coastguard Worker }
726*495ae853SAndroid Build Coastguard Worker }
727*495ae853SAndroid Build Coastguard Worker
728*495ae853SAndroid Build Coastguard Worker
729*495ae853SAndroid Build Coastguard Worker /* adjust ref pointer */
730*495ae853SAndroid Build Coastguard Worker pu1_ref = ps_me_ctxt->apu1_ref_buf_luma[i4_reflist] + s_skip_mv.i2_mvx
731*495ae853SAndroid Build Coastguard Worker + (s_skip_mv.i2_mvy * ps_me_ctxt->i4_rec_strd);
732*495ae853SAndroid Build Coastguard Worker
733*495ae853SAndroid Build Coastguard Worker if(u4_use_stat_sad == 1)
734*495ae853SAndroid Build Coastguard Worker {
735*495ae853SAndroid Build Coastguard Worker UWORD32 u4_is_nonzero;
736*495ae853SAndroid Build Coastguard Worker
737*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->pf_ime_compute_sad_stat_luma_16x16(
738*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->pu1_src_buf_luma, pu1_ref, ps_me_ctxt->i4_src_strd,
739*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_rec_strd, ps_me_ctxt->pu2_sad_thrsh,
740*495ae853SAndroid Build Coastguard Worker &i4_mb_distortion, &u4_is_nonzero);
741*495ae853SAndroid Build Coastguard Worker
742*495ae853SAndroid Build Coastguard Worker if (u4_is_nonzero == 0 || i4_mb_distortion <= ps_me_ctxt->i4_min_sad)
743*495ae853SAndroid Build Coastguard Worker {
744*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->u4_min_sad_reached = 1; /* found min sad */
745*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_min_sad = (u4_is_nonzero == 0) ? 0 : i4_mb_distortion;
746*495ae853SAndroid Build Coastguard Worker }
747*495ae853SAndroid Build Coastguard Worker }
748*495ae853SAndroid Build Coastguard Worker else
749*495ae853SAndroid Build Coastguard Worker {
750*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->pf_ime_compute_sad_16x16[ps_me_ctxt->u4_enable_fast_sad](
751*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->pu1_src_buf_luma, pu1_ref, ps_me_ctxt->i4_src_strd,
752*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_rec_strd, INT_MAX, &i4_mb_distortion);
753*495ae853SAndroid Build Coastguard Worker
754*495ae853SAndroid Build Coastguard Worker if(i4_mb_distortion <= ps_me_ctxt->i4_min_sad)
755*495ae853SAndroid Build Coastguard Worker {
756*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->i4_min_sad = i4_mb_distortion;
757*495ae853SAndroid Build Coastguard Worker ps_me_ctxt->u4_min_sad_reached = 1; /* found min sad */
758*495ae853SAndroid Build Coastguard Worker }
759*495ae853SAndroid Build Coastguard Worker }
760*495ae853SAndroid Build Coastguard Worker
761*495ae853SAndroid Build Coastguard Worker
762*495ae853SAndroid Build Coastguard Worker /* for skip mode cost & distortion are identical
763*495ae853SAndroid Build Coastguard Worker * But we shall add a bias to favor skip mode.
764*495ae853SAndroid Build Coastguard Worker * Doc. JVT B118 Suggests SKIP_BIAS as 16.
765*495ae853SAndroid Build Coastguard Worker * TODO : Empirical analysis of SKIP_BIAS is necessary */
766*495ae853SAndroid Build Coastguard Worker
767*495ae853SAndroid Build Coastguard Worker i4_mb_cost = i4_mb_distortion - (ps_me_ctxt->u4_lambda_motion * (ps_me_ctxt->i4_skip_bias[0] + ps_me_ctxt->i4_skip_bias[1] * i4_is_slice_type_b));
768*495ae853SAndroid Build Coastguard Worker
769*495ae853SAndroid Build Coastguard Worker if (i4_mb_cost <= ps_smb_part_info->i4_mb_cost)
770*495ae853SAndroid Build Coastguard Worker {
771*495ae853SAndroid Build Coastguard Worker ps_smb_part_info->i4_mb_cost = i4_mb_cost;
772*495ae853SAndroid Build Coastguard Worker ps_smb_part_info->i4_mb_distortion = i4_mb_distortion;
773*495ae853SAndroid Build Coastguard Worker ps_smb_part_info->s_mv_curr.i2_mvx = s_skip_mv.i2_mvx;
774*495ae853SAndroid Build Coastguard Worker ps_smb_part_info->s_mv_curr.i2_mvy = s_skip_mv.i2_mvy;
775*495ae853SAndroid Build Coastguard Worker }
776*495ae853SAndroid Build Coastguard Worker }
777*495ae853SAndroid Build Coastguard Worker
778