1 /******************************************************************************
2 *
3 * Copyright (C) 2018 The Android Open Source Project
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 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 /*!
21 ******************************************************************************
22 * \file ihevce_common_utils.c
23 *
24 * \brief
25 * Contains definitions of common utility functions used across encoder
26 *
27 * \date
28 * 18/09/2012
29 *
30 * \author
31 * ittiam
32 *
33 * List of Functions
34 * ihevce_copy_2d()
35 * ihevce_hbd_copy_2d()
36 * ihevce_2d_square_copy_luma()
37 * ihevce_wt_avg_2d()
38 * ihevce_itrans_recon_dc_compute()
39 * ihevce_itrans_recon_dc()
40 * ihevce_hbd_itrans_recon_dc()
41 * ihevce_truncate_16bit_data_to_8bit()
42 * ihevce_convert_16bit_recon_to_8bit()
43 * ihevce_convert_16bit_input_to_8bit()
44 * ihevce_find_num_clusters_of_identical_points_1D()
45 * ihevce_hbd_compute_ssd()
46 * ihevce_compare_pu_mv_t()
47 * ihevce_set_pred_buf_as_free()
48 * ihevce_get_free_pred_buf_indices()
49 * ihevce_scale_mv()
50 * ihevce_osal_alloc()
51 * ihevce_osal_free()
52 * ihevce_osal_init()
53 * ihevce_osal_delete()
54 * ihevce_sum_abs_seq()
55 * ihevce_ssd_calculator()
56 * ihevce_chroma_interleave_ssd_calculator()
57 * ihevce_ssd_and_sad_calculator()
58 * ihevce_chroma_interleave_2d_copy()
59 * ihevce_hbd_chroma_interleave_2d_copy()
60 * ihevce_hbd_chroma_interleave_ssd_calculator()
61 * ihevce_get_chroma_eo_sao_params()
62 * ihevce_get_chroma_eo_sao_params_hbd()
63 * ihevce_compute_area_of_valid_cus_in_ctb()
64 * ihevce_create_cuNode_children()
65 * ihevce_cu_tree_init()
66 *
67 ******************************************************************************
68 */
69
70 /*****************************************************************************/
71 /* File Includes */
72 /*****************************************************************************/
73
74 /* System include files */
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <assert.h>
78 #include <string.h>
79
80 /* User include files */
81 #include "ihevc_typedefs.h"
82 #include "itt_video_api.h"
83 #include "ihevce_api.h"
84
85 #include "rc_cntrl_param.h"
86 #include "rc_frame_info_collector.h"
87 #include "rc_look_ahead_params.h"
88
89 #include "ihevc_defs.h"
90 #include "ihevc_debug.h"
91 #include "ihevc_structs.h"
92 #include "ihevc_platform_macros.h"
93 #include "ihevc_deblk.h"
94 #include "ihevc_itrans_recon.h"
95 #include "ihevc_chroma_itrans_recon.h"
96 #include "ihevc_chroma_intra_pred.h"
97 #include "ihevc_intra_pred.h"
98 #include "ihevc_inter_pred.h"
99 #include "ihevc_mem_fns.h"
100 #include "ihevc_padding.h"
101 #include "ihevc_weighted_pred.h"
102 #include "ihevc_sao.h"
103 #include "ihevc_resi_trans.h"
104 #include "ihevc_quant_iquant_ssd.h"
105 #include "ihevc_cabac_tables.h"
106
107 #include "ihevce_defs.h"
108 #include "ihevce_hle_interface.h"
109 #include "ihevce_lap_enc_structs.h"
110 #include "ihevce_multi_thrd_structs.h"
111 #include "ihevce_me_common_defs.h"
112 #include "ihevce_had_satd.h"
113 #include "ihevce_error_codes.h"
114 #include "ihevce_bitstream.h"
115 #include "ihevce_cabac.h"
116 #include "ihevce_rdoq_macros.h"
117 #include "ihevce_function_selector.h"
118 #include "ihevce_enc_structs.h"
119 #include "ihevce_entropy_structs.h"
120 #include "ihevce_cmn_utils_instr_set_router.h"
121 #include "ihevce_enc_loop_structs.h"
122 #include "ihevce_common_utils.h"
123 #include "ihevce_global_tables.h"
124
125 #include "cast_types.h"
126 #include "osal.h"
127 #include "osal_defaults.h"
128
129 /*****************************************************************************/
130 /* Function Definitions */
131 /*****************************************************************************/
132
133 /**
134 ******************************************************************************
135 *
136 * @brief Performs the 2D copy
137 *
138 * @par Description
139 * This routine Performs the 2D copy
140 *
141 * @param[inout] pu1_dst
142 * pointer to the destination buffer
143 *
144 * @param[in] dst_strd
145 * destination stride in terms of the size of input/output unit
146 *
147 * @param[inout] pu1_src
148 * pointer to the source buffer
149 *
150 * @param[in] src_strd
151 * source stride in terms of the size of input/output unit
152 *
153 * @param[in] blk_wd
154 * number of samples to copy in a row
155 *
156 * @param[in] blk_ht
157 * number of rows to copy
158 *
159 ******************************************************************************
160 */
ihevce_copy_2d(UWORD8 * pu1_dst,WORD32 dst_stride,UWORD8 * pu1_src,WORD32 src_stride,WORD32 blk_wd,WORD32 blk_ht)161 void ihevce_copy_2d(
162 UWORD8 *pu1_dst,
163 WORD32 dst_stride,
164 UWORD8 *pu1_src,
165 WORD32 src_stride,
166 WORD32 blk_wd,
167 WORD32 blk_ht)
168 {
169 WORD32 i;
170
171 for(i = 0; i < blk_ht; i++)
172 {
173 memcpy(pu1_dst, pu1_src, blk_wd);
174 pu1_dst += dst_stride;
175 pu1_src += src_stride;
176 }
177 }
178
179 /**
180 ******************************************************************************
181 *
182 * @brief Performs the 2D copy of luma data
183 *
184 * @par Description
185 * This routine performs the 2D square copy of luma data
186 *
187 * @param[inout] p_dst
188 * pointer to the destination buffer
189 *
190 * @param[in] dst_strd
191 * destination stride in terms of the size of input/output unit
192 *
193 * @param[inout] p_src
194 * pointer to the source buffer
195 *
196 * @param[in] src_strd
197 * source stride in terms of the size of input/output unit
198 *
199 * @param[in] num_cols_to_copy
200 * number of units in a line to copy from src to dst buffer
201 * Assumption : num_cols_to_copy <= min (dst_strd, src_strd)
202 *
203 * @param[in] unit_size
204 * size of the unit in bytes
205 *
206 * @return none
207 *
208 * Assumptions : num_cols_to_copy = num_lines_to_copy,
209 * num_lines_to_copy can have {4, 16, 32, 64}
210 *
211 ******************************************************************************
212 */
ihevce_2d_square_copy_luma(void * p_dst,WORD32 dst_strd,void * p_src,WORD32 src_strd,WORD32 num_cols_to_copy,WORD32 unit_size)213 void ihevce_2d_square_copy_luma(
214 void *p_dst,
215 WORD32 dst_strd,
216 void *p_src,
217 WORD32 src_strd,
218 WORD32 num_cols_to_copy,
219 WORD32 unit_size)
220 {
221 UWORD8 *pu1_dst = (UWORD8 *)p_dst;
222 UWORD8 *pu1_src = (UWORD8 *)p_src;
223 WORD32 i;
224
225 for(i = 0; i < num_cols_to_copy; i++)
226 {
227 memcpy(pu1_dst, pu1_src, (num_cols_to_copy * unit_size));
228 pu1_dst += (dst_strd * unit_size);
229 pu1_src += (src_strd * unit_size);
230 }
231 }
232
233 /**
234 ********************************************************************************
235 *
236 * @brief Weighted pred of 2 predictor buffers as per spec
237 *
238 * @param[in] pu1_pred0 : Pred0 buffer
239 *
240 * @param[in] pu1_pred1 : Pred1 buffer
241 *
242 * @param[in] pred0_strd : Stride of pred0 buffer
243 *
244 * @param[in] pred1_strd : Stride of pred1 buffer
245 *
246 * @param[in] wd : Width of pred block
247 *
248 * @param[in] ht : Height of pred block
249 *
250 * @param[out] pu1_dst : Destination buffer that will hold result
251 *
252 * @param[in] dst_strd : Stride of dest buffer
253 *
254 * @param[in] w0 : Weighting factor of Pred0
255 *
256 * @param[in] w1 : weighting factor of pred1
257 *
258 * @param[in] o0 : offset for pred0
259 *
260 * @param[in] o1 : offset for pred1
261 *
262 * @param[in] log_wdc : shift factor as per spec
263 *
264 * @return none
265 *
266 ********************************************************************************
267 */
ihevce_wt_avg_2d(UWORD8 * pu1_pred0,UWORD8 * pu1_pred1,WORD32 pred0_strd,WORD32 pred1_strd,WORD32 wd,WORD32 ht,UWORD8 * pu1_dst,WORD32 dst_strd,WORD32 w0,WORD32 w1,WORD32 o0,WORD32 o1,WORD32 log_wdc)268 void ihevce_wt_avg_2d(
269 UWORD8 *pu1_pred0,
270 UWORD8 *pu1_pred1,
271 WORD32 pred0_strd,
272 WORD32 pred1_strd,
273 WORD32 wd,
274 WORD32 ht,
275 UWORD8 *pu1_dst,
276 WORD32 dst_strd,
277 WORD32 w0,
278 WORD32 w1,
279 WORD32 o0,
280 WORD32 o1,
281 WORD32 log_wdc)
282 {
283 /* Total Rounding term to be added, including offset */
284 WORD32 rnd = (o0 + o1 + 1) >> 1; // << log_wdc;
285 /* Downshift */
286 WORD32 shift = log_wdc + 1;
287 /* loop counters */
288 WORD32 i, j;
289
290 /* Dst = ((w0*p0 + w1*p1) + ((o0 + o1 + 1) << logWDc)) >> (logWDc + 1) */
291 /* In above formula, the additive term is constant and is evaluated */
292 /* outside loop and stored as "rnd". */
293 for(i = 0; i < ht; i++)
294 {
295 for(j = 0; j < wd; j++)
296 {
297 WORD32 tmp;
298 tmp = IHEVCE_WT_PRED(pu1_pred0[j], pu1_pred1[j], w0, w1, rnd, shift);
299 pu1_dst[j] = (UWORD8)(CLIP3(tmp, 0, 255));
300 }
301 pu1_pred0 += pred0_strd;
302 pu1_pred1 += pred1_strd;
303 pu1_dst += dst_strd;
304 }
305 }
306 /**
307 ******************************************************************************
308 *
309 * @brief Performs the Recon for DC only coefficient case
310 *
311 * @par Description
312 * This routine performs the Recon for DC only coefficient case
313 *
314 * @param[inout] pu1_dst
315 * pointer to the destination buffer
316 *
317 * @param[in] pu1_pred
318 * pointer to the pred buffer
319 *
320 * @param[in] dst_strd
321 * destination stride
322 *
323 * @param[in] pred_strd
324 * pred buffer stride
325 *
326 * @param[in] trans_size
327 * transform size
328 *
329 * @param[in] col_mult
330 * chroma multiplier
331 *
332 * @param[in] dc_value
333 * residue value
334 *
335 * @return none
336 *
337 ******************************************************************************
338 */
ihevce_itrans_recon_dc_compute(UWORD8 * pu1_dst,UWORD8 * pu1_pred,WORD32 dst_strd,WORD32 pred_strd,WORD32 trans_size,WORD32 col_mult,WORD32 dc_value)339 static INLINE void ihevce_itrans_recon_dc_compute(
340 UWORD8 *pu1_dst,
341 UWORD8 *pu1_pred,
342 WORD32 dst_strd,
343 WORD32 pred_strd,
344 WORD32 trans_size,
345 WORD32 col_mult,
346 WORD32 dc_value)
347 {
348 WORD32 row, col;
349
350 for(row = 0; row < trans_size; row++)
351 {
352 for(col = 0; col < trans_size; col++)
353 {
354 pu1_dst[row * dst_strd + col * col_mult] =
355 CLIP_U8(pu1_pred[row * pred_strd + col * col_mult] + dc_value);
356 }
357 }
358 }
359
360 /**
361 ******************************************************************************
362 *
363 * @brief Performs the IQ+IT+Recon for DC only coefficient case
364 *
365 * @par Description
366 * This routine performs the IQ+IT+Recon for DC only coefficient case
367 *
368 * @param[in] pu1_pred
369 * pointer to the pred buffer
370 *
371 * @param[in] pred_strd
372 * pred buffer stride
373 *
374 * @param[inout] pu1_dst
375 * pointer to the destination buffer
376 *
377 * @param[in] dst_strd
378 * destination stride
379 *
380 * @param[in] trans_size
381 * transform size
382 *
383 * @param[in] i2_deq_value
384 * Dequant Coeffs
385 *
386 * @param[in] chroma plane
387 * -1 : luma, 0 : chroma U, 1 : chroma V
388 *
389 * @return none
390 *
391 ******************************************************************************
392 */
ihevce_itrans_recon_dc(UWORD8 * pu1_pred,WORD32 pred_strd,UWORD8 * pu1_dst,WORD32 dst_strd,WORD32 trans_size,WORD16 i2_deq_value,CHROMA_PLANE_ID_T e_chroma_plane)393 void ihevce_itrans_recon_dc(
394 UWORD8 *pu1_pred,
395 WORD32 pred_strd,
396 UWORD8 *pu1_dst,
397 WORD32 dst_strd,
398 WORD32 trans_size,
399 WORD16 i2_deq_value,
400 CHROMA_PLANE_ID_T e_chroma_plane)
401 {
402 WORD32 add, shift;
403 WORD32 dc_value;
404 UWORD8 *pu1_pred_tmp, *pu1_dst_tmp;
405 WORD32 col_mult;
406
407 assert(e_chroma_plane == NULL_PLANE || e_chroma_plane == U_PLANE || e_chroma_plane == V_PLANE);
408 if(e_chroma_plane == NULL_PLANE)
409 {
410 pu1_pred_tmp = pu1_pred;
411 pu1_dst_tmp = pu1_dst;
412 col_mult = 1;
413 }
414 else
415 {
416 col_mult = 2;
417 pu1_pred_tmp = pu1_pred + e_chroma_plane;
418 pu1_dst_tmp = pu1_dst + e_chroma_plane;
419 }
420
421 shift = IT_SHIFT_STAGE_1;
422 add = 1 << (shift - 1);
423 dc_value = CLIP_S16((i2_deq_value * 64 + add) >> shift);
424 shift = IT_SHIFT_STAGE_2;
425 add = 1 << (shift - 1);
426 dc_value = CLIP_S16((dc_value * 64 + add) >> shift);
427 ihevce_itrans_recon_dc_compute(
428 pu1_dst_tmp, pu1_pred_tmp, dst_strd, pred_strd, trans_size, col_mult, dc_value);
429 }
430
431 /*!
432 ******************************************************************************
433 * \if Function name : ihevce_find_num_clusters_of_identical_points_1D \endif
434 *
435 * \brief
436 *
437 *
438 *****************************************************************************
439 */
ihevce_find_num_clusters_of_identical_points_1D(UWORD8 * pu1_inp_array,UWORD8 * pu1_out_array,UWORD8 * pu1_freq_of_out_data_in_inp,WORD32 i4_num_inp_array_elements)440 WORD32 ihevce_find_num_clusters_of_identical_points_1D(
441 UWORD8 *pu1_inp_array,
442 UWORD8 *pu1_out_array,
443 UWORD8 *pu1_freq_of_out_data_in_inp,
444 WORD32 i4_num_inp_array_elements)
445 {
446 WORD32 i;
447 UWORD8 u1_value = pu1_inp_array[0];
448 WORD32 i4_num_clusters = i4_num_inp_array_elements;
449 WORD32 i4_output_array_idx = 1;
450
451 pu1_freq_of_out_data_in_inp[0] = 1;
452 pu1_out_array[0] = u1_value;
453
454 if(1 == i4_num_inp_array_elements)
455 {
456 return 1;
457 }
458
459 for(i = 1; i < i4_num_inp_array_elements; i++)
460 {
461 if(pu1_inp_array[i] == u1_value)
462 {
463 pu1_freq_of_out_data_in_inp[0]++;
464 i4_num_clusters--;
465 }
466 else
467 {
468 pu1_out_array[i4_output_array_idx] = pu1_inp_array[i];
469
470 i4_output_array_idx++;
471 }
472 }
473
474 if(i4_num_clusters > 1)
475 {
476 WORD32 i4_num_sub_clusters;
477
478 i4_num_sub_clusters = ihevce_find_num_clusters_of_identical_points_1D(
479 &pu1_out_array[1],
480 &pu1_out_array[1],
481 &pu1_freq_of_out_data_in_inp[1],
482 i4_num_clusters - 1);
483
484 i4_num_clusters = 1 + i4_num_sub_clusters;
485 }
486
487 return i4_num_clusters;
488 }
489
490 /**
491 *******************************************************************************
492 *
493 * @brief Compare Motion vectors function
494 *
495 * @par Description:
496 * Checks if MVs and Reference idx are excatly matching.
497 *
498 * @param[inout] ps_1
499 * motion vector 1 to be compared
500 *
501 * @param[in] ps_2
502 * motion vector 2 to be compared
503 *
504 * @returns
505 * 0 : if not matching 1 : if matching
506 *
507 * @remarks
508 *
509 *******************************************************************************
510 */
ihevce_compare_pu_mv_t(pu_mv_t * ps_pu_mv_1,pu_mv_t * ps_pu_mv_2,WORD32 i4_pred_mode_1,WORD32 i4_pred_mode_2)511 WORD32 ihevce_compare_pu_mv_t(
512 pu_mv_t *ps_pu_mv_1, pu_mv_t *ps_pu_mv_2, WORD32 i4_pred_mode_1, WORD32 i4_pred_mode_2)
513 {
514 WORD32 i4_l0_match, i4_l1_match;
515 WORD32 i4_pred_l0, i4_pred_l1;
516
517 i4_pred_l0 = (i4_pred_mode_1 != PRED_L1);
518 i4_pred_l1 = (i4_pred_mode_1 != PRED_L0);
519
520 if(i4_pred_mode_1 != i4_pred_mode_2)
521 return 0;
522
523 i4_l0_match = 0;
524 i4_l1_match = 0;
525
526 if(i4_pred_l0)
527 {
528 if(ps_pu_mv_1->i1_l0_ref_idx == ps_pu_mv_2->i1_l0_ref_idx)
529 {
530 if(0 == memcmp(&ps_pu_mv_1->s_l0_mv, &ps_pu_mv_2->s_l0_mv, sizeof(mv_t)))
531 i4_l0_match = 1;
532 }
533 }
534 if(i4_pred_l1)
535 {
536 if(ps_pu_mv_1->i1_l1_ref_idx == ps_pu_mv_2->i1_l1_ref_idx)
537 {
538 if(0 == memcmp(&ps_pu_mv_1->s_l1_mv, &ps_pu_mv_2->s_l1_mv, sizeof(mv_t)))
539 i4_l1_match = 1;
540 }
541 }
542
543 if(i4_pred_l0 && i4_pred_l1)
544 return (i4_l0_match & i4_l1_match);
545 else if(i4_pred_l0)
546 return i4_l0_match;
547 else
548 return i4_l1_match;
549
550 } /* End of ihevce_compare_pu_mv_t */
551
552 /*!
553 ******************************************************************************
554 * \if Function name : ihevce_set_pred_buf_as_free \endif
555 *
556 * \brief
557 * Mark buffer as free
558 *
559 *****************************************************************************
560 */
ihevce_set_pred_buf_as_free(UWORD32 * pu4_idx_array,UWORD8 u1_buf_id)561 void ihevce_set_pred_buf_as_free(UWORD32 *pu4_idx_array, UWORD8 u1_buf_id)
562 {
563 (*pu4_idx_array) &= ~(1 << u1_buf_id);
564 }
565
566 /*!
567 ******************************************************************************
568 * \if Function name : ihevce_get_free_pred_buf_indices \endif
569 *
570 * \brief
571 * get free buffer indices
572 *
573 *****************************************************************************
574 */
ihevce_get_free_pred_buf_indices(UWORD8 * pu1_idx_array,UWORD32 * pu4_bitfield,UWORD8 u1_num_bufs_requested)575 UWORD8 ihevce_get_free_pred_buf_indices(
576 UWORD8 *pu1_idx_array, UWORD32 *pu4_bitfield, UWORD8 u1_num_bufs_requested)
577 {
578 UWORD8 i;
579
580 UWORD8 u1_num_free_bufs_found = 0;
581 UWORD32 u4_local_bitfield = *pu4_bitfield;
582
583 ASSERT(u1_num_bufs_requested <= (32 - ihevce_num_ones_generic(u4_local_bitfield)));
584
585 for(i = 0; u1_num_free_bufs_found < u1_num_bufs_requested; i++)
586 {
587 if(!(u4_local_bitfield & (1 << i)))
588 {
589 pu1_idx_array[u1_num_free_bufs_found++] = i;
590 u4_local_bitfield |= (1 << i);
591 }
592 }
593
594 (*pu4_bitfield) = u4_local_bitfield;
595
596 return u1_num_free_bufs_found;
597 }
598
599 /*!
600 ******************************************************************************
601 * \if Function name : ihevce_scale_mv \endif
602 *
603 * \brief
604 * Scale mv basing on displacement of POC
605 *
606 *****************************************************************************
607 */
ihevce_scale_mv(mv_t * ps_mv,WORD32 i4_poc_to,WORD32 i4_poc_from,WORD32 i4_curr_poc)608 void ihevce_scale_mv(mv_t *ps_mv, WORD32 i4_poc_to, WORD32 i4_poc_from, WORD32 i4_curr_poc)
609 {
610 WORD32 td, tb, tx;
611 WORD32 dist_scale_factor;
612 WORD32 mvx, mvy;
613
614 td = CLIP_S8(i4_curr_poc - i4_poc_from);
615 tb = CLIP_S8(i4_curr_poc - i4_poc_to);
616
617 tx = (16384 + (abs(td) >> 1)) / td;
618
619 dist_scale_factor = (tb * tx + 32) >> 6;
620 dist_scale_factor = CLIP3(dist_scale_factor, -4096, 4095);
621
622 mvx = ps_mv->i2_mvx;
623 mvy = ps_mv->i2_mvy;
624
625 mvx = SIGN(dist_scale_factor * mvx) * ((abs(dist_scale_factor * mvx) + 127) >> 8);
626 mvy = SIGN(dist_scale_factor * mvy) * ((abs(dist_scale_factor * mvy) + 127) >> 8);
627
628 ps_mv->i2_mvx = CLIP_S16(mvx);
629 ps_mv->i2_mvy = CLIP_S16(mvy);
630 }
631
632 /*!
633 ******************************************************************************
634 * \if Function name : ihevce_osal_alloc \endif
635 *
636 * \brief
637 * Memory allocate call back function passed to OSAL
638 *
639 * \param[in] pv_handle : handle to hle ctxt
640 * \param[in] u4_size : size of memory required
641 *
642 * \return
643 * Memory pointer
644 *
645 * \author
646 * Ittiam
647 *
648 *****************************************************************************
649 */
ihevce_osal_alloc(void * pv_handle,UWORD32 u4_size)650 void *ihevce_osal_alloc(void *pv_handle, UWORD32 u4_size)
651 {
652 ihevce_hle_ctxt_t *ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_handle;
653 iv_mem_rec_t s_mem_tab;
654
655 /* def init of memtab */
656 s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
657 s_mem_tab.i4_mem_alignment = 8;
658 s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
659
660 /* allocate memory for required size */
661 s_mem_tab.i4_mem_size = u4_size;
662
663 ps_hle_ctxt->ihevce_mem_alloc(
664 ps_hle_ctxt->pv_mem_mgr_hdl, &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api, &s_mem_tab);
665
666 return (s_mem_tab.pv_base);
667 }
668
669 /*!
670 ******************************************************************************
671 * \if Function name : ihevce_osal_free \endif
672 *
673 * \brief
674 * Memory free call back function passed to OSAL
675 *
676 * \param[in] pv_handle : handle to hle ctxt
677 * \param[in] pv_mem : memory to be freed
678 *
679 * \return
680 * none
681 *
682 * \author
683 * Ittiam
684 *
685 *****************************************************************************
686 */
ihevce_osal_free(void * pv_handle,void * pv_mem)687 void ihevce_osal_free(void *pv_handle, void *pv_mem)
688 {
689 ihevce_hle_ctxt_t *ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_handle;
690 iv_mem_rec_t s_mem_tab;
691
692 /* def init of memtab */
693 s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
694 s_mem_tab.i4_mem_alignment = 8;
695 s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
696
697 /* free memory */
698 s_mem_tab.pv_base = pv_mem;
699
700 ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_mem_tab);
701
702 return;
703 }
704
705 /*!
706 ******************************************************************************
707 * \if Function name : ihevce_osal_init \endif
708 *
709 * \brief
710 * Function to initialise OSAL handle
711 *
712 * \return
713 * None
714 *
715 * \author
716 * Ittiam
717 *
718 *****************************************************************************
719 */
ihevce_osal_init(void * pv_hle_ctxt)720 WORD32 ihevce_osal_init(void *pv_hle_ctxt)
721 {
722 /* local variables */
723 ihevce_hle_ctxt_t *ps_hle_ctxt;
724 osal_cb_funcs_t s_cb_funcs;
725 WORD32 status = 0;
726 void *pv_osal_handle;
727 iv_mem_rec_t s_mem_tab;
728
729 ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_hle_ctxt;
730
731 /* def init of memtab */
732 s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
733 s_mem_tab.i4_mem_alignment = 8;
734 s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
735
736 /* --------------------------------------------------------------------- */
737 /* OSAL Hanndle create */
738 /* --------------------------------------------------------------------- */
739
740 /* Allocate memory for the handle */
741 s_mem_tab.i4_mem_size = OSAL_HANDLE_SIZE;
742
743 ps_hle_ctxt->ihevce_mem_alloc(
744 ps_hle_ctxt->pv_mem_mgr_hdl, &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api, &s_mem_tab);
745 if(NULL == s_mem_tab.pv_base)
746 {
747 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
748 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
749 "IHEVCE ERROR: Error in OSAL initialization\n");
750 return (-1);
751 }
752
753 pv_osal_handle = s_mem_tab.pv_base;
754
755 /* Initialize OSAL call back functions */
756 s_cb_funcs.mmr_handle = (void *)ps_hle_ctxt;
757 s_cb_funcs.osal_alloc = &ihevce_osal_alloc;
758 s_cb_funcs.osal_free = &ihevce_osal_free;
759
760 status = osal_init(pv_osal_handle);
761 if(OSAL_SUCCESS != status)
762 {
763 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
764 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
765 "IHEVCE ERROR: Error in OSAL initialization\n");
766 return (-1);
767 }
768
769 status = osal_register_callbacks(pv_osal_handle, &s_cb_funcs);
770 if(OSAL_SUCCESS != status)
771 {
772 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
773 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
774 "IHEVCE ERROR: Error in OSAL initialization\n");
775 return (-1);
776 }
777 ps_hle_ctxt->pv_osal_handle = pv_osal_handle;
778
779 return (0);
780 }
781
782 /*!
783 ******************************************************************************
784 * \if Function name : ihevce_osal_delete \endif
785 *
786 * \brief
787 * Function to delete OSAL handle
788 *
789 * \return
790 * None
791 *
792 * \author
793 * Ittiam
794 *
795 *****************************************************************************
796 */
ihevce_osal_delete(void * pv_hle_ctxt)797 WORD32 ihevce_osal_delete(void *pv_hle_ctxt)
798 {
799 /* local variables */
800 ihevce_hle_ctxt_t *ps_hle_ctxt;
801 void *pv_osal_handle;
802 iv_mem_rec_t s_mem_tab;
803
804 ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_hle_ctxt;
805 pv_osal_handle = ps_hle_ctxt->pv_osal_handle;
806
807 /* def init of memtab */
808 s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
809 s_mem_tab.i4_mem_alignment = 8;
810 s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
811
812 if(0 != osal_close(pv_osal_handle))
813 {
814 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
815 ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
816 "IHEVCE ERROR>> Unable to close OSAL\n");
817 return (-1);
818 }
819
820 /* free osal handle */
821 s_mem_tab.pv_base = pv_osal_handle;
822
823 ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_mem_tab);
824
825 return (0);
826 }
827
828 /**
829 *******************************************************************************
830 *
831 * @brief
832 * Compute SSD between two blocks (8 bit input)
833 *
834 * @par Description:
835 *
836 * @param[in] pu1_inp
837 * UWORD8 pointer to the src block
838 *
839 * @param[in] pu1_ref
840 * UWORD8 pointer to the ref block
841 *
842 * @param[in] inp_stride
843 * UWORD32 Source stride
844 *
845 * @param[in] ref_stride
846 * UWORD32 ref stride
847 *
848 * @param[in] wd
849 * UWORD32 width of the block
850 *
851 * @param[in] ht
852 * UWORD32 height of the block
853 *
854 * @returns SSD
855 *
856 * @remarks none
857 *
858 *******************************************************************************
859 */
ihevce_ssd_calculator(UWORD8 * pu1_inp,UWORD8 * pu1_ref,UWORD32 inp_stride,UWORD32 ref_stride,UWORD32 wd,UWORD32 ht)860 LWORD64 ihevce_ssd_calculator(
861 UWORD8 *pu1_inp, UWORD8 *pu1_ref, UWORD32 inp_stride, UWORD32 ref_stride, UWORD32 wd, UWORD32 ht)
862 {
863 UWORD32 i, j;
864 LWORD64 ssd = 0;
865
866 for(i = 0; i < ht; i++)
867 {
868 for(j = 0; j < wd; j++)
869 {
870 ssd += (pu1_inp[j] - pu1_ref[j]) * (pu1_inp[j] - pu1_ref[j]);
871 }
872
873 pu1_inp += inp_stride;
874 pu1_ref += ref_stride;
875 }
876
877 return ssd;
878 }
879
880 /**
881 *******************************************************************************
882 *
883 * @brief
884 * Compute SSD between two blocks (8 bit input, chroma interleaved input)
885 *
886 * @par Description:
887 *
888 * @param[in] pu1_inp
889 * UWORD8 pointer to the src block
890 *
891 * @param[in] pu1_ref
892 * UWORD8 pointer to the ref block
893 *
894 * @param[in] inp_stride
895 * UWORD32 Source stride
896 *
897 * @param[in] ref_stride
898 * UWORD32 ref stride
899 *
900 * @param[in] wd
901 * UWORD32 width of the block
902 *
903 * @param[in] ht
904 * UWORD32 height of the block
905 *
906 * @returns SSD
907 *
908 * @remarks none
909 *
910 *******************************************************************************
911 */
ihevce_chroma_interleave_ssd_calculator(UWORD8 * pu1_inp,UWORD8 * pu1_ref,UWORD32 inp_stride,UWORD32 ref_stride,UWORD32 wd,UWORD32 ht)912 LWORD64 ihevce_chroma_interleave_ssd_calculator(
913 UWORD8 *pu1_inp, UWORD8 *pu1_ref, UWORD32 inp_stride, UWORD32 ref_stride, UWORD32 wd, UWORD32 ht)
914 {
915 UWORD32 i, j;
916 LWORD64 ssd = 0;
917
918 /* run a loop and find the ssd by doing diff followed by square */
919 for(i = 0; i < ht; i++)
920 {
921 for(j = 0; j < wd; j++)
922 {
923 WORD32 val;
924
925 /* note that chroma is interleaved */
926 val = pu1_inp[j * 2] - pu1_ref[j * 2];
927 ssd += val * val;
928 }
929 /* row level update */
930 pu1_inp += inp_stride;
931 pu1_ref += ref_stride;
932 }
933
934 return (ssd);
935 }
936
937 /**
938 *******************************************************************************
939 *
940 * @brief
941 * Compute SSD & SAD between two blocks (8 bit input)
942 *
943 * @par Description:
944 *
945 * @param[in] pu1_recon
946 * UWORD8 pointer to the block 1
947 *
948 * @param[in] recon_strd
949 * UWORD32 stride of block 1
950 *
951 * @param[in] pu1_src
952 * UWORD8 pointer to the block 2
953 *
954 * @param[in] src_strd
955 * UWORD32 stride of block 2
956 *
957 * @param[in] trans_size
958 * UWORD32 block wd/ht
959 *
960 * @param[out] *pu4_blk_sad
961 * UWORD32 block SAD
962 *
963 * @returns SSD
964 *
965 * @remarks none
966 *
967 *******************************************************************************
968 */
ihevce_ssd_and_sad_calculator(UWORD8 * pu1_recon,WORD32 recon_strd,UWORD8 * pu1_src,WORD32 src_strd,WORD32 trans_size,UWORD32 * pu4_blk_sad)969 LWORD64 ihevce_ssd_and_sad_calculator(
970 UWORD8 *pu1_recon,
971 WORD32 recon_strd,
972 UWORD8 *pu1_src,
973 WORD32 src_strd,
974 WORD32 trans_size,
975 UWORD32 *pu4_blk_sad)
976 {
977 WORD32 i, j, sad = 0;
978 LWORD64 ssd = 0;
979
980 /* run a loop and find the ssd by doing diff followed by square */
981 for(i = 0; i < trans_size; i++)
982 {
983 for(j = 0; j < trans_size; j++)
984 {
985 WORD32 val;
986
987 val = *pu1_src++ - *pu1_recon++;
988 ssd += val * val;
989 sad += abs(val);
990 }
991 /* row level update */
992 pu1_src += src_strd - trans_size;
993 pu1_recon += recon_strd - trans_size;
994 }
995 *pu4_blk_sad = sad;
996
997 /* The return value is of type WORD32 */
998 ssd = CLIP3(ssd, 0, 0x7fffffff);
999
1000 return (ssd);
1001 }
1002
1003 /*!
1004 ******************************************************************************
1005 * \if Function name : ihevce_chroma_interleave_2d_copy \endif
1006 *
1007 * \brief
1008 * This function copies one plane (u/v) of interleaved chroma buffer from
1009 * source to destination
1010 ******************************************************************************
1011 */
ihevce_chroma_interleave_2d_copy(UWORD8 * pu1_uv_src_bp,WORD32 src_strd,UWORD8 * pu1_uv_dst_bp,WORD32 dst_strd,WORD32 w,WORD32 h,CHROMA_PLANE_ID_T e_chroma_plane)1012 void ihevce_chroma_interleave_2d_copy(
1013 UWORD8 *pu1_uv_src_bp,
1014 WORD32 src_strd,
1015 UWORD8 *pu1_uv_dst_bp,
1016 WORD32 dst_strd,
1017 WORD32 w,
1018 WORD32 h,
1019 CHROMA_PLANE_ID_T e_chroma_plane)
1020 {
1021 WORD32 i, j;
1022
1023 UWORD8 *pu1_src = (U_PLANE == e_chroma_plane) ? pu1_uv_src_bp : pu1_uv_src_bp + 1;
1024 UWORD8 *pu1_dst = (U_PLANE == e_chroma_plane) ? pu1_uv_dst_bp : pu1_uv_dst_bp + 1;
1025
1026 for(i = 0; i < h; i++)
1027 {
1028 for(j = 0; j < w; j++)
1029 {
1030 /* note that chroma is interleaved */
1031 pu1_dst[j * 2] = pu1_src[j * 2];
1032 }
1033
1034 /* row level update */
1035 pu1_src += src_strd;
1036 pu1_dst += dst_strd;
1037 }
1038 }
1039
1040 /**
1041 *******************************************************************************
1042 *
1043 * @brief
1044 * Gets edge offset params
1045 *
1046 * @par Description:
1047 * Given the ctb and sao angle this function will calculate accumulated
1048 * error between source and recon and the corresponding count for 4 edge
1049 * indexes one each for peak,valley, half peak and half valley.
1050 *
1051 * @param[in]
1052 * ps_sao_ctxt: Pointer to SAO context
1053 * eo_sao_class: specifies edge offset class
1054 * pi4_acc_error_category: pointer to an array to store accumulated error between source and recon
1055 * pi4_category_count : pointer to an array to store number of peaks,valleys,half peaks and half valleys.
1056 * @returns
1057 *
1058 * @remarks
1059 * None
1060 *
1061 *******************************************************************************/
ihevce_get_chroma_eo_sao_params(void * pv_sao_ctxt,WORD32 eo_sao_class,WORD32 * pi4_acc_error_category,WORD32 * pi4_category_count)1062 void ihevce_get_chroma_eo_sao_params(
1063 void *pv_sao_ctxt,
1064 WORD32 eo_sao_class,
1065 WORD32 *pi4_acc_error_category,
1066 WORD32 *pi4_category_count)
1067 {
1068 WORD32 row_start, row_end, col_start, col_end, row, col;
1069 WORD32 row_offset = 0, col_offset = 0;
1070 WORD32 a, b, c, pel_error, edgeidx;
1071 sao_ctxt_t *ps_sao_ctxt = (sao_ctxt_t *)pv_sao_ctxt;
1072
1073 row_start = 0;
1074 row_end = ps_sao_ctxt->i4_sao_blk_ht >> 1;
1075 col_start = 0;
1076 col_end = ps_sao_ctxt->i4_sao_blk_wd;
1077
1078 if((ps_sao_ctxt->i4_ctb_x == 0) && (eo_sao_class != SAO_EDGE_90_DEG))
1079 {
1080 col_start = 2;
1081 }
1082
1083 if(((ps_sao_ctxt->i4_ctb_x + 1) == ps_sao_ctxt->ps_sps->i2_pic_wd_in_ctb) &&
1084 (eo_sao_class != SAO_EDGE_90_DEG))
1085 {
1086 col_end = ps_sao_ctxt->i4_sao_blk_wd - 2;
1087 }
1088
1089 if((ps_sao_ctxt->i4_ctb_y == 0) && (eo_sao_class != SAO_EDGE_0_DEG))
1090 {
1091 row_start = 1;
1092 }
1093
1094 if(((ps_sao_ctxt->i4_ctb_y + 1) == ps_sao_ctxt->ps_sps->i2_pic_ht_in_ctb) &&
1095 (eo_sao_class != SAO_EDGE_0_DEG))
1096 {
1097 row_end = row_end - 1; //ps_sao_ctxt->i4_sao_blk_ht - 1;
1098 }
1099
1100 if(eo_sao_class == SAO_EDGE_0_DEG)
1101 {
1102 row_offset = 0;
1103 col_offset = 2;
1104 }
1105 else if(eo_sao_class == SAO_EDGE_90_DEG)
1106 {
1107 row_offset = 1;
1108 col_offset = 0;
1109 }
1110 else if(eo_sao_class == SAO_EDGE_135_DEG)
1111 {
1112 row_offset = 1;
1113 col_offset = 2;
1114 }
1115 else if(eo_sao_class == SAO_EDGE_45_DEG)
1116 {
1117 row_offset = 1;
1118 col_offset = -2;
1119 }
1120
1121 for(row = row_start; row < row_end; row++)
1122 {
1123 for(col = col_start; col < col_end; col++)
1124 {
1125 c = ps_sao_ctxt
1126 ->pu1_cur_chroma_recon_buf[col + row * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1127 a = ps_sao_ctxt->pu1_cur_chroma_recon_buf
1128 [(col - col_offset) +
1129 (row - row_offset) * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1130 b = ps_sao_ctxt->pu1_cur_chroma_recon_buf
1131 [(col + col_offset) +
1132 (row + row_offset) * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1133 pel_error =
1134 ps_sao_ctxt
1135 ->pu1_cur_chroma_src_buf[col + row * ps_sao_ctxt->i4_cur_chroma_src_stride] -
1136 ps_sao_ctxt
1137 ->pu1_cur_chroma_recon_buf[col + row * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1138 edgeidx = 2 + SIGN(c - a) + SIGN(c - b);
1139
1140 if(pel_error != 0)
1141 {
1142 pi4_acc_error_category[edgeidx] += pel_error;
1143 pi4_category_count[edgeidx]++;
1144 }
1145 }
1146 }
1147 }
1148
1149 /**
1150 *******************************************************************************
1151 *
1152 * @brief
1153 * Gets edge offset params
1154 *
1155 * @par Description:
1156 * Given the ctb and sao angle this function will calculate accumulated
1157 * error between source and recon and the coresponding count for 4 edge
1158 * indexes one each for peak,valley, half peak and half valley.
1159 *
1160 * @param[in]
1161 * ps_sao_ctxt: Pointer to SAO context
1162 * eo_sao_class: specifies edge offset class
1163 * pi4_acc_error_category: pointer to an array to store accumulated error between source and recon
1164 * pi4_category_count : pointer to an array to store number of peaks,valleys,half peaks and half valleys.
1165 * @returns
1166 *
1167 * @remarks
1168 * None
1169 *
1170 *******************************************************************************/
ihevce_get_luma_eo_sao_params(void * pv_sao_ctxt,WORD32 eo_sao_class,WORD32 * pi4_acc_error_category,WORD32 * pi4_category_count)1171 void ihevce_get_luma_eo_sao_params(
1172 void *pv_sao_ctxt,
1173 WORD32 eo_sao_class,
1174 WORD32 *pi4_acc_error_category,
1175 WORD32 *pi4_category_count)
1176 {
1177 WORD32 row_start, row_end, col_start, col_end, row, col;
1178 WORD32 row_offset = 0, col_offset = 0;
1179 WORD32 a, b, c, pel_error, edgeidx;
1180 sao_ctxt_t *ps_sao_ctxt = (sao_ctxt_t *)pv_sao_ctxt;
1181
1182 row_start = 0;
1183 row_end = ps_sao_ctxt->i4_sao_blk_ht;
1184 col_start = 0;
1185 col_end = ps_sao_ctxt->i4_sao_blk_wd;
1186
1187 if((ps_sao_ctxt->i4_ctb_x == 0) && (eo_sao_class != SAO_EDGE_90_DEG))
1188 {
1189 col_start = 1;
1190 }
1191
1192 if(((ps_sao_ctxt->i4_ctb_x + 1) == ps_sao_ctxt->ps_sps->i2_pic_wd_in_ctb) &&
1193 (eo_sao_class != SAO_EDGE_90_DEG))
1194 {
1195 col_end = ps_sao_ctxt->i4_sao_blk_wd - 1;
1196 }
1197
1198 if((ps_sao_ctxt->i4_ctb_y == 0) && (eo_sao_class != SAO_EDGE_0_DEG))
1199 {
1200 row_start = 1;
1201 }
1202
1203 if(((ps_sao_ctxt->i4_ctb_y + 1) == ps_sao_ctxt->ps_sps->i2_pic_ht_in_ctb) &&
1204 (eo_sao_class != SAO_EDGE_0_DEG))
1205 {
1206 row_end = ps_sao_ctxt->i4_sao_blk_ht - 1;
1207 }
1208
1209 if(eo_sao_class == SAO_EDGE_0_DEG)
1210 {
1211 row_offset = 0;
1212 col_offset = 1;
1213 }
1214 else if(eo_sao_class == SAO_EDGE_90_DEG)
1215 {
1216 row_offset = 1;
1217 col_offset = 0;
1218 }
1219 else if(eo_sao_class == SAO_EDGE_135_DEG)
1220 {
1221 row_offset = 1;
1222 col_offset = 1;
1223 }
1224 else if(eo_sao_class == SAO_EDGE_45_DEG)
1225 {
1226 row_offset = 1;
1227 col_offset = -1;
1228 }
1229
1230 for(row = row_start; row < row_end; row++)
1231 {
1232 for(col = col_start; col < col_end; col++)
1233 {
1234 c = ps_sao_ctxt
1235 ->pu1_cur_luma_recon_buf[col + row * ps_sao_ctxt->i4_cur_luma_recon_stride];
1236 a = ps_sao_ctxt->pu1_cur_luma_recon_buf
1237 [(col - col_offset) +
1238 (row - row_offset) * ps_sao_ctxt->i4_cur_luma_recon_stride];
1239 b = ps_sao_ctxt->pu1_cur_luma_recon_buf
1240 [(col + col_offset) +
1241 (row + row_offset) * ps_sao_ctxt->i4_cur_luma_recon_stride];
1242 pel_error =
1243 ps_sao_ctxt->pu1_cur_luma_src_buf[col + row * ps_sao_ctxt->i4_cur_luma_src_stride] -
1244 ps_sao_ctxt
1245 ->pu1_cur_luma_recon_buf[col + row * ps_sao_ctxt->i4_cur_luma_recon_stride];
1246 edgeidx = 2 + SIGN(c - a) + SIGN(c - b);
1247
1248 if(pel_error != 0)
1249 {
1250 pi4_acc_error_category[edgeidx] += pel_error;
1251 pi4_category_count[edgeidx]++;
1252 }
1253 }
1254 }
1255 }
1256
1257 /*!
1258 ******************************************************************************
1259 * \if Function name : ihevce_compute_area_of_valid_cus_in_ctb \endif
1260 *
1261 * \brief
1262 *
1263 *
1264 *****************************************************************************
1265 */
ihevce_compute_area_of_valid_cus_in_ctb(cur_ctb_cu_tree_t * ps_cu_tree)1266 WORD32 ihevce_compute_area_of_valid_cus_in_ctb(cur_ctb_cu_tree_t *ps_cu_tree)
1267 {
1268 WORD32 i4_area;
1269
1270 if(NULL == ps_cu_tree)
1271 {
1272 return 0;
1273 }
1274
1275 if(ps_cu_tree->is_node_valid)
1276 {
1277 i4_area = ps_cu_tree->u1_cu_size * ps_cu_tree->u1_cu_size;
1278 }
1279 else
1280 {
1281 i4_area = ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_tl) +
1282 ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_tr) +
1283 ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_bl) +
1284 ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_br);
1285 }
1286
1287 return i4_area;
1288 }
1289
1290 /*!
1291 ******************************************************************************
1292 * \if Function name : ihevce_create_cuNode_children \endif
1293 *
1294 * \brief
1295 *
1296 *
1297 *****************************************************************************
1298 */
ihevce_create_cuNode_children(cur_ctb_cu_tree_t * ps_cu_tree_root,cur_ctb_cu_tree_t * ps_cu_tree_cur_node,WORD32 nodes_already_created)1299 static WORD32 ihevce_create_cuNode_children(
1300 cur_ctb_cu_tree_t *ps_cu_tree_root,
1301 cur_ctb_cu_tree_t *ps_cu_tree_cur_node,
1302 WORD32 nodes_already_created)
1303 {
1304 cur_ctb_cu_tree_t *ps_tl;
1305 cur_ctb_cu_tree_t *ps_tr;
1306 cur_ctb_cu_tree_t *ps_bl;
1307 cur_ctb_cu_tree_t *ps_br;
1308
1309 ps_tl = ps_cu_tree_root + nodes_already_created;
1310 ps_tr = ps_tl + 1;
1311 ps_bl = ps_tr + 1;
1312 ps_br = ps_bl + 1;
1313 /*
1314 ps_tl = (ai4_child_node_enable[0]) ? ps_tl : NULL;
1315 ps_tr = (ai4_child_node_enable[1]) ? ps_tr : NULL;
1316 ps_bl = (ai4_child_node_enable[2]) ? ps_bl : NULL;
1317 ps_br = (ai4_child_node_enable[3]) ? ps_br : NULL;
1318 */
1319 ps_cu_tree_cur_node->ps_child_node_tl = ps_tl;
1320 ps_cu_tree_cur_node->ps_child_node_tr = ps_tr;
1321 ps_cu_tree_cur_node->ps_child_node_bl = ps_bl;
1322 ps_cu_tree_cur_node->ps_child_node_br = ps_br;
1323
1324 return 4;
1325 }
1326
1327 /*!
1328 ******************************************************************************
1329 * \if Function name : ihevce_cu_tree_init \endif
1330 *
1331 * \brief
1332 *
1333 *
1334 *****************************************************************************
1335 */
ihevce_cu_tree_init(cur_ctb_cu_tree_t * ps_cu_tree,cur_ctb_cu_tree_t * ps_cu_tree_root,WORD32 * pi4_nodes_created_in_cu_tree,WORD32 tree_depth,CU_POS_T e_grandparent_blk_pos,CU_POS_T e_parent_blk_pos,CU_POS_T e_cur_blk_pos)1336 void ihevce_cu_tree_init(
1337 cur_ctb_cu_tree_t *ps_cu_tree,
1338 cur_ctb_cu_tree_t *ps_cu_tree_root,
1339 WORD32 *pi4_nodes_created_in_cu_tree,
1340 WORD32 tree_depth,
1341 CU_POS_T e_grandparent_blk_pos,
1342 CU_POS_T e_parent_blk_pos,
1343 CU_POS_T e_cur_blk_pos)
1344 {
1345 WORD32 cu_pos_x = 0;
1346 WORD32 cu_pos_y = 0;
1347 WORD32 cu_size = 0;
1348
1349 WORD32 children_nodes_required = 1;
1350 WORD32 node_validity = 0;
1351
1352 switch(tree_depth)
1353 {
1354 case 0:
1355 {
1356 /* 64x64 block */
1357 cu_size = 64;
1358 cu_pos_x = 0;
1359 cu_pos_y = 0;
1360
1361 break;
1362 }
1363 case 1:
1364 {
1365 /* 32x32 block */
1366 cu_size = 32;
1367
1368 /* Explanation for logic below - */
1369 /* * pos_x and pos_y are in units of 8x8 CU's */
1370 /* * pos_x = 0 for TL and BL children */
1371 /* * pos_x = 4 for TR and BR children */
1372 /* * pos_y = 0 for TL and TR children */
1373 /* * pos_y = 4 for BL and BR children */
1374 cu_pos_x = (e_cur_blk_pos & 1) << 2;
1375 cu_pos_y = (e_cur_blk_pos & 2) << 1;
1376
1377 break;
1378 }
1379 case 2:
1380 {
1381 /* 16x16 block */
1382 WORD32 cu_pos_x_parent;
1383 WORD32 cu_pos_y_parent;
1384
1385 cu_size = 16;
1386
1387 /* Explanation for logic below - */
1388 /* See similar explanation above */
1389 cu_pos_x_parent = (e_parent_blk_pos & 1) << 2;
1390 cu_pos_y_parent = (e_parent_blk_pos & 2) << 1;
1391 cu_pos_x = cu_pos_x_parent + ((e_cur_blk_pos & 1) << 1);
1392 cu_pos_y = cu_pos_y_parent + (e_cur_blk_pos & 2);
1393
1394 break;
1395 }
1396 case 3:
1397 {
1398 /* 8x8 block */
1399 WORD32 cu_pos_x_grandparent;
1400 WORD32 cu_pos_y_grandparent;
1401
1402 WORD32 cu_pos_x_parent;
1403 WORD32 cu_pos_y_parent;
1404
1405 cu_size = 8;
1406
1407 cu_pos_x_grandparent = (e_grandparent_blk_pos & 1) << 2;
1408 cu_pos_y_grandparent = (e_grandparent_blk_pos & 2) << 1;
1409 cu_pos_x_parent = cu_pos_x_grandparent + ((e_parent_blk_pos & 1) << 1);
1410 cu_pos_y_parent = cu_pos_y_grandparent + (e_parent_blk_pos & 2);
1411 cu_pos_x = cu_pos_x_parent + (e_cur_blk_pos & 1);
1412 cu_pos_y = cu_pos_y_parent + ((e_cur_blk_pos & 2) >> 1);
1413
1414 children_nodes_required = 0;
1415
1416 break;
1417 }
1418 }
1419
1420 /* Fill the current cu_tree node */
1421 CU_TREE_NODE_FILL(ps_cu_tree, node_validity, cu_pos_x, cu_pos_y, cu_size, 1);
1422
1423 if(children_nodes_required)
1424 {
1425 tree_depth++;
1426
1427 (*pi4_nodes_created_in_cu_tree) += ihevce_create_cuNode_children(
1428 ps_cu_tree_root, ps_cu_tree, (*pi4_nodes_created_in_cu_tree));
1429
1430 ihevce_cu_tree_init(
1431 ps_cu_tree->ps_child_node_tl,
1432 ps_cu_tree_root,
1433 pi4_nodes_created_in_cu_tree,
1434 tree_depth,
1435 e_parent_blk_pos,
1436 e_cur_blk_pos,
1437 POS_TL);
1438
1439 ihevce_cu_tree_init(
1440 ps_cu_tree->ps_child_node_tr,
1441 ps_cu_tree_root,
1442 pi4_nodes_created_in_cu_tree,
1443 tree_depth,
1444 e_parent_blk_pos,
1445 e_cur_blk_pos,
1446 POS_TR);
1447
1448 ihevce_cu_tree_init(
1449 ps_cu_tree->ps_child_node_bl,
1450 ps_cu_tree_root,
1451 pi4_nodes_created_in_cu_tree,
1452 tree_depth,
1453 e_parent_blk_pos,
1454 e_cur_blk_pos,
1455 POS_BL);
1456
1457 ihevce_cu_tree_init(
1458 ps_cu_tree->ps_child_node_br,
1459 ps_cu_tree_root,
1460 pi4_nodes_created_in_cu_tree,
1461 tree_depth,
1462 e_parent_blk_pos,
1463 e_cur_blk_pos,
1464 POS_BR);
1465 }
1466 else
1467 {
1468 NULLIFY_THE_CHILDREN_NODES(ps_cu_tree);
1469 }
1470 }
1471