• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,CHROMA_PLANE_ID_T chroma_plane)860 LWORD64 ihevce_ssd_calculator(
861     UWORD8 *pu1_inp, UWORD8 *pu1_ref, UWORD32 inp_stride, UWORD32 ref_stride, UWORD32 wd,
862     UWORD32 ht, CHROMA_PLANE_ID_T chroma_plane)
863 {
864     UWORD32 i, j;
865     LWORD64 ssd = 0;
866     UNUSED(chroma_plane);
867     for(i = 0; i < ht; i++)
868     {
869         for(j = 0; j < wd; j++)
870         {
871             ssd += (pu1_inp[j] - pu1_ref[j]) * (pu1_inp[j] - pu1_ref[j]);
872         }
873 
874         pu1_inp += inp_stride;
875         pu1_ref += ref_stride;
876     }
877 
878     return ssd;
879 }
880 
881 /**
882 *******************************************************************************
883 *
884 * @brief
885 *  Compute SSD between two blocks (8 bit input, chroma interleaved input)
886 *
887 * @par Description:
888 *
889 * @param[in] pu1_inp
890 *  UWORD8 pointer to the src block
891 *
892 * @param[in] pu1_ref
893 *  UWORD8 pointer to the ref block
894 *
895 * @param[in] inp_stride
896 *  UWORD32 Source stride
897 *
898 * @param[in] ref_stride
899 *  UWORD32 ref stride
900 *
901 * @param[in] wd
902 *  UWORD32 width of the block
903 *
904 * @param[in] ht
905 *  UWORD32 height of the block
906 *
907 * @returns SSD
908 *
909 * @remarks none
910 *
911 *******************************************************************************
912 */
ihevce_chroma_interleave_ssd_calculator(UWORD8 * pu1_inp,UWORD8 * pu1_ref,UWORD32 inp_stride,UWORD32 ref_stride,UWORD32 wd,UWORD32 ht,CHROMA_PLANE_ID_T chroma_plane)913 LWORD64 ihevce_chroma_interleave_ssd_calculator(
914     UWORD8 *pu1_inp, UWORD8 *pu1_ref, UWORD32 inp_stride, UWORD32 ref_stride, UWORD32 wd,
915     UWORD32 ht, CHROMA_PLANE_ID_T chroma_plane)
916 {
917     UWORD32 i, j;
918     LWORD64 ssd = 0;
919     pu1_inp += chroma_plane;
920     pu1_ref += chroma_plane;
921 
922     /* run a loop and find the ssd by doing diff followed by square */
923     for(i = 0; i < ht; i++)
924     {
925         for(j = 0; j < wd; j++)
926         {
927             WORD32 val;
928 
929             /* note that chroma is interleaved */
930             val = pu1_inp[j * 2] - pu1_ref[j * 2];
931             ssd += val * val;
932         }
933         /* row level update */
934         pu1_inp += inp_stride;
935         pu1_ref += ref_stride;
936     }
937 
938     return (ssd);
939 }
940 
941 /**
942 *******************************************************************************
943 *
944 * @brief
945 *  Compute SSD & SAD between two blocks (8 bit input)
946 *
947 * @par Description:
948 *
949 * @param[in] pu1_recon
950 *  UWORD8 pointer to the block 1
951 *
952 * @param[in] recon_strd
953 *  UWORD32 stride of block 1
954 *
955 * @param[in] pu1_src
956 *  UWORD8 pointer to the block 2
957 *
958 * @param[in] src_strd
959 *  UWORD32 stride of block 2
960 *
961 * @param[in] trans_size
962 *  UWORD32 block wd/ht
963 *
964 * @param[out] *pu4_blk_sad
965 *  UWORD32 block SAD
966 *
967 * @returns SSD
968 *
969 * @remarks none
970 *
971 *******************************************************************************
972 */
ihevce_ssd_and_sad_calculator(UWORD8 * pu1_recon,WORD32 recon_strd,UWORD8 * pu1_src,WORD32 src_strd,WORD32 trans_size,UWORD32 * pu4_blk_sad)973 LWORD64 ihevce_ssd_and_sad_calculator(
974     UWORD8 *pu1_recon,
975     WORD32 recon_strd,
976     UWORD8 *pu1_src,
977     WORD32 src_strd,
978     WORD32 trans_size,
979     UWORD32 *pu4_blk_sad)
980 {
981     WORD32 i, j, sad = 0;
982     LWORD64 ssd = 0;
983 
984     /* run a loop and find the ssd by doing diff followed by square */
985     for(i = 0; i < trans_size; i++)
986     {
987         for(j = 0; j < trans_size; j++)
988         {
989             WORD32 val;
990 
991             val = *pu1_src++ - *pu1_recon++;
992             ssd += val * val;
993             sad += abs(val);
994         }
995         /* row level update */
996         pu1_src += src_strd - trans_size;
997         pu1_recon += recon_strd - trans_size;
998     }
999     *pu4_blk_sad = sad;
1000 
1001     /* The return value is of type WORD32 */
1002     ssd = CLIP3(ssd, 0, 0x7fffffff);
1003 
1004     return (ssd);
1005 }
1006 
1007 /*!
1008 ******************************************************************************
1009 * \if Function name : ihevce_chroma_interleave_2d_copy \endif
1010 *
1011 * \brief
1012 *    This function copies one plane (u/v) of interleaved chroma buffer from
1013 *    source to destination
1014 ******************************************************************************
1015 */
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)1016 void ihevce_chroma_interleave_2d_copy(
1017     UWORD8 *pu1_uv_src_bp,
1018     WORD32 src_strd,
1019     UWORD8 *pu1_uv_dst_bp,
1020     WORD32 dst_strd,
1021     WORD32 w,
1022     WORD32 h,
1023     CHROMA_PLANE_ID_T e_chroma_plane)
1024 {
1025     WORD32 i, j;
1026 
1027     UWORD8 *pu1_src = (U_PLANE == e_chroma_plane) ? pu1_uv_src_bp : pu1_uv_src_bp + 1;
1028     UWORD8 *pu1_dst = (U_PLANE == e_chroma_plane) ? pu1_uv_dst_bp : pu1_uv_dst_bp + 1;
1029 
1030     for(i = 0; i < h; i++)
1031     {
1032         for(j = 0; j < w; j++)
1033         {
1034             /* note that chroma is interleaved */
1035             pu1_dst[j * 2] = pu1_src[j * 2];
1036         }
1037 
1038         /* row level update */
1039         pu1_src += src_strd;
1040         pu1_dst += dst_strd;
1041     }
1042 }
1043 
1044 /**
1045 *******************************************************************************
1046 *
1047 * @brief
1048 *     Gets edge offset params
1049 *
1050 * @par Description:
1051 *     Given the ctb and sao angle this function will calculate accumulated
1052 *     error between source and recon and the corresponding count for 4 edge
1053 *     indexes one each for peak,valley, half peak and half valley.
1054 *
1055 * @param[in]
1056 *   ps_sao_ctxt:   Pointer to SAO context
1057 *   eo_sao_class: specifies edge offset class
1058 *   pi4_acc_error_category: pointer to an array to store accumulated error between source and recon
1059 *   pi4_category_count    : pointer to an array to store number of peaks,valleys,half peaks and half valleys.
1060 * @returns
1061 *
1062 * @remarks
1063 *  None
1064 *
1065 *******************************************************************************/
ihevce_get_chroma_eo_sao_params(void * pv_sao_ctxt,WORD32 eo_sao_class,WORD32 * pi4_acc_error_category,WORD32 * pi4_category_count)1066 void ihevce_get_chroma_eo_sao_params(
1067     void *pv_sao_ctxt,
1068     WORD32 eo_sao_class,
1069     WORD32 *pi4_acc_error_category,
1070     WORD32 *pi4_category_count)
1071 {
1072     WORD32 row_start, row_end, col_start, col_end, row, col;
1073     WORD32 row_offset = 0, col_offset = 0;
1074     WORD32 a, b, c, pel_error, edgeidx;
1075     sao_ctxt_t *ps_sao_ctxt = (sao_ctxt_t *)pv_sao_ctxt;
1076 
1077     row_start = 0;
1078     row_end = ps_sao_ctxt->i4_sao_blk_ht >> 1;
1079     col_start = 0;
1080     col_end = ps_sao_ctxt->i4_sao_blk_wd;
1081 
1082     if((ps_sao_ctxt->i4_ctb_x == 0) && (eo_sao_class != SAO_EDGE_90_DEG))
1083     {
1084         col_start = 2;
1085     }
1086 
1087     if(((ps_sao_ctxt->i4_ctb_x + 1) == ps_sao_ctxt->ps_sps->i2_pic_wd_in_ctb) &&
1088        (eo_sao_class != SAO_EDGE_90_DEG))
1089     {
1090         col_end = ps_sao_ctxt->i4_sao_blk_wd - 2;
1091     }
1092 
1093     if((ps_sao_ctxt->i4_ctb_y == 0) && (eo_sao_class != SAO_EDGE_0_DEG))
1094     {
1095         row_start = 1;
1096     }
1097 
1098     if(((ps_sao_ctxt->i4_ctb_y + 1) == ps_sao_ctxt->ps_sps->i2_pic_ht_in_ctb) &&
1099        (eo_sao_class != SAO_EDGE_0_DEG))
1100     {
1101         row_end = row_end - 1;  //ps_sao_ctxt->i4_sao_blk_ht - 1;
1102     }
1103 
1104     if(eo_sao_class == SAO_EDGE_0_DEG)
1105     {
1106         row_offset = 0;
1107         col_offset = 2;
1108     }
1109     else if(eo_sao_class == SAO_EDGE_90_DEG)
1110     {
1111         row_offset = 1;
1112         col_offset = 0;
1113     }
1114     else if(eo_sao_class == SAO_EDGE_135_DEG)
1115     {
1116         row_offset = 1;
1117         col_offset = 2;
1118     }
1119     else if(eo_sao_class == SAO_EDGE_45_DEG)
1120     {
1121         row_offset = 1;
1122         col_offset = -2;
1123     }
1124 
1125     for(row = row_start; row < row_end; row++)
1126     {
1127         for(col = col_start; col < col_end; col++)
1128         {
1129             c = ps_sao_ctxt
1130                     ->pu1_cur_chroma_recon_buf[col + row * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1131             a = ps_sao_ctxt->pu1_cur_chroma_recon_buf
1132                     [(col - col_offset) +
1133                      (row - row_offset) * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1134             b = ps_sao_ctxt->pu1_cur_chroma_recon_buf
1135                     [(col + col_offset) +
1136                      (row + row_offset) * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1137             pel_error =
1138                 ps_sao_ctxt
1139                     ->pu1_cur_chroma_src_buf[col + row * ps_sao_ctxt->i4_cur_chroma_src_stride] -
1140                 ps_sao_ctxt
1141                     ->pu1_cur_chroma_recon_buf[col + row * ps_sao_ctxt->i4_cur_chroma_recon_stride];
1142             edgeidx = 2 + SIGN(c - a) + SIGN(c - b);
1143 
1144             if(pel_error != 0)
1145             {
1146                 pi4_acc_error_category[edgeidx] += pel_error;
1147                 pi4_category_count[edgeidx]++;
1148             }
1149         }
1150     }
1151 }
1152 
1153 /**
1154 *******************************************************************************
1155 *
1156 * @brief
1157 *     Gets edge offset params
1158 *
1159 * @par Description:
1160 *     Given the ctb and sao angle this function will calculate accumulated
1161 *     error between source and recon and the coresponding count for 4 edge
1162 *     indexes one each for peak,valley, half peak and half valley.
1163 *
1164 * @param[in]
1165 *   ps_sao_ctxt:   Pointer to SAO context
1166 *   eo_sao_class: specifies edge offset class
1167 *   pi4_acc_error_category: pointer to an array to store accumulated error between source and recon
1168 *   pi4_category_count    : pointer to an array to store number of peaks,valleys,half peaks and half valleys.
1169 * @returns
1170 *
1171 * @remarks
1172 *  None
1173 *
1174 *******************************************************************************/
ihevce_get_luma_eo_sao_params(void * pv_sao_ctxt,WORD32 eo_sao_class,WORD32 * pi4_acc_error_category,WORD32 * pi4_category_count)1175 void ihevce_get_luma_eo_sao_params(
1176     void *pv_sao_ctxt,
1177     WORD32 eo_sao_class,
1178     WORD32 *pi4_acc_error_category,
1179     WORD32 *pi4_category_count)
1180 {
1181     WORD32 row_start, row_end, col_start, col_end, row, col;
1182     WORD32 row_offset = 0, col_offset = 0;
1183     WORD32 a, b, c, pel_error, edgeidx;
1184     sao_ctxt_t *ps_sao_ctxt = (sao_ctxt_t *)pv_sao_ctxt;
1185 
1186     row_start = 0;
1187     row_end = ps_sao_ctxt->i4_sao_blk_ht;
1188     col_start = 0;
1189     col_end = ps_sao_ctxt->i4_sao_blk_wd;
1190 
1191     if((ps_sao_ctxt->i4_ctb_x == 0) && (eo_sao_class != SAO_EDGE_90_DEG))
1192     {
1193         col_start = 1;
1194     }
1195 
1196     if(((ps_sao_ctxt->i4_ctb_x + 1) == ps_sao_ctxt->ps_sps->i2_pic_wd_in_ctb) &&
1197        (eo_sao_class != SAO_EDGE_90_DEG))
1198     {
1199         col_end = ps_sao_ctxt->i4_sao_blk_wd - 1;
1200     }
1201 
1202     if((ps_sao_ctxt->i4_ctb_y == 0) && (eo_sao_class != SAO_EDGE_0_DEG))
1203     {
1204         row_start = 1;
1205     }
1206 
1207     if(((ps_sao_ctxt->i4_ctb_y + 1) == ps_sao_ctxt->ps_sps->i2_pic_ht_in_ctb) &&
1208        (eo_sao_class != SAO_EDGE_0_DEG))
1209     {
1210         row_end = ps_sao_ctxt->i4_sao_blk_ht - 1;
1211     }
1212 
1213     if(eo_sao_class == SAO_EDGE_0_DEG)
1214     {
1215         row_offset = 0;
1216         col_offset = 1;
1217     }
1218     else if(eo_sao_class == SAO_EDGE_90_DEG)
1219     {
1220         row_offset = 1;
1221         col_offset = 0;
1222     }
1223     else if(eo_sao_class == SAO_EDGE_135_DEG)
1224     {
1225         row_offset = 1;
1226         col_offset = 1;
1227     }
1228     else if(eo_sao_class == SAO_EDGE_45_DEG)
1229     {
1230         row_offset = 1;
1231         col_offset = -1;
1232     }
1233 
1234     for(row = row_start; row < row_end; row++)
1235     {
1236         for(col = col_start; col < col_end; col++)
1237         {
1238             c = ps_sao_ctxt
1239                     ->pu1_cur_luma_recon_buf[col + row * ps_sao_ctxt->i4_cur_luma_recon_stride];
1240             a = ps_sao_ctxt->pu1_cur_luma_recon_buf
1241                     [(col - col_offset) +
1242                      (row - row_offset) * ps_sao_ctxt->i4_cur_luma_recon_stride];
1243             b = ps_sao_ctxt->pu1_cur_luma_recon_buf
1244                     [(col + col_offset) +
1245                      (row + row_offset) * ps_sao_ctxt->i4_cur_luma_recon_stride];
1246             pel_error =
1247                 ps_sao_ctxt->pu1_cur_luma_src_buf[col + row * ps_sao_ctxt->i4_cur_luma_src_stride] -
1248                 ps_sao_ctxt
1249                     ->pu1_cur_luma_recon_buf[col + row * ps_sao_ctxt->i4_cur_luma_recon_stride];
1250             edgeidx = 2 + SIGN(c - a) + SIGN(c - b);
1251 
1252             if(pel_error != 0)
1253             {
1254                 pi4_acc_error_category[edgeidx] += pel_error;
1255                 pi4_category_count[edgeidx]++;
1256             }
1257         }
1258     }
1259 }
1260 
1261 /*!
1262 ******************************************************************************
1263 * \if Function name : ihevce_compute_area_of_valid_cus_in_ctb \endif
1264 *
1265 * \brief
1266 *
1267 *
1268 *****************************************************************************
1269 */
ihevce_compute_area_of_valid_cus_in_ctb(cur_ctb_cu_tree_t * ps_cu_tree)1270 WORD32 ihevce_compute_area_of_valid_cus_in_ctb(cur_ctb_cu_tree_t *ps_cu_tree)
1271 {
1272     WORD32 i4_area;
1273 
1274     if(NULL == ps_cu_tree)
1275     {
1276         return 0;
1277     }
1278 
1279     if(ps_cu_tree->is_node_valid)
1280     {
1281         i4_area = ps_cu_tree->u1_cu_size * ps_cu_tree->u1_cu_size;
1282     }
1283     else
1284     {
1285         i4_area = ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_tl) +
1286                   ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_tr) +
1287                   ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_bl) +
1288                   ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_br);
1289     }
1290 
1291     return i4_area;
1292 }
1293 
1294 /*!
1295 ******************************************************************************
1296 * \if Function name : ihevce_create_cuNode_children \endif
1297 *
1298 * \brief
1299 *
1300 *
1301 *****************************************************************************
1302 */
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)1303 static WORD32 ihevce_create_cuNode_children(
1304     cur_ctb_cu_tree_t *ps_cu_tree_root,
1305     cur_ctb_cu_tree_t *ps_cu_tree_cur_node,
1306     WORD32 nodes_already_created)
1307 {
1308     cur_ctb_cu_tree_t *ps_tl;
1309     cur_ctb_cu_tree_t *ps_tr;
1310     cur_ctb_cu_tree_t *ps_bl;
1311     cur_ctb_cu_tree_t *ps_br;
1312 
1313     ps_tl = ps_cu_tree_root + nodes_already_created;
1314     ps_tr = ps_tl + 1;
1315     ps_bl = ps_tr + 1;
1316     ps_br = ps_bl + 1;
1317     /*
1318     ps_tl = (ai4_child_node_enable[0]) ? ps_tl : NULL;
1319     ps_tr = (ai4_child_node_enable[1]) ? ps_tr : NULL;
1320     ps_bl = (ai4_child_node_enable[2]) ? ps_bl : NULL;
1321     ps_br = (ai4_child_node_enable[3]) ? ps_br : NULL;
1322     */
1323     ps_cu_tree_cur_node->ps_child_node_tl = ps_tl;
1324     ps_cu_tree_cur_node->ps_child_node_tr = ps_tr;
1325     ps_cu_tree_cur_node->ps_child_node_bl = ps_bl;
1326     ps_cu_tree_cur_node->ps_child_node_br = ps_br;
1327 
1328     return 4;
1329 }
1330 
1331 /*!
1332 ******************************************************************************
1333 * \if Function name : ihevce_cu_tree_init \endif
1334 *
1335 * \brief
1336 *
1337 *
1338 *****************************************************************************
1339 */
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)1340 void ihevce_cu_tree_init(
1341     cur_ctb_cu_tree_t *ps_cu_tree,
1342     cur_ctb_cu_tree_t *ps_cu_tree_root,
1343     WORD32 *pi4_nodes_created_in_cu_tree,
1344     WORD32 tree_depth,
1345     CU_POS_T e_grandparent_blk_pos,
1346     CU_POS_T e_parent_blk_pos,
1347     CU_POS_T e_cur_blk_pos)
1348 {
1349     WORD32 cu_pos_x = 0;
1350     WORD32 cu_pos_y = 0;
1351     WORD32 cu_size = 0;
1352 
1353     WORD32 children_nodes_required = 1;
1354     WORD32 node_validity = 0;
1355 
1356     switch(tree_depth)
1357     {
1358     case 0:
1359     {
1360         /* 64x64 block */
1361         cu_size = 64;
1362         cu_pos_x = 0;
1363         cu_pos_y = 0;
1364 
1365         break;
1366     }
1367     case 1:
1368     {
1369         /* 32x32 block */
1370         cu_size = 32;
1371 
1372         /* Explanation for logic below - */
1373         /* * pos_x and pos_y are in units of 8x8 CU's */
1374         /* * pos_x = 0 for TL and BL children */
1375         /* * pos_x = 4 for TR and BR children */
1376         /* * pos_y = 0 for TL and TR children */
1377         /* * pos_y = 4 for BL and BR children */
1378         cu_pos_x = (e_cur_blk_pos & 1) << 2;
1379         cu_pos_y = (e_cur_blk_pos & 2) << 1;
1380 
1381         break;
1382     }
1383     case 2:
1384     {
1385         /* 16x16 block */
1386         WORD32 cu_pos_x_parent;
1387         WORD32 cu_pos_y_parent;
1388 
1389         cu_size = 16;
1390 
1391         /* Explanation for logic below - */
1392         /* See similar explanation above */
1393         cu_pos_x_parent = (e_parent_blk_pos & 1) << 2;
1394         cu_pos_y_parent = (e_parent_blk_pos & 2) << 1;
1395         cu_pos_x = cu_pos_x_parent + ((e_cur_blk_pos & 1) << 1);
1396         cu_pos_y = cu_pos_y_parent + (e_cur_blk_pos & 2);
1397 
1398         break;
1399     }
1400     case 3:
1401     {
1402         /* 8x8 block */
1403         WORD32 cu_pos_x_grandparent;
1404         WORD32 cu_pos_y_grandparent;
1405 
1406         WORD32 cu_pos_x_parent;
1407         WORD32 cu_pos_y_parent;
1408 
1409         cu_size = 8;
1410 
1411         cu_pos_x_grandparent = (e_grandparent_blk_pos & 1) << 2;
1412         cu_pos_y_grandparent = (e_grandparent_blk_pos & 2) << 1;
1413         cu_pos_x_parent = cu_pos_x_grandparent + ((e_parent_blk_pos & 1) << 1);
1414         cu_pos_y_parent = cu_pos_y_grandparent + (e_parent_blk_pos & 2);
1415         cu_pos_x = cu_pos_x_parent + (e_cur_blk_pos & 1);
1416         cu_pos_y = cu_pos_y_parent + ((e_cur_blk_pos & 2) >> 1);
1417 
1418         children_nodes_required = 0;
1419 
1420         break;
1421     }
1422     }
1423 
1424     /* Fill the current cu_tree node */
1425     CU_TREE_NODE_FILL(ps_cu_tree, node_validity, cu_pos_x, cu_pos_y, cu_size, 1);
1426 
1427     if(children_nodes_required)
1428     {
1429         tree_depth++;
1430 
1431         (*pi4_nodes_created_in_cu_tree) += ihevce_create_cuNode_children(
1432             ps_cu_tree_root, ps_cu_tree, (*pi4_nodes_created_in_cu_tree));
1433 
1434         ihevce_cu_tree_init(
1435             ps_cu_tree->ps_child_node_tl,
1436             ps_cu_tree_root,
1437             pi4_nodes_created_in_cu_tree,
1438             tree_depth,
1439             e_parent_blk_pos,
1440             e_cur_blk_pos,
1441             POS_TL);
1442 
1443         ihevce_cu_tree_init(
1444             ps_cu_tree->ps_child_node_tr,
1445             ps_cu_tree_root,
1446             pi4_nodes_created_in_cu_tree,
1447             tree_depth,
1448             e_parent_blk_pos,
1449             e_cur_blk_pos,
1450             POS_TR);
1451 
1452         ihevce_cu_tree_init(
1453             ps_cu_tree->ps_child_node_bl,
1454             ps_cu_tree_root,
1455             pi4_nodes_created_in_cu_tree,
1456             tree_depth,
1457             e_parent_blk_pos,
1458             e_cur_blk_pos,
1459             POS_BL);
1460 
1461         ihevce_cu_tree_init(
1462             ps_cu_tree->ps_child_node_br,
1463             ps_cu_tree_root,
1464             pi4_nodes_created_in_cu_tree,
1465             tree_depth,
1466             e_parent_blk_pos,
1467             e_cur_blk_pos,
1468             POS_BR);
1469     }
1470     else
1471     {
1472         NULLIFY_THE_CHILDREN_NODES(ps_cu_tree);
1473     }
1474 }
1475