• 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_cabac_cu_pu.c
23 *
24 * @brief
25 *  This file contains function definitions for cabac entropy coding of CU
26 *  and PU structures in HEVC syntax
27 *
28 * @author
29 *  ittiam
30 *
31 * @List of Functions
32 *  ihevce_cabac_encode_intra_pu()
33 *  ihevce_cabac_encode_skip_flag()
34 *  ihevce_cabac_encode_part_mode()
35 *  ihevce_cabac_encode_merge_idx()
36 *  ihevce_cabac_encode_inter_pred_idc()
37 *  ihevce_cabac_encode_refidx()
38 *  ihevce_cabac_encode_mvd()
39 *  ihevce_cabac_encode_inter_pu()
40 *  ihevce_cabac_encode_coding_unit()
41 *  ihevce_cabac_encode_sao()
42 *  ihevce_encode_coding_quadtree()
43 *  ihevce_encode_slice_data()
44 *
45 ******************************************************************************
46 */
47 
48 /*****************************************************************************/
49 /* File Includes                                                             */
50 /*****************************************************************************/
51 /* System include files */
52 #include <stdio.h>
53 #include <string.h>
54 #include <stdlib.h>
55 #include <assert.h>
56 #include <stdarg.h>
57 #include <math.h>
58 
59 /* User include files */
60 #include "ihevc_typedefs.h"
61 #include "itt_video_api.h"
62 #include "ihevce_api.h"
63 
64 #include "rc_cntrl_param.h"
65 #include "rc_frame_info_collector.h"
66 #include "rc_look_ahead_params.h"
67 
68 #include "ihevc_defs.h"
69 #include "ihevc_structs.h"
70 #include "ihevc_platform_macros.h"
71 #include "ihevc_deblk.h"
72 #include "ihevc_itrans_recon.h"
73 #include "ihevc_chroma_itrans_recon.h"
74 #include "ihevc_chroma_intra_pred.h"
75 #include "ihevc_intra_pred.h"
76 #include "ihevc_inter_pred.h"
77 #include "ihevc_mem_fns.h"
78 #include "ihevc_padding.h"
79 #include "ihevc_weighted_pred.h"
80 #include "ihevc_sao.h"
81 #include "ihevc_resi_trans.h"
82 #include "ihevc_quant_iquant_ssd.h"
83 #include "ihevc_cabac_tables.h"
84 
85 #include "ihevce_defs.h"
86 #include "ihevce_lap_enc_structs.h"
87 #include "ihevce_multi_thrd_structs.h"
88 #include "ihevce_me_common_defs.h"
89 #include "ihevce_had_satd.h"
90 #include "ihevce_error_codes.h"
91 #include "ihevce_bitstream.h"
92 #include "ihevce_cabac.h"
93 #include "ihevce_rdoq_macros.h"
94 #include "ihevce_function_selector.h"
95 #include "ihevce_enc_structs.h"
96 #include "ihevce_entropy_structs.h"
97 #include "ihevce_cmn_utils_instr_set_router.h"
98 #include "ihevce_enc_loop_structs.h"
99 #include "ihevce_trace.h"
100 
101 #define TEST_CABAC_BITESTIMATE 0
102 
103 // clang-format off
104 /**
105 ******************************************************************************
106 * @brief  LUT for binarization of inter partmode bins for cu size > mincu size
107 *  as per Table9-34 of spec
108 *
109 * @input   : amp_enable flag  and part_mode
110 *
111 * @output  : packed bins and count of bins as per following bit packed format
112 *            Bins      : (bits3-bit0) first bin starts from bit3
113 *            Bins Count: (bits7-bit4)
114 *            0xFF in the following table is invalid entry
115 *
116 * @remarks See Table 9-34 of HEVC spec for Binarization of part_mode
117 *******************************************************************************
118 */
119 #define INVALID 0xFF
120 const UWORD8 gu1_hevce_inter_part_mode_bins[2][8] = {
121 
122     /*  cusize > minCUsize, no amp       */
123     { 0x18, 0x24, 0x20, INVALID, INVALID, INVALID, INVALID, INVALID, },
124 
125     /*  cusize > minCUsize, amp enable, minCUsize > 8 (irrelevant)  */
126     { 0x18, 0x36, 0x32, INVALID, 0x44, 0x45, 0x40, 0x41, },
127 
128 };
129 
130 /**
131 ******************************************************************************
132 * @brief  LUT for binarization of inter partmode bins for cu size = mincu size
133 *  as per Table9-34 of spec
134 *
135 * @input   : mincusize==8 flag  and part_mode
136 *
137 * @output  : packed bins and count of bins as per following bit packed format
138 *            Bins      : (bits3-bit0) first bin starts from bit3
139 *            Bins Count: (bits7-bit4)
140 *            0xFF in the following table is invalid entry
141 *
142 * @remarks See Table 9-34 of HEVC spec for Binarization of part_mode
143 *******************************************************************************
144 */
145 const UWORD8 gu1_hevce_inter_part_mode_bins_mincu[2][4] = {
146 
147     /*  cusize == minCUsize,  minCUsize > 8      */
148     { 0x18, 0x24, 0x32, 0x30, },
149 
150     /* cusize == minCUsize,   minCUsize = 8       */
151     { 0x18, 0x24, 0x20, INVALID },
152 
153 };
154 // clang-format on
155 
156 /*****************************************************************************/
157 /* Function Definitions                                                      */
158 /*****************************************************************************/
159 /**
160 ******************************************************************************
161 *
162 *  @brief Entropy encoding of luma and chroma intra pred modes
163 *
164 *  @par   Description
165 *  Encodes prev_intra_ped_mode, mpm_idx and rem_intra_pred_mode for each
166 *  luma partition and chrom intra pred of cu as per section:7.3.9.1
167 *
168 *  Binzarization, context model as per Table 9-32 for luma
169 *  Binzarization, context model as per Table 9-35, section 9.3.2.8 for chroma
170 *
171 *  @param[inout]   ps_entropy_ctxt
172 *  pointer to entropy context (handle)
173 *
174 *  @param[in]   part_mode
175 *  indicates whether the mode is 2Nx2N or NxN luma parition
176 *
177 *  @param[in]   ps_enc_cu
178 *  pointer to the intra cu whose luma and chroma pred modes are encoded
179 *
180 *  @return      success or failure error code
181 *
182 ******************************************************************************
183 */
ihevce_cabac_encode_intra_pu(entropy_context_t * ps_entropy_ctxt,WORD32 part_mode,cu_enc_loop_out_t * ps_enc_cu)184 WORD32 ihevce_cabac_encode_intra_pu(
185     entropy_context_t *ps_entropy_ctxt, WORD32 part_mode, cu_enc_loop_out_t *ps_enc_cu)
186 {
187     WORD32 error = IHEVCE_SUCCESS;
188     cab_ctxt_t *ps_cabac = &ps_entropy_ctxt->s_cabac_ctxt;
189     intra_prev_rem_flags_t *ps_prev_mpm_rem_flags = &ps_enc_cu->as_prev_rem[0];
190     WORD32 i, num_parts;
191 
192     /* intra can only be 2Nx2N partition or a NxN partition     */
193     num_parts = (PART_NxN == part_mode) ? 4 : 1;
194 
195     if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
196     {
197         WORD32 cu_size = ps_enc_cu->b4_cu_size << 3;
198 
199         /*PIC_INFO : INTRA CU in frame*/
200         ps_entropy_ctxt->ps_pic_level_info->i8_total_intra_cu++;
201         ps_entropy_ctxt->ps_pic_level_info->i8_total_pu += num_parts;
202         ps_entropy_ctxt->ps_pic_level_info->i8_total_intra_pu += num_parts;
203         /*PIC_INFO : Total CU in frame based on cu size */
204 
205         if(PART_2Nx2N == part_mode)
206         {
207             // clang-format off
208             if(cu_size == 64)
209                 ps_entropy_ctxt->ps_pic_level_info->i8_total_2nx2n_intra_pu[3]++;
210             else
211                 ps_entropy_ctxt->ps_pic_level_info->i8_total_2nx2n_intra_pu[cu_size >> 4]++;
212             // clang-format on
213         }
214         else if(PART_NxN == part_mode)
215         {
216             ps_entropy_ctxt->ps_pic_level_info->i8_total_nxn_intra_pu++;
217         }
218     }
219     /* encode prev intra pred mode flags  : context model based */
220     for(i = 0; i < num_parts; i++)
221     {
222         WORD32 prev_intra_pred_flag = ps_prev_mpm_rem_flags[i].b1_prev_intra_luma_pred_flag;
223         error |=
224             ihevce_cabac_encode_bin(ps_cabac, prev_intra_pred_flag, IHEVC_CAB_INTRA_LUMA_PRED_FLAG);
225         AEV_TRACE("prev_intra_pred_luma_flag", prev_intra_pred_flag, ps_cabac->u4_range);
226     }
227 
228     /* encode mpm_idx or rem_intra_pred_mode bypass bins */
229     for(i = 0; i < num_parts; i++)
230     {
231         if(ps_prev_mpm_rem_flags[i].b1_prev_intra_luma_pred_flag)
232         {
233             WORD32 mpm_idx = ps_prev_mpm_rem_flags[i].b2_mpm_idx;
234 
235             /* tunary bins for cmax = 2 */
236             WORD32 num_bins = mpm_idx ? 2 : 1;
237             UWORD32 bins = mpm_idx ? ((1 << 1) | (mpm_idx - 1)) : 0;
238 
239             ASSERT(mpm_idx < 3);
240 
241             error |= ihevce_cabac_encode_bypass_bins(ps_cabac, bins, num_bins);
242             AEV_TRACE("mpm_idx", mpm_idx, ps_cabac->u4_range);
243         }
244         else
245         {
246             WORD32 rem_intra_pred_mode = ps_prev_mpm_rem_flags[i].b5_rem_intra_pred_mode;
247             error |= ihevce_cabac_encode_bypass_bins(ps_cabac, rem_intra_pred_mode, 5);
248             AEV_TRACE("rem_intra_luma_pred_mode", rem_intra_pred_mode, ps_cabac->u4_range);
249         }
250     }
251 
252     /************************************************************************/
253     /* encode the chroma intra prediction mode as per Table 9-35            */
254     /* First bin is context model based prefix : 0 if chroma_mode==4 else 1 */
255     /* If chroma pred mode is not 4, suffix bins are coded as bypass bins   */
256     /************************************************************************/
257     {
258         WORD32 chroma_pred_mode = ps_enc_cu->b3_chroma_intra_pred_mode;
259         WORD32 prefix_bin = (chroma_pred_mode == 4) ? 0 : 1;
260 
261         /* encode prefix bin */
262         error |= ihevce_cabac_encode_bin(ps_cabac, prefix_bin, IHEVC_CAB_CHROMA_PRED_MODE);
263 
264         /* encode suffix bins */
265         if(prefix_bin)
266         {
267             error |= ihevce_cabac_encode_bypass_bins(ps_cabac, chroma_pred_mode, 2);
268         }
269         AEV_TRACE("intra_chroma_pred_mode", chroma_pred_mode, ps_cabac->u4_range);
270     }
271 
272     return (error);
273 }
274 
275 /**
276 ******************************************************************************
277 *
278 *  @brief Entropy encoding of skip flag (Coding Unit syntax)
279 *
280 *  @par   Description
281 *  context increment for skip flag is derived based on left and top skip flag
282 *  as per section 9.3.3.1.1, Table 9-38
283 *
284 *  @param[inout]   ps_entropy_ctxt
285 *  pointer to entropy context (handle)
286 *
287 *  @param[in]   ps_enc_cu
288 *  pointer to inter cu whose skip flag is to be coded
289 *
290 *  @param[in]   top_avail
291 *  top availabilty flag for current cu (boolean)
292 *
293 *  @param[in]   left_avail
294 *  left availabilty flag for current cu (boolean)
295 *
296 *  @return      success or failure error code
297 *
298 ******************************************************************************
299 */
ihevce_cabac_encode_skip_flag(entropy_context_t * ps_entropy_ctxt,cu_enc_loop_out_t * ps_enc_cu,WORD32 top_avail,WORD32 left_avail)300 WORD32 ihevce_cabac_encode_skip_flag(
301     entropy_context_t *ps_entropy_ctxt,
302     cu_enc_loop_out_t *ps_enc_cu,
303     WORD32 top_avail,
304     WORD32 left_avail)
305 
306 {
307     WORD32 error = IHEVCE_SUCCESS;
308     WORD32 skip_flag = ps_enc_cu->b1_skip_flag;
309     cab_ctxt_t *ps_cabac = &ps_entropy_ctxt->s_cabac_ctxt;
310 
311     /* CU top left co-ordinates w.r.t ctb */
312     WORD32 cu_x0 = ps_enc_cu->b3_cu_pos_x << 3;
313     WORD32 cu_y0 = ps_enc_cu->b3_cu_pos_y << 3;
314 
315     /* CU size in pels */
316     WORD32 cu_size = ps_enc_cu->b4_cu_size << 3;
317 
318     /* CU x co-ordinate w.r.t frame start           */
319     WORD32 ctb_x0_frm = (ps_entropy_ctxt->i4_ctb_x << ps_entropy_ctxt->i1_log2_ctb_size);
320 
321     WORD32 cu_x0_frm = cu_x0 + ctb_x0_frm;
322 
323     /* bit postion from where top skip flag is extracted; 1bit per 8 pel   */
324     WORD32 x_pos = ((cu_x0_frm >> 3) & 0x7);
325 
326     /* bit postion from where left skip flag is extracted; 1bit per 8 pel  */
327     WORD32 y_pos = ((cu_y0 >> 3) & 0x7);
328 
329     /* top and left skip flags computed based on nbr availability */
330     UWORD8 *pu1_top_skip_flags = ps_entropy_ctxt->pu1_skip_cu_top + (cu_x0_frm >> 6);
331     UWORD32 u4_skip_left_flags = ps_entropy_ctxt->u4_skip_cu_left;
332 
333     /* context incerements based on top and left neigbours */
334     UWORD32 ctxt_inc = 0;
335 
336     if(top_avail)
337     {
338         WORD32 val;
339         EXTRACT_BIT(val, pu1_top_skip_flags[0], x_pos);
340         ctxt_inc += val;
341     }
342 
343     if(left_avail)
344     {
345         WORD32 val;
346         EXTRACT_BIT(val, u4_skip_left_flags, y_pos);
347         ctxt_inc += val;
348     }
349 
350     if(CABAC_MODE_COMPUTE_BITS == ps_cabac->e_cabac_op_mode)
351     {
352         //ASSERT(ctxt_inc == ps_entropy_ctxt->i4_num_nbr_skip_cus);
353         ctxt_inc = ps_entropy_ctxt->i4_num_nbr_skip_cus;
354         ASSERT(ctxt_inc < 3);
355         ASSERT((WORD32)ctxt_inc <= (top_avail + left_avail));
356     }
357 
358     /* encode the skip flag */
359     error |= ihevce_cabac_encode_bin(ps_cabac, skip_flag, (IHEVC_CAB_SKIP_FLAG + ctxt_inc));
360 
361     AEV_TRACE("cu_skip_flag", skip_flag, ps_cabac->u4_range);
362 
363     if(CABAC_MODE_ENCODE_BITS == ps_cabac->e_cabac_op_mode)
364     {
365         /* update top and left skip flags only in encode mode */
366         if(skip_flag)
367         {
368             SET_BITS(pu1_top_skip_flags[0], x_pos, (cu_size >> 3));
369             SET_BITS(u4_skip_left_flags, y_pos, (cu_size >> 3));
370         }
371         else
372         {
373             CLEAR_BITS(pu1_top_skip_flags[0], x_pos, (cu_size >> 3));
374             CLEAR_BITS(u4_skip_left_flags, y_pos, (cu_size >> 3));
375         }
376 
377         ps_entropy_ctxt->u4_skip_cu_left = u4_skip_left_flags;
378     }
379 
380     return (error);
381 }
382 
383 /**
384 ******************************************************************************
385 *
386 *  @brief Entropy encoding of partition mode (Coding Unit syntax)
387 *
388 *  @par   Description
389 *  Binarization process and context modelling of partition mode is done as per
390 *  section 9.3.2.6 (Table 9-34) and se
391 *
392 *  @param[inout]   ps_cabac
393 *  pointer to cabac encoding context (handle)
394 *
395 *  @param[in]   intra
396 *  boolean indicating if current cu is intra cu
397 *
398 *  @param[in]   is_mincu
399 *  boolean indicating if current cu size is equal to mincu
400 *
401 *  @param[in]   amp_enabled
402 *  flag to indicate if AMP(Assymetric motion partition) is enabled at sps level
403 *
404 *  @param[in]   cu_eq_8
405 *  boolean indicating if current cu size is equal to 8
406 *
407 *  @param[in]   part_mode
408 *  partition mode of current CU
409 *
410 *  @return      success or failure error code
411 *
412 ******************************************************************************
413 */
ihevce_cabac_encode_part_mode(cab_ctxt_t * ps_cabac,WORD32 intra,WORD32 is_mincu,WORD32 amp_enabled,WORD32 cu_eq_8,WORD32 part_mode)414 WORD32 ihevce_cabac_encode_part_mode(
415     cab_ctxt_t *ps_cabac,
416     WORD32 intra,
417     WORD32 is_mincu,
418     WORD32 amp_enabled,
419     WORD32 cu_eq_8,
420     WORD32 part_mode)
421 {
422     /* Binarization depends on intra/inter, is_mincu, amp flag, cbsize == 8 */
423     WORD32 bins;
424     WORD32 bin_count, i;
425     WORD32 error = IHEVCE_SUCCESS;
426 
427     (void)is_mincu;
428     (void)amp_enabled;
429     (void)cu_eq_8;
430     if(intra)
431     {
432         /* sanity checks for intra part mode */
433         ASSERT(is_mincu);
434         ASSERT((part_mode == SIZE_NxN) || (part_mode == SIZE_2Nx2N));
435 
436         bins = (part_mode == SIZE_2Nx2N) ? 1 : 0;
437         error |= ihevce_cabac_encode_bin(ps_cabac, bins, IHEVC_CAB_PART_MODE);
438     }
439     else
440     {
441         /* sanity checks for inter part mode....Too many but good to have  */
442         ASSERT((amp_enabled == 0) || (amp_enabled == 1));
443         ASSERT((is_mincu == 0) || (is_mincu == 1));
444         ASSERT((cu_eq_8 == 0) || (cu_eq_8 == 1));
445         ASSERT((part_mode <= SIZE_nRx2N) && (part_mode >= SIZE_2Nx2N));
446         if(!amp_enabled)
447             ASSERT(part_mode <= SIZE_NxN);
448         if(!is_mincu)
449             ASSERT(part_mode != SIZE_NxN);
450         if(is_mincu)
451             ASSERT(part_mode <= SIZE_NxN);
452         if(cu_eq_8)
453             ASSERT(part_mode < SIZE_NxN);
454         if(cu_eq_8)
455             ASSERT(is_mincu);
456 
457         /* look up table for bins and number of bins for inter pred mode    */
458         if(!is_mincu)
459         {
460             bins = gu1_hevce_inter_part_mode_bins[amp_enabled][part_mode];
461         }
462         else
463         {
464             bins = gu1_hevce_inter_part_mode_bins_mincu[cu_eq_8][part_mode];
465         }
466 
467         bin_count = (bins >> 4) & 0xF;
468 
469         /* Encode the context model based bins, max of 3 */
470         for(i = 0; i < MIN(bin_count, 3); i++)
471         {
472             //TODO: HM-8.0-dev uses 0 context increment for bin2 (i===2) when amp is enabled
473             WORD32 ctxt_inc = IHEVC_CAB_PART_MODE + i;
474             WORD32 bin = (bins >> (3 - i)) & 0x1;
475             error |= ihevce_cabac_encode_bin(ps_cabac, bin, ctxt_inc);
476         }
477 
478         /* Encode the last bin as bypass bin for amp partitions */
479         if(bin_count == 4)
480         {
481             error |= ihevce_cabac_encode_bypass_bin(ps_cabac, (bins & 0x1));
482         }
483     }
484     AEV_TRACE("part_mode", part_mode, ps_cabac->u4_range);
485     return (error);
486 }
487 
488 /**
489 ******************************************************************************
490 *
491 *  @brief Entropy encoding of merge_idx of inter prediction unit as per sec
492 *  as per sec 9.3.2 Table9-32. (tunary binarization)
493 *
494 *  @par   Description
495 *  trunacted unary binarization is done based on max merge candidates
496 *  First bin is context modelled bin and the rest are coded as bypass
497 *
498 *  @param[inout]   ps_cabac
499 *  pointer to cabac encoding context (handle)
500 *
501 *  @param[in]   merge_idx
502 *  merge idx of the pu to be encoded;
503 *
504 *  @param[in]   max_merge_cand
505 *  maximum merge candidates signalled in the slice header*
506 *
507 *  @return      success or failure error code
508 *
509 ******************************************************************************
510 */
ihevce_cabac_encode_merge_idx(cab_ctxt_t * ps_cabac,WORD32 merge_idx,WORD32 max_merge_cand)511 WORD32 ihevce_cabac_encode_merge_idx(cab_ctxt_t *ps_cabac, WORD32 merge_idx, WORD32 max_merge_cand)
512 {
513     WORD32 ret = IHEVCE_SUCCESS;
514     WORD32 ctxt_inc = IHEVC_CAB_MERGE_IDX_EXT;
515 
516     /* sanity checks */
517     ASSERT((merge_idx >= 0) && (merge_idx < max_merge_cand));
518 
519     /* encode the merge idx only if required */
520     if(max_merge_cand > 1)
521     {
522         /* encode the context modelled first bin */
523         ret |= ihevce_cabac_encode_bin(ps_cabac, (merge_idx > 0), ctxt_inc);
524 
525         /* encode the remaining bins as bypass tunary */
526         if((max_merge_cand > 2) && (merge_idx > 0))
527         {
528             ret |=
529                 ihevce_cabac_encode_tunary_bypass(ps_cabac, (merge_idx - 1), (max_merge_cand - 2));
530         }
531 
532         AEV_TRACE("merge_idx", merge_idx, ps_cabac->u4_range);
533     }
534 
535     return (ret);
536 }
537 
538 /**
539 ******************************************************************************
540 *
541 *  @brief Entropy encoding of inter_pred_idc for prediction unit of B slice as
542 *   per sec 9.3.2.9 Table9-36
543 *
544 *  @par   Description
545 *  Max of two context modelled bins coded for pu size > 8x4 or 4x8
546 *  one context modelled bin coded for pu size = 8x4 or 4x8; bipred not allowed
547 *  for 8x4 or 4x8.
548 *
549 *  @param[inout]   ps_cabac
550 *  pointer to cabac encoding context (handle)
551 *
552 *  @param[in]   inter_pred_idc
553 *  inter pred mode  to be encoded; shall be PRED_L0 or PRED_L1 or PRED_BI
554 *
555 *  @param[in]   cu_depth
556 *  depth of the cu to which current pu belongs (required for context increment)
557 *
558 *  @param[in]   pu_w_plus_pu_h
559 *  required to check if pu_w_plus_pu_h is 12 (8x4PU or 4x8PU)
560 *
561 *  @return      success or failure error code
562 *
563 ******************************************************************************
564 */
ihevce_cabac_encode_inter_pred_idc(cab_ctxt_t * ps_cabac,WORD32 inter_pred_idc,WORD32 cu_depth,WORD32 pu_w_plus_pu_h)565 WORD32 ihevce_cabac_encode_inter_pred_idc(
566     cab_ctxt_t *ps_cabac, WORD32 inter_pred_idc, WORD32 cu_depth, WORD32 pu_w_plus_pu_h)
567 {
568     WORD32 ret = IHEVCE_SUCCESS;
569     WORD32 ctxt_inc;
570 
571     ASSERT(inter_pred_idc <= PRED_BI);
572 
573     /* check if PU is 8x4/4x8  */
574     if(pu_w_plus_pu_h == 12)
575     {
576         /* case of 8x4 or 4x8 where bi_pred is not allowed */
577         ASSERT((inter_pred_idc == PRED_L0) || (inter_pred_idc == PRED_L1));
578 
579         ctxt_inc = IHEVC_CAB_INTER_PRED_IDC + 4;
580         ret |= ihevce_cabac_encode_bin(ps_cabac, inter_pred_idc, ctxt_inc);
581     }
582     else
583     {
584         /* larger PUs can be encoded as bi_pred/l0/l1 inter_pred_idc */
585         WORD32 is_bipred = (inter_pred_idc == PRED_BI);
586 
587         ctxt_inc = IHEVC_CAB_INTER_PRED_IDC + cu_depth;
588         ret |= ihevce_cabac_encode_bin(ps_cabac, is_bipred, ctxt_inc);
589 
590         if(!is_bipred)
591         {
592             ctxt_inc = IHEVC_CAB_INTER_PRED_IDC + 4;
593             ret |= ihevce_cabac_encode_bin(ps_cabac, inter_pred_idc, ctxt_inc);
594         }
595     }
596 
597     AEV_TRACE("inter_pred_idc", inter_pred_idc, ps_cabac->u4_range);
598 
599     return (ret);
600 }
601 
602 /**
603 ******************************************************************************
604 *
605 *  @brief Entropy encoding of refidx for prediction unit; Binarization done as
606 *   tunary code as per sec 9.3.2 Table9-32
607 *
608 *  @par   Description
609 *  First two bins are context modelled while the rest are coded as bypass
610 *
611 *  @param[inout]   ps_cabac
612 *  pointer to cabac encoding context (handle)
613 *
614 *  @param[in]   ref_idx
615 *  ref idx of partition unit
616 *
617 *  @param[in]   active_refs
618 *  max number of active references signalled in slice header
619 *
620 *  @return      success or failure error code
621 *
622 ******************************************************************************
623 */
ihevce_cabac_encode_refidx(cab_ctxt_t * ps_cabac,WORD32 ref_idx,WORD32 active_refs)624 WORD32 ihevce_cabac_encode_refidx(cab_ctxt_t *ps_cabac, WORD32 ref_idx, WORD32 active_refs)
625 {
626     /************************************************************/
627     /* encode ref_idx as tunary binarization Table 9-32         */
628     /* First 2 bin use context model and rest coded as  bypass  */
629     /************************************************************/
630     WORD32 ret = IHEVCE_SUCCESS;
631     WORD32 ctxt_inc = IHEVC_CAB_INTER_REF_IDX;
632 
633     /* sanity checks */
634     ASSERT((ref_idx >= 0) && (ref_idx < active_refs));
635 
636     /* encode the ref idx only if required */
637     if(active_refs > 1)
638     {
639         /* encode the context modelled first bin */
640         ret |= ihevce_cabac_encode_bin(ps_cabac, (ref_idx > 0), ctxt_inc);
641 
642         if((active_refs > 2) && (ref_idx > 0))
643         {
644             /* encode the context modelled second bin */
645             ctxt_inc++;
646             ret |= ihevce_cabac_encode_bin(ps_cabac, (ref_idx > 1), ctxt_inc);
647         }
648 
649         if((active_refs > 3) && (ref_idx > 1))
650         {
651             /* encode remaining bypass bins */
652             ret |= ihevce_cabac_encode_tunary_bypass(ps_cabac, (ref_idx - 2), (active_refs - 3));
653         }
654 
655         AEV_TRACE("ref_idx", ref_idx, ps_cabac->u4_range);
656     }
657 
658     return (ret);
659 }
660 
661 /**
662 ******************************************************************************
663 *
664 *  @brief Entropy encoding of mvd for inter pu as per section 7.3.10.2
665 *
666 *  @par   Description
667 *  syntax coded as per section 7.3.10.2 for mvdx and mvdy
668 *  context modeling of abs_mvd_greater0 abs_mvd_greater1 done as per Table 9-32
669 *  binazrization of abs_mvd_minus2 is done as done as EG1 code section 9.3.2.4
670 *
671 *  @param[inout]   ps_cabac
672 *  pointer to cabac encoding context (handle)
673 *
674 *  @param[in]   ps_mvd
675 *  pointer to mvd struct containing mvdx and mvdy
676 *
677 *  @return      success or failure error code
678 *
679 ******************************************************************************
680 */
ihevce_cabac_encode_mvd(cab_ctxt_t * ps_cabac,mv_t * ps_mvd)681 WORD32 ihevce_cabac_encode_mvd(cab_ctxt_t *ps_cabac, mv_t *ps_mvd)
682 {
683     WORD32 ret = IHEVCE_SUCCESS;
684     WORD32 mvd_x = ps_mvd->i2_mvx;
685     WORD32 mvd_y = ps_mvd->i2_mvy;
686 
687     WORD32 abs_mvd_x = ABS(mvd_x);
688     WORD32 abs_mvd_y = ABS(mvd_y);
689 
690     WORD32 abs_mvd_x_gt0 = abs_mvd_x > 0;
691     WORD32 abs_mvd_y_gt0 = abs_mvd_y > 0;
692 
693     WORD32 abs_mvd_x_gt1 = abs_mvd_x > 1;
694     WORD32 abs_mvd_y_gt1 = abs_mvd_y > 1;
695 
696     WORD32 ctxt_inc = IHEVC_CAB_MVD_GRT0;
697 
698     /* encode absmvd_x > 0 */
699     ret |= ihevce_cabac_encode_bin(ps_cabac, abs_mvd_x_gt0, ctxt_inc);
700     AEV_TRACE("abs_mvd_greater0_flag[0]", abs_mvd_x_gt0, ps_cabac->u4_range);
701 
702     /* encode absmvd_y > 0 */
703     ret |= ihevce_cabac_encode_bin(ps_cabac, abs_mvd_y_gt0, ctxt_inc);
704     AEV_TRACE("abs_mvd_greater0_flag[1]", abs_mvd_y_gt0, ps_cabac->u4_range);
705 
706     ctxt_inc = IHEVC_CAB_MVD_GRT1;
707 
708     /* encode abs_mvd_x > 1 iff (abs_mvd_x > 0) */
709     if(abs_mvd_x_gt0)
710     {
711         ret |= ihevce_cabac_encode_bin(ps_cabac, abs_mvd_x_gt1, ctxt_inc);
712         AEV_TRACE("abs_mvd_greater1_flag[0]", abs_mvd_x_gt1, ps_cabac->u4_range);
713     }
714 
715     /* encode abs_mvd_y > 1 iff (abs_mvd_y > 0) */
716     if(abs_mvd_y_gt0)
717     {
718         ret |= ihevce_cabac_encode_bin(ps_cabac, abs_mvd_y_gt1, ctxt_inc);
719         AEV_TRACE("abs_mvd_greater1_flag[1]", abs_mvd_y_gt1, ps_cabac->u4_range);
720     }
721 
722     /* encode abs_mvd_x - 2 iff (abs_mvd_x > 1) */
723     if(abs_mvd_x_gt1)
724     {
725         ret |= ihevce_cabac_encode_egk(ps_cabac, (abs_mvd_x - 2), 1);
726         AEV_TRACE("abs_mvd_minus2[0]", (abs_mvd_x - 2), ps_cabac->u4_range);
727     }
728 
729     /* encode mvd_x sign iff (abs_mvd_x > 0) */
730     if(abs_mvd_x_gt0)
731     {
732         ret |= ihevce_cabac_encode_bypass_bin(ps_cabac, (mvd_x < 0));
733         AEV_TRACE("mvd_sign_flag[0]", (mvd_x < 0), ps_cabac->u4_range);
734     }
735 
736     /* encode abs_mvd_y - 2 iff (abs_mvd_y > 1) */
737     if(abs_mvd_y_gt1)
738     {
739         ret |= ihevce_cabac_encode_egk(ps_cabac, (abs_mvd_y - 2), 1);
740         AEV_TRACE("abs_mvd_minus2[1]", (abs_mvd_y - 2), ps_cabac->u4_range);
741     }
742 
743     /* encode mvd_y sign iff (abs_mvd_y > 0) */
744     if(abs_mvd_y_gt0)
745     {
746         ret |= ihevce_cabac_encode_bypass_bin(ps_cabac, (mvd_y < 0));
747         AEV_TRACE("mvd_sign_flag[1]", (mvd_y < 0), ps_cabac->u4_range);
748     }
749 
750     return ret;
751 }
752 
753 /**
754 ******************************************************************************
755 *
756 *  @brief Entropy encoding of all syntax elements of inter PUs in a CU
757 *
758 *  @par   Description
759 *  syntax coded as per section 7.3.10.1 for inter prediction unit
760 *
761 *  @param[inout]   ps_entropy_ctxt
762 *  pointer to entropy context (handle)
763 *
764 *  @param[in]   ps_enc_cu
765 *  pointer to current cu whose inter prediction units are to be encoded
766 *
767 *  @param[in]   cu_depth
768 *  depth of the the current cu in coding tree
769 *
770 *  @return      success or failure error code
771 *
772 ******************************************************************************
773 */
ihevce_cabac_encode_inter_pu(entropy_context_t * ps_entropy_ctxt,cu_enc_loop_out_t * ps_enc_cu,WORD32 cu_depth)774 WORD32 ihevce_cabac_encode_inter_pu(
775     entropy_context_t *ps_entropy_ctxt, cu_enc_loop_out_t *ps_enc_cu, WORD32 cu_depth)
776 {
777     WORD32 ret = IHEVCE_SUCCESS;
778 
779     slice_header_t *ps_slice_hdr = ps_entropy_ctxt->ps_slice_hdr;
780     cab_ctxt_t *ps_cabac = &ps_entropy_ctxt->s_cabac_ctxt;
781     pu_t *ps_pu = ps_enc_cu->ps_pu;
782 
783     WORD32 merge_idx = ps_pu->b3_merge_idx;
784     WORD32 max_merge_cand = ps_slice_hdr->i1_max_num_merge_cand;
785     WORD32 ctxt_inc;
786 
787     if(ps_enc_cu->b1_skip_flag)
788     {
789         WORD32 cu_size = ps_enc_cu->b4_cu_size << 3;
790         /*PIC_INFO : SKIP CU in frame*/
791         if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
792         {
793             ps_entropy_ctxt->ps_pic_level_info->i8_total_skip_cu++;
794             ps_entropy_ctxt->ps_pic_level_info->i8_total_pu++;
795             if(cu_size == 64)
796                 ps_entropy_ctxt->ps_pic_level_info->i8_total_2nx2n_inter_pu[3]++;
797             else
798                 ps_entropy_ctxt->ps_pic_level_info->i8_total_2nx2n_inter_pu[cu_size >> 4]++;
799         }
800         /* encode the merge idx for skip cu and return */
801         ret |= ihevce_cabac_encode_merge_idx(ps_cabac, merge_idx, max_merge_cand);
802     }
803     else
804     {
805         /* MODE_INTER */
806         WORD32 part_mode = ps_enc_cu->b3_part_mode;
807         WORD32 num_parts, i;
808 
809         num_parts = (part_mode == SIZE_2Nx2N) ? 1 : ((part_mode == SIZE_NxN) ? 4 : 2);
810 
811         /*PIC_INFO : INTER CU in frame*/
812         if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
813         {
814             WORD32 cu_size = ps_enc_cu->b4_cu_size << 3;
815             ps_entropy_ctxt->ps_pic_level_info->i8_total_inter_cu++;
816             ps_entropy_ctxt->ps_pic_level_info->i8_total_pu += num_parts;
817 
818             // clang-format off
819             if(PART_2Nx2N == part_mode)
820             {
821                 if(cu_size == 64)
822                     ps_entropy_ctxt->ps_pic_level_info->i8_total_2nx2n_inter_pu[3]++;
823                 else
824                     ps_entropy_ctxt->ps_pic_level_info->i8_total_2nx2n_inter_pu[cu_size >> 4]++;
825             }
826             else if((PART_2NxN == part_mode) || (PART_Nx2N == part_mode))
827             {
828                 if(cu_size == 64)
829                     ps_entropy_ctxt->ps_pic_level_info->i8_total_smp_inter_pu[3]++;
830                 else
831                     ps_entropy_ctxt->ps_pic_level_info->i8_total_smp_inter_pu[cu_size >> 4]++;
832             }
833             else if((PART_2NxnU == part_mode) || (PART_2NxnD == part_mode) ||
834                     (PART_nLx2N == part_mode) || (PART_nRx2N == part_mode))
835             {
836                 ps_entropy_ctxt->ps_pic_level_info->i8_total_amp_inter_pu[cu_size >> 5]++;
837             }
838             else
839             {
840                 ps_entropy_ctxt->ps_pic_level_info->i8_total_nxn_inter_pu[cu_size >> 5]++;
841             }
842             // clang-format on
843         }
844 
845         /* encode each pu partition */
846         for(i = 0; i < num_parts; i++)
847         {
848             /* encode the merge flag context modelled bin */
849             WORD32 merge_flag;
850             UWORD32 u4_bits_estimated_merge_flag = 0;
851             ps_pu = ps_enc_cu->ps_pu + i;
852 
853             /* encode the merge flag context modelled bin */
854             merge_flag = ps_pu->b1_merge_flag;
855             u4_bits_estimated_merge_flag = ps_cabac->u4_bits_estimated_q12;
856             ctxt_inc = IHEVC_CAB_MERGE_FLAG_EXT;
857             ret |= ihevce_cabac_encode_bin(ps_cabac, merge_flag, ctxt_inc);
858 
859             if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
860             {
861                 // clang-format off
862                 /*PIC INFO : Populate merge flag */
863                 ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_merge_flag =
864                     (ps_cabac->u4_bits_estimated_q12 -
865                         u4_bits_estimated_merge_flag);
866                 // clang-format on
867             }
868             AEV_TRACE("merge_flag", merge_flag, ps_cabac->u4_range);
869 
870             if(merge_flag)
871             {
872                 merge_idx = ps_pu->b3_merge_idx;
873                 if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
874                     ps_entropy_ctxt->ps_pic_level_info->i8_total_merge_pu++;
875                 /* encode the merge idx for the pu */
876                 ret |= ihevce_cabac_encode_merge_idx(ps_cabac, merge_idx, max_merge_cand);
877             }
878             else
879             {
880                 /* encode the inter_pred_idc, ref_idx and mvd */
881                 WORD32 inter_pred_idc = ps_pu->b2_pred_mode;
882                 WORD32 ref_l0_active = ps_slice_hdr->i1_num_ref_idx_l0_active;
883                 WORD32 ref_l1_active = ps_slice_hdr->i1_num_ref_idx_l1_active;
884 
885                 /*PIC_INFO : L0 L1 BI ro r1.. in frame*/
886                 if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
887                 {
888                     ps_entropy_ctxt->ps_pic_level_info->i8_total_non_skipped_inter_pu++;
889                     // clang-format off
890                     if(inter_pred_idc == PRED_L0)
891                     {
892                         ps_entropy_ctxt->ps_pic_level_info->i8_total_L0_mode++;
893                         ps_entropy_ctxt->ps_pic_level_info->i8_total_L0_ref_idx[ps_pu->mv.i1_l0_ref_idx]++;
894                     }
895                     else if(inter_pred_idc == PRED_L1)
896                     {
897                         ps_entropy_ctxt->ps_pic_level_info->i8_total_L1_mode++;
898                         ps_entropy_ctxt->ps_pic_level_info->i8_total_L1_ref_idx[ps_pu->mv.i1_l1_ref_idx]++;
899                     }
900                     else if(inter_pred_idc == PRED_BI)
901                     {
902                         ps_entropy_ctxt->ps_pic_level_info->i8_total_BI_mode++;
903                         if(inter_pred_idc != PRED_L1)
904                             ps_entropy_ctxt->ps_pic_level_info->i8_total_L0_ref_idx[ps_pu->mv.i1_l0_ref_idx]++;
905                         if(inter_pred_idc != PRED_L0)
906                             ps_entropy_ctxt->ps_pic_level_info->i8_total_L1_ref_idx[ps_pu->mv.i1_l1_ref_idx]++;
907                     }
908                     // clang-format on
909                 }
910                 if(ps_slice_hdr->i1_slice_type == BSLICE)
911                 {
912                     /* Encode inter_pred_idc as per sec 9.3.2.9 Table9-36 */
913                     WORD32 pu_w_plus_pu_h;
914                     WORD32 inter_pred_idc = ps_pu->b2_pred_mode;
915 
916                     /* required to check if w+h==12 case */
917                     pu_w_plus_pu_h = ((ps_pu->b4_wd + 1) << 2) + ((ps_pu->b4_ht + 1) << 2);
918 
919                     ret |= ihevce_cabac_encode_inter_pred_idc(
920                         ps_cabac, inter_pred_idc, cu_depth, pu_w_plus_pu_h);
921                 }
922                 else
923                 {
924                     ASSERT(inter_pred_idc == 0);
925                 }
926 
927                 /* Decode ref idx and mvd  for L0 (PRED_L0 or PRED_BI) */
928                 if(inter_pred_idc != PRED_L1)
929                 {
930                     UWORD32 u4_bits_estimated_prev_mvd_ref_id;
931                     /* encode L0 ref_idx  */
932                     WORD32 ref_idx_l0 = ps_pu->mv.i1_l0_ref_idx;
933 
934                     /*PIC INFO : Populate Ref Indx L0 Bits*/
935                     u4_bits_estimated_prev_mvd_ref_id = ps_cabac->u4_bits_estimated_q12;
936                     ret |= ihevce_cabac_encode_refidx(ps_cabac, ref_idx_l0, ref_l0_active);
937 
938                     if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
939                     {
940                         // clang-format off
941                         ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_ref_id +=
942                             (ps_cabac->u4_bits_estimated_q12 -
943                                 u4_bits_estimated_prev_mvd_ref_id);
944                         // clang-format on
945                     }
946                     /* Encode the mvd for L0 */
947                     /*PIC INFO : Populate MVD Bits*/
948                     u4_bits_estimated_prev_mvd_ref_id = ps_cabac->u4_bits_estimated_q12;
949 
950                     ret |= ihevce_cabac_encode_mvd(ps_cabac, &ps_pu->mv.s_l0_mv);
951 
952                     if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
953                     {  // clang-format off
954                         ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_mvd +=
955                             (ps_cabac->u4_bits_estimated_q12 -
956                                 u4_bits_estimated_prev_mvd_ref_id);
957                         // clang-format on
958                     }
959 
960                     /* Encode the mvp_l0_flag */
961                     ctxt_inc = IHEVC_CAB_MVP_L0L1;
962                     ret |= ihevce_cabac_encode_bin(ps_cabac, ps_pu->b1_l0_mvp_idx, ctxt_inc);
963 
964                     AEV_TRACE("mvp_l0/l1_flag", ps_pu->b1_l0_mvp_idx, ps_cabac->u4_range);
965                 }
966 
967                 /* Encode ref idx and MVD for L1  (PRED_L1 or PRED_BI) */
968                 if(inter_pred_idc != PRED_L0)
969                 {
970                     /* encode L1 ref_idx  */
971                     WORD32 ref_idx_l1 = ps_pu->mv.i1_l1_ref_idx;
972 
973                     UWORD32 u4_bits_estimated_prev_mvd_ref_id;
974                     /*PIC INFO : Populate Ref Indx L1 Bits*/
975                     u4_bits_estimated_prev_mvd_ref_id = ps_cabac->u4_bits_estimated_q12;
976 
977                     ret |= ihevce_cabac_encode_refidx(ps_cabac, ref_idx_l1, ref_l1_active);
978 
979                     if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
980                     {  // clang-format off
981                         ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_ref_id +=
982                             (ps_cabac->u4_bits_estimated_q12 -
983                                 u4_bits_estimated_prev_mvd_ref_id);
984                     }  // clang-format on
985 
986                     /* Check for zero mvd in case of bi_pred */
987                     if(ps_slice_hdr->i1_mvd_l1_zero_flag && inter_pred_idc == PRED_BI)
988                     {
989                         ASSERT(ps_pu->mv.s_l1_mv.i2_mvx == 0);
990                         ASSERT(ps_pu->mv.s_l1_mv.i2_mvy == 0);
991                     }
992                     else
993                     {
994                         /* Encode the mvd for L1 */
995                         /*PIC INFO : Populate MVD Bits*/
996                         u4_bits_estimated_prev_mvd_ref_id = ps_cabac->u4_bits_estimated_q12;
997 
998                         /* Encode the mvd for L1 */
999                         ret |= ihevce_cabac_encode_mvd(ps_cabac, &ps_pu->mv.s_l1_mv);
1000 
1001                         if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1002                         {
1003                             ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_mvd +=
1004                                 (ps_cabac->u4_bits_estimated_q12 -
1005                                  u4_bits_estimated_prev_mvd_ref_id);
1006                         }
1007                     }
1008 
1009                     /* Encode the mvp_l1_flag */
1010                     ctxt_inc = IHEVC_CAB_MVP_L0L1;
1011                     ret |= ihevce_cabac_encode_bin(ps_cabac, ps_pu->b1_l1_mvp_idx, ctxt_inc);
1012 
1013                     AEV_TRACE("mvp_l0/l1_flag", ps_pu->b1_l1_mvp_idx, ps_cabac->u4_range);
1014                 }
1015             }
1016         }
1017     }
1018 
1019     return ret;
1020 }
1021 
1022 /**
1023 ******************************************************************************
1024 *
1025 *  @brief Entropy encoding of coding unit (Coding Unit syntax)
1026 *
1027 *  @par   Description
1028 *  Entropy encode of  coding unit (Coding Unit syntax) as per section:7.3.9.1
1029 *  General Coding unit syntax
1030 *
1031 *  @param[inout]   ps_entropy_ctxt
1032 *  pointer to entropy context (handle)
1033 *
1034 *  @param[in]   ps_enc_cu
1035 *  pointer to current cu whose entropy encode is done
1036 *
1037 *  @param[in]   cu_depth
1038 *  depth of the the current cu in coding tree
1039 *
1040 *  @param[in]   top_avail
1041 *  top availabilty flag for current cu (boolean)
1042 *
1043 *  @param[in]   left_avail
1044 *  left availabilty flag for current cu (boolean)
1045 *
1046 *  @return      success or failure error code
1047 *
1048 ******************************************************************************
1049 */
ihevce_cabac_encode_coding_unit(entropy_context_t * ps_entropy_ctxt,cu_enc_loop_out_t * ps_enc_cu,WORD32 cu_depth,WORD32 top_avail,WORD32 left_avail)1050 WORD32 ihevce_cabac_encode_coding_unit(
1051     entropy_context_t *ps_entropy_ctxt,
1052     cu_enc_loop_out_t *ps_enc_cu,
1053     WORD32 cu_depth,
1054     WORD32 top_avail,
1055     WORD32 left_avail)
1056 {
1057     WORD32 ret = IHEVCE_SUCCESS;
1058     sps_t *ps_sps = ps_entropy_ctxt->ps_sps;
1059     pps_t *ps_pps = ps_entropy_ctxt->ps_pps;
1060     slice_header_t *ps_slice_hdr = ps_entropy_ctxt->ps_slice_hdr;
1061 
1062     WORD32 skip_flag = 0;
1063     WORD32 no_res_flag = 0;
1064 
1065     /* CU top left co-ordinates w.r.t ctb */
1066     WORD32 cu_x0 = ps_enc_cu->b3_cu_pos_x << 3;
1067     WORD32 cu_y0 = ps_enc_cu->b3_cu_pos_y << 3;
1068 
1069     /* CU size in pels */
1070     WORD32 cu_size = ps_enc_cu->b4_cu_size << 3;
1071     WORD32 log2_cb_size;
1072 
1073     cab_ctxt_t *ps_cabac = &ps_entropy_ctxt->s_cabac_ctxt;
1074 
1075     UWORD32 u4_header_bits_temp = ps_cabac->u4_bits_estimated_q12;
1076 
1077     (void)cu_depth;
1078     (void)top_avail;
1079     (void)left_avail;
1080     /* Sanity checks */
1081     ASSERT((cu_x0 + cu_size) <= (1 << ps_entropy_ctxt->i1_log2_ctb_size));
1082     ASSERT((cu_y0 + cu_size) <= (1 << ps_entropy_ctxt->i1_log2_ctb_size));
1083 
1084     /* code tq bypass flag */
1085     ASSERT(ps_pps->i1_transquant_bypass_enable_flag == 0);
1086 
1087     /* log2_cb_size based on cu size */
1088     GETRANGE(log2_cb_size, cu_size);
1089     log2_cb_size -= 1;
1090 
1091     if(ps_pps->i1_transquant_bypass_enable_flag)
1092     {
1093         ihevce_cabac_encode_bin(
1094             ps_cabac, ps_enc_cu->b1_tq_bypass_flag, IHEVC_CAB_CU_TQ_BYPASS_FLAG);
1095 
1096         AEV_TRACE("cu_transquant_bypass_flag", ps_enc_cu->b1_tq_bypass_flag, ps_cabac->u4_range);
1097     }
1098     /* code the skip flag for inter slices */
1099     if(ps_slice_hdr->i1_slice_type != ISLICE)
1100     {
1101         skip_flag = ps_enc_cu->b1_skip_flag;
1102 
1103         ret |= ihevce_cabac_encode_skip_flag(ps_entropy_ctxt, ps_enc_cu, top_avail, left_avail);
1104     }
1105     /*PIC_INFO : Total CU in frame based on cu size */
1106     if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1107     {
1108         // clang-format off
1109         if(cu_size == 64)
1110             ps_entropy_ctxt->ps_pic_level_info->i8_total_cu_based_on_size[3]++;
1111         else
1112             ps_entropy_ctxt->ps_pic_level_info->i8_total_cu_based_on_size[cu_size >> 4]++;
1113         // clang-format on
1114     }
1115     if(skip_flag)
1116     {
1117         /* encode merge idx for the skip cu */
1118         ret |= ihevce_cabac_encode_inter_pu(ps_entropy_ctxt, ps_enc_cu, cu_depth);
1119 
1120         if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1121         {
1122             /*PIC INFO: Populated non-coded TUs in CU*/
1123             ps_entropy_ctxt->ps_pic_level_info->i8_total_non_coded_tu +=
1124                 ps_enc_cu->u2_num_tus_in_cu;
1125             // clang-format off
1126             if(cu_size == 64)
1127                 ps_entropy_ctxt->ps_pic_level_info->i8_total_tu_based_on_size[3] +=
1128                     ps_enc_cu->u2_num_tus_in_cu;
1129             else if(cu_size == 32)
1130                 ps_entropy_ctxt->ps_pic_level_info->i8_total_tu_based_on_size[3] +=
1131                     ps_enc_cu->u2_num_tus_in_cu;
1132             else
1133                 ps_entropy_ctxt->ps_pic_level_info->i8_total_tu_based_on_size[cu_size >> 3] +=
1134                     ps_enc_cu->u2_num_tus_in_cu;
1135             // clang-format on
1136 
1137             /*PIC INFO: Populate cu header bits*/
1138             ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_cu_hdr_bits +=
1139                 (ps_cabac->u4_bits_estimated_q12 - u4_header_bits_temp);
1140         }
1141     }
1142     else
1143     {
1144         WORD32 pred_mode = PRED_MODE_INTRA;
1145         WORD32 part_mode = ps_enc_cu->b3_part_mode;
1146         WORD32 pcm_flag = ps_enc_cu->b1_pcm_flag;
1147         WORD32 is_mincu;
1148         WORD32 is_intra;
1149 
1150         is_mincu = (cu_size == (1 << ps_sps->i1_log2_min_coding_block_size));
1151         /* encode pred mode flag for inter slice */
1152         if(ps_slice_hdr->i1_slice_type != ISLICE)
1153         {
1154             pred_mode = ps_enc_cu->b1_pred_mode_flag;
1155 
1156             ret |= ihevce_cabac_encode_bin(ps_cabac, pred_mode, IHEVC_CAB_PRED_MODE);
1157 
1158             AEV_TRACE("pred_mode_flag", pred_mode, ps_cabac->u4_range);
1159         }
1160         is_intra = (PRED_MODE_INTRA == pred_mode);
1161 
1162         /* encode partition mode for inter pred or smallest intra pred cu */
1163         if((!is_intra) || is_mincu)
1164         {
1165             WORD32 amp_enabled = ps_sps->i1_amp_enabled_flag;
1166             WORD32 cusize_8 = (cu_size == 8);
1167 
1168             ret |= ihevce_cabac_encode_part_mode(
1169                 ps_cabac, is_intra, is_mincu, amp_enabled, cusize_8, part_mode);
1170         }
1171         else
1172         {
1173             ASSERT(part_mode == SIZE_2Nx2N);
1174         }
1175 
1176         /* encode intra / inter pu modes of the current CU */
1177         if(is_intra)
1178         {
1179             /* NOTE: I_PCM not supported in encoder */
1180             ASSERT(0 == pcm_flag);
1181             ASSERT(0 == ps_sps->i1_pcm_enabled_flag);
1182 
1183             ret |= ihevce_cabac_encode_intra_pu(ps_entropy_ctxt, part_mode, ps_enc_cu);
1184         }
1185         else
1186         {
1187             ret |= ihevce_cabac_encode_inter_pu(ps_entropy_ctxt, ps_enc_cu, cu_depth);
1188         }
1189         /* encode no residue syntax flag and transform tree conditionally */
1190         if(!pcm_flag)
1191         {
1192             pu_t *ps_pu = &ps_enc_cu->ps_pu[0];
1193             WORD32 merge_cu;
1194             /* Encode residue syntax flag for inter cus not merged as 2Nx2N */
1195             if(!is_intra)
1196                 merge_cu = (part_mode == PART_2Nx2N) && ps_pu->b1_merge_flag;
1197 
1198             if(!is_intra && !merge_cu)
1199             {
1200                 no_res_flag = ps_enc_cu->b1_no_residual_syntax_flag;
1201 
1202 #if 1 /* HACK FOR COMPLIANCE WITH HM REFERENCE DECODER */
1203                 /*********************************************************/
1204                 /* currently the HM decoder expects qtroot cbf instead of */
1205                 /* no_residue_flag which has opposite meaning             */
1206                 /* This will be fixed once the software / spec is fixed   */
1207                 /*********************************************************/
1208                 ret |= ihevce_cabac_encode_bin(ps_cabac, !no_res_flag, IHEVC_CAB_NORES_IDX);
1209 
1210                 AEV_TRACE("no_residual_syntax_flag (HACKY)", !no_res_flag, ps_cabac->u4_range);
1211 #else
1212                 ret |= ihevce_cabac_encode_bin(ps_cabac, no_res_flag, IHEVC_CAB_NORES_IDX);
1213 
1214                 AEV_TRACE("no_residual_syntax_flag", no_res_flag, ps_cabac->u4_range);
1215 #endif
1216             }
1217             /*initialize header bits*/
1218             ps_cabac->u4_header_bits_estimated_q12 = ps_cabac->u4_bits_estimated_q12;
1219 
1220             if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1221             {  // clang-format off
1222                 /*PIC INFO: Populate cu header bits*/
1223                 ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_cu_hdr_bits +=
1224                     (ps_cabac->u4_bits_estimated_q12 - u4_header_bits_temp);
1225             }  // clang-format on
1226 
1227             ps_cabac->u4_true_tu_split_flag_q12 = 0;
1228             /* encode transform tree if no_residue_flag is 0 */
1229             if(!no_res_flag)
1230             {
1231                 ps_entropy_ctxt->i4_tu_idx = 0;
1232 
1233                 ret |= ihevce_encode_transform_tree(
1234                     ps_entropy_ctxt, cu_x0, cu_y0, log2_cb_size, 0, 0, ps_enc_cu);
1235             }
1236             else
1237             {
1238                 if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1239                 {
1240                     /*PIC INFO: Populated non-coded TUs in CU*/
1241                     ps_entropy_ctxt->ps_pic_level_info->i8_total_non_coded_tu +=
1242                         ps_enc_cu->u2_num_tus_in_cu;
1243                     // clang-format off
1244                     if(cu_size == 64)
1245                         ps_entropy_ctxt->ps_pic_level_info->i8_total_tu_based_on_size[3] +=
1246                             ps_enc_cu->u2_num_tus_in_cu;
1247                     else if(cu_size == 32)
1248                         ps_entropy_ctxt->ps_pic_level_info->i8_total_tu_based_on_size[3] +=
1249                             ps_enc_cu->u2_num_tus_in_cu;
1250                     else
1251                         ps_entropy_ctxt->ps_pic_level_info->i8_total_tu_based_on_size[cu_size >> 3] +=
1252                             ps_enc_cu->u2_num_tus_in_cu;
1253                     // clang-format on
1254                 }
1255             }
1256             ps_cabac->u4_cbf_bits_q12 = ps_cabac->u4_bits_estimated_q12 -
1257                                         ps_cabac->u4_header_bits_estimated_q12 -
1258                                         ps_cabac->u4_true_tu_split_flag_q12;
1259         }
1260     }
1261 
1262     /*duplicate the qp values for 8x8 CU array to maintain neighbour qp*/
1263     if(CABAC_MODE_ENCODE_BITS == ps_entropy_ctxt->s_cabac_ctxt.e_cabac_op_mode)
1264     {
1265         WORD32 i, j;
1266         WORD32 cur_cu_offset, cur_qp, qp_left, qp_top;
1267         WORD32 is_last_blk_in_qg;
1268         /* CU x co-ordinate w.r.t frame start           */
1269         WORD32 ctb_x0_frm = (ps_entropy_ctxt->i4_ctb_x << ps_entropy_ctxt->i1_log2_ctb_size);
1270 
1271         WORD32 cu_x0_frm = cu_x0 + ctb_x0_frm;
1272 
1273         /* CU y co-ordinate w.r.t frame start           */
1274         WORD32 ctb_y0_frm = (ps_entropy_ctxt->i4_ctb_y << ps_entropy_ctxt->i1_log2_ctb_size);
1275 
1276         WORD32 cu_y0_frm = cu_y0 + ctb_y0_frm;
1277 
1278         WORD32 pic_width = ps_sps->i2_pic_width_in_luma_samples;
1279         WORD32 pic_height = ps_sps->i2_pic_height_in_luma_samples;
1280 
1281         /* Added code for handling the QP neighbour population depending
1282             on the diff_cu_qp_delta_depth: Lokesh  */
1283         /* is_last_blk_in_qg variables is to find if the coding block is the last CU in the Quantization group
1284             3 - i1_diff_cu_qp_delta_depth is done as the cu_pos_x and cu_pos_y are in terms of 8x8 positions in the CTB: Lokesh*/
1285         WORD32 log2_min_cu_qp_delta_size =
1286             ps_entropy_ctxt->i1_log2_ctb_size - ps_entropy_ctxt->ps_pps->i1_diff_cu_qp_delta_depth;
1287         UWORD32 min_cu_qp_delta_size = 1 << log2_min_cu_qp_delta_size;
1288 
1289         WORD32 block_addr_align = 15 << (log2_min_cu_qp_delta_size - 3);
1290 
1291         ps_entropy_ctxt->i4_qg_pos_x = ps_enc_cu->b3_cu_pos_x & block_addr_align;
1292         ps_entropy_ctxt->i4_qg_pos_y = ps_enc_cu->b3_cu_pos_y & block_addr_align;
1293 
1294         /* Condition for detecting last cu in a qp group.                                       */
1295         /* Case 1: Current cu position + size exceed or meets the next qp group start location  */
1296         /* Case 2: Current cu position + size hits the incomplete ctb boundary in atleast one   */
1297         /*         direction and the qp grp limit in other direction                            */
1298 
1299         /* case 1 */
1300         is_last_blk_in_qg =
1301             ((cu_x0 + cu_size) >=
1302                  ((ps_entropy_ctxt->i4_qg_pos_x << 3) + (WORD32)min_cu_qp_delta_size) &&
1303              (cu_y0 + cu_size) >=
1304                  ((ps_entropy_ctxt->i4_qg_pos_y << 3) + (WORD32)min_cu_qp_delta_size));
1305 
1306         /* case 2 : x direction incomplete ctb */
1307         if((cu_x0_frm + cu_size) >= pic_width)
1308         {
1309             is_last_blk_in_qg |=
1310                 ((cu_y0 + cu_size) >=
1311                  ((ps_entropy_ctxt->i4_qg_pos_y << 3) + (WORD32)min_cu_qp_delta_size));
1312         }
1313 
1314         /* case 2 : y direction incomplete ctb */
1315         if((cu_y0_frm + cu_size) >= pic_height)
1316         {
1317             is_last_blk_in_qg |=
1318                 ((cu_x0 + cu_size) >=
1319                  ((ps_entropy_ctxt->i4_qg_pos_x << 3) + (WORD32)min_cu_qp_delta_size));
1320         }
1321 
1322         cur_cu_offset = ps_enc_cu->b3_cu_pos_x + (ps_enc_cu->b3_cu_pos_y * 8);
1323 
1324         if((ps_entropy_ctxt->i4_is_cu_cbf_zero || no_res_flag || skip_flag) &&
1325            ((ps_entropy_ctxt->i1_encode_qp_delta)))
1326         {
1327             {  // clang-format off
1328                 /*it should remember average of qp_top and qp_left*/
1329                 if(ps_entropy_ctxt->i4_qg_pos_x > 0)
1330                 {
1331                     qp_left =
1332                         ps_entropy_ctxt->ai4_8x8_cu_qp[(ps_entropy_ctxt->i4_qg_pos_x - 1) +
1333                                             (ps_entropy_ctxt->i4_qg_pos_y * 8)];
1334                 }
1335                 if(ps_entropy_ctxt->i4_qg_pos_y > 0)
1336                 {
1337                     qp_top =
1338                         ps_entropy_ctxt->ai4_8x8_cu_qp[ps_entropy_ctxt->i4_qg_pos_x +
1339                                             (ps_entropy_ctxt->i4_qg_pos_y - 1) *
1340                                                 8];
1341                 }  // clang-format on
1342                 if(ps_entropy_ctxt->i4_qg_pos_x == 0)
1343                 {
1344                     /*previous coded Qp*/
1345                     qp_left = ps_entropy_ctxt->i1_cur_qp;
1346                 }
1347                 if(ps_entropy_ctxt->i4_qg_pos_y == 0)
1348                 {
1349                     /*previous coded Qp*/
1350                     qp_top = ps_entropy_ctxt->i1_cur_qp;
1351                 }
1352                 cur_qp = (qp_top + qp_left + 1) >> 1;
1353                 /*In case of skip or zero cbf CU the previous qp used has to be updated*/
1354                 if(is_last_blk_in_qg)
1355                     ps_entropy_ctxt->i1_cur_qp = cur_qp;
1356             }
1357         }
1358         else
1359         {
1360             cur_qp = (WORD32)ps_enc_cu->ps_enc_tu->s_tu.b7_qp;
1361         }
1362 
1363         if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1364         {
1365             WORD32 temp = 0;
1366             /*PIC_INFO: Accumalate average qp, min qp and max qp*/
1367             ps_entropy_ctxt->ps_pic_level_info->i8_total_qp += cur_qp;
1368             if(cu_size == 64)
1369                 temp = 6;
1370             else if(cu_size == 32)
1371                 temp = 4;
1372             else if(cu_size == 16)
1373                 temp = 2;
1374             else if(cu_size == 8)
1375                 temp = 0;
1376 
1377             ps_entropy_ctxt->ps_pic_level_info->i8_total_qp_min_cu += (cur_qp * (1 << temp));
1378             if(cur_qp < ps_entropy_ctxt->ps_pic_level_info->i4_min_qp)
1379                 ps_entropy_ctxt->ps_pic_level_info->i4_min_qp = cur_qp;
1380             if(cur_qp > ps_entropy_ctxt->ps_pic_level_info->i4_max_qp)
1381                 ps_entropy_ctxt->ps_pic_level_info->i4_max_qp = cur_qp;
1382         }
1383 
1384         for(i = 0; i < (WORD32)ps_enc_cu->b4_cu_size; i++)
1385         {
1386             for(j = 0; j < (WORD32)ps_enc_cu->b4_cu_size; j++)
1387             {
1388                 ps_entropy_ctxt->ai4_8x8_cu_qp[cur_cu_offset + (i * 8) + j] = cur_qp;
1389             }
1390         }
1391         ps_entropy_ctxt->i4_is_cu_cbf_zero = 1;
1392     }
1393 
1394     return ret;
1395 }
1396 
1397 /**
1398 ******************************************************************************
1399 *
1400 *  @brief Entropy encoding of SAO related syntax elements as per sec 7.3.8.3
1401 *
1402 *  @par   Description
1403 *  Encoding of sao related syntax elements at ctb level.
1404 *
1405 *  @param[inout]   ps_entropy_ctxt
1406 *  pointer to entropy context (handle)
1407 *
1408 *  @param[in]   ps_ctb_enc_loop_out
1409 *  pointer to ctb level output structure from enc loop
1410 *
1411 *  @return      success or failure error code
1412 *
1413 ******************************************************************************
1414 */
ihevce_cabac_encode_sao(entropy_context_t * ps_entropy_ctxt,ctb_enc_loop_out_t * ps_ctb_enc_loop_out)1415 WORD32 ihevce_cabac_encode_sao(
1416     entropy_context_t *ps_entropy_ctxt, ctb_enc_loop_out_t *ps_ctb_enc_loop_out)
1417 {
1418     WORD32 error = IHEVCE_SUCCESS;
1419     sao_enc_t *ps_sao;
1420     nbr_avail_flags_t *ps_ctb_nbr_avail_flags;
1421     slice_header_t *ps_slice_hdr = ps_entropy_ctxt->ps_slice_hdr;
1422     cab_ctxt_t *ps_cabac = &ps_entropy_ctxt->s_cabac_ctxt;
1423 
1424     UWORD8 u1_left_avail, u1_top_avail;
1425 
1426     ps_ctb_nbr_avail_flags = &ps_ctb_enc_loop_out->s_ctb_nbr_avail_flags;
1427 
1428     ps_sao = &ps_ctb_enc_loop_out->s_sao;
1429 
1430     ASSERT(ps_sao->b1_sao_merge_left_flag < 2);
1431 
1432     u1_left_avail = ps_ctb_nbr_avail_flags->u1_left_avail;
1433     u1_top_avail = ps_ctb_nbr_avail_flags->u1_top_avail;
1434 
1435     if(u1_left_avail == 1)
1436     {
1437         /*Encode the sao_merge_left_flag as FL as per table 9-32*/
1438         error |=
1439             ihevce_cabac_encode_bin(ps_cabac, ps_sao->b1_sao_merge_left_flag, IHEVC_CAB_SAO_MERGE);
1440 
1441         AEV_TRACE("sao_merge_flag", ps_sao->b1_sao_merge_left_flag, ps_cabac->u4_range);
1442     }
1443 
1444     if((u1_top_avail == 1) && (!ps_sao->b1_sao_merge_left_flag))
1445     {
1446         /*Encode the sao_merge_up_flag as FL as per table 9-32*/
1447         error |=
1448             ihevce_cabac_encode_bin(ps_cabac, ps_sao->b1_sao_merge_up_flag, IHEVC_CAB_SAO_MERGE);
1449 
1450         AEV_TRACE("sao_merge_flag", ps_sao->b1_sao_merge_up_flag, ps_cabac->u4_range);
1451     }
1452 
1453     if((!ps_sao->b1_sao_merge_left_flag) && (!ps_sao->b1_sao_merge_up_flag))
1454     {
1455         WORD32 c_idx;
1456         WORD32 sao_type_idx = ps_sao->b3_y_type_idx;
1457 
1458         /*Run a loop for y,cb and cr to encode the type idx for luma and chroma*/
1459         for(c_idx = 0; c_idx < 3; c_idx++)
1460         {
1461             if((ps_slice_hdr->i1_slice_sao_luma_flag && c_idx == 0) ||
1462                (ps_slice_hdr->i1_slice_sao_chroma_flag && c_idx > 0))
1463             {
1464                 WORD32 ctxt_bin;
1465 
1466                 /**************************************************************************/
1467                 /* encode the sao_type_idx as per Table 9-33                              */
1468                 /* First bin is context model based prefix : 1 if sao_type_idx > 0 else 0 */
1469                 /* Second bin is coded as bypass bin if sao_type_ide > 0                  */
1470                 /**************************************************************************/
1471 
1472                 if(c_idx < 2)
1473                 {
1474                     WORD32 sao_type_idx_temp;
1475 
1476                     ASSERT(ps_sao->b3_cb_type_idx == ps_sao->b3_cr_type_idx);
1477 
1478                     sao_type_idx = c_idx ? ps_sao->b3_cb_type_idx : ps_sao->b3_y_type_idx;
1479 
1480                     ctxt_bin = sao_type_idx ? 1 : 0;
1481 
1482                     if(sao_type_idx > 1)
1483                     {
1484                         sao_type_idx_temp = 2;
1485                     }
1486                     else
1487                     {
1488                         sao_type_idx_temp = sao_type_idx;
1489                     }
1490 
1491                     ASSERT(sao_type_idx_temp < 3);
1492 
1493                     /*Encode the first bin as context bin as per table 9-37*/
1494                     error |= ihevce_cabac_encode_bin(ps_cabac, ctxt_bin, IHEVC_CAB_SAO_TYPE);
1495 
1496                     if(sao_type_idx_temp)
1497                     {
1498                         /*Binarisation for sao_type_idx is TR(truncated rice) process as per
1499                             * table 9-32 with cMax=2 and cRiceParam=0
1500                             */
1501 
1502                         /* Encode the second bin as bypass bin as per below table*/
1503                         /*
1504                             |Symbol | Prefix |Prefix length |Prefix bins|
1505                             |   0   |    0   |     1        |     0     |
1506                             |   1   |    1   |     2        |     10    |
1507                             |   2   |    2   |     2        |     11    |
1508 
1509                             Since cRiceParam=0, there is no suffix code
1510                             */
1511 
1512                         error |= ihevce_cabac_encode_bypass_bin(ps_cabac, sao_type_idx_temp - 1);
1513                     }
1514                     AEV_TRACE("sao_type_idx", sao_type_idx_temp, ps_cabac->u4_range);
1515                 }
1516 
1517                 if(sao_type_idx != 0)
1518                 {
1519                     WORD32 i;
1520                     UWORD8 u1_bit_depth = ps_entropy_ctxt->ps_sps->i1_bit_depth_luma_minus8 + 8;
1521                     WORD8 *sao_offset;
1522                     WORD32 sao_band_position;
1523                     WORD32 c_max = (1 << (MIN(u1_bit_depth, 10) - 5)) -
1524                                    1;  //( 1 << (MIN(BIT_DEPTH, 10) - 5)) - 1;
1525 
1526                     if(c_idx == 0)
1527                     {
1528                         //sao_offset[0] = ps_sao->b4_y_offset_1;
1529                         //sao_offset[1] = ps_sao->b4_y_offset_2;
1530                         //sao_offset[2] = ps_sao->b4_y_offset_3;
1531                         //sao_offset[3] = ps_sao->b4_y_offset_4;
1532                         sao_offset = &ps_sao->u1_y_offset[1];
1533                         sao_band_position = ps_sao->b5_y_band_pos;
1534                     }
1535                     else if(c_idx == 1)
1536                     {
1537                         //sao_offset[0] = ps_sao->b4_cb_offset_1;
1538                         //sao_offset[1] = ps_sao->b4_cb_offset_2;
1539                         //sao_offset[2] = ps_sao->b4_cb_offset_3;
1540                         //sao_offset[3] = ps_sao->b4_cb_offset_4;
1541                         sao_offset = &ps_sao->u1_cb_offset[1];
1542                         sao_band_position = ps_sao->b5_cb_band_pos;
1543                     }
1544                     else
1545                     {
1546                         //sao_offset[0] = ps_sao->b4_cr_offset_1;
1547                         //sao_offset[1] = ps_sao->b4_cr_offset_2;
1548                         //sao_offset[2] = ps_sao->b4_cr_offset_3;
1549                         //sao_offset[3] = ps_sao->b4_cr_offset_4;
1550                         sao_offset = &ps_sao->u1_cr_offset[1];
1551                         sao_band_position = ps_sao->b5_cr_band_pos;
1552                     }
1553 
1554                     for(i = 0; i < 4; i++)
1555                     {
1556                         /*Encode the sao offset value as tunary bypass*/
1557                         error |=
1558                             ihevce_cabac_encode_tunary_bypass(ps_cabac, abs(sao_offset[i]), c_max);
1559 
1560                         AEV_TRACE("sao_offset_abs", abs(sao_offset[i]), ps_cabac->u4_range);
1561                     }
1562 
1563                     /*Band offset case*/
1564                     if(sao_type_idx == 1)
1565                     {
1566                         for(i = 0; i < 4; i++)
1567                         {
1568                             if(sao_offset[i] != 0)
1569                             {
1570                                 /*Encode the sao offset sign as FL as per table 9-32*/
1571                                 error |= ihevce_cabac_encode_bypass_bin(
1572                                     ps_cabac,
1573                                     (abs(sao_offset[i]) + sao_offset[i] == 0));  //,
1574                                 //IHEVC_CAB_SAO_MERGE
1575                                 //);
1576 
1577                                 AEV_TRACE(
1578                                     "sao_offset_sign",
1579                                     (abs(sao_offset[i]) + sao_offset[i] == 0),
1580                                     ps_cabac->u4_range);
1581                             }
1582                         }
1583 
1584                         /*Encode the sao band position as FL as per table 9-32*/
1585                         error |= ihevce_cabac_encode_bypass_bins(ps_cabac, sao_band_position, 5);
1586                         AEV_TRACE("sao_band_position", sao_band_position, ps_cabac->u4_range);
1587                     }
1588                     else
1589                     {
1590                         /*Encode the sao edge offset class for luma and chroma as FL as per table 9-32*/
1591                         if(c_idx == 0)
1592                         {
1593                             error |= ihevce_cabac_encode_bypass_bins(
1594                                 ps_cabac, (ps_sao->b3_y_type_idx - 2), 2);
1595                             AEV_TRACE(
1596                                 "sao_eo_class", (ps_sao->b3_y_type_idx - 2), ps_cabac->u4_range);
1597                         }
1598 
1599                         if(c_idx == 1)
1600                         {
1601                             ASSERT(ps_sao->b3_cb_type_idx == ps_sao->b3_cr_type_idx);
1602                             error |= ihevce_cabac_encode_bypass_bins(
1603                                 ps_cabac, (ps_sao->b3_cb_type_idx - 2), 2);
1604                             AEV_TRACE(
1605                                 "sao_eo_class", (ps_sao->b3_cb_type_idx - 2), ps_cabac->u4_range);
1606                         }
1607                     }
1608                 }
1609             }
1610         }
1611     }
1612 
1613     return (error);
1614 }
1615 
1616 /**
1617 ******************************************************************************
1618 *
1619 *  @brief Encodes a coding quad tree (QuadTree syntax) as per section 7.3.8
1620 *
1621 *  @par   Description
1622 *  Entropy encode of coding quad tree based on cu split flags of ctb as per
1623 *  section:7.3.8
1624 *
1625 *  @param[inout]   ps_entropy_ctxt
1626 *  pointer to entropy context (handle)
1627 *
1628 *  @param[in]      x0_frm
1629 *  x co-ordinate of current cu node of coding tree
1630 *
1631 *  @param[in]      y0_frm
1632 *  y co-ordinate of current cu node of coding tree
1633 *
1634 *  @param[in]      log2_cb_size
1635 *  current cu node block size
1636 *
1637 *  @param[in]      ct_depth
1638 *  depth of current cu node w.r.t ctb
1639 *
1640 *  @param[in]      ps_ctb
1641 *  pointer to current ctb structure
1642 *
1643 *  @return      success or failure error code
1644 *
1645 ******************************************************************************
1646 */
ihevce_encode_coding_quadtree(entropy_context_t * ps_entropy_ctxt,WORD32 x0_frm,WORD32 y0_frm,WORD32 log2_cb_size,WORD32 ct_depth,ctb_enc_loop_out_t * ps_ctb,ihevce_tile_params_t * ps_tile_params)1647 WORD32 ihevce_encode_coding_quadtree(
1648     entropy_context_t *ps_entropy_ctxt,
1649     WORD32 x0_frm,
1650     WORD32 y0_frm,
1651     WORD32 log2_cb_size,
1652     WORD32 ct_depth,
1653     ctb_enc_loop_out_t *ps_ctb,
1654     ihevce_tile_params_t *ps_tile_params)
1655 {
1656     WORD32 ret = IHEVCE_SUCCESS;
1657     sps_t *ps_sps = ps_entropy_ctxt->ps_sps;
1658     pps_t *ps_pps = ps_entropy_ctxt->ps_pps;
1659     WORD32 split_cu_flag;
1660     WORD32 cu_idx = ps_entropy_ctxt->i4_cu_idx;
1661     cu_enc_loop_out_t *ps_enc_cu = ps_ctb->ps_enc_cu + cu_idx;
1662 
1663     /* CU size in pels */
1664     WORD32 cu_size = ps_enc_cu->b4_cu_size << 3;
1665 
1666     WORD32 pic_width = ps_tile_params->i4_curr_tile_width;
1667     WORD32 pic_height = ps_tile_params->i4_curr_tile_height;
1668 
1669     WORD32 log2_min_cb_size = ps_sps->i1_log2_min_coding_block_size;
1670     WORD32 ctb_size = (1 << (log2_cb_size + ct_depth));
1671     cab_ctxt_t *ps_cabac = &ps_entropy_ctxt->s_cabac_ctxt;
1672 
1673     /* top row cu depth stored for frm_width (1byte per mincusize=8) */
1674     UWORD8 *pu1_cu_depth_top = ps_entropy_ctxt->pu1_cu_depth_top;
1675 
1676     /* left cu depth stored for one ctb column (1byte per mincusize=8) */
1677     UWORD8 *pu1_cu_depth_left = &ps_entropy_ctxt->au1_cu_depth_left[0];
1678 
1679     /* calculation of top and left nbr availability */
1680     WORD32 top_avail;
1681     WORD32 left_avail;
1682 
1683     /* top and left cu within ctb  or outside ctb boundary */
1684     left_avail = (x0_frm & (ctb_size - 1)) ? 1 : ps_ctb->s_ctb_nbr_avail_flags.u1_left_avail;
1685     top_avail = (y0_frm & (ctb_size - 1)) ? 1 : ps_ctb->s_ctb_nbr_avail_flags.u1_top_avail;
1686 
1687     /* Sanity checks */
1688     ASSERT(ct_depth <= 3);
1689     ASSERT((cu_idx >= 0) && (cu_idx < ps_ctb->u1_num_cus_in_ctb));
1690     ASSERT(cu_size >= (1 << log2_min_cb_size));
1691     ASSERT(((ps_enc_cu->b3_cu_pos_x << 3) + cu_size) <= (UWORD32)ctb_size);
1692     ASSERT(((ps_enc_cu->b3_cu_pos_y << 3) + cu_size) <= (UWORD32)ctb_size);
1693 
1694     /* Encode cu split flags based on following conditions; See section 7.3.8*/
1695     if(((x0_frm + (1 << log2_cb_size)) <= pic_width) &&
1696        ((y0_frm + (1 << log2_cb_size)) <= pic_height) && (log2_cb_size > log2_min_cb_size) &&
1697        (ps_entropy_ctxt->i1_ctb_num_pcm_blks == 0))
1698     {
1699         /* encode the split cu flag */
1700         WORD32 ctxt_inc = IHEVC_CAB_SPLIT_CU_FLAG;
1701         UWORD32 u4_bits_estimated_prev;
1702         /* Context increment for skip flag as per Table 9-38 */
1703         if(top_avail)
1704         {
1705             ctxt_inc += (pu1_cu_depth_top[x0_frm >> 3] > ct_depth);
1706         }
1707 
1708         if(left_avail)
1709         {
1710             ctxt_inc += (pu1_cu_depth_left[(y0_frm >> 3) & 0x7] > ct_depth);
1711         }
1712 
1713         /* split if actual cu size is smaller than target cu size */
1714         split_cu_flag = cu_size < (1 << log2_cb_size);
1715         u4_bits_estimated_prev = ps_cabac->u4_bits_estimated_q12;
1716         ret |= ihevce_cabac_encode_bin(ps_cabac, split_cu_flag, ctxt_inc);
1717 
1718         if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1719         {  // clang-format off
1720             /*PIC INFO : populate cu split flag*/
1721             ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_split_cu_flag +=
1722                 (ps_cabac->u4_bits_estimated_q12 - u4_bits_estimated_prev);
1723         }  // clang-format on
1724 
1725         AEV_TRACE("split_cu_flag", split_cu_flag, ps_cabac->u4_range);
1726         if(split_cu_flag == 0)
1727         {
1728             AEV_TRACE("split_cu_flag : X0", (x0_frm >> 6) << 6, ps_cabac->u4_range);
1729             AEV_TRACE("split_cu_flag : Y0", (y0_frm >> 6) << 6, ps_cabac->u4_range);
1730         }
1731     }
1732     else
1733     {
1734         /*********************************************************************/
1735         /* split cu is implicitly derived as 1 in frame/slice boundary case  */
1736         /* else split cu is implicitly derived as 0 if mincu size is reached */
1737         /*********************************************************************/
1738         if(log2_cb_size > ps_sps->i1_log2_min_coding_block_size)
1739             split_cu_flag = 1;
1740         else
1741             split_cu_flag = 0;
1742     }
1743 
1744     /************************************************************************/
1745     /* Reset qp delata coded flag appropriately so as to signal qp rightly  */
1746     /* during transform coding                                              */
1747     /************************************************************************/
1748     if((ps_pps->i1_cu_qp_delta_enabled_flag) && (ct_depth <= (ps_pps->i1_diff_cu_qp_delta_depth)))
1749 
1750     {
1751         ps_entropy_ctxt->i1_encode_qp_delta = 1;
1752     }
1753     /*else
1754     {
1755         ps_entropy_ctxt->i1_encode_qp_delta = 0;
1756     }*/
1757 
1758     if(split_cu_flag)
1759     {
1760         /* recurse quad tree till a leaf node is reached */
1761         WORD32 x1_frm = x0_frm + ((1 << log2_cb_size) >> 1);
1762         WORD32 y1_frm = y0_frm + ((1 << log2_cb_size) >> 1);
1763 
1764         /* node0 of quad tree */
1765         ret |= ihevce_encode_coding_quadtree(
1766             ps_entropy_ctxt, x0_frm, y0_frm, log2_cb_size - 1, ct_depth + 1, ps_ctb, ps_tile_params);
1767 
1768         if(x1_frm < pic_width)
1769         { /* node1 of quad tree */
1770             ret |= ihevce_encode_coding_quadtree(
1771                 ps_entropy_ctxt,
1772                 x1_frm,
1773                 y0_frm,
1774                 log2_cb_size - 1,
1775                 ct_depth + 1,
1776                 ps_ctb,
1777                 ps_tile_params);
1778         }
1779 
1780         if(y1_frm < pic_height)
1781         {
1782             /* node2 of quad tree */
1783             ret |= ihevce_encode_coding_quadtree(
1784                 ps_entropy_ctxt,
1785                 x0_frm,
1786                 y1_frm,
1787                 log2_cb_size - 1,
1788                 ct_depth + 1,
1789                 ps_ctb,
1790                 ps_tile_params);
1791         }
1792 
1793         if((x1_frm < pic_width) && (y1_frm < pic_height))
1794         {
1795             /* node3 of quad tree */
1796             ret |= ihevce_encode_coding_quadtree(
1797                 ps_entropy_ctxt,
1798                 x1_frm,
1799                 y1_frm,
1800                 log2_cb_size - 1,
1801                 ct_depth + 1,
1802                 ps_ctb,
1803                 ps_tile_params);
1804         }
1805     }
1806     else
1807     {
1808         /* leaf node is reached! Encode the CU */
1809         WORD32 i;
1810 
1811         /* sanity checks */
1812         ASSERT(ps_entropy_ctxt->i1_ctb_num_pcm_blks == 0);
1813 
1814         if(ps_entropy_ctxt->i1_ctb_num_pcm_blks == 0)
1815         {
1816             UWORD32 u4_bits_eztimated = ps_entropy_ctxt->s_cabac_ctxt.u4_bits_estimated_q12;
1817             /* Encode a non-PCM CU */
1818             /*PCM INFO: populate total TUs*/
1819             if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1820             {
1821                 ps_entropy_ctxt->ps_pic_level_info->i8_total_tu += ps_enc_cu->u2_num_tus_in_cu;
1822             }
1823 
1824             ret |= ihevce_cabac_encode_coding_unit(
1825                 ps_entropy_ctxt, ps_enc_cu, ct_depth, top_avail, left_avail);
1826 
1827             if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
1828             {
1829                 // clang-format off
1830                 if(PRED_MODE_INTRA == ps_enc_cu->b1_pred_mode_flag)
1831                 {
1832                     ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_intra +=
1833                         (ps_entropy_ctxt->s_cabac_ctxt.u4_bits_estimated_q12 -
1834                             u4_bits_eztimated);
1835                 }
1836                 else
1837                 {
1838                     ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_inter +=
1839                         (ps_entropy_ctxt->s_cabac_ctxt.u4_bits_estimated_q12 -
1840                             u4_bits_eztimated);
1841                 }
1842                 // clang-format on
1843             }
1844         }
1845         else
1846         {  //TODO: //PCM not supported in this encoder
1847         }
1848 
1849         /* update cu_idx, left and top arrays for cudepth  after encoding cu */
1850         ps_entropy_ctxt->i4_cu_idx++;
1851         for(i = 0; i < (cu_size >> 3); i++)
1852         {
1853             pu1_cu_depth_top[(x0_frm >> 3) + i] = ct_depth;
1854             pu1_cu_depth_left[((y0_frm >> 3) & 0x7) + i] = ct_depth;
1855         }
1856     }
1857 
1858     return ret;
1859 }
1860 
1861 /**
1862 ******************************************************************************
1863 *
1864 *  @brief Encodes slice data (General Slice syntax) as per section 7.3.6.1
1865 *
1866 *  @par   Description
1867 *  Entropy encode of all ctbs in a slice as per section 7.3.6.1
1868 *
1869 *  @param[inout]   ps_entropy_ctxt
1870 *  pointer to entropy context (handle)
1871 *
1872 *  @return      success or failure error code
1873 *
1874 ******************************************************************************
1875 */
ihevce_encode_slice_data(entropy_context_t * ps_entropy_ctxt,ihevce_tile_params_t * ps_tile_params,WORD32 * pi4_end_of_slice_flag)1876 WORD32 ihevce_encode_slice_data(
1877     entropy_context_t *ps_entropy_ctxt,
1878     ihevce_tile_params_t *ps_tile_params,
1879     WORD32 *pi4_end_of_slice_flag)
1880 {
1881     WORD32 ret = IHEVCE_SUCCESS;
1882     WORD32 end_of_slice_seg_flag = 0;
1883     sps_t *ps_sps = ps_entropy_ctxt->ps_sps;
1884     pps_t *ps_pps = ps_entropy_ctxt->ps_pps;
1885     slice_header_t *ps_slice_hdr = ps_entropy_ctxt->ps_slice_hdr;
1886 
1887     cab_ctxt_t *ps_cabac = &ps_entropy_ctxt->s_cabac_ctxt;
1888 
1889     /* State of previous CTB before it's terminate bin is encoded */
1890     cab_ctxt_t s_cabac_prev_ctb;
1891 
1892     /* State after current CTB's encoding is complete but before
1893     the termintate bin encoding */
1894     cab_ctxt_t s_cabac_after_ctb;
1895 
1896     /* Storing the last 4 bytes before adding terminate bin
1897     as these 4 bytes might get corrupted while encoding terminate bin */
1898     UWORD32 u4_prev_ctb_temp, u4_cur_ctb_temp;
1899     WORD8 i1_last_cu_qp = 0;
1900     bitstrm_t *ps_bit_strm = &ps_entropy_ctxt->s_bit_strm;
1901 
1902     WORD32 log2_ctb_size, ctb_size;
1903     //WORD32 pic_width  = ps_sps->i2_pic_width_in_luma_samples;
1904     //WORD32 pic_height = ps_sps->i2_pic_height_in_luma_samples;
1905     WORD32 pic_width = ps_tile_params->i4_curr_tile_width;
1906     WORD32 pic_height = ps_tile_params->i4_curr_tile_height;
1907     WORD32 num_ctb_in_row;
1908 
1909     WORD32 i4_curr_ctb_x, i4_curr_ctb_y;
1910     UWORD32 u4_slice_seg_hdr_size = (UWORD32)ps_entropy_ctxt->i4_slice_seg_len;
1911     UWORD32 u4_slice_start_offset = ps_bit_strm->u4_strm_buf_offset - u4_slice_seg_hdr_size;
1912 
1913     WORD32 ctb_slice_address = ps_slice_hdr->i2_slice_address;
1914     WORD32 slice_qp = ps_slice_hdr->i1_slice_qp_delta + ps_pps->i1_pic_init_qp;
1915     WORD32 cabac_init_idc;
1916     WORD32 x0_frm, y0_frm;
1917     ctb_enc_loop_out_t *ps_first_ctb;  // Points to first CTB of ctb-row
1918     ctb_enc_loop_out_t *ps_ctb;
1919     WORD32 ctb_ctr = 0;  //count ctb encoded in a ctb-row
1920 
1921     ihevce_sys_api_t *ps_sys_api = (ihevce_sys_api_t *)ps_entropy_ctxt->pv_sys_api;
1922 
1923     /* Structure to backup pic info in case we need to revert back to pervious
1924     CTB when i4_slice_segment_mode is 2 */
1925     s_pic_level_acc_info_t s_pic_level_info_backup;  // info before
1926 
1927     /* Initialize the CTB size from sps parameters */
1928     log2_ctb_size =
1929         ps_sps->i1_log2_min_coding_block_size + ps_sps->i1_log2_diff_max_min_coding_block_size;
1930 
1931     ctb_size = (1 << log2_ctb_size);
1932 
1933     /* sanity checks */
1934     ASSERT((log2_ctb_size >= 3) && (log2_ctb_size <= 6));
1935 
1936     ps_entropy_ctxt->i1_log2_ctb_size = (WORD8)log2_ctb_size;
1937 
1938     /* Initiallise before starting slice. For single slice case both
1939     x and y will be set to zero */
1940     ps_entropy_ctxt->i4_ctb_x = ps_entropy_ctxt->i4_next_slice_seg_x;
1941     ps_entropy_ctxt->i4_ctb_y = ps_entropy_ctxt->i4_next_slice_seg_y;
1942     num_ctb_in_row = (ps_sps->i2_pic_width_in_luma_samples + ctb_size - 1) >> log2_ctb_size;
1943 
1944     /* initialize the cabac init idc based on slice type */
1945     if(ps_slice_hdr->i1_slice_type == ISLICE)
1946     {
1947         cabac_init_idc = 0;
1948     }
1949     else if(ps_slice_hdr->i1_slice_type == PSLICE)
1950     {
1951         cabac_init_idc = ps_slice_hdr->i1_cabac_init_flag ? 2 : 1;
1952     }
1953     else
1954     {
1955         cabac_init_idc = ps_slice_hdr->i1_cabac_init_flag ? 1 : 2;
1956     }
1957     ps_cabac->i1_entropy_coding_sync_enabled_flag = ps_pps->i1_entropy_coding_sync_enabled_flag;
1958 
1959     /* Dependent slices should be ON only when slice segment mode is enabled */
1960     if(ps_slice_hdr->i1_dependent_slice_flag == 1)
1961     {
1962         ASSERT(
1963             (ps_entropy_ctxt->i4_slice_segment_mode == 1) ||
1964             (ps_entropy_ctxt->i4_slice_segment_mode == 2));
1965     }
1966 
1967     /* initialize the cabac engine. For dependent slice segments
1968     cabac context models will not be reset */
1969     if(ps_slice_hdr->i1_dependent_slice_flag == 1)
1970     {
1971         ret = ihevce_cabac_reset(ps_cabac, ps_bit_strm, CABAC_MODE_ENCODE_BITS);
1972     }
1973     else
1974     {
1975         ret = ihevce_cabac_init(
1976             ps_cabac,
1977             ps_bit_strm,
1978             CLIP3(slice_qp, 0, IHEVC_MAX_QP),
1979             cabac_init_idc,
1980             CABAC_MODE_ENCODE_BITS);
1981 
1982         /* initialize qp to slice start qp */
1983         ps_entropy_ctxt->i1_cur_qp = slice_qp;
1984     }
1985 
1986     /* initialize slice x and y offset in pels w.r.t top left conrner */
1987     x0_frm = ps_entropy_ctxt->i4_ctb_x << log2_ctb_size;
1988     y0_frm = ps_entropy_ctxt->i4_ctb_y << log2_ctb_size;
1989 
1990     /* Pointing ctb structure to the correct CTB in frame based on
1991     slice address */
1992     ps_first_ctb = ps_entropy_ctxt->ps_frm_ctb + ctb_slice_address;
1993     ps_ctb = ps_first_ctb - 1;
1994 
1995     //ps_entropy_ctxt->i4_ctb_slice_x = 0;
1996     //ps_entropy_ctxt->i4_ctb_slice_y = 0;
1997 
1998     /* Setting to NULL to detect if first CTB of slice itself
1999     exceeds the i4_slice_segment_max_length. Will be used only if
2000     i4_slice_segment_mode is non-zero */
2001     s_cabac_prev_ctb.pu1_strm_buffer = NULL;
2002 
2003     do
2004     {
2005         UWORD8 au1_cu_depth_top[8] = { 0 }, au1_cu_depth_left[8] = { 0 };
2006         UWORD8 u1_skip_cu_top = 0;
2007         UWORD32 u4_skip_cu_left = 0;
2008 
2009         /* By default assume that slice-segment is going to end after
2010         current CTB */
2011         end_of_slice_seg_flag = 1;
2012 
2013         i4_curr_ctb_x = ps_entropy_ctxt->i4_ctb_x;
2014         i4_curr_ctb_y = ps_entropy_ctxt->i4_ctb_y;
2015 
2016         if(1 == ps_tile_params->i4_tiles_enabled_flag)
2017         {
2018             ps_ctb = ps_first_ctb + ctb_ctr;
2019         }
2020         else
2021         {
2022             ps_ctb++;
2023         }
2024 
2025         /* Store some parameters. Will be used if current CTB's encoding
2026         has to be reverted in the event of overflow beyond i4_slice_segment_max_length */
2027         if(2 == ps_entropy_ctxt->i4_slice_segment_mode)
2028         {
2029             /* Store CU depths flag */
2030             memcpy(au1_cu_depth_top, &ps_entropy_ctxt->pu1_cu_depth_top[i4_curr_ctb_x * 8], 8);
2031             memcpy(au1_cu_depth_left, ps_entropy_ctxt->au1_cu_depth_left, 8);
2032 
2033             /* Store CU skip flags */
2034             u1_skip_cu_top = *(ps_entropy_ctxt->pu1_skip_cu_top + i4_curr_ctb_x);
2035             u4_skip_cu_left = ps_entropy_ctxt->u4_skip_cu_left;
2036 
2037             /* Backup current state of pic info */
2038             s_pic_level_info_backup = *(ps_entropy_ctxt->ps_pic_level_info);
2039         }
2040 
2041         /* Section:7.3.7 Coding tree unit syntax */
2042         /* coding_tree_unit() inlined here */
2043         ps_entropy_ctxt->i1_ctb_num_pcm_blks = 0;
2044 
2045         /* Simple Neigbour avail calculation */
2046         ps_ctb->s_ctb_nbr_avail_flags.u1_left_avail = (x0_frm > 0);
2047         ps_ctb->s_ctb_nbr_avail_flags.u1_top_avail = (y0_frm > 0);
2048 
2049         ps_entropy_ctxt->i4_cu_idx = 0;
2050 
2051         /* Encode SAO syntax as per section 7.3.8.3 */
2052         if(ps_sps->i1_sample_adaptive_offset_enabled_flag)
2053         {
2054             if((ps_slice_hdr->i1_slice_sao_luma_flag) || (ps_slice_hdr->i1_slice_sao_chroma_flag))
2055             {
2056                 /*PIC INFO: SAO encode biys*/
2057                 UWORD32 u4_bits_estimated_prev =
2058                     ps_entropy_ctxt->s_cabac_ctxt.u4_bits_estimated_q12;
2059 
2060                 ret |= ihevce_cabac_encode_sao(ps_entropy_ctxt, ps_ctb);
2061 
2062                 if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
2063                 {
2064                     ps_entropy_ctxt->ps_pic_level_info->u8_bits_estimated_sao +=
2065                         (ps_entropy_ctxt->s_cabac_ctxt.u4_bits_estimated_q12 -
2066                          u4_bits_estimated_prev);
2067                 }
2068             }
2069         }
2070 
2071         ps_entropy_ctxt->s_cabac_ctxt.u4_bits_estimated_q12 = 0;
2072 
2073         if(ps_cabac->e_cabac_op_mode == CABAC_MODE_ENCODE_BITS)
2074         {
2075             /*PIC_INFO: Update total no.of CUS*/
2076             ps_entropy_ctxt->ps_pic_level_info->i8_total_cu += ps_ctb->u1_num_cus_in_ctb;
2077         }
2078         /* call recursive coding tree structure to encode all cus in ctb */
2079         ret |= ihevce_encode_coding_quadtree(
2080             ps_entropy_ctxt, x0_frm, y0_frm, log2_ctb_size, 0, ps_ctb, ps_tile_params);
2081 
2082         /* post ctb encode increments */
2083         ctb_ctr++;
2084         x0_frm += ctb_size;
2085         ps_entropy_ctxt->i4_ctb_x++;
2086         //ps_entropy_ctxt->i4_ctb_slice_x++;
2087 
2088         if(ps_pps->i1_entropy_coding_sync_enabled_flag && ps_entropy_ctxt->i4_ctb_x == 2)
2089         {
2090             /*backup cabac context at end of second CTB(top right neighbour for start of bottom row)*/
2091             ihevce_cabac_ctxt_backup(ps_cabac);
2092         }
2093 
2094         /* end of row check using x0_frm offset */
2095         if(x0_frm >= pic_width)
2096         {
2097             ctb_ctr = 0;
2098             ps_first_ctb += num_ctb_in_row;
2099             x0_frm = 0;
2100             y0_frm += ctb_size;
2101 
2102             ps_entropy_ctxt->i4_ctb_x = 0;
2103             ps_entropy_ctxt->i4_ctb_y++;
2104             //ps_entropy_ctxt->i4_ctb_slice_y++;
2105         }
2106 
2107         /* Detect end of slice. Which would mean end-of-slice-segment too */
2108         *pi4_end_of_slice_flag = (y0_frm >= pic_height);
2109 
2110         if(0 == ps_entropy_ctxt->i4_slice_segment_mode)
2111         {
2112             /* If slice ends then so does slice segment  */
2113             end_of_slice_seg_flag = *pi4_end_of_slice_flag;
2114 
2115             /*  encode terminate bin */
2116             ret |= ihevce_cabac_encode_terminate(ps_cabac, end_of_slice_seg_flag, 0);
2117         }
2118         else if(1 == ps_entropy_ctxt->i4_slice_segment_mode)
2119         {
2120             ps_entropy_ctxt->i4_slice_seg_len++;
2121             if((ps_entropy_ctxt->i4_slice_seg_len) >= ps_entropy_ctxt->i4_slice_segment_max_length)
2122             {
2123                 /* Store the address of CTB from where next slice segment will start */
2124                 ps_entropy_ctxt->i4_next_slice_seg_x = ps_entropy_ctxt->i4_ctb_x;
2125                 ps_entropy_ctxt->i4_next_slice_seg_y = ps_entropy_ctxt->i4_ctb_y;
2126             }
2127             else
2128             {
2129                 /* If slice ends then so does slice segment  */
2130                 end_of_slice_seg_flag = *pi4_end_of_slice_flag;
2131             }
2132 
2133             /*  encode terminate bin */
2134             ret |= ihevce_cabac_encode_terminate(ps_cabac, end_of_slice_seg_flag, 0);
2135         }
2136         else if(2 == ps_entropy_ctxt->i4_slice_segment_mode)
2137         {
2138             //WORD32 i4_slice_seg_len_prev = i4_slice_seg_len;
2139 
2140             /* Store some parameters. Will be used to revert back to this state if
2141             i4_slice_segment_max_length is not exceeded after encoding end-of-slice */
2142             s_cabac_after_ctb = *ps_cabac;
2143             u4_cur_ctb_temp =
2144                 *((UWORD32 *)(ps_cabac->pu1_strm_buffer + ps_cabac->u4_strm_buf_offset - 4));
2145 
2146             /*  encode terminate bin. For dependent slices, always simulate
2147             end-of-slice to check if i4_slice_segment_max_length is surpassed */
2148             ret |= ihevce_cabac_encode_terminate(ps_cabac, 1, 0);
2149 
2150             //i4_slice_seg_len_prev   = i4_slice_seg_len;
2151             ps_entropy_ctxt->i4_slice_seg_len =
2152                 (WORD32)(ps_cabac->u4_strm_buf_offset - u4_slice_start_offset);
2153 
2154             //ps_entropy_ctxt->i4_slice_seg_len = i4_slice_seg_len; //No need to update it.
2155 
2156             if(ps_entropy_ctxt->i4_slice_seg_len > ps_entropy_ctxt->i4_slice_segment_max_length)
2157             {
2158                 if(s_cabac_prev_ctb.pu1_strm_buffer == NULL)
2159                 {
2160                     /* Bytes in a single CTB has exceeded the i4_slice_segment_max_length
2161                     set by the user. Close the slice-segment and print a warning */
2162 
2163                     /* Store the address of CTB from where next slice segment will start */
2164                     ps_entropy_ctxt->i4_next_slice_seg_x = ps_entropy_ctxt->i4_ctb_x;
2165                     ps_entropy_ctxt->i4_next_slice_seg_y = ps_entropy_ctxt->i4_ctb_y;
2166 
2167                     ps_sys_api->ihevce_printf(
2168                         ps_sys_api->pv_cb_handle,
2169                         "IHEVCE_WARNING: CTB(%2d, %2d) encoded using %d bytes; "
2170                         "this exceeds max slice segment size %d as requested "
2171                         "by the user\n",
2172                         i4_curr_ctb_x,
2173                         i4_curr_ctb_y,
2174                         ps_entropy_ctxt->i4_slice_seg_len,
2175                         ps_entropy_ctxt->i4_slice_segment_max_length);
2176                 }
2177                 else /* Revert back to previous CTB's state and close current slice */
2178                 {
2179                     *ps_cabac = s_cabac_prev_ctb;
2180                     *((UWORD32 *)(ps_cabac->pu1_strm_buffer + ps_cabac->u4_strm_buf_offset - 4)) =
2181                         u4_prev_ctb_temp;
2182 
2183                     memcpy(
2184                         &ps_entropy_ctxt->pu1_cu_depth_top[i4_curr_ctb_x * 8], au1_cu_depth_top, 8);
2185                     memcpy(ps_entropy_ctxt->au1_cu_depth_left, au1_cu_depth_left, 8);
2186 
2187                     *(ps_entropy_ctxt->pu1_skip_cu_top + i4_curr_ctb_x) = u1_skip_cu_top;
2188                     ps_entropy_ctxt->u4_skip_cu_left = u4_skip_cu_left;
2189 
2190                     ps_entropy_ctxt->i1_cur_qp = i1_last_cu_qp;
2191 
2192                     /* Restore pic info */
2193                     *(ps_entropy_ctxt->ps_pic_level_info) = s_pic_level_info_backup;
2194 
2195                     /*  encode terminate bin with end-of-slice */
2196                     ret |= ihevce_cabac_encode_terminate(ps_cabac, 1, 0);
2197 
2198                     /* Store the address of CTB from where next slice segment will start */
2199                     ps_entropy_ctxt->i4_next_slice_seg_x = i4_curr_ctb_x;
2200                     ps_entropy_ctxt->i4_next_slice_seg_y = i4_curr_ctb_y;
2201 
2202                     /* As we are reverted back to the previous CTB, force end of slice to zero */
2203                     *pi4_end_of_slice_flag = 0;
2204                 }
2205             }
2206             else if(0 == *pi4_end_of_slice_flag)
2207             {
2208                 /* As this is not the end of slice, therefore revert back
2209                 the end-of-slice encoding and then add terminate bit */
2210 
2211                 /* Signal that this is not slice segment end */
2212                 end_of_slice_seg_flag = 0;
2213 
2214                 *ps_cabac = s_cabac_after_ctb;
2215                 *((UWORD32 *)(ps_cabac->pu1_strm_buffer + ps_cabac->u4_strm_buf_offset - 4)) =
2216                     u4_cur_ctb_temp;
2217 
2218                 /*  encode terminate bin */
2219                 ret |= ihevce_cabac_encode_terminate(ps_cabac, 0, 0);
2220             }
2221 
2222             /* Update variables storing previous CTB's state in order to be
2223             able to revert to previous CTB's state */
2224             s_cabac_prev_ctb = s_cabac_after_ctb;
2225             u4_prev_ctb_temp = u4_cur_ctb_temp;
2226 
2227             i1_last_cu_qp = ps_entropy_ctxt->i1_cur_qp;
2228         }
2229         else  //No other slice segment mode supported
2230         {
2231             ASSERT(0);
2232         }
2233 
2234         AEV_TRACE("end_of_slice_flag", end_of_slice_seg_flag, ps_cabac->u4_range);
2235 
2236         if((0 == ps_entropy_ctxt->i4_ctb_x) && (!end_of_slice_seg_flag) &&
2237            (ps_pps->i1_entropy_coding_sync_enabled_flag))
2238         {
2239             /* initialize qp to slice start qp */
2240             ps_entropy_ctxt->i1_cur_qp = slice_qp;
2241 
2242             /* flush and align to byte bounary for entropy sync every row */
2243             ret |= ihevce_cabac_encode_terminate(ps_cabac, 1, 1);
2244 
2245             /*This will be entered only during row end, tap bits generated in that row to cal entry point offset*/
2246             /*add error check to make sure row count doesnt exceed the size of array allocated*/
2247             ASSERT(ps_entropy_ctxt->i4_ctb_y < MAX_NUM_CTB_ROWS_FRM);
2248             ps_slice_hdr->pu4_entry_point_offset[ps_entropy_ctxt->i4_ctb_y] =
2249                 ps_cabac->u4_strm_buf_offset;
2250 
2251             /*init the cabac context with top right neighbour*/
2252             ret |= ihevce_cabac_ctxt_row_init(ps_cabac);
2253         }
2254 
2255     } while(!end_of_slice_seg_flag);
2256 
2257     if(end_of_slice_seg_flag && ps_pps->i1_entropy_coding_sync_enabled_flag)
2258     {
2259         ps_slice_hdr->pu4_entry_point_offset[ps_entropy_ctxt->i4_ctb_y] =
2260             ps_cabac->u4_strm_buf_offset;
2261     }
2262 
2263     return ret;
2264 }
2265