1 /******************************************************************************
2 *
3 * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 /**
19 *******************************************************************************
20 * @file
21 * ihevcd_mv_pred.c
22 *
23 * @brief
24 * Contains functions for motion vector prediction
25 *
26 * @author
27 * Ittiam
28 *
29 * @par List of Functions:
30 * - ihevcd_scale_mv()
31 * - ihevcd_mv_pred()
32 *
33 * @remarks
34 * None
35 *
36 *******************************************************************************
37 */
38 /*****************************************************************************/
39 /* File Includes */
40 /*****************************************************************************/
41
42 #include <stdio.h>
43 #include <stddef.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include "ihevc_typedefs.h"
48 #include "iv.h"
49 #include "ivd.h"
50 #include "ihevcd_cxa.h"
51 #include "ithread.h"
52
53 #include "ihevc_defs.h"
54 #include "ihevc_debug.h"
55 #include "ihevc_structs.h"
56 #include "ihevc_macros.h"
57 #include "ihevc_platform_macros.h"
58 #include "ihevc_cabac_tables.h"
59 #include "ihevc_disp_mgr.h"
60 #include "ihevc_buf_mgr.h"
61 #include "ihevc_dpb_mgr.h"
62
63 #include "ihevcd_defs.h"
64 #include "ihevcd_function_selector.h"
65 #include "ihevcd_structs.h"
66 #include "ihevcd_error.h"
67 #include "ihevcd_nal.h"
68 #include "ihevcd_bitstream.h"
69 #include "ihevcd_fmt_conv.h"
70 #include "ihevcd_job_queue.h"
71 #include "ihevcd_debug.h"
72 #include "ihevcd_mv_merge.h"
73
74 /**
75 *******************************************************************************
76 *
77 * @brief Function scaling motion vector
78 *
79 *
80 * @par Description:
81 * Scales mv based on difference between current POC and current
82 * reference POC and neighbour reference poc
83 *
84 * @param[inout] mv
85 * motion vector to be scaled
86 *
87 * @param[in] cur_ref_poc
88 * Current PU refernce pic poc
89 *
90 * @param[in] nbr_ref_poc
91 * Neighbor PU reference pic poc
92 *
93 * @param[in] cur_poc
94 * Picture order count of current pic
95 *
96 * @returns
97 * None
98 *
99 * @remarks
100 *
101 *******************************************************************************
102 */
ihevcd_scale_mv(mv_t * ps_mv,WORD32 cur_ref_poc,WORD32 nbr_ref_poc,WORD32 cur_poc)103 void ihevcd_scale_mv(mv_t *ps_mv,
104 WORD32 cur_ref_poc,
105 WORD32 nbr_ref_poc,
106 WORD32 cur_poc)
107 {
108 WORD32 td, tb, tx;
109 WORD32 dist_scale_factor;
110 WORD32 mvx, mvy;
111
112 td = CLIP_S8(cur_poc - nbr_ref_poc);
113 tb = CLIP_S8(cur_poc - cur_ref_poc);
114
115 if(0 != td)
116 {
117 tx = (16384 + (abs(td) >> 1)) / td;
118
119 dist_scale_factor = (tb * tx + 32) >> 6;
120 dist_scale_factor = CLIP3(dist_scale_factor, -4096, 4095);
121
122 mvx = ps_mv->i2_mvx;
123 mvy = ps_mv->i2_mvy;
124
125 mvx = SIGN(dist_scale_factor * mvx)
126 * ((abs(dist_scale_factor * mvx) + 127) >> 8);
127 mvy = SIGN(dist_scale_factor * mvy)
128 * ((abs(dist_scale_factor * mvy) + 127) >> 8);
129
130 ps_mv->i2_mvx = CLIP_S16(mvx);
131 ps_mv->i2_mvy = CLIP_S16(mvy);
132 }
133 }
134
135 /**
136 *******************************************************************************
137 *
138 * @brief Function scaling temporal motion vector
139 *
140 *
141 * @par Description:
142 * Scales mv based on difference between current POC and current
143 * reference POC and neighbour reference poc
144 *
145 * @param[inout] mv
146 * motion vector to be scaled
147 *
148 * @param[in] cur_ref_poc
149 * Current PU refernce pic poc
150 *
151 * @param[in] nbr_ref_poc
152 * Neighbor PU reference pic poc
153 *
154 * @param[in] cur_poc
155 * Picture order count of current pic
156 *
157 * @returns
158 * None
159 *
160 * @remarks
161 *
162 *******************************************************************************
163 */
ihevcd_scale_collocated_mv(mv_t * ps_mv,WORD32 cur_ref_poc,WORD32 col_ref_poc,WORD32 col_poc,WORD32 cur_poc)164 void ihevcd_scale_collocated_mv(mv_t *ps_mv,
165 WORD32 cur_ref_poc,
166 WORD32 col_ref_poc,
167 WORD32 col_poc,
168 WORD32 cur_poc)
169 {
170 WORD32 td, tb, tx;
171 WORD32 dist_scale_factor;
172 WORD32 mvx, mvy;
173
174 td = CLIP_S8(col_poc - col_ref_poc);
175 tb = CLIP_S8(cur_poc - cur_ref_poc);
176
177 tx = (16384 + (abs(td) >> 1)) / td;
178
179 dist_scale_factor = (tb * tx + 32) >> 6;
180 dist_scale_factor = CLIP3(dist_scale_factor, -4096, 4095);
181
182 mvx = ps_mv->i2_mvx;
183 mvy = ps_mv->i2_mvy;
184
185 mvx = SIGN(dist_scale_factor * mvx)
186 * ((abs(dist_scale_factor * mvx) + 127) >> 8);
187 mvy = SIGN(dist_scale_factor * mvy)
188 * ((abs(dist_scale_factor * mvy) + 127) >> 8);
189
190 ps_mv->i2_mvx = CLIP_S16(mvx);
191 ps_mv->i2_mvy = CLIP_S16(mvy);
192 }
193
194 #define CHECK_NBR_MV_ST(pi4_avail_flag, cur_ref_poc, u1_nbr_pred_flag, nbr_ref_poc, \
195 ps_mv, ps_nbr_mv ) \
196 { \
197 if((u1_nbr_pred_flag) && (cur_ref_poc == nbr_ref_poc)) \
198 { \
199 *pi4_avail_flag = 1; \
200 *ps_mv = *ps_nbr_mv; \
201 break ; \
202 } \
203 }
204 #define CHECK_NBR_MV_LT(pi4_avail_flag, u1_cur_ref_lt, cur_poc, cur_ref_poc, \
205 u1_nbr_pred_flag, u1_nbr_ref_lt, nbr_ref_poc, \
206 ps_mv, ps_nbr_mv ) \
207 { \
208 WORD32 cur_lt, nbr_lt; \
209 cur_lt = (LONG_TERM_REF == (u1_cur_ref_lt)); \
210 nbr_lt = (LONG_TERM_REF == (u1_nbr_ref_lt)); \
211 if((u1_nbr_pred_flag) && (cur_lt == nbr_lt)) \
212 { \
213 *pi4_avail_flag = 1; \
214 *ps_mv = *ps_nbr_mv; \
215 if(SHORT_TERM_REF == u1_nbr_ref_lt) \
216 { \
217 ihevcd_scale_mv(ps_mv, cur_ref_poc, nbr_ref_poc, \
218 cur_poc); \
219 } \
220 break ; \
221 } \
222 }
223
224
GET_MV_NBR_ST(ref_list_t ** ps_ref_pic_list,WORD32 * pi4_avail_flag,pic_buf_t * ps_cur_pic_buf_lx,pu_t ** aps_nbr_pu,mv_t * ps_mv,WORD32 num_nbrs,WORD32 lx)225 void GET_MV_NBR_ST(ref_list_t **ps_ref_pic_list, WORD32 *pi4_avail_flag, pic_buf_t *ps_cur_pic_buf_lx, pu_t **aps_nbr_pu, mv_t *ps_mv, WORD32 num_nbrs, WORD32 lx)
226 {
227 WORD32 i, nbr_pred_lx;
228 pic_buf_t *ps_nbr_pic_buf_lx;
229 /* Short Term */
230 /* L0 */
231 if(0 == lx)
232 {
233 for(i = 0; i < num_nbrs; i++)
234 {
235 nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
236 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
237 CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
238 ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
239 nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
240
241 nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
242 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
243 CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
244 ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
245 }
246 }
247 /* L1 */
248 else
249 {
250 for(i = 0; i < num_nbrs; i++)
251 {
252 nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
253 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
254 CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
255 ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
256
257 nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
258 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
259 CHECK_NBR_MV_ST(pi4_avail_flag, ps_cur_pic_buf_lx->i4_abs_poc, nbr_pred_lx,
260 ps_nbr_pic_buf_lx->i4_abs_poc, ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
261 }
262 }
263 }
264
GET_MV_NBR_LT(ref_list_t ** ps_ref_pic_list,slice_header_t * ps_slice_hdr,WORD32 * pi4_avail_flag,pic_buf_t * ps_cur_pic_buf_lx,pu_t ** aps_nbr_pu,mv_t * ps_mv,WORD32 num_nbrs,WORD32 lx)265 void GET_MV_NBR_LT(ref_list_t **ps_ref_pic_list, slice_header_t *ps_slice_hdr, WORD32 *pi4_avail_flag, pic_buf_t *ps_cur_pic_buf_lx, pu_t **aps_nbr_pu, mv_t *ps_mv, WORD32 num_nbrs, WORD32 lx)
266 {
267 WORD32 i, nbr_pred_lx;
268 pic_buf_t *ps_nbr_pic_buf_lx;
269 /* Long Term*/
270 /* L0 */
271 if(0 == lx)
272 {
273 for(i = 0; i < num_nbrs; i++)
274 {
275 nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
276 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
277 CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
278 nbr_pred_lx,
279 ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
280 ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
281
282 nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
283 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
284 CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
285 nbr_pred_lx,
286 ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
287 ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
288 }
289 }
290 /* L1 */
291 else
292 {
293 for(i = 0; i < num_nbrs; i++)
294 {
295 nbr_pred_lx = (PRED_L0 != aps_nbr_pu[i]->b2_pred_mode);
296 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[1][aps_nbr_pu[i]->mv.i1_l1_ref_idx].pv_pic_buf));
297 CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
298 nbr_pred_lx,
299 ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
300 ps_mv, &aps_nbr_pu[i]->mv.s_l1_mv);
301
302 nbr_pred_lx = (PRED_L1 != aps_nbr_pu[i]->b2_pred_mode);
303 ps_nbr_pic_buf_lx = (pic_buf_t *)((ps_ref_pic_list[0][aps_nbr_pu[i]->mv.i1_l0_ref_idx].pv_pic_buf));
304 CHECK_NBR_MV_LT(pi4_avail_flag, ps_cur_pic_buf_lx->u1_used_as_ref, ps_slice_hdr->i4_abs_pic_order_cnt, ps_cur_pic_buf_lx->i4_abs_poc,
305 nbr_pred_lx,
306 ps_nbr_pic_buf_lx->u1_used_as_ref, ps_nbr_pic_buf_lx->i4_abs_poc,
307 ps_mv, &aps_nbr_pu[i]->mv.s_l0_mv);
308 }
309 }
310 }
311 /**
312 *******************************************************************************
313 *
314 * @brief
315 * This function performs Motion Vector prediction and return a list of mv
316 *
317 * @par Description:
318 * MV predictor list is computed using neighbor mvs and colocated mv
319 *
320 * @param[in] ps_ctxt
321 * pointer to mv predictor context
322 *
323 * @param[in] ps_top_nbr_4x4
324 * pointer to top 4x4 nbr structure
325 *
326 * @param[in] ps_left_nbr_4x4
327 * pointer to left 4x4 nbr structure
328 *
329 * @param[in] ps_top_left_nbr_4x4
330 * pointer to top left 4x4 nbr structure
331 *
332 * @param[in] left_nbr_4x4_strd
333 * left nbr buffer stride in terms of 4x4 units
334 *
335 * @param[in] ps_avail_flags
336 * Neighbor availability flags container
337 *
338 * @param[in] ps_col_mv
339 * Colocated MV pointer
340 *
341 * @param[in] ps_pu
342 * Current Partition PU strucrture pointer
343 *
344 * @param[inout] ps_pred_mv
345 * pointer to store predicted MV list
346 *
347 * @returns
348 * None
349 * @remarks
350 *
351 *
352 *******************************************************************************
353 */
ihevcd_mv_pred(mv_ctxt_t * ps_mv_ctxt,UWORD32 * pu4_top_pu_idx,UWORD32 * pu4_left_pu_idx,UWORD32 * pu4_top_left_pu_idx,WORD32 left_nbr_4x4_strd,pu_t * ps_pu,WORD32 lb_avail,WORD32 l_avail,WORD32 tr_avail,WORD32 t_avail,WORD32 tl_avail,pu_mv_t * ps_pred_mv)354 void ihevcd_mv_pred(mv_ctxt_t *ps_mv_ctxt,
355 UWORD32 *pu4_top_pu_idx,
356 UWORD32 *pu4_left_pu_idx,
357 UWORD32 *pu4_top_left_pu_idx,
358 WORD32 left_nbr_4x4_strd,
359 pu_t *ps_pu,
360 WORD32 lb_avail,
361 WORD32 l_avail,
362 WORD32 tr_avail,
363 WORD32 t_avail,
364 WORD32 tl_avail,
365 pu_mv_t *ps_pred_mv)
366 {
367 slice_header_t *ps_slice_hdr;
368 ref_list_t *ps_ref_pic_list[2];
369 pu_t *ps_pic_pu;
370 WORD32 max_l0_mvp_cand, max_l1_mvp_cand;
371 WORD32 l0_done_flag, l1_done_flag;
372 WORD32 num_l0_mvp_cand, num_l1_mvp_cand;
373 WORD32 is_scaled_flag_list /* Indicates whether A0 or A1 is available */;
374 WORD32 avail_a_flag[2];
375 mv_t as_mv_a[2];
376 WORD32 part_pos_x;
377 WORD32 part_pos_y;
378 WORD32 part_wd;
379 WORD32 part_ht;
380 pic_buf_t *ps_cur_pic_buf_l0, *ps_cur_pic_buf_l1;
381 WORD32 nbr_avail[3]; /*[A0/A1] */ /* [B0/B1/B2] */
382 pu_t *aps_nbr_pu[3]; /*[A0/A1] */ /* [B0/B1/B2] */
383 WORD32 num_nbrs = 0;
384
385 /*******************************************/
386 /* Neighbor location: Graphical indication */
387 /* */
388 /* B2 _____________B1 B0 */
389 /* | | */
390 /* | | */
391 /* | | */
392 /* | PU ht| */
393 /* | | */
394 /* | | */
395 /* A1|______wd_______| */
396 /* A0 */
397 /* */
398 /*******************************************/
399
400 ps_slice_hdr = ps_mv_ctxt->ps_slice_hdr;
401 ps_pic_pu = ps_mv_ctxt->ps_pic_pu;
402 max_l0_mvp_cand = ps_pu->b1_l0_mvp_idx + 1;
403 max_l1_mvp_cand = ps_pu->b1_l1_mvp_idx + 1;
404 num_l0_mvp_cand = 0;
405 num_l1_mvp_cand = 0;
406
407 /* Initializing reference list */
408 ps_ref_pic_list[0] = ps_slice_hdr->as_ref_pic_list0;
409 ps_ref_pic_list[1] = ps_slice_hdr->as_ref_pic_list1;
410 if(PSLICE == ps_slice_hdr->i1_slice_type)
411 ps_ref_pic_list[1] = ps_slice_hdr->as_ref_pic_list0;
412
413 ps_cur_pic_buf_l0 = (pic_buf_t *)((ps_ref_pic_list[0][ps_pu->mv.i1_l0_ref_idx].pv_pic_buf));
414 ps_cur_pic_buf_l1 = (pic_buf_t *)((ps_ref_pic_list[1][ps_pu->mv.i1_l1_ref_idx].pv_pic_buf));
415
416 is_scaled_flag_list = 0;
417
418 part_pos_x = ps_pu->b4_pos_x << 2;
419 part_pos_y = ps_pu->b4_pos_y << 2;
420 part_wd = (ps_pu->b4_wd + 1) << 2;
421 part_ht = (ps_pu->b4_ht + 1) << 2;
422
423 /************************************************************/
424 /* Calculating of motion vector A from neighbors A0 and A1 */
425 /************************************************************/
426 {
427 nbr_avail[0] = 0;
428 nbr_avail[1] = 0;
429
430 /* Pointers to A0 and A1 */
431 {
432 WORD32 y_a0, y_a1;
433 WORD32 pu_idx_a0, pu_idx_a1;
434
435 /* TODO: y_a0, y_a1 is coded assuming left nbr pointer starts at PU */
436 y_a0 = (part_ht >> 2);
437 y_a1 = ((part_ht - 1) >> 2);
438
439 pu_idx_a0 = *(pu4_left_pu_idx + (y_a0 * left_nbr_4x4_strd));
440 pu_idx_a1 = *(pu4_left_pu_idx + (y_a1 * left_nbr_4x4_strd));
441
442 if(lb_avail && (!ps_pic_pu[pu_idx_a0].b1_intra_flag))
443 {
444 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_a0];
445 num_nbrs++;
446 nbr_avail[0] = 1;
447 }
448 if(l_avail && (!ps_pic_pu[pu_idx_a1].b1_intra_flag))
449 {
450 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_a1];
451 num_nbrs++;
452 nbr_avail[1] = 1;
453 }
454 }
455 /* Setting is scaled flag based on availability of A0 and A1 */
456 if((nbr_avail[0] == 1) || (nbr_avail[1]))
457 {
458 is_scaled_flag_list = 1;
459 }
460
461 avail_a_flag[0] = 0;
462 avail_a_flag[1] = 0;
463
464 /* L0 */
465 GET_MV_NBR_ST(ps_ref_pic_list, &avail_a_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_a[0], num_nbrs, 0);
466 if(0 == avail_a_flag[0])
467 {
468 GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_a_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_a[0], num_nbrs, 0);
469 }
470
471 /* L1 */
472 if(PRED_L0 != ps_pu->b2_pred_mode)
473 {
474 GET_MV_NBR_ST(ps_ref_pic_list, &avail_a_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_a[1], num_nbrs, 1);
475 if(0 == avail_a_flag[1])
476 {
477 GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_a_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_a[1], num_nbrs, 1);
478 }
479 }
480
481 l0_done_flag = (PRED_L1 == ps_pu->b2_pred_mode);
482 l1_done_flag = (PRED_L0 == ps_pu->b2_pred_mode);
483
484 if(avail_a_flag[0])
485 {
486 num_l0_mvp_cand++;
487 if(max_l0_mvp_cand == num_l0_mvp_cand)
488 {
489 ps_pred_mv->s_l0_mv = as_mv_a[0];
490 l0_done_flag = 1;
491 }
492 }
493 if(avail_a_flag[1])
494 {
495 num_l1_mvp_cand++;
496 if(max_l1_mvp_cand == num_l1_mvp_cand)
497 {
498 ps_pred_mv->s_l1_mv = as_mv_a[1];
499 l1_done_flag = 1;
500 }
501 }
502 if(l0_done_flag && l1_done_flag)
503 return;
504 }
505
506 /************************************************************/
507 /* Calculating of motion vector B from neighbors B0 and B1 */
508 /************************************************************/
509 {
510 WORD32 avail_b_flag[2];
511 mv_t as_mv_b[2];
512
513 /* Pointers to B0, B1 and B2 */
514 {
515 WORD32 x_b0, x_b1, x_b2;
516 WORD32 pu_idx_b0, pu_idx_b1, pu_idx_b2;
517
518 /* Relative co-ordiante of Xp,Yp w.r.t CTB start will work */
519 /* as long as minCTB = 16 */
520 x_b0 = (part_pos_x + part_wd);
521 x_b1 = (part_pos_x + part_wd - 1);
522 x_b2 = (part_pos_x - 1);
523 /* Getting offset back to given pointer */
524 x_b0 = x_b0 - part_pos_x;
525 x_b1 = x_b1 - part_pos_x;
526 x_b2 = x_b2 - part_pos_x;
527
528 /* Below derivation are based on top pointer */
529 /* is pointing first pixel of PU */
530 pu_idx_b0 = *(pu4_top_pu_idx + (x_b0 >> 2));
531 pu_idx_b0 = pu_idx_b0 * tr_avail;
532 pu_idx_b1 = *(pu4_top_pu_idx + (x_b1 >> 2));
533 pu_idx_b1 = pu_idx_b1 * t_avail;
534 /* At CTB boundary, use top-left passed in */
535 if(part_pos_y)
536 {
537 pu_idx_b2 = *pu4_top_left_pu_idx;
538 }
539 else
540 {
541 /* Not at CTB boundary, use top and */
542 /* add correction to go to top-left */
543 pu_idx_b2 = *((pu4_top_pu_idx)+(x_b2 >> 2));
544 }
545 pu_idx_b2 = pu_idx_b2 * tl_avail;
546
547 num_nbrs = 0;
548 nbr_avail[0] = 0;
549 nbr_avail[1] = 0;
550 nbr_avail[2] = 0;
551
552 if(tr_avail && (!ps_pic_pu[pu_idx_b0].b1_intra_flag))
553 {
554 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_b0];
555 num_nbrs++;
556 nbr_avail[0] = 1;
557 }
558 if(t_avail && (!ps_pic_pu[pu_idx_b1].b1_intra_flag))
559 {
560 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_b1];
561 num_nbrs++;
562 nbr_avail[1] = 1;
563 }
564 if(tl_avail && (!ps_pic_pu[pu_idx_b2].b1_intra_flag))
565 {
566 aps_nbr_pu[num_nbrs] = &ps_pic_pu[pu_idx_b2];
567 num_nbrs++;
568 nbr_avail[2] = 1;
569 }
570 }
571
572 /* L0 */
573 avail_b_flag[0] = 0;
574 avail_b_flag[1] = 0;
575
576 GET_MV_NBR_ST(ps_ref_pic_list, &avail_b_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_b[0], num_nbrs, 0);
577
578 /* L1 */
579 if(PRED_L0 != ps_pu->b2_pred_mode)
580 {
581 /* B0 Short Term */
582 GET_MV_NBR_ST(ps_ref_pic_list, &avail_b_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_b[1], num_nbrs, 1);
583 }
584
585 if(avail_b_flag[0])
586 {
587 if(((0 == num_l0_mvp_cand)
588 || (as_mv_a[0].i2_mvx != as_mv_b[0].i2_mvx)
589 || (as_mv_a[0].i2_mvy != as_mv_b[0].i2_mvy)))
590 {
591 num_l0_mvp_cand++;
592 if(max_l0_mvp_cand == num_l0_mvp_cand)
593 {
594 ps_pred_mv->s_l0_mv = as_mv_b[0];
595 l0_done_flag = 1;
596 }
597 }
598 }
599 if(avail_b_flag[1])
600 {
601 if(((0 == num_l1_mvp_cand)
602 || (as_mv_a[1].i2_mvx != as_mv_b[1].i2_mvx)
603 || (as_mv_a[1].i2_mvy != as_mv_b[1].i2_mvy)))
604 {
605 num_l1_mvp_cand++;
606 if(max_l1_mvp_cand == num_l1_mvp_cand)
607 {
608 ps_pred_mv->s_l1_mv = as_mv_b[1];
609 l1_done_flag = 1;
610 }
611 }
612 }
613 if(l0_done_flag && l1_done_flag)
614 return;
615
616 if((is_scaled_flag_list == 0) && (avail_b_flag[0] == 1))
617 {
618 avail_a_flag[0] = 1;
619 as_mv_a[0] = as_mv_b[0];
620 }
621 if((is_scaled_flag_list == 0) && (avail_b_flag[1] == 1))
622 {
623 avail_a_flag[1] = 1;
624 as_mv_a[1] = as_mv_b[1];
625 }
626
627 if(0 == is_scaled_flag_list)
628 {
629 avail_b_flag[0] = avail_b_flag[1] = 0;
630
631 GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_b_flag[0], ps_cur_pic_buf_l0, aps_nbr_pu, &as_mv_b[0], num_nbrs, 0);
632
633 if(PRED_L0 != ps_pu->b2_pred_mode)
634 {
635 GET_MV_NBR_LT(ps_ref_pic_list, ps_slice_hdr, &avail_b_flag[1], ps_cur_pic_buf_l1, aps_nbr_pu, &as_mv_b[1], num_nbrs, 1);
636 }
637
638 if(avail_b_flag[0])
639 {
640 if(((0 == num_l0_mvp_cand)
641 || (as_mv_a[0].i2_mvx != as_mv_b[0].i2_mvx)
642 || (as_mv_a[0].i2_mvy != as_mv_b[0].i2_mvy)))
643 {
644 num_l0_mvp_cand++;
645 if(max_l0_mvp_cand == num_l0_mvp_cand)
646 {
647 ps_pred_mv->s_l0_mv = as_mv_b[0];
648 l0_done_flag = 1;
649 }
650 }
651 }
652 if(avail_b_flag[1])
653 {
654 if(((0 == num_l1_mvp_cand)
655 || (as_mv_a[1].i2_mvx != as_mv_b[1].i2_mvx)
656 || (as_mv_a[1].i2_mvy != as_mv_b[1].i2_mvy)))
657 {
658 num_l1_mvp_cand++;
659 if(max_l1_mvp_cand == num_l1_mvp_cand)
660 {
661 ps_pred_mv->s_l1_mv = as_mv_b[1];
662 l1_done_flag = 1;
663 }
664 }
665 }
666 if(l0_done_flag && l1_done_flag)
667 return;
668 }
669 /***********************************************************/
670 /* Collocated MV prediction */
671 /***********************************************************/
672 if((2 != num_l0_mvp_cand) || (2 != num_l1_mvp_cand))
673 {
674 mv_t as_mv_col[2], s_mv_col_l0, s_mv_col_l1;
675 WORD32 avail_col_flag[2] = { 0 };
676 WORD32 x_col, y_col, avail_col_l0, avail_col_l1;
677 // ihevcd_collocated_mvp((mv_ctxt_t *)ps_mv_ctxt,ps_pu,part_pos_x,part_pos_y,part_wd,part_ht,as_mv_col,avail_col_flag,1);
678 x_col = part_pos_x + part_wd;
679 y_col = part_pos_y + part_ht;
680 ihevcd_collocated_mvp(ps_mv_ctxt, ps_pu, as_mv_col, avail_col_flag, 1, x_col, y_col);
681
682 avail_col_l0 = avail_col_flag[0];
683 avail_col_l1 = avail_col_flag[1];
684 if(avail_col_l0 || avail_col_l1)
685 {
686 s_mv_col_l0 = as_mv_col[0];
687 s_mv_col_l1 = as_mv_col[1];
688 }
689
690 if(avail_col_l0 == 0 || avail_col_l1 == 0)
691 {
692 /* Checking Collocated MV availability at Center of PU */
693 x_col = part_pos_x + (part_wd >> 1);
694 y_col = part_pos_y + (part_ht >> 1);
695 ihevcd_collocated_mvp(ps_mv_ctxt, ps_pu, as_mv_col, avail_col_flag, 1, x_col, y_col);
696
697 if(avail_col_l0 == 0)
698 {
699 s_mv_col_l0 = as_mv_col[0];
700 }
701 if(avail_col_l1 == 0)
702 {
703 s_mv_col_l1 = as_mv_col[1];
704 }
705
706 avail_col_l0 |= avail_col_flag[0];
707 avail_col_l1 |= avail_col_flag[1];
708 }
709
710 /* Checking if mvp index matches collocated mv */
711 if(avail_col_l0)
712 {
713 if(2 != num_l0_mvp_cand)
714 {
715 num_l0_mvp_cand++;
716 if(max_l0_mvp_cand == num_l0_mvp_cand)
717 {
718 ps_pred_mv->s_l0_mv = s_mv_col_l0;
719 l0_done_flag = 1;
720 }
721 }
722 }
723 if(avail_col_l1)
724 {
725 if(2 != num_l1_mvp_cand)
726 {
727 num_l1_mvp_cand++;
728 if(max_l1_mvp_cand == num_l1_mvp_cand)
729 {
730 ps_pred_mv->s_l1_mv = s_mv_col_l1;
731 l1_done_flag = 1;
732 }
733 }
734 }
735 if(l0_done_flag && l1_done_flag)
736 return;
737 }
738
739 if(0 == l0_done_flag)
740 {
741 ps_pred_mv->s_l0_mv.i2_mvx = 0;
742 ps_pred_mv->s_l0_mv.i2_mvy = 0;
743 }
744 if(0 == l1_done_flag)
745 {
746 ps_pred_mv->s_l1_mv.i2_mvx = 0;
747 ps_pred_mv->s_l1_mv.i2_mvy = 0;
748 }
749 }
750 }
751