xref: /aosp_15_r20/external/libavc/encoder/svc/isvce_process.c (revision 495ae853bb871d1e5a258cb02c2cc13cde8ddb9a)
1 /******************************************************************************
2  *
3  * Copyright (C) 2022 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 *******************************************************************************
23 * @file
24 *  isvce_process.c
25 *
26 * @brief
27 *  Contains functions for codec thread
28 *
29 * @author
30 *  Harish
31 *
32 * @par List of Functions:
33 * - isvce_generate_sps_pps()
34 * - isvce_init_entropy_ctxt()
35 * - isvce_entropy()
36 * - isvce_pack_header_data()
37 * - isvce_update_proc_ctxt()
38 * - isvce_init_proc_ctxt()
39 * - isvce_pad_recon_buffer()
40 * - isvce_dblk_n_mbs()
41 * - isvce_process()
42 * - isvce_set_rc_pic_params()
43 * - isvce_update_rc_post_enc()
44 * - isvce_isvce_isvce_process_ctxt_thread()
45 *
46 * @remarks
47 *  None
48 *
49 *******************************************************************************
50 */
51 
52 #include <stdio.h>
53 #include <stddef.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <limits.h>
57 #include <assert.h>
58 #include <math.h>
59 #include <stdbool.h>
60 
61 #include "ih264_typedefs.h"
62 /* Dependencies of ih264_buf_mgr.h */
63 /* Dependencies of ih264_list.h */
64 #include "ih264_error.h"
65 /* Dependencies of ih264_common_tables.h */
66 #include "ih264_defs.h"
67 #include "ih264_structs.h"
68 #include "ih264_buf_mgr.h"
69 #include "ih264_common_tables.h"
70 #include "ih264_list.h"
71 #include "ih264_platform_macros.h"
72 #include "ih264_trans_data.h"
73 #include "ih264_size_defs.h"
74 /* Dependencies of ih264e_cabac_structs.h */
75 #include "ih264_cabac_tables.h"
76 /* Dependencies of ime_structs.h */
77 #include "ime_defs.h"
78 #include "ime_distortion_metrics.h"
79 /* Dependencies of ih264e_structs.h */
80 #include "iv2.h"
81 #include "ive2.h"
82 #include "ih264_defs.h"
83 #include "ih264_deblk_edge_filters.h"
84 #include "ih264_inter_pred_filters.h"
85 #include "ih264_structs.h"
86 #include "ih264_trans_quant_itrans_iquant.h"
87 /* Dependencies of ih264e_bitstream.h */
88 #include "ih264e_error.h"
89 #include "ih264e_bitstream.h"
90 #include "ih264e_cabac_structs.h"
91 #include "irc_cntrl_param.h"
92 #include "irc_frame_info_collector.h"
93 #include "ime_statistics.h"
94 #include "ime_structs.h"
95 /* Dependencies of 'ih264e_utils.h' */
96 #include "ih264e_defs.h"
97 #include "ih264e_structs.h"
98 #include "ih264e_utils.h"
99 #include "ime.h"
100 #include "isvce_cabac.h"
101 #include "isvce_cavlc.h"
102 #include "isvce_deblk.h"
103 #include "isvce_defs.h"
104 #include "isvce_downscaler.h"
105 #include "isvce_encode_header.h"
106 #include "isvce_ibl_eval.h"
107 #include "isvce_ilp_mv.h"
108 #include "isvce_intra_modes_eval.h"
109 #include "isvce_me.h"
110 #include "isvce_rate_control.h"
111 #include "isvce_residual_pred.h"
112 #include "isvce_sub_pic_rc.h"
113 #include "isvce_utils.h"
114 
115 /*****************************************************************************/
116 /* Function Definitions                                                      */
117 /*****************************************************************************/
118 
119 /**
120 ******************************************************************************
121 *
122 *  @brief This function generates sps, pps set on request
123 *
124 *  @par   Description
125 *  When the encoder is set in header generation mode, the following function
126 *  is called. This generates sps and pps headers and returns the control back
127 *  to caller.
128 *
129 *  @param[in]    ps_codec
130 *  pointer to codec context
131 *
132 *  @return      success or failure error code
133 *
134 ******************************************************************************
135 */
isvce_generate_sps_pps(isvce_codec_t * ps_codec,isvce_inp_buf_t * ps_inp_buf)136 IH264E_ERROR_T isvce_generate_sps_pps(isvce_codec_t *ps_codec, isvce_inp_buf_t *ps_inp_buf)
137 {
138     sps_t *ps_sps;
139     pps_t *ps_pps;
140     subset_sps_t *ps_subset_sps;
141 
142     WORD32 i;
143 
144     isvce_process_ctxt_t *ps_proc = ps_codec->as_process;
145     isvce_entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy;
146     bitstrm_t *ps_bitstrm = ps_entropy->ps_bitstrm;
147     isvce_out_buf_t *ps_out_buf = ps_codec->as_out_buf;
148 
149     UWORD8 u1_profile_idc = IH264_PROFILE_BASELINE;
150 
151     ASSERT(1 == MAX_CTXT_SETS);
152 
153     ih264e_bitstrm_init(ps_bitstrm, ps_out_buf->as_bits_buf[ps_proc->u1_spatial_layer_id].pv_buf,
154                         ps_out_buf->as_bits_buf[ps_proc->u1_spatial_layer_id].u4_bufsize);
155 
156     ps_sps = ps_codec->ps_sps_base;
157     isvce_populate_sps(ps_codec, ps_sps, 0, u1_profile_idc, ps_inp_buf, 0);
158 
159     ps_pps = ps_codec->ps_pps_base;
160     isvce_populate_pps(ps_codec, ps_pps, 0, 0, 0);
161 
162     for(i = 1; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
163     {
164         ps_subset_sps = ps_codec->ps_subset_sps_base + i;
165         isvce_populate_subset_sps(ps_codec, ps_subset_sps, i, ps_inp_buf, i);
166 
167         ps_pps = ps_codec->ps_pps_base + i;
168         isvce_populate_pps(ps_codec, ps_pps, i, i, i);
169     }
170 
171     ps_entropy->i4_error_code = IH264E_SUCCESS;
172 
173     ps_entropy->i4_error_code = isvce_generate_sps(ps_bitstrm, ps_sps, NAL_SPS);
174     if(ps_entropy->i4_error_code != IH264E_SUCCESS)
175     {
176         return ps_entropy->i4_error_code;
177     }
178 
179     ps_pps = ps_codec->ps_pps_base;
180     ps_entropy->i4_error_code = isvce_generate_pps(ps_bitstrm, ps_pps, ps_sps);
181 
182     for(i = 1; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
183     {
184         ps_subset_sps = ps_codec->ps_subset_sps_base + i;
185         isvce_generate_subset_sps(ps_bitstrm, ps_subset_sps);
186 
187         /* populate pps header */
188         ps_pps = ps_codec->ps_pps_base + i;
189         isvce_generate_pps(ps_bitstrm, ps_pps, &ps_subset_sps->s_sps);
190     }
191 
192     /* queue output buffer */
193     ps_out_buf->as_bits_buf[ps_proc->u1_spatial_layer_id].u4_bytes = ps_bitstrm->u4_strm_buf_offset;
194 
195     return ps_entropy->i4_error_code;
196 }
197 
198 /**
199 *******************************************************************************
200 *
201 * @brief   initialize entropy context.
202 *
203 * @par Description:
204 *  Before invoking the call to perform to entropy coding the entropy context
205 *  associated with the job needs to be initialized. This involves the start
206 *  mb address, end mb address, slice index and the pointer to location at
207 *  which the mb residue info and mb header info are packed.
208 *
209 * @param[in] ps_proc
210 *  Pointer to the current process context
211 *
212 * @returns error status
213 *
214 * @remarks none
215 *
216 *******************************************************************************
217 */
isvce_init_entropy_ctxt(isvce_process_ctxt_t * ps_proc)218 IH264E_ERROR_T isvce_init_entropy_ctxt(isvce_process_ctxt_t *ps_proc)
219 {
220     /* codec context */
221     isvce_codec_t *ps_codec = ps_proc->ps_codec;
222 
223     /* entropy ctxt */
224     isvce_entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy;
225 
226     /* start address */
227     ps_entropy->i4_mb_start_add = ps_entropy->i4_mb_y * ps_entropy->i4_wd_mbs + ps_entropy->i4_mb_x;
228 
229     /* end address */
230     ps_entropy->i4_mb_end_add = ps_entropy->i4_mb_start_add + ps_entropy->i4_mb_cnt;
231 
232     /* slice index */
233     ps_entropy->i4_cur_slice_idx = ps_proc->pu1_slice_idx[ps_entropy->i4_mb_start_add];
234 
235     /* sof */
236     /* @ start of frame or start of a new slice, set sof flag */
237     if(ps_entropy->i4_mb_start_add == 0)
238     {
239         ps_entropy->i4_sof = 1;
240     }
241 
242     if(ps_entropy->i4_mb_x == 0)
243     {
244         /* packed mb coeff data */
245         ps_entropy->pv_mb_coeff_data = ((UWORD8 *) ps_entropy->pv_pic_mb_coeff_data) +
246                                        ps_entropy->i4_mb_y * ps_codec->u4_size_coeff_data;
247 
248         /* packed mb header data */
249         ps_entropy->pv_mb_header_data = ((UWORD8 *) ps_entropy->pv_pic_mb_header_data) +
250                                         ps_entropy->i4_mb_y * ps_codec->u4_size_header_data;
251     }
252 
253     return IH264E_SUCCESS;
254 }
255 
256 /**
257 *******************************************************************************
258 *
259 * @brief
260 *  Function to update rc context after encoding
261 *
262 * @par   Description
263 *  This function updates the rate control context after the frame is encoded.
264 *  Number of bits consumed by the current frame, frame distortion, frame cost,
265 *  number of intra/inter mb's, ... are passed on to rate control context for
266 *  updating the rc model.
267 *
268 * @param[in] ps_codec
269 *  Handle to codec context
270 *
271 * @param[in] ctxt_sel
272 *  frame context selector
273 *
274 * @param[in] pic_cnt
275 *  pic count
276 *
277 * @returns i4_stuffing_byte
278 *  number of stuffing bytes (if necessary)
279 *
280 * @remarks
281 *
282 *******************************************************************************
283 */
isvce_update_rc_post_enc(isvce_codec_t * ps_codec,WORD32 ctxt_sel,WORD32 i4_is_first_frm)284 WORD32 isvce_update_rc_post_enc(isvce_codec_t *ps_codec, WORD32 ctxt_sel, WORD32 i4_is_first_frm)
285 {
286     WORD32 i4_proc_ctxt_sel_base = ctxt_sel ? (MAX_PROCESS_CTXT / 2) : 0;
287 
288     isvce_process_ctxt_t *ps_proc = &ps_codec->as_process[i4_proc_ctxt_sel_base];
289 
290 #if ENABLE_RE_ENC_AS_SKIP
291     isvce_entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy;
292 
293     UWORD8 u1_is_post_enc_skip = 0;
294 #endif
295 
296     /* frame qp */
297     UWORD8 u1_frame_qp = ps_codec->au4_frame_qp[ps_proc->u1_spatial_layer_id];
298 
299     /* cbr rc return status */
300     WORD32 i4_stuffing_byte = 0;
301 
302     /* current frame stats */
303     frame_info_t s_frame_info;
304     picture_type_e rc_pic_type = I_PIC;
305 
306     /* temp var */
307     WORD32 i, j;
308 
309     /********************************************************************/
310     /*                            BEGIN INIT                            */
311     /********************************************************************/
312 
313     /* init frame info */
314     irc_init_frame_info(&s_frame_info);
315 
316     /* get frame info */
317     for(i = 0; i < (WORD32) ps_codec->s_cfg.u4_num_cores; i++)
318     {
319         /*****************************************************************/
320         /* One frame can be encoded by max of u4_num_cores threads       */
321         /* Accumulating the num mbs, sad, qp and intra_mb_cost from      */
322         /* u4_num_cores threads                                          */
323         /*****************************************************************/
324         for(j = 0; j < MAX_MB_TYPE; j++)
325         {
326             s_frame_info.num_mbs[j] += ps_proc[i].s_frame_info.num_mbs[j];
327 
328             s_frame_info.tot_mb_sad[j] += ps_proc[i].s_frame_info.tot_mb_sad[j];
329 
330             s_frame_info.qp_sum[j] += ps_proc[i].s_frame_info.qp_sum[j];
331         }
332 
333         s_frame_info.intra_mb_cost_sum += ps_proc[i].s_frame_info.intra_mb_cost_sum;
334 
335         s_frame_info.activity_sum += ps_proc[i].s_frame_info.activity_sum;
336 
337         /*****************************************************************/
338         /* gather number of residue and header bits consumed by the frame*/
339         /*****************************************************************/
340         isvce_update_rc_bits_info(&s_frame_info, &ps_proc[i].s_entropy);
341     }
342 
343     /* get pic type */
344     switch(ps_codec->pic_type)
345     {
346         case PIC_I:
347         case PIC_IDR:
348             rc_pic_type = I_PIC;
349             break;
350         case PIC_P:
351             rc_pic_type = P_PIC;
352             break;
353         case PIC_B:
354             rc_pic_type = B_PIC;
355             break;
356         default:
357             assert(0);
358             break;
359     }
360 
361     /* update rc lib with current frame stats */
362     i4_stuffing_byte = isvce_rc_post_enc(
363         ps_codec->s_rate_control.apps_rate_control_api[ps_proc->u1_spatial_layer_id],
364         &(s_frame_info), ps_codec->s_rate_control.pps_pd_frm_rate,
365         ps_codec->s_rate_control.pps_time_stamp, ps_codec->s_rate_control.pps_frame_time,
366         (ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs), &rc_pic_type, i4_is_first_frm,
367         &ps_codec->s_rate_control.post_encode_skip[ctxt_sel], u1_frame_qp,
368         &ps_codec->s_rate_control.ai4_num_intra_in_prev_frame[ps_proc->u1_spatial_layer_id],
369         &ps_codec->s_rate_control.ai4_avg_activity[ps_proc->u1_spatial_layer_id]
370 #if ENABLE_RE_ENC_AS_SKIP
371         ,
372         &u1_is_post_enc_skip
373 #endif
374     );
375 
376 #if ENABLE_RE_ENC_AS_SKIP
377     if(u1_is_post_enc_skip)
378     {
379         buffer_container_t s_dst;
380 
381         WORD32 i;
382 
383         isa_dependent_fxns_t *ps_isa_dependent_fxns = &ps_codec->s_isa_dependent_fxns;
384         mem_fxns_t *ps_mem_fxns = &ps_isa_dependent_fxns->s_mem_fxns;
385         svc_ilp_data_t *ps_svc_ilp_data = &ps_codec->s_svc_ilp_data;
386 
387         UWORD8 u1_spatial_layer_id = ps_proc->u1_spatial_layer_id;
388         UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
389 
390         UWORD32 u4_wd = ps_codec->s_cfg.u4_wd;
391         UWORD32 u4_ht = ps_codec->s_cfg.u4_ht;
392         DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio;
393 
394         WORD32 i4_layer_luma_wd =
395             (WORD32) (((DOUBLE) u4_wd /
396                        pow(d_spatial_res_ratio, u1_num_spatial_layers - u1_spatial_layer_id - 1)) +
397                       0.99);
398         WORD32 i4_layer_luma_ht =
399             (WORD32) (((DOUBLE) u4_ht /
400                        pow(d_spatial_res_ratio, u1_num_spatial_layers - u1_spatial_layer_id - 1)) +
401                       0.99);
402 
403         if(CABAC == ps_entropy->u1_entropy_coding_mode_flag)
404         {
405             isvce_reencode_as_skip_frame_cabac(ps_entropy);
406         }
407         else
408         {
409             isvce_reencode_as_skip_frame_cavlc(ps_entropy);
410         }
411 
412         if(u1_num_spatial_layers > 1)
413         {
414             for(i = 0; i < ps_proc->i4_ht_mbs; i++)
415             {
416                 for(j = 0; j < ps_proc->i4_wd_mbs; j++)
417                 {
418                     isvce_update_ibl_info(ps_proc->ps_intra_pred_ctxt, u1_num_spatial_layers,
419                                           u1_spatial_layer_id, PSKIP, j, i, 0);
420                 }
421             }
422 
423             if(ENABLE_ILP_MV)
424             {
425                 svc_layer_data_t *ps_layer_data;
426 
427                 svc_au_data_t *ps_svc_au_data = ps_svc_ilp_data->ps_svc_au_data;
428 
429                 WORD32 i4_num_mbs = ps_proc->i4_ht_mbs * ps_proc->i4_wd_mbs;
430 
431                 ps_layer_data = &ps_svc_au_data->ps_svc_layer_data[ps_entropy->u1_spatial_layer_id];
432 
433                 memset(ps_layer_data->ps_mb_info, 0,
434                        i4_num_mbs * sizeof(ps_layer_data->ps_mb_info[0]));
435 
436                 for(i = 0; i < i4_num_mbs; i++)
437                 {
438                     ps_layer_data->pu4_num_pus_in_mb[i] = 1;
439                 }
440             }
441         }
442 
443         for(i = 0; i < NUM_SP_COMPONENTS; i++)
444         {
445             UWORD8 u1_is_chroma = (Y != ((COMPONENT_TYPE) i));
446             WORD32 i4_src_strd = ps_proc->aps_ref_pic[0]
447                                      ->ps_layer_yuv_buf_props[u1_spatial_layer_id]
448                                      .as_component_bufs[i]
449                                      .i4_data_stride;
450             WORD32 i4_dst_strd = ps_proc->ps_cur_pic->ps_layer_yuv_buf_props[u1_spatial_layer_id]
451                                      .as_component_bufs[i]
452                                      .i4_data_stride;
453 
454             if(u1_spatial_layer_id < (u1_num_spatial_layers - 1))
455             {
456                 s_dst.i4_data_stride = ps_svc_ilp_data->ps_intra_recon_bufs[u1_spatial_layer_id]
457                                            .as_component_bufs[i]
458                                            .i4_data_stride;
459                 s_dst.pv_data =
460                     ((UWORD8 *) ps_svc_ilp_data->ps_intra_recon_bufs[u1_spatial_layer_id]
461                          .as_component_bufs[i]
462                          .pv_data);
463 
464                 ps_mem_fxns->pf_memset_2d((UWORD8 *) s_dst.pv_data, s_dst.i4_data_stride, 0,
465                                           i4_layer_luma_wd, (i4_layer_luma_ht >> u1_is_chroma));
466 
467                 if(ENABLE_RESIDUAL_PREDICTION)
468                 {
469                     WORD16 *pi2_res;
470                     yuv_buf_props_t *ps_residual_buf =
471                         &ps_codec->s_svc_ilp_data.ps_residual_bufs[u1_spatial_layer_id];
472 
473                     pi2_res = ps_residual_buf->as_component_bufs[u1_is_chroma].pv_data;
474 
475                     ps_mem_fxns->pf_memset_2d(
476                         (UWORD8 *) pi2_res,
477                         ps_residual_buf->as_component_bufs[u1_is_chroma].i4_data_stride *
478                             (sizeof(WORD16) / sizeof(UWORD8)),
479                         0,
480                         ps_residual_buf->as_component_bufs[u1_is_chroma].i4_data_stride *
481                             (sizeof(WORD16) / sizeof(UWORD8)),
482                         i4_layer_luma_ht >> u1_is_chroma);
483                 }
484             }
485 
486             ps_mem_fxns->pf_copy_2d(
487                 (UWORD8 *) (ps_proc->ps_cur_pic->ps_layer_yuv_buf_props[u1_spatial_layer_id]
488                                 .as_component_bufs[i]
489                                 .pv_data) -
490                     PAD_LEFT - (PAD_TOP * i4_dst_strd),
491                 i4_dst_strd,
492                 (UWORD8 *) (ps_proc->aps_ref_pic[0]
493                                 ->ps_layer_yuv_buf_props[u1_spatial_layer_id]
494                                 .as_component_bufs[i]
495                                 .pv_data) -
496                     PAD_LEFT - (PAD_TOP * i4_src_strd),
497                 i4_src_strd, (i4_layer_luma_wd + PAD_WD),
498                 (i4_layer_luma_ht >> u1_is_chroma) + PAD_HT);
499         }
500 
501         RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
502     }
503 
504 #endif
505     return i4_stuffing_byte;
506 }
507 
508 /**
509 *******************************************************************************
510 *
511 * @brief entry point for entropy coding
512 *
513 * @par Description
514 *  This function calls lower level functions to perform entropy coding for a
515 *  group (n rows) of mb's. After encoding 1 row of mb's,  the function takes
516 *  back the control, updates the ctxt and calls lower level functions again.
517 *  This process is repeated till all the rows or group of mb's (which ever is
518 *  minimum) are coded
519 *
520 * @param[in] ps_proc
521 *  process context
522 *
523 * @returns  error status
524 *
525 * @remarks
526 *
527 *******************************************************************************
528 */
isvce_entropy(isvce_process_ctxt_t * ps_proc)529 IH264E_ERROR_T isvce_entropy(isvce_process_ctxt_t *ps_proc)
530 {
531     svc_nalu_ext_t *aps_svc_nalu_ext[2];
532     isvce_out_buf_t s_out_buf;
533     sei_params_t s_sei;
534     nalu_info_t *ps_slice_nalu_info;
535     nalu_info_t *ps_non_vcl_nalu_info;
536 
537     UWORD8 *pu1_proc_map;
538     UWORD8 *pu1_entropy_map_curr;
539     WORD32 i4_wd_mbs, i4_ht_mbs;
540     UWORD32 u4_mb_cnt, u4_mb_idx, u4_mb_end_idx, u4_insert_per_idr;
541     WORD32 bitstream_start_offset, bitstream_end_offset;
542 
543     isvce_codec_t *ps_codec = ps_proc->ps_codec;
544     isvce_entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy;
545     isvce_cabac_ctxt_t *ps_cabac_ctxt = ps_entropy->ps_cabac;
546     sps_t *ps_sps = ps_entropy->ps_sps_base;
547     subset_sps_t *ps_subset_sps = ps_entropy->ps_subset_sps_base;
548     pps_t *ps_pps = ps_entropy->ps_pps_base;
549     slice_header_t *ps_slice_hdr =
550         ps_entropy->ps_slice_hdr_base + (ps_entropy->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT);
551     svc_slice_header_t *ps_svc_slice_hdr = NULL;
552     bitstrm_t *ps_bitstrm = ps_entropy->ps_bitstrm;
553 #if ENABLE_RE_ENC_AS_SKIP
554     bitstrm_t *ps_bitstrm_after_slice_hdr = ps_entropy->ps_bitstrm_after_slice_hdr;
555 #endif
556     nalu_descriptors_t *ps_nalu_descriptor =
557         &ps_codec->as_nalu_descriptors[ps_proc->u1_spatial_layer_id];
558 
559     WORD32 i4_slice_type = ps_proc->i4_slice_type;
560     WORD32 ctxt_sel = ps_proc->i4_encode_api_call_cnt % MAX_CTXT_SETS;
561 
562     aps_svc_nalu_ext[0] =
563         ps_entropy->ps_svc_nalu_ext_base + (ps_entropy->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT);
564     aps_svc_nalu_ext[1] = ps_entropy->ps_svc_nalu_ext_base + 1 +
565                           (ps_entropy->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT);
566 
567     /********************************************************************/
568     /*                            BEGIN INIT                            */
569     /********************************************************************/
570 
571     /* entropy encode start address */
572     u4_mb_idx = ps_entropy->i4_mb_start_add;
573 
574     /* entropy encode end address */
575     u4_mb_end_idx = ps_entropy->i4_mb_end_add;
576 
577     /* width in mbs */
578     i4_wd_mbs = ps_entropy->i4_wd_mbs;
579 
580     /* height in mbs */
581     i4_ht_mbs = ps_entropy->i4_ht_mbs;
582 
583     /* total mb cnt */
584     u4_mb_cnt = i4_wd_mbs * i4_ht_mbs;
585 
586     /* proc map */
587     pu1_proc_map = ps_proc->pu1_proc_map + ps_entropy->i4_mb_y * i4_wd_mbs;
588 
589     /* entropy map */
590     pu1_entropy_map_curr = ps_entropy->pu1_entropy_map + ps_entropy->i4_mb_y * i4_wd_mbs;
591 
592     /********************************************************************/
593     /* @ start of frame / slice,                                        */
594     /*      initialize the output buffer,                               */
595     /*      initialize the bit stream buffer,                           */
596     /*      check if sps and pps headers have to be generated,          */
597     /*      populate and generate slice header                          */
598     /********************************************************************/
599     if(ps_entropy->i4_sof)
600     {
601         /********************************************************************/
602         /*      initialize the output buffer                                */
603         /********************************************************************/
604         s_out_buf = ps_codec->as_out_buf[ctxt_sel];
605 
606         /* is last frame to encode */
607         s_out_buf.u4_is_last = ps_entropy->u4_is_last;
608 
609         /* frame idx */
610         s_out_buf.u4_timestamp_high = ps_entropy->u4_timestamp_high;
611         s_out_buf.u4_timestamp_low = ps_entropy->u4_timestamp_low;
612 
613         /********************************************************************/
614         /*      initialize the bit stream buffer                            */
615         /********************************************************************/
616         ih264e_bitstrm_init(ps_bitstrm, s_out_buf.as_bits_buf[ps_proc->u1_spatial_layer_id].pv_buf,
617                             s_out_buf.as_bits_buf[ps_proc->u1_spatial_layer_id].u4_bufsize);
618 
619         /********************************************************************/
620         /*                    BEGIN HEADER GENERATION                       */
621         /********************************************************************/
622         if(1 == ps_entropy->i4_gen_header)
623         {
624             WORD32 i;
625 
626             ps_non_vcl_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
627             isvce_nalu_info_buf_init(ps_non_vcl_nalu_info,
628                                      -((WORD32) isvce_get_num_bits(ps_bitstrm)), NAL_SPS,
629                                      ps_proc->u1_spatial_layer_id,
630                                      ps_proc->ps_cur_pic->i1_temporal_id, 1, !!ps_proc->u4_is_idr);
631 
632             ps_entropy->i4_error_code = isvce_generate_sps(ps_bitstrm, ps_sps, NAL_SPS);
633             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
634 
635             ps_non_vcl_nalu_info->i8_num_bits += isvce_get_num_bits(ps_bitstrm);
636             isvce_update_nalu_count(ps_nalu_descriptor);
637 
638             for(i = 1; i < ps_proc->s_svc_params.u1_num_spatial_layers; i++)
639             {
640                 ps_subset_sps = ps_entropy->ps_subset_sps_base + i;
641 
642                 ps_non_vcl_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
643                 isvce_nalu_info_buf_init(
644                     ps_non_vcl_nalu_info, -((WORD32) isvce_get_num_bits(ps_bitstrm)),
645                     NAL_SUBSET_SPS, ps_proc->u1_spatial_layer_id,
646                     ps_proc->ps_cur_pic->i1_temporal_id, 1, !!ps_proc->u4_is_idr);
647 
648                 ps_entropy->i4_error_code = isvce_generate_subset_sps(ps_bitstrm, ps_subset_sps);
649 
650                 ps_non_vcl_nalu_info->i8_num_bits += isvce_get_num_bits(ps_bitstrm);
651                 isvce_update_nalu_count(ps_nalu_descriptor);
652             }
653 
654             ps_non_vcl_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
655             isvce_nalu_info_buf_init(ps_non_vcl_nalu_info,
656                                      -((WORD32) isvce_get_num_bits(ps_bitstrm)), NAL_PPS,
657                                      ps_proc->u1_spatial_layer_id,
658                                      ps_proc->ps_cur_pic->i1_temporal_id, 1, !!ps_proc->u4_is_idr);
659 
660             ps_entropy->i4_error_code = isvce_generate_pps(ps_bitstrm, ps_pps, ps_sps);
661             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
662 
663             ps_non_vcl_nalu_info->i8_num_bits += isvce_get_num_bits(ps_bitstrm);
664             isvce_update_nalu_count(ps_nalu_descriptor);
665 
666             for(i = 1; i < ps_proc->s_svc_params.u1_num_spatial_layers; i++)
667             {
668                 ps_pps = ps_entropy->ps_pps_base + i;
669                 ps_subset_sps = ps_entropy->ps_subset_sps_base + i;
670 
671                 ps_non_vcl_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
672                 isvce_nalu_info_buf_init(
673                     ps_non_vcl_nalu_info, -((WORD32) isvce_get_num_bits(ps_bitstrm)), NAL_PPS,
674                     ps_proc->u1_spatial_layer_id, ps_proc->ps_cur_pic->i1_temporal_id, 1,
675                     !!ps_proc->u4_is_idr);
676 
677                 ps_entropy->i4_error_code =
678                     isvce_generate_pps(ps_bitstrm, ps_pps, &ps_subset_sps->s_sps);
679 
680                 RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
681 
682                 ps_non_vcl_nalu_info->i8_num_bits += isvce_get_num_bits(ps_bitstrm);
683                 isvce_update_nalu_count(ps_nalu_descriptor);
684             }
685 
686             ps_entropy->i4_gen_header = 0;
687         }
688 
689         ps_svc_slice_hdr = ps_entropy->ps_svc_slice_hdr_base +
690                            (ps_entropy->i4_cur_slice_idx % SVC_MAX_SLICE_HDR_CNT);
691 
692         if((ps_codec->s_cfg.s_svc_params.u1_num_temporal_layers > 1) ||
693            (ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers > 1))
694         {
695             isvce_populate_svc_nalu_extension(ps_proc, aps_svc_nalu_ext[0], NAL_PREFIX,
696                                               ps_proc->u4_is_idr);
697 
698             if(ps_proc->u1_spatial_layer_id > 0)
699             {
700                 isvce_populate_svc_nalu_extension(ps_proc, aps_svc_nalu_ext[1],
701                                                   NAL_CODED_SLICE_EXTENSION, ps_proc->u4_is_idr);
702             }
703         }
704         else
705         {
706             isvce_populate_svc_nalu_extension(ps_proc, aps_svc_nalu_ext[0], NAL_PREFIX,
707                                               ps_proc->u4_is_idr);
708         }
709 
710         if(ps_proc->u1_spatial_layer_id > 0)
711         {
712             ps_subset_sps = ps_entropy->ps_subset_sps_base + ps_proc->u1_spatial_layer_id;
713             ps_pps = ps_entropy->ps_pps_base + ps_proc->u1_spatial_layer_id;
714 
715             ps_entropy->i4_error_code = isvce_populate_svc_slice(
716                 ps_proc, ps_svc_slice_hdr, ps_pps, ps_subset_sps, aps_svc_nalu_ext[1]);
717 
718             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
719 
720             ps_slice_hdr = &ps_svc_slice_hdr->s_slice_header;
721         }
722         else
723         {
724             ps_pps = ps_entropy->ps_pps_base;
725             ps_sps = ps_entropy->ps_sps_base;
726 
727             ps_entropy->i4_error_code = isvce_populate_slice_header(
728                 ps_proc, ps_slice_hdr, ps_pps, ps_sps, aps_svc_nalu_ext[0]->u1_idr_flag);
729 
730             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
731         }
732 
733         /* generate sei */
734         u4_insert_per_idr = (NAL_SLICE_IDR == ps_slice_hdr->i1_nal_unit_type);
735 
736         memset(&s_sei, 0, sizeof(sei_params_t));
737         s_sei.u1_sei_mdcv_params_present_flag =
738             ps_codec->s_cfg.s_sei.u1_sei_mdcv_params_present_flag;
739         s_sei.s_sei_mdcv_params = ps_codec->s_cfg.s_sei.s_sei_mdcv_params;
740         s_sei.u1_sei_cll_params_present_flag = ps_codec->s_cfg.s_sei.u1_sei_cll_params_present_flag;
741         s_sei.s_sei_cll_params = ps_codec->s_cfg.s_sei.s_sei_cll_params;
742         s_sei.u1_sei_ave_params_present_flag = ps_codec->s_cfg.s_sei.u1_sei_ave_params_present_flag;
743         s_sei.s_sei_ave_params = ps_codec->s_cfg.s_sei.s_sei_ave_params;
744         s_sei.u1_sei_ccv_params_present_flag = 0;
745         s_sei.s_sei_ccv_params =
746             ps_codec->as_inp_list[ps_codec->i4_poc % SVC_MAX_NUM_INP_FRAMES].s_inp_props.s_sei_ccv;
747 
748         if((1 == ps_sps->i1_vui_parameters_present_flag) &&
749            (1 == ps_codec->s_cfg.s_vui.u1_video_signal_type_present_flag) &&
750            (1 == ps_codec->s_cfg.s_vui.u1_colour_description_present_flag) &&
751            (2 != ps_codec->s_cfg.s_vui.u1_colour_primaries) &&
752            (2 != ps_codec->s_cfg.s_vui.u1_matrix_coefficients) &&
753            (2 != ps_codec->s_cfg.s_vui.u1_transfer_characteristics) &&
754            (4 != ps_codec->s_cfg.s_vui.u1_transfer_characteristics) &&
755            (5 != ps_codec->s_cfg.s_vui.u1_transfer_characteristics))
756         {
757             s_sei.u1_sei_ccv_params_present_flag =
758                 ps_codec->as_inp_list[ps_codec->i4_poc % SVC_MAX_NUM_INP_FRAMES]
759                     .s_inp_props.u1_sei_ccv_params_present_flag;
760         }
761 
762         if((1 == s_sei.u1_sei_mdcv_params_present_flag && u4_insert_per_idr) ||
763            (1 == s_sei.u1_sei_cll_params_present_flag && u4_insert_per_idr) ||
764            (1 == s_sei.u1_sei_ave_params_present_flag && u4_insert_per_idr) ||
765            (1 == s_sei.u1_sei_ccv_params_present_flag))
766         {
767             ps_non_vcl_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
768             isvce_nalu_info_buf_init(ps_non_vcl_nalu_info,
769                                      -((WORD32) isvce_get_num_bits(ps_bitstrm)), NAL_SEI,
770                                      ps_proc->u1_spatial_layer_id,
771                                      ps_proc->ps_cur_pic->i1_temporal_id, 1, !!ps_proc->u4_is_idr);
772 
773             ps_entropy->i4_error_code = ih264e_generate_sei(ps_bitstrm, &s_sei, u4_insert_per_idr);
774             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
775 
776             ps_non_vcl_nalu_info->i8_num_bits += isvce_get_num_bits(ps_bitstrm);
777             isvce_update_nalu_count(ps_nalu_descriptor);
778         }
779 
780         ps_codec->as_inp_list[ps_codec->i4_poc % SVC_MAX_NUM_INP_FRAMES]
781             .s_inp_props.u1_sei_ccv_params_present_flag = 0;
782 
783         if((ps_proc->u1_spatial_layer_id == 0) &&
784            (ps_codec->s_cfg.s_svc_params.u1_num_temporal_layers > 1 ||
785             ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers > 1))
786         {
787             ps_non_vcl_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
788             isvce_nalu_info_buf_init(ps_non_vcl_nalu_info,
789                                      -((WORD32) isvce_get_num_bits(ps_bitstrm)), NAL_PREFIX,
790                                      ps_proc->u1_spatial_layer_id,
791                                      ps_proc->ps_cur_pic->i1_temporal_id, 1, !!ps_proc->u4_is_idr);
792 
793             ps_entropy->i4_error_code =
794                 isvce_generate_svc_nalu_extension(ps_bitstrm, aps_svc_nalu_ext[0], NAL_PREFIX);
795 
796             ps_entropy->i4_error_code = isvce_generate_prefix_nal(
797                 ps_bitstrm, aps_svc_nalu_ext[0], ps_slice_hdr, ps_sps->u1_max_num_ref_frames,
798                 ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers);
799             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
800 
801             ps_non_vcl_nalu_info->i8_num_bits += isvce_get_num_bits(ps_bitstrm);
802             isvce_update_nalu_count(ps_nalu_descriptor);
803         }
804 
805         ps_slice_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
806         isvce_nalu_info_buf_init(ps_slice_nalu_info, -((WORD32) isvce_get_num_bits(ps_bitstrm)),
807                                  ps_slice_hdr->i1_nal_unit_type, ps_proc->u1_spatial_layer_id,
808                                  ps_proc->ps_cur_pic->i1_temporal_id, 1, !!ps_proc->u4_is_idr);
809 
810         if(ps_proc->u1_spatial_layer_id > 0)
811         {
812             ps_subset_sps = ps_entropy->ps_subset_sps_base + ps_proc->u1_spatial_layer_id;
813             ps_pps = ps_entropy->ps_pps_base + ps_proc->u1_spatial_layer_id;
814 
815             ps_entropy->i4_error_code = isvce_generate_svc_nalu_extension(
816                 ps_bitstrm, aps_svc_nalu_ext[1], NAL_CODED_SLICE_EXTENSION);
817 
818             ps_entropy->i4_error_code = isvce_generate_slice_header_svc(
819                 ps_bitstrm, ps_pps, aps_svc_nalu_ext[1], ps_svc_slice_hdr, ps_subset_sps);
820 
821             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
822         }
823         else
824         {
825             /* generate slice header */
826             ps_entropy->i4_error_code = isvce_generate_slice_header(
827                 ps_bitstrm, ps_slice_hdr, ps_pps, ps_sps, aps_svc_nalu_ext[0]->u1_idr_flag);
828 
829             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
830         }
831 
832         /* once start of frame / slice is done, you can reset it */
833         /* it is the responsibility of the caller to set this flag */
834         ps_entropy->i4_sof = 0;
835 
836         if(CABAC == ps_entropy->u1_entropy_coding_mode_flag)
837         {
838             BITSTREAM_BYTE_ALIGN(ps_bitstrm);
839             BITSTREAM_FLUSH(ps_bitstrm, ps_entropy->i4_error_code);
840             isvce_init_cabac_ctxt(ps_entropy, ps_slice_hdr);
841         }
842 
843 #if ENABLE_RE_ENC_AS_SKIP
844         ps_bitstrm_after_slice_hdr[0] = ps_bitstrm[0];
845 #endif
846     }
847 
848     /* begin entropy coding for the mb set */
849     while(u4_mb_idx < u4_mb_end_idx)
850     {
851         mb_bits_info_t s_mb_bits = {
852             .i8_header_bits = -((WORD64) ps_entropy->u4_header_bits[i4_slice_type == PSLICE]),
853             .i8_texture_bits = -((WORD64) ps_entropy->u4_residue_bits[i4_slice_type == PSLICE])};
854 
855         /* init ptrs/indices */
856         if(ps_entropy->i4_mb_x == i4_wd_mbs)
857         {
858             ps_entropy->i4_mb_y++;
859             ps_entropy->i4_mb_x = 0;
860 
861             /* packed mb coeff data */
862             ps_entropy->pv_mb_coeff_data = ((UWORD8 *) ps_entropy->pv_pic_mb_coeff_data) +
863                                            ps_entropy->i4_mb_y * ps_codec->u4_size_coeff_data;
864 
865             /* packed mb header data */
866             ps_entropy->pv_mb_header_data = ((UWORD8 *) ps_entropy->pv_pic_mb_header_data) +
867                                             ps_entropy->i4_mb_y * ps_codec->u4_size_header_data;
868 
869             /* proc map */
870             pu1_proc_map = ps_proc->pu1_proc_map + ps_entropy->i4_mb_y * i4_wd_mbs;
871 
872             /* entropy map */
873             pu1_entropy_map_curr = ps_entropy->pu1_entropy_map + ps_entropy->i4_mb_y * i4_wd_mbs;
874         }
875 
876         DEBUG("\nmb indices x, y %d, %d", ps_entropy->i4_mb_x, ps_entropy->i4_mb_y);
877         ENTROPY_TRACE("mb index x %d", ps_entropy->i4_mb_x);
878         ENTROPY_TRACE("mb index y %d", ps_entropy->i4_mb_y);
879 
880         /* wait until the curr mb is core coded */
881         /* The wait for curr mb to be core coded is essential when entropy is
882          * launched as a separate job
883          */
884         while(1)
885         {
886             volatile UWORD8 *pu1_buf1;
887             WORD32 idx = ps_entropy->i4_mb_x;
888 
889             pu1_buf1 = pu1_proc_map + idx;
890             if(*pu1_buf1) break;
891             ithread_yield();
892         }
893 
894         /* write mb layer */
895         ps_entropy->i4_error_code =
896             ps_codec->pf_write_mb_syntax_layer[ps_entropy->u1_entropy_coding_mode_flag]
897                                               [i4_slice_type](ps_entropy);
898         RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
899 
900         /* Starting bitstream offset for header in bits */
901         bitstream_start_offset = isvce_get_num_bits(ps_bitstrm);
902 
903         /* set entropy map */
904         pu1_entropy_map_curr[ps_entropy->i4_mb_x] = 1;
905         ASSERT(ps_entropy->i4_mb_x < i4_wd_mbs);
906 
907         u4_mb_idx++;
908         ps_entropy->i4_mb_x++;
909         /* check for eof */
910         if(CABAC == ps_entropy->u1_entropy_coding_mode_flag)
911         {
912             if(ps_entropy->i4_mb_x < i4_wd_mbs)
913             {
914                 isvce_cabac_encode_terminate(ps_cabac_ctxt, 0);
915             }
916         }
917 
918         if(ps_entropy->i4_mb_x == i4_wd_mbs)
919         {
920             /* if slices are enabled */
921             if(ps_codec->s_cfg.e_slice_mode == IVE_SLICE_MODE_BLOCKS)
922             {
923                 /* current slice index */
924                 WORD32 i4_curr_slice_idx = ps_entropy->i4_cur_slice_idx;
925 
926                 /* slice map */
927                 UWORD8 *pu1_slice_idx = ps_entropy->pu1_slice_idx;
928 
929                 /* No need to open a slice at end of frame. The current slice can be
930                  * closed at the time of signaling eof flag.
931                  */
932                 if((u4_mb_idx != u4_mb_cnt) && (i4_curr_slice_idx != pu1_slice_idx[u4_mb_idx]))
933                 {
934                     if(CAVLC == ps_entropy->u1_entropy_coding_mode_flag)
935                     { /* mb skip run */
936                         if((i4_slice_type != ISLICE) && *ps_entropy->pi4_mb_skip_run)
937                         {
938                             if(*ps_entropy->pi4_mb_skip_run)
939                             {
940                                 PUT_BITS_UEV(ps_bitstrm, *ps_entropy->pi4_mb_skip_run,
941                                              ps_entropy->i4_error_code, "mb skip run");
942                                 *ps_entropy->pi4_mb_skip_run = 0;
943                                 RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
944                             }
945                         }
946                         /* put rbsp trailing bits for the previous slice */
947                         ps_entropy->i4_error_code = ih264e_put_rbsp_trailing_bits(ps_bitstrm);
948                         RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
949                     }
950                     else
951                     {
952                         isvce_cabac_encode_terminate(ps_cabac_ctxt, 1);
953                     }
954 
955                     /* update slice header pointer */
956                     i4_curr_slice_idx = pu1_slice_idx[u4_mb_idx];
957                     ps_entropy->i4_cur_slice_idx = i4_curr_slice_idx;
958                     ps_slice_hdr =
959                         ps_entropy->ps_slice_hdr_base + (i4_curr_slice_idx % SVC_MAX_SLICE_HDR_CNT);
960 
961                     ps_entropy->u1_spatial_layer_id = ps_proc->u1_spatial_layer_id;
962 
963                     /* populate slice header */
964                     ps_entropy->i4_mb_start_add = u4_mb_idx;
965 
966                     /* generate slice header */
967                     if(ps_proc->u1_spatial_layer_id > 0)
968                     {
969                         ps_entropy->i4_error_code =
970                             isvce_generate_slice_header_svc(ps_bitstrm, ps_pps, aps_svc_nalu_ext[1],
971                                                             ps_svc_slice_hdr, ps_subset_sps);
972 
973                         RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
974 
975                         ps_slice_hdr = &ps_svc_slice_hdr->s_slice_header;
976                     }
977                     else
978                     {
979                         ps_entropy->i4_error_code =
980                             isvce_populate_slice_header(ps_proc, ps_slice_hdr, ps_pps, ps_sps,
981                                                         aps_svc_nalu_ext[0]->u1_idr_flag);
982 
983                         RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
984 
985                         ps_entropy->i4_error_code =
986                             isvce_generate_slice_header(ps_bitstrm, ps_slice_hdr, ps_pps, ps_sps,
987                                                         aps_svc_nalu_ext[0]->u1_idr_flag);
988 
989                         RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
990                     }
991 
992                     if(CABAC == ps_entropy->u1_entropy_coding_mode_flag)
993                     {
994                         BITSTREAM_BYTE_ALIGN(ps_bitstrm);
995                         BITSTREAM_FLUSH(ps_bitstrm, ps_entropy->i4_error_code);
996                         isvce_init_cabac_ctxt(ps_entropy, ps_slice_hdr);
997                     }
998                 }
999                 else
1000                 {
1001                     if(CABAC == ps_entropy->u1_entropy_coding_mode_flag && u4_mb_idx != u4_mb_cnt)
1002                     {
1003                         isvce_cabac_encode_terminate(ps_cabac_ctxt, 0);
1004                     }
1005                 }
1006             }
1007         }
1008 
1009         /* Ending bitstream offset for header in bits */
1010         bitstream_end_offset = isvce_get_num_bits(ps_bitstrm);
1011         ps_entropy->u4_header_bits[i4_slice_type == PSLICE] +=
1012             bitstream_end_offset - bitstream_start_offset;
1013 
1014         {
1015             svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt = ps_proc->ps_sub_pic_rc_ctxt;
1016             svc_sub_pic_rc_entropy_variables_t *ps_sub_pic_rc_variables =
1017                 &ps_sub_pic_rc_ctxt->s_sub_pic_rc_entropy_variables;
1018 
1019             s_mb_bits.i8_header_bits += ps_entropy->u4_header_bits[i4_slice_type == PSLICE];
1020             s_mb_bits.i8_texture_bits += ps_entropy->u4_residue_bits[i4_slice_type == PSLICE];
1021 
1022             ps_sub_pic_rc_variables->s_mb_bits = s_mb_bits;
1023             ps_sub_pic_rc_variables->u1_spatial_layer_id = ps_proc->u1_spatial_layer_id;
1024             ps_sub_pic_rc_variables->s_mb_pos.i4_abscissa = ps_entropy->i4_mb_x - 1;
1025             ps_sub_pic_rc_variables->s_mb_pos.i4_ordinate = ps_entropy->i4_mb_y;
1026 
1027             isvce_sub_pic_rc_get_entropy_data(ps_proc->ps_sub_pic_rc_ctxt);
1028         }
1029     }
1030 
1031     /* check for eof */
1032     if(u4_mb_idx == u4_mb_cnt)
1033     {
1034         /* set end of frame flag */
1035         ps_entropy->i4_eof = 1;
1036     }
1037     else
1038     {
1039         if(CABAC == ps_entropy->u1_entropy_coding_mode_flag &&
1040            ps_codec->s_cfg.e_slice_mode != IVE_SLICE_MODE_BLOCKS)
1041         {
1042             isvce_cabac_encode_terminate(ps_cabac_ctxt, 0);
1043         }
1044     }
1045 
1046     if(ps_entropy->i4_eof)
1047     {
1048         if(CAVLC == ps_entropy->u1_entropy_coding_mode_flag)
1049         {
1050             /* mb skip run */
1051             if((i4_slice_type != ISLICE) && *ps_entropy->pi4_mb_skip_run)
1052             {
1053                 if(*ps_entropy->pi4_mb_skip_run)
1054                 {
1055                     PUT_BITS_UEV(ps_bitstrm, *ps_entropy->pi4_mb_skip_run,
1056                                  ps_entropy->i4_error_code, "mb skip run");
1057                     *ps_entropy->pi4_mb_skip_run = 0;
1058                     RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
1059                 }
1060             }
1061             /* put rbsp trailing bits */
1062             ps_entropy->i4_error_code = ih264e_put_rbsp_trailing_bits(ps_bitstrm);
1063             RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
1064         }
1065         else
1066         {
1067             isvce_cabac_encode_terminate(ps_cabac_ctxt, 1);
1068         }
1069 
1070         /* update current frame stats to rc library */
1071         /* number of bytes to stuff */
1072         {
1073             WORD32 i4_stuff_bytes;
1074 
1075             /* update */
1076             i4_stuff_bytes = isvce_update_rc_post_enc(ps_codec, ctxt_sel, (ps_codec->i4_poc == 0));
1077 
1078             if(ps_proc->u1_spatial_layer_id == (ps_proc->s_svc_params.u1_num_spatial_layers - 1))
1079             {
1080                 /* cbr rc - house keeping */
1081                 if(ps_codec->s_rate_control.post_encode_skip[ctxt_sel])
1082                 {
1083                     ps_entropy->ps_bitstrm->u4_strm_buf_offset = 0;
1084                 }
1085                 else if(i4_stuff_bytes > 0)
1086                 {
1087                     /* add filler nal units */
1088                     ps_entropy->i4_error_code =
1089                         ih264e_add_filler_nal_unit(ps_bitstrm, i4_stuff_bytes);
1090                     RETURN_ENTROPY_IF_ERROR(ps_codec, ps_entropy, ctxt_sel);
1091                 }
1092             }
1093         }
1094 
1095         /*
1096          *Frame number is to be incremented only if the current frame is a
1097          * reference frame. After each successful frame encode, we increment
1098          * frame number by 1
1099          */
1100         if(!ps_codec->s_rate_control.post_encode_skip[ctxt_sel] && ps_codec->u4_is_curr_frm_ref &&
1101            (ps_proc->u1_spatial_layer_id == ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers - 1))
1102         {
1103             ps_codec->i4_frame_num++;
1104         }
1105 
1106         /********************************************************************/
1107         /*      signal the output                                           */
1108         /********************************************************************/
1109         ps_codec->as_out_buf[ctxt_sel].as_bits_buf[ps_entropy->u1_spatial_layer_id].u4_bytes =
1110             ps_bitstrm->u4_strm_buf_offset;
1111 
1112         ps_slice_nalu_info = isvce_get_next_nalu_info_buf(ps_nalu_descriptor);
1113         ps_slice_nalu_info->i8_num_bits += isvce_get_num_bits(ps_bitstrm);
1114         isvce_update_nalu_count(ps_nalu_descriptor);
1115 
1116         DEBUG("entropy status %x", ps_entropy->i4_error_code);
1117         ps_entropy->i4_eof = 0;
1118     }
1119 
1120     /* Dont execute any further instructions until store synchronization took
1121      * place */
1122     DATA_SYNC();
1123 
1124     /* allow threads to dequeue entropy jobs */
1125     ps_codec->ae_entropy_thread_exit_state[ctxt_sel] = INACTIVE;
1126 
1127     return ps_entropy->i4_error_code;
1128 }
1129 
1130 /**
1131 *******************************************************************************
1132 *
1133 * @brief Packs header information of a mb in to a buffer
1134 *
1135 * @par Description:
1136 *  After the deciding the mode info of a macroblock, the syntax elements
1137 *  associated with the mb are packed and stored. The entropy thread unpacks
1138 *  this buffer and generates the end bit stream.
1139 *
1140 * @param[in] ps_proc
1141 *  Pointer to the current process context
1142 *
1143 * @returns error status
1144 *
1145 * @remarks none
1146 *
1147 *******************************************************************************
1148 */
isvce_pack_header_data(isvce_process_ctxt_t * ps_proc)1149 IH264E_ERROR_T isvce_pack_header_data(isvce_process_ctxt_t *ps_proc)
1150 {
1151     /* curr mb type */
1152     UWORD32 u4_mb_type = ps_proc->ps_mb_info->u2_mb_type;
1153 
1154     /* pack mb syntax layer of curr mb (used for entropy coding) */
1155     if(u4_mb_type == I4x4)
1156     {
1157         /* pointer to mb header storage space */
1158         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1159         isvce_mb_hdr_i4x4_t *ps_mb_hdr = (isvce_mb_hdr_i4x4_t *) ps_proc->pv_mb_header_data;
1160 
1161         /* temp var */
1162         WORD32 i4, byte;
1163 
1164         /* mb type plus mode */
1165         ps_mb_hdr->common.u1_mb_type_mode = (ps_proc->u1_c_i8_mode << 6) + u4_mb_type;
1166 
1167         /* cbp */
1168         ps_mb_hdr->common.u1_cbp = ps_proc->u4_cbp;
1169 
1170         /* mb qp delta */
1171         ps_mb_hdr->common.u1_mb_qp = ps_proc->u1_mb_qp;
1172 
1173         ps_mb_hdr->common.u1_residual_prediction_flag =
1174             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1175 
1176         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1177 
1178         /* sub mb modes */
1179         for(i4 = 0; i4 < 16; i4++)
1180         {
1181             byte = 0;
1182 
1183             if(ps_proc->au1_predicted_intra_luma_mb_4x4_modes[i4] ==
1184                ps_proc->au1_intra_luma_mb_4x4_modes[i4])
1185             {
1186                 byte |= 1;
1187             }
1188             else
1189             {
1190                 if(ps_proc->au1_intra_luma_mb_4x4_modes[i4] <
1191                    ps_proc->au1_predicted_intra_luma_mb_4x4_modes[i4])
1192                 {
1193                     byte |= (ps_proc->au1_intra_luma_mb_4x4_modes[i4] << 1);
1194                 }
1195                 else
1196                 {
1197                     byte |= (ps_proc->au1_intra_luma_mb_4x4_modes[i4] - 1) << 1;
1198                 }
1199             }
1200 
1201             i4++;
1202 
1203             if(ps_proc->au1_predicted_intra_luma_mb_4x4_modes[i4] ==
1204                ps_proc->au1_intra_luma_mb_4x4_modes[i4])
1205             {
1206                 byte |= 16;
1207             }
1208             else
1209             {
1210                 if(ps_proc->au1_intra_luma_mb_4x4_modes[i4] <
1211                    ps_proc->au1_predicted_intra_luma_mb_4x4_modes[i4])
1212                 {
1213                     byte |= (ps_proc->au1_intra_luma_mb_4x4_modes[i4] << 5);
1214                 }
1215                 else
1216                 {
1217                     byte |= (ps_proc->au1_intra_luma_mb_4x4_modes[i4] - 1) << 5;
1218                 }
1219             }
1220 
1221             ps_mb_hdr->au1_sub_blk_modes[i4 >> 1] = byte;
1222         }
1223 
1224         /* end of mb layer */
1225         pu1_ptr += sizeof(isvce_mb_hdr_i4x4_t);
1226         ps_proc->pv_mb_header_data = pu1_ptr;
1227     }
1228     else if(u4_mb_type == I16x16)
1229     {
1230         /* pointer to mb header storage space */
1231         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1232         isvce_mb_hdr_i16x16_t *ps_mb_hdr = (isvce_mb_hdr_i16x16_t *) ps_proc->pv_mb_header_data;
1233 
1234         /* mb type plus mode */
1235         ps_mb_hdr->common.u1_mb_type_mode =
1236             (ps_proc->u1_c_i8_mode << 6) + (ps_proc->u1_l_i16_mode << 4) + u4_mb_type;
1237 
1238         /* cbp */
1239         ps_mb_hdr->common.u1_cbp = ps_proc->u4_cbp;
1240 
1241         /* mb qp delta */
1242         ps_mb_hdr->common.u1_mb_qp = ps_proc->u1_mb_qp;
1243 
1244         ps_mb_hdr->common.u1_residual_prediction_flag =
1245             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1246 
1247         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1248 
1249         /* end of mb layer */
1250         pu1_ptr += sizeof(isvce_mb_hdr_i16x16_t);
1251         ps_proc->pv_mb_header_data = pu1_ptr;
1252     }
1253     else if(u4_mb_type == P16x16)
1254     {
1255         /* pointer to mb header storage space */
1256         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1257         isvce_mb_hdr_p16x16_t *ps_mb_hdr = (isvce_mb_hdr_p16x16_t *) ps_proc->pv_mb_header_data;
1258 
1259         /* mb type */
1260         ps_mb_hdr->common.u1_mb_type_mode = u4_mb_type;
1261 
1262         /* cbp */
1263         ps_mb_hdr->common.u1_cbp = ps_proc->u4_cbp;
1264 
1265         /* mb qp delta */
1266         ps_mb_hdr->common.u1_mb_qp = ps_proc->u1_mb_qp;
1267 
1268         ps_mb_hdr->common.u1_residual_prediction_flag =
1269             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1270 
1271         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1272 
1273         ps_mb_hdr->u1_mvp_idx = ps_proc->ps_mb_info->as_pu->au1_mvp_idx[L0];
1274 
1275         if(0 == ps_proc->ps_mb_info->as_pu->au1_mvp_idx[L0])
1276         {
1277             ps_mb_hdr->ai2_mvd[0] = ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvx -
1278                                     ps_proc->ps_pred_mv[L0].s_mv.i2_mvx;
1279             ps_mb_hdr->ai2_mvd[1] = ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvy -
1280                                     ps_proc->ps_pred_mv[L0].s_mv.i2_mvy;
1281         }
1282         else
1283         {
1284             ps_mb_hdr->ai2_mvd[0] = ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvx -
1285                                     ps_proc->ps_ilp_mv->as_mv[0][L0].s_mv.i2_mvx;
1286             ps_mb_hdr->ai2_mvd[1] = ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvy -
1287                                     ps_proc->ps_ilp_mv->as_mv[0][L0].s_mv.i2_mvy;
1288         }
1289 
1290         /* end of mb layer */
1291         pu1_ptr += sizeof(isvce_mb_hdr_p16x16_t);
1292         ps_proc->pv_mb_header_data = pu1_ptr;
1293     }
1294     else if(u4_mb_type == PSKIP)
1295     {
1296         /* pointer to mb header storage space */
1297         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1298         isvce_mb_hdr_pskip_t *ps_mb_hdr = (isvce_mb_hdr_pskip_t *) ps_proc->pv_mb_header_data;
1299 
1300         /* mb type */
1301         ps_mb_hdr->common.u1_mb_type_mode = u4_mb_type;
1302 
1303         ps_mb_hdr->common.u1_residual_prediction_flag =
1304             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1305 
1306         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1307 
1308         /* end of mb layer */
1309         pu1_ptr += sizeof(isvce_mb_hdr_pskip_t);
1310         ps_proc->pv_mb_header_data = pu1_ptr;
1311     }
1312     else if(u4_mb_type == B16x16)
1313     {
1314         WORD32 i;
1315 
1316         /* pointer to mb header storage space */
1317         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1318         isvce_mb_hdr_b16x16_t *ps_mb_hdr = (isvce_mb_hdr_b16x16_t *) ps_proc->pv_mb_header_data;
1319 
1320         UWORD32 u4_pred_mode = ps_proc->ps_mb_info->as_pu->u1_pred_mode;
1321 
1322         /* mb type plus mode */
1323         ps_mb_hdr->common.u1_mb_type_mode = (u4_pred_mode << 4) + u4_mb_type;
1324 
1325         /* cbp */
1326         ps_mb_hdr->common.u1_cbp = ps_proc->u4_cbp;
1327 
1328         /* mb qp delta */
1329         ps_mb_hdr->common.u1_mb_qp = ps_proc->u1_mb_qp;
1330 
1331         ps_mb_hdr->common.u1_residual_prediction_flag =
1332             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1333 
1334         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1335 
1336         for(i = 0; i < NUM_PRED_DIRS; i++)
1337         {
1338             PRED_MODE_T e_pred_mode = (PRED_MODE_T) i;
1339             PRED_MODE_T e_cmpl_pred_mode = (e_pred_mode == L0) ? L1 : L0;
1340 
1341             if(u4_pred_mode != e_pred_mode)
1342             {
1343                 ps_mb_hdr->au1_mvp_idx[e_cmpl_pred_mode] =
1344                     ps_proc->ps_mb_info->as_pu->au1_mvp_idx[e_cmpl_pred_mode];
1345 
1346                 if(0 == ps_proc->ps_mb_info->as_pu->au1_mvp_idx[e_cmpl_pred_mode])
1347                 {
1348                     ps_mb_hdr->ai2_mvd[e_cmpl_pred_mode][0] =
1349                         ps_proc->ps_mb_info->as_pu->as_me_info[e_cmpl_pred_mode].s_mv.i2_mvx -
1350                         ps_proc->ps_pred_mv[e_cmpl_pred_mode].s_mv.i2_mvx;
1351                     ps_mb_hdr->ai2_mvd[e_cmpl_pred_mode][1] =
1352                         ps_proc->ps_mb_info->as_pu->as_me_info[e_cmpl_pred_mode].s_mv.i2_mvy -
1353                         ps_proc->ps_pred_mv[e_cmpl_pred_mode].s_mv.i2_mvy;
1354                 }
1355                 else
1356                 {
1357                     ps_mb_hdr->ai2_mvd[e_cmpl_pred_mode][0] =
1358                         ps_proc->ps_mb_info->as_pu->as_me_info[e_cmpl_pred_mode].s_mv.i2_mvx -
1359                         ps_proc->ps_ilp_mv->as_mv[0][e_cmpl_pred_mode].s_mv.i2_mvx;
1360                     ps_mb_hdr->ai2_mvd[e_cmpl_pred_mode][1] =
1361                         ps_proc->ps_mb_info->as_pu->as_me_info[e_cmpl_pred_mode].s_mv.i2_mvy -
1362                         ps_proc->ps_ilp_mv->as_mv[0][e_cmpl_pred_mode].s_mv.i2_mvy;
1363                 }
1364             }
1365         }
1366 
1367         /* end of mb layer */
1368         pu1_ptr += sizeof(isvce_mb_hdr_b16x16_t);
1369         ps_proc->pv_mb_header_data = pu1_ptr;
1370     }
1371     else if(u4_mb_type == BDIRECT)
1372     {
1373         /* pointer to mb header storage space */
1374         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1375         isvce_mb_hdr_bdirect_t *ps_mb_hdr = (isvce_mb_hdr_bdirect_t *) ps_proc->pv_mb_header_data;
1376 
1377         /* mb type plus mode */
1378         ps_mb_hdr->common.u1_mb_type_mode = u4_mb_type;
1379 
1380         /* cbp */
1381         ps_mb_hdr->common.u1_cbp = ps_proc->u4_cbp;
1382 
1383         /* mb qp delta */
1384         ps_mb_hdr->common.u1_mb_qp = ps_proc->u1_mb_qp;
1385 
1386         ps_mb_hdr->common.u1_residual_prediction_flag =
1387             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1388 
1389         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1390 
1391         /* end of mb layer */
1392         pu1_ptr += sizeof(isvce_mb_hdr_bdirect_t);
1393         ps_proc->pv_mb_header_data = pu1_ptr;
1394     }
1395     else if(u4_mb_type == BSKIP)
1396     {
1397         UWORD32 u4_pred_mode = ps_proc->ps_mb_info->as_pu->u1_pred_mode;
1398 
1399         /* pointer to mb header storage space */
1400         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1401         isvce_mb_hdr_bskip_t *ps_mb_hdr = (isvce_mb_hdr_bskip_t *) ps_proc->pv_mb_header_data;
1402 
1403         /* mb type plus mode */
1404         ps_mb_hdr->common.u1_mb_type_mode = (u4_pred_mode << 4) + u4_mb_type;
1405 
1406         ps_mb_hdr->common.u1_residual_prediction_flag =
1407             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1408 
1409         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1410 
1411         /* end of mb layer */
1412         pu1_ptr += sizeof(isvce_mb_hdr_bskip_t);
1413         ps_proc->pv_mb_header_data = pu1_ptr;
1414     }
1415     else if(u4_mb_type == BASE_MODE)
1416     {
1417         isvce_mb_hdr_base_mode_t *ps_mb_hdr =
1418             (isvce_mb_hdr_base_mode_t *) ps_proc->pv_mb_header_data;
1419 
1420         UWORD8 *pu1_ptr = ps_proc->pv_mb_header_data;
1421 
1422         ASSERT(ps_proc->ps_mb_info->u1_base_mode_flag == 1);
1423 
1424         ps_mb_hdr->common.u1_mb_type_mode = u4_mb_type;
1425 
1426         ps_mb_hdr->common.u1_cbp = ps_proc->u4_cbp;
1427 
1428         ps_mb_hdr->common.u1_mb_qp = ps_proc->u1_mb_qp;
1429 
1430         ps_mb_hdr->common.u1_residual_prediction_flag =
1431             ps_proc->ps_mb_info->u1_residual_prediction_flag;
1432 
1433         ps_mb_hdr->common.u1_base_mode_flag = ps_proc->ps_mb_info->u1_base_mode_flag;
1434 
1435         pu1_ptr += sizeof(isvce_mb_hdr_base_mode_t);
1436         ps_proc->pv_mb_header_data = pu1_ptr;
1437     }
1438 
1439     return IH264E_SUCCESS;
1440 }
1441 
1442 /**
1443 *******************************************************************************
1444 *
1445 * @brief   update process context after encoding an mb. This involves preserving
1446 * the current mb information for later use, initialize the proc ctxt elements to
1447 * encode next mb.
1448 *
1449 * @par Description:
1450 *  This function performs house keeping tasks after encoding an mb.
1451 *  After encoding an mb, various elements of the process context needs to be
1452 *  updated to encode the next mb. For instance, the source, recon and reference
1453 *  pointers, mb indices have to be adjusted to the next mb. The slice index of
1454 *  the current mb needs to be updated. If mb qp modulation is enabled, then if
1455 *  the qp changes the quant param structure needs to be updated. Also to
1456 *encoding the next mb, the current mb info is used as part of mode prediction or
1457 *mv prediction. Hence the current mb info has to preserved at top/top left/left
1458 *  locations.
1459 *
1460 * @param[in] ps_proc
1461 *  Pointer to the current process context
1462 *
1463 * @returns none
1464 *
1465 * @remarks none
1466 *
1467 *******************************************************************************
1468 */
isvce_update_proc_ctxt(isvce_process_ctxt_t * ps_proc)1469 WORD32 isvce_update_proc_ctxt(isvce_process_ctxt_t *ps_proc)
1470 {
1471     /* error status */
1472     WORD32 error_status = IH264_SUCCESS;
1473 
1474     /* codec context */
1475     isvce_codec_t *ps_codec = ps_proc->ps_codec;
1476     isa_dependent_fxns_t *ps_isa_dependent_fxns = &ps_codec->s_isa_dependent_fxns;
1477     mem_fxns_t *ps_mem_fxns = &ps_isa_dependent_fxns->s_mem_fxns;
1478 
1479     /* curr mb indices */
1480     WORD32 i4_mb_x = ps_proc->i4_mb_x;
1481     WORD32 i4_mb_y = ps_proc->i4_mb_y;
1482 
1483     /* mb syntax elements of neighbors */
1484     isvce_mb_info_t *ps_left_syn = ps_proc->s_nbr_info.ps_left_mb_info;
1485     isvce_mb_info_t *ps_top_syn =
1486         ps_proc->s_nbr_info_base.ps_layer_nbr_info[ps_proc->u1_spatial_layer_id]
1487             .ps_top_row_mb_info +
1488         i4_mb_x + i4_mb_y * ps_proc->i4_wd_mbs;
1489 
1490     /* curr mb type */
1491     UWORD32 u4_mb_type = ps_proc->ps_mb_info->u2_mb_type;
1492 
1493     /* curr mb type */
1494     UWORD32 u4_is_intra = ps_proc->ps_mb_info->u1_is_intra;
1495 
1496     /* width in mbs */
1497     WORD32 i4_wd_mbs = ps_proc->i4_wd_mbs;
1498 
1499     /*height in mbs*/
1500     WORD32 i4_ht_mbs = ps_proc->i4_ht_mbs;
1501 
1502     /* proc map */
1503     UWORD8 *pu1_proc_map = ps_proc->pu1_proc_map + (i4_mb_y * i4_wd_mbs);
1504 
1505     /* deblk context */
1506     isvce_deblk_ctxt_t *ps_deblk = &ps_proc->s_deblk_ctxt;
1507 
1508     /* deblk bs context */
1509     isvce_bs_ctxt_t *ps_bs = &(ps_deblk->s_bs_ctxt);
1510 
1511     /* sub mb modes */
1512     UWORD8 *pu1_top_mb_intra_modes =
1513         (ps_proc->s_nbr_info_base.ps_layer_nbr_info[ps_proc->u1_spatial_layer_id]
1514              .ps_top_mb_intra_modes +
1515          i4_mb_x + i4_mb_y * ps_proc->i4_wd_mbs)
1516             ->au1_intra_modes;
1517 
1518     /*************************************************************/
1519     /* During MV prediction, when top right mb is not available, */
1520     /* top left mb info. is used for prediction. Hence the curr  */
1521     /* top, which will be top left for the next mb needs to be   */
1522     /* preserved before updating it with curr mb info.           */
1523     /*************************************************************/
1524 
1525     /*************************************************/
1526     /* update top and left with curr mb info results */
1527     /*************************************************/
1528     ps_left_syn[0] = ps_top_syn[0] = ps_proc->ps_mb_info[0];
1529     ps_left_syn->u2_mb_type = ps_top_syn->u2_mb_type = u4_mb_type;
1530     ps_left_syn->i4_mb_distortion = ps_top_syn->i4_mb_distortion = ps_proc->i4_mb_distortion;
1531 
1532     if(u4_is_intra)
1533     {
1534         /* mb / sub mb modes */
1535         if(I16x16 == u4_mb_type)
1536         {
1537             pu1_top_mb_intra_modes[0] =
1538                 ps_proc->s_nbr_info.ps_left_mb_intra_modes->au1_intra_modes[0] =
1539                     ps_proc->u1_l_i16_mode;
1540         }
1541         else if(I4x4 == u4_mb_type)
1542         {
1543             ps_mem_fxns->pf_mem_cpy_mul8(
1544                 ps_proc->s_nbr_info.ps_left_mb_intra_modes->au1_intra_modes,
1545                 ps_proc->au1_intra_luma_mb_4x4_modes, 16);
1546             ps_mem_fxns->pf_mem_cpy_mul8(pu1_top_mb_intra_modes,
1547                                          ps_proc->au1_intra_luma_mb_4x4_modes, 16);
1548         }
1549         else if(I8x8 == u4_mb_type)
1550         {
1551             memcpy(ps_proc->s_nbr_info.ps_left_mb_intra_modes->au1_intra_modes,
1552                    ps_proc->au1_intra_luma_mb_8x8_modes, 4);
1553             memcpy(pu1_top_mb_intra_modes, ps_proc->au1_intra_luma_mb_8x8_modes, 4);
1554         }
1555 
1556         *ps_proc->pu4_mb_pu_cnt = 1;
1557     }
1558 
1559     /*
1560      * Mark that the MB has been coded intra
1561      * So that future AIRs can skip it
1562      */
1563     ps_proc->pu1_is_intra_coded[i4_mb_x + (i4_mb_y * i4_wd_mbs)] = u4_is_intra;
1564 
1565     /**************************************************/
1566     /* pack mb header info. for entropy coding        */
1567     /**************************************************/
1568     isvce_pack_header_data(ps_proc);
1569 
1570     /*
1571      * We need to sync the cache to make sure that the nmv content of proc
1572      * is updated to cache properly
1573      */
1574     DATA_SYNC();
1575 
1576     /* Just before finishing the row, enqueue the job in to entropy queue.
1577      * The master thread depending on its convenience shall dequeue it and
1578      * performs entropy.
1579      *
1580      * WARN !! Placing this block post proc map update can cause queuing of
1581      * entropy jobs in out of order.
1582      */
1583     if(i4_mb_x == i4_wd_mbs - 1)
1584     {
1585         /* job structures */
1586         job_t s_job;
1587 
1588         /* job class */
1589         s_job.i4_cmd = CMD_ENTROPY;
1590 
1591         /* number of mbs to be processed in the current job */
1592         s_job.i2_mb_cnt = ps_proc->i4_wd_mbs;
1593 
1594         /* job start index x */
1595         s_job.i2_mb_x = 0;
1596 
1597         /* job start index y */
1598         s_job.i2_mb_y = ps_proc->i4_mb_y;
1599 
1600         /* queue the job */
1601         error_status = ih264_list_queue(ps_proc->pv_entropy_jobq, &s_job, 1);
1602 
1603         if(error_status != IH264_SUCCESS)
1604         {
1605             return error_status;
1606         }
1607 
1608         if(ps_proc->i4_mb_y == (i4_ht_mbs - 1))
1609         {
1610             ih264_list_terminate(ps_codec->pv_entropy_jobq);
1611         }
1612     }
1613 
1614     /* update proc map */
1615     pu1_proc_map[i4_mb_x] = 1;
1616     ASSERT(i4_mb_x < i4_wd_mbs);
1617 
1618     /**************************************************/
1619     /* update proc ctxt elements for encoding next mb */
1620     /**************************************************/
1621     /* update indices */
1622     i4_mb_x++;
1623     ps_proc->i4_mb_x = i4_mb_x;
1624 
1625     if(ps_proc->i4_mb_x == i4_wd_mbs)
1626     {
1627         ps_proc->i4_mb_y++;
1628         ps_proc->i4_mb_x = 0;
1629     }
1630 
1631     /* update slice index */
1632     ps_proc->i4_cur_slice_idx =
1633         ps_proc->pu1_slice_idx[ps_proc->i4_mb_y * i4_wd_mbs + ps_proc->i4_mb_x];
1634 
1635     /* update buffers pointers */
1636     ps_proc->s_src_buf_props.as_component_bufs[0].pv_data =
1637         ((UWORD8 *) ps_proc->s_src_buf_props.as_component_bufs[0].pv_data) + MB_SIZE;
1638     ps_proc->s_rec_buf_props.as_component_bufs[0].pv_data =
1639         ((UWORD8 *) ps_proc->s_rec_buf_props.as_component_bufs[0].pv_data) + MB_SIZE;
1640     ps_proc->as_ref_buf_props[0].as_component_bufs[0].pv_data =
1641         ((UWORD8 *) ps_proc->as_ref_buf_props[0].as_component_bufs[0].pv_data) + MB_SIZE;
1642     ps_proc->as_ref_buf_props[1].as_component_bufs[0].pv_data =
1643         ((UWORD8 *) ps_proc->as_ref_buf_props[1].as_component_bufs[0].pv_data) + MB_SIZE;
1644 
1645     /*
1646      * Note: Although chroma mb size is 8, as the chroma buffers are
1647      * interleaved, the stride per MB is MB_SIZE
1648      */
1649     ps_proc->s_src_buf_props.as_component_bufs[1].pv_data =
1650         ((UWORD8 *) ps_proc->s_src_buf_props.as_component_bufs[1].pv_data) + MB_SIZE;
1651     ps_proc->s_rec_buf_props.as_component_bufs[1].pv_data =
1652         ((UWORD8 *) ps_proc->s_rec_buf_props.as_component_bufs[1].pv_data) + MB_SIZE;
1653     ps_proc->as_ref_buf_props[0].as_component_bufs[1].pv_data =
1654         ((UWORD8 *) ps_proc->as_ref_buf_props[0].as_component_bufs[1].pv_data) + MB_SIZE;
1655     ps_proc->as_ref_buf_props[1].as_component_bufs[1].pv_data =
1656         ((UWORD8 *) ps_proc->as_ref_buf_props[1].as_component_bufs[1].pv_data) + MB_SIZE;
1657 
1658     /* Reset cost, distortion params */
1659     ps_proc->i4_mb_cost = INT_MAX;
1660     ps_proc->i4_mb_distortion = SHRT_MAX;
1661 
1662     ps_proc->ps_mb_info++;
1663     ps_proc->pu4_mb_pu_cnt++;
1664 
1665     /* Update colocated pu */
1666     if(ps_proc->i4_slice_type == BSLICE)
1667     {
1668         ps_proc->ps_col_mb++;
1669     }
1670 
1671     if(ps_proc->u4_disable_deblock_level != 1)
1672     {
1673         ps_bs->i4_mb_x = ps_proc->i4_mb_x;
1674         ps_bs->i4_mb_y = ps_proc->i4_mb_y;
1675 
1676 #ifndef N_MB_ENABLE /* For N MB processing update take place inside deblocking \
1677                        function */
1678         ASSERT(0);
1679         ps_deblk->i4_mb_x++;
1680 
1681         ((UWORD8 *) ps_deblk->s_rec_pic_buf_props.as_component_bufs[0].pv_data) += MB_SIZE;
1682         /*
1683          * Note: Although chroma mb size is 8, as the chroma buffers are
1684          * interleaved, the stride per MB is MB_SIZE
1685          */
1686         ((UWORD8 *) ps_deblk->s_rec_pic_buf_props.as_component_bufs[1].pv_data) += MB_SIZE;
1687 #endif
1688     }
1689 
1690     return error_status;
1691 }
1692 
1693 /**
1694 *******************************************************************************
1695 *
1696 * @brief This function performs luma & chroma padding
1697 *
1698 * @par Description:
1699 *
1700 * @param[in] ps_proc
1701 *  Process context corresponding to the job
1702 *
1703 * @param[in] pu1_curr_pic_luma
1704 *  Pointer to luma buffer
1705 *
1706 * @param[in] pu1_curr_pic_chroma
1707 *  Pointer to chroma buffer
1708 *
1709 * @param[in] i4_mb_x
1710 *  mb index x
1711 *
1712 * @param[in] i4_mb_y
1713 *  mb index y
1714 *
1715 *  @param[in] i4_pad_ht
1716 *  number of rows to be padded
1717 *
1718 * @returns  error status
1719 *
1720 * @remarks none
1721 *
1722 *******************************************************************************
1723 */
isvce_pad_recon_buffer(isvce_process_ctxt_t * ps_proc,UWORD8 * pu1_curr_pic_luma,WORD32 i4_luma_stride,UWORD8 * pu1_curr_pic_chroma,WORD32 i4_chroma_stride,WORD32 i4_mb_x,WORD32 i4_mb_y,WORD32 i4_pad_ht)1724 IH264E_ERROR_T isvce_pad_recon_buffer(isvce_process_ctxt_t *ps_proc, UWORD8 *pu1_curr_pic_luma,
1725                                       WORD32 i4_luma_stride, UWORD8 *pu1_curr_pic_chroma,
1726                                       WORD32 i4_chroma_stride, WORD32 i4_mb_x, WORD32 i4_mb_y,
1727                                       WORD32 i4_pad_ht)
1728 {
1729     /* codec context */
1730     isvce_codec_t *ps_codec = ps_proc->ps_codec;
1731 
1732     if(i4_mb_x == 0)
1733     {
1734         /* padding left luma */
1735         ps_codec->pf_pad_left_luma(pu1_curr_pic_luma, i4_luma_stride, i4_pad_ht, PAD_LEFT);
1736 
1737         /* padding left chroma */
1738         ps_codec->pf_pad_left_chroma(pu1_curr_pic_chroma, i4_chroma_stride, i4_pad_ht >> 1,
1739                                      PAD_LEFT);
1740     }
1741     if(i4_mb_x == ps_proc->i4_wd_mbs - 1)
1742     {
1743         /* padding right luma */
1744         ps_codec->pf_pad_right_luma(pu1_curr_pic_luma + MB_SIZE, i4_luma_stride, i4_pad_ht,
1745                                     PAD_RIGHT);
1746 
1747         /* padding right chroma */
1748         ps_codec->pf_pad_right_chroma(pu1_curr_pic_chroma + MB_SIZE, i4_chroma_stride,
1749                                       i4_pad_ht >> 1, PAD_RIGHT);
1750 
1751         if(i4_mb_y == ps_proc->i4_ht_mbs - 1)
1752         {
1753             UWORD8 *pu1_rec_luma =
1754                 pu1_curr_pic_luma + MB_SIZE + PAD_RIGHT + ((i4_pad_ht - 1) * i4_luma_stride);
1755             UWORD8 *pu1_rec_chroma = pu1_curr_pic_chroma + MB_SIZE + PAD_RIGHT +
1756                                      (((i4_pad_ht >> 1) - 1) * i4_chroma_stride);
1757 
1758             /* padding bottom luma */
1759             ps_codec->pf_pad_bottom(pu1_rec_luma, i4_luma_stride, i4_luma_stride, PAD_BOT);
1760 
1761             /* padding bottom chroma */
1762             ps_codec->pf_pad_bottom(pu1_rec_chroma, i4_chroma_stride, i4_chroma_stride,
1763                                     (PAD_BOT >> 1));
1764         }
1765     }
1766 
1767     if(i4_mb_y == 0)
1768     {
1769         UWORD8 *pu1_rec_luma = pu1_curr_pic_luma;
1770         UWORD8 *pu1_rec_chroma = pu1_curr_pic_chroma;
1771         WORD32 wd = MB_SIZE;
1772 
1773         if(i4_mb_x == 0)
1774         {
1775             pu1_rec_luma -= PAD_LEFT;
1776             pu1_rec_chroma -= PAD_LEFT;
1777 
1778             wd += PAD_LEFT;
1779         }
1780         if(i4_mb_x == ps_proc->i4_wd_mbs - 1)
1781         {
1782             wd += PAD_RIGHT;
1783         }
1784 
1785         /* padding top luma */
1786         ps_codec->pf_pad_top(pu1_rec_luma, i4_luma_stride, wd, PAD_TOP);
1787 
1788         /* padding top chroma */
1789         ps_codec->pf_pad_top(pu1_rec_chroma, i4_chroma_stride, wd, (PAD_TOP >> 1));
1790     }
1791 
1792     return IH264E_SUCCESS;
1793 }
1794 
1795 /**
1796 *******************************************************************************
1797 *
1798 * @brief This function performs deblocking
1799 *
1800 * @par Description:
1801 *
1802 * @param[in] ps_proc
1803 *  Process context corresponding to the job
1804 *
1805 * @returns  error status
1806 *
1807 * @remarks none
1808 *
1809 *******************************************************************************
1810 */
isvce_dblk_n_mbs(isvce_process_ctxt_t * ps_proc,UWORD8 u1_inter_layer_deblk_flag)1811 static IH264E_ERROR_T isvce_dblk_n_mbs(isvce_process_ctxt_t *ps_proc,
1812                                        UWORD8 u1_inter_layer_deblk_flag)
1813 {
1814     WORD32 i;
1815     WORD32 row, col;
1816 
1817     n_mb_process_ctxt_t *ps_n_mb_ctxt = &ps_proc->s_n_mb_ctxt;
1818     isvce_deblk_ctxt_t *ps_deblk = &ps_proc->s_deblk_ctxt;
1819 
1820     UWORD8 *pu1_deblk_map = ps_proc->pu1_deblk_map + ps_deblk->i4_mb_y * ps_proc->i4_wd_mbs;
1821     UWORD8 *pu1_deblk_map_prev_row = pu1_deblk_map - ps_proc->i4_wd_mbs;
1822     WORD32 u4_deblk_prev_row = 0;
1823     WORD32 i4_n_mbs = ps_n_mb_ctxt->i4_n_mbs;
1824     WORD32 i4_n_mb_process_count = 0;
1825     WORD32 i4_mb_x = ps_proc->i4_mb_x;
1826     WORD32 i4_mb_y = ps_proc->i4_mb_y;
1827 
1828     ASSERT(i4_n_mbs == ps_proc->i4_wd_mbs);
1829 
1830     if(ps_proc->u4_disable_deblock_level != 1)
1831     {
1832         if((i4_mb_y > 0) || (i4_mb_y == (ps_proc->i4_ht_mbs - 1)))
1833         {
1834             /* if number of mb's to be processed are less than 'N', go back.
1835              * exception to the above clause is end of row */
1836             if(((i4_mb_x - (ps_n_mb_ctxt->i4_mb_x - 1)) < i4_n_mbs) &&
1837                (i4_mb_x < (ps_proc->i4_wd_mbs - 1)))
1838             {
1839                 return IH264E_SUCCESS;
1840             }
1841             else
1842             {
1843                 WORD32 i4_num_deblk_rows = 1;
1844 
1845                 if(i4_mb_y == (ps_proc->i4_ht_mbs - 1))
1846                 {
1847                     i4_num_deblk_rows += (ps_proc->i4_ht_mbs > 1);
1848                 }
1849 
1850                 if(1 == ps_proc->i4_ht_mbs)
1851                 {
1852                     ps_deblk->i4_mb_y = 0;
1853                     pu1_deblk_map_prev_row = pu1_deblk_map;
1854                 }
1855 
1856                 for(i = 0; i < i4_num_deblk_rows; i++)
1857                 {
1858                     if(i == 1)
1859                     {
1860                         /* Deblock last row */
1861                         ps_n_mb_ctxt->i4_mb_x = 0;
1862                         ps_n_mb_ctxt->i4_mb_y = ps_proc->i4_mb_y;
1863                         ps_deblk->i4_mb_x = 0;
1864                         ps_deblk->i4_mb_y = ps_proc->i4_mb_y;
1865                         pu1_deblk_map_prev_row = pu1_deblk_map;
1866                         pu1_deblk_map += ps_proc->i4_wd_mbs;
1867                     }
1868 
1869                     i4_n_mb_process_count = MIN(i4_mb_x - (ps_n_mb_ctxt->i4_mb_x - 1), i4_n_mbs);
1870 
1871                     /* performing deblocking for required number of MBs */
1872                     u4_deblk_prev_row = 1;
1873 
1874                     /* checking whether the top rows are deblocked */
1875                     for(col = 0; col < i4_n_mb_process_count; col++)
1876                     {
1877                         u4_deblk_prev_row &= pu1_deblk_map_prev_row[ps_deblk->i4_mb_x + col];
1878                     }
1879 
1880                     /* checking whether the top right MB is deblocked */
1881                     if((ps_deblk->i4_mb_x + i4_n_mb_process_count) != ps_proc->i4_wd_mbs)
1882                     {
1883                         u4_deblk_prev_row &=
1884                             pu1_deblk_map_prev_row[ps_deblk->i4_mb_x + i4_n_mb_process_count];
1885                     }
1886 
1887                     /* Top or Top right MBs not deblocked */
1888                     if((u4_deblk_prev_row != 1) && (i4_mb_y > 0))
1889                     {
1890                         return IH264E_SUCCESS;
1891                     }
1892 
1893                     for(row = 0; row < i4_n_mb_process_count; row++)
1894                     {
1895                         isvce_deblock_mb(ps_proc, ps_deblk, u1_inter_layer_deblk_flag);
1896 
1897                         pu1_deblk_map[ps_deblk->i4_mb_x] = 1;
1898 
1899                         ps_deblk->i4_mb_x++;
1900                     }
1901                 }
1902             }
1903         }
1904     }
1905 
1906     return IH264E_SUCCESS;
1907 }
1908 
1909 /**
1910 *******************************************************************************
1911 *
1912 * @brief This function performs 'intra base' deblocking
1913 *
1914 * @par Description:
1915 *
1916 * @param[in] ps_proc
1917 *  Process context corresponding to the job
1918 *
1919 * @returns  error status
1920 *
1921 * @remarks none
1922 *
1923 *******************************************************************************
1924 */
isvce_intra_base_dblk(isvce_process_ctxt_t * ps_proc)1925 static IH264E_ERROR_T isvce_intra_base_dblk(isvce_process_ctxt_t *ps_proc)
1926 {
1927     isvce_codec_t *ps_codec = ps_proc->ps_codec;
1928     isvce_deblk_ctxt_t *ps_deblk = &ps_proc->s_deblk_ctxt;
1929 
1930     IH264E_ERROR_T e_ret = IH264E_SUCCESS;
1931 
1932     if(ps_proc->u1_spatial_layer_id < (ps_proc->s_svc_params.u1_num_spatial_layers - 1))
1933     {
1934         ps_deblk->i4_mb_x = ps_proc->i4_mb_x;
1935         ps_deblk->i4_mb_y = ps_proc->i4_mb_y - 1;
1936 
1937         ps_deblk->s_rec_pic_buf_props =
1938             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[ps_proc->u1_spatial_layer_id];
1939 
1940         e_ret = isvce_dblk_n_mbs(ps_proc, 1);
1941 
1942         ps_deblk->s_rec_pic_buf_props = ps_proc->s_rec_pic_buf_props;
1943     }
1944 
1945     return e_ret;
1946 }
1947 
1948 /**
1949 *******************************************************************************
1950 *
1951 * @brief This function performs luma & chroma core coding for a set of mb's.
1952 *
1953 * @par Description:
1954 *  The mb to be coded is taken and is evaluated over a predefined set of modes
1955 *  (intra (i16, i4, i8)/inter (mv, skip)) for best cost. The mode with least
1956 *cost is selected and using intra/inter prediction filters, prediction is
1957 *carried out. The deviation between src and pred signal constitutes error
1958 *signal. This error signal is transformed (hierarchical transform if necessary)
1959 *and quantized. The quantized residue is packed in to entropy buffer for entropy
1960 *coding. This is repeated for all the mb's enlisted under the job.
1961 *
1962 * @param[in] ps_proc
1963 *  Process context corresponding to the job
1964 *
1965 * @returns  error status
1966 *
1967 * @remarks none
1968 *
1969 *******************************************************************************
1970 */
isvce_process(isvce_process_ctxt_t * ps_proc)1971 WORD32 isvce_process(isvce_process_ctxt_t *ps_proc)
1972 {
1973     UWORD32 u4_cbp_l, u4_cbp_c;
1974     WORD32 i4_mb_idx;
1975     WORD32 luma_idx, chroma_idx, is_intra;
1976 
1977     isvce_codec_t *ps_codec = ps_proc->ps_codec;
1978     isa_dependent_fxns_t *ps_isa_dependent_fxns = &ps_codec->s_isa_dependent_fxns;
1979     enc_loop_fxns_t *ps_enc_loop_fxns = &ps_isa_dependent_fxns->s_enc_loop_fxns;
1980 
1981     WORD32 error_status = IH264_SUCCESS;
1982     WORD32 i4_wd_mbs = ps_proc->i4_wd_mbs;
1983     WORD32 i4_mb_cnt = ps_proc->i4_mb_cnt;
1984     UWORD32 u4_valid_modes = 0;
1985     WORD32 i4_gate_threshold = 0;
1986     WORD32 ctxt_sel = ps_proc->i4_encode_api_call_cnt % MAX_CTXT_SETS;
1987     bool b_enable_intra4x4_eval = true;
1988 
1989     /*
1990      * list of modes for evaluation
1991      * -------------------------------------------------------------------------
1992      * Note on enabling I4x4 and I16x16
1993      * At very low QP's the hadamard transform in I16x16 will push up the maximum
1994      * coeff value very high. CAVLC may not be able to represent the value and
1995      * hence the stream may not be decodable in some clips.
1996      * Hence at low QPs, we will enable I4x4 and disable I16x16 irrespective of
1997      * preset.
1998      */
1999     if(ps_proc->i4_slice_type == ISLICE)
2000     {
2001         u4_valid_modes |= ps_codec->s_cfg.u4_enable_intra_16x16 ? (1 << I16x16) : 0;
2002 
2003         /* enable intra 8x8 */
2004         u4_valid_modes |= ps_codec->s_cfg.u4_enable_intra_8x8 ? (1 << I8x8) : 0;
2005 
2006         /* enable intra 4x4 */
2007         u4_valid_modes |= ps_codec->s_cfg.u4_enable_intra_4x4 ? (1 << I4x4) : 0;
2008         u4_valid_modes |= (ps_proc->u1_frame_qp <= 10) << I4x4;
2009     }
2010     else if(ps_proc->i4_slice_type == PSLICE)
2011     {
2012         u4_valid_modes |= ps_codec->s_cfg.u4_enable_intra_16x16 ? (1 << I16x16) : 0;
2013 
2014         /* enable intra 4x4 */
2015         if(ps_codec->s_cfg.u4_enc_speed_preset == IVE_SLOWEST)
2016         {
2017             u4_valid_modes |= ps_codec->s_cfg.u4_enable_intra_4x4 ? (1 << I4x4) : 0;
2018         }
2019         u4_valid_modes |= (ps_proc->u1_frame_qp <= 10) << I4x4;
2020 
2021         /* enable inter P16x16 */
2022         u4_valid_modes |= (1 << P16x16);
2023     }
2024     else if(ps_proc->i4_slice_type == BSLICE)
2025     {
2026         u4_valid_modes |= ps_codec->s_cfg.u4_enable_intra_16x16 ? (1 << I16x16) : 0;
2027 
2028         /* enable intra 4x4 */
2029         if(ps_codec->s_cfg.u4_enc_speed_preset == IVE_SLOWEST)
2030         {
2031             u4_valid_modes |= ps_codec->s_cfg.u4_enable_intra_4x4 ? (1 << I4x4) : 0;
2032         }
2033         u4_valid_modes |= (ps_proc->u1_frame_qp <= 10) << I4x4;
2034 
2035         /* enable inter B16x16 */
2036         u4_valid_modes |= (1 << B16x16);
2037     }
2038 
2039     ps_proc->s_entropy.i4_mb_x = ps_proc->i4_mb_x;
2040     ps_proc->s_entropy.i4_mb_y = ps_proc->i4_mb_y;
2041     ps_proc->s_entropy.i4_mb_cnt = MIN(ps_proc->i4_nmb_ntrpy, i4_wd_mbs - ps_proc->i4_mb_x);
2042 
2043     /* compute recon when :
2044      *   1. current frame is to be used as a reference
2045      *   2. dump recon for bit stream sanity check
2046      */
2047     ps_proc->u4_compute_recon = ((ps_proc->s_svc_params.u1_num_spatial_layers > 1) &&
2048                                  (ENABLE_RESIDUAL_PREDICTION || ENABLE_IBL_MODE)) ||
2049                                 ps_codec->u4_is_curr_frm_ref || ps_codec->s_cfg.u4_enable_recon;
2050 
2051     for(i4_mb_idx = 0; i4_mb_idx < i4_mb_cnt; i4_mb_idx++)
2052     {
2053         /* since we have not yet found sad, we have not yet got min sad */
2054         /* we need to initialize these variables for each MB */
2055         /* TODO how to get the min sad into the codec */
2056         ps_proc->u4_min_sad = ps_codec->s_cfg.i4_min_sad;
2057         ps_proc->u4_min_sad_reached = 0;
2058 
2059         ps_proc->ps_mb_info->u1_mb_qp = ps_proc->u1_mb_qp;
2060 
2061         /* wait until the proc of [top + 1] mb is computed.
2062          * We wait till the proc dependencies are satisfied */
2063         if(ps_proc->i4_mb_y > 0)
2064         {
2065             UWORD8 *pu1_proc_map_top;
2066 
2067             pu1_proc_map_top = ps_proc->pu1_proc_map + ((ps_proc->i4_mb_y - 1) * i4_wd_mbs);
2068 
2069             while(1)
2070             {
2071                 volatile UWORD8 *pu1_buf;
2072                 WORD32 idx = MIN(i4_mb_cnt - 1, i4_mb_idx + 1);
2073 
2074                 idx = MIN(idx, ((WORD32) ps_codec->s_cfg.i4_wd_mbs - 1));
2075                 pu1_buf = pu1_proc_map_top + idx;
2076                 if(*pu1_buf) break;
2077                 ithread_yield();
2078             }
2079         }
2080 
2081         if(ENABLE_ILP_MV && (ps_proc->u1_spatial_layer_id > 0) &&
2082            (ps_proc->i4_slice_type != ISLICE))
2083         {
2084             svc_ilp_mv_ctxt_t *ps_svc_ilp_mv_ctxt = ps_proc->ps_svc_ilp_mv_ctxt;
2085             coordinates_t s_mb_pos = {ps_proc->i4_mb_x, ps_proc->i4_mb_y};
2086 
2087             ps_svc_ilp_mv_ctxt->s_ilp_mv_variables.ps_svc_ilp_data = &ps_codec->s_svc_ilp_data;
2088             ps_svc_ilp_mv_ctxt->s_ilp_mv_variables.s_mb_pos = s_mb_pos;
2089             ps_svc_ilp_mv_ctxt->s_ilp_mv_variables.u1_spatial_layer_id =
2090                 ps_proc->u1_spatial_layer_id;
2091 
2092             isvce_get_mb_ilp_mv(ps_svc_ilp_mv_ctxt);
2093 
2094             ps_proc->ps_ilp_mv = &ps_svc_ilp_mv_ctxt->s_ilp_mv_outputs.s_ilp_mv;
2095             ps_proc->s_me_ctxt.ps_ilp_me_cands =
2096                 &ps_svc_ilp_mv_ctxt->s_ilp_mv_outputs.s_ilp_me_cands;
2097         }
2098         else
2099         {
2100             ps_proc->ps_ilp_mv = NULL;
2101             ps_proc->s_me_ctxt.ps_ilp_me_cands = NULL;
2102         }
2103 
2104         ps_proc->ps_mb_info->u2_mb_type = INVALID_MB_TYPE;
2105         ps_proc->i4_mb_distortion = SHRT_MAX;
2106 
2107         {
2108             WORD32 i4_mb_id = ps_proc->i4_mb_x + ps_proc->i4_mb_y * i4_wd_mbs;
2109 
2110             WORD32 i4_air_enable_inter =
2111                 (ps_codec->s_cfg.e_air_mode == IVE_AIR_MODE_NONE) ||
2112                 (ps_codec->pu2_intr_rfrsh_map[i4_mb_id] != ps_codec->i4_air_pic_cnt);
2113 
2114             if((u4_valid_modes & (1 << P16x16)) || (u4_valid_modes & (1 << B16x16)))
2115             {
2116                 if(ps_proc->i4_mb_x % ps_proc->u4_nmb_me == 0)
2117                 {
2118                     isvce_compute_me_nmb(
2119                         ps_proc, MIN((WORD32) ps_proc->u4_nmb_me, i4_wd_mbs - ps_proc->i4_mb_x));
2120                 }
2121 
2122                 {
2123                     UWORD32 u4_mb_index = ps_proc->i4_mb_x % ps_proc->u4_nmb_me;
2124 
2125                     ps_proc->u4_min_sad_reached =
2126                         ps_proc->ps_nmb_info[u4_mb_index].u4_min_sad_reached;
2127                     ps_proc->u4_min_sad = ps_proc->ps_nmb_info[u4_mb_index].u4_min_sad;
2128 
2129                     ps_proc->ps_skip_mv = &(ps_proc->ps_nmb_info[u4_mb_index].as_skip_mv[0]);
2130                     ps_proc->ps_ngbr_avbl = &(ps_proc->ps_nmb_info[u4_mb_index].s_ngbr_avbl);
2131                     ps_proc->ps_pred_mv = &(ps_proc->ps_nmb_info[u4_mb_index].as_pred_mv[0]);
2132 
2133                     ps_proc->i4_mb_distortion = ps_proc->ps_nmb_info[u4_mb_index].i4_mb_distortion;
2134 
2135                     ps_proc->i4_mb_cost = ps_proc->ps_nmb_info[u4_mb_index].i4_mb_cost;
2136                     ps_proc->u4_min_sad = ps_proc->ps_nmb_info[u4_mb_index].u4_min_sad;
2137                     ps_proc->u4_min_sad_reached =
2138                         ps_proc->ps_nmb_info[u4_mb_index].u4_min_sad_reached;
2139                     ps_proc->ps_mb_info->u2_mb_type = ps_proc->ps_nmb_info[u4_mb_index].u4_mb_type;
2140 
2141                     ps_proc->pu1_best_subpel_buf =
2142                         ps_proc->ps_nmb_info[u4_mb_index].pu1_best_sub_pel_buf;
2143                     ps_proc->u4_bst_spel_buf_strd =
2144                         ps_proc->ps_nmb_info[u4_mb_index].u4_bst_spel_buf_strd;
2145                 }
2146 
2147                 isvce_derive_nghbr_avbl_of_mbs(ps_proc);
2148             }
2149             else
2150             {
2151                 ps_proc->ps_ngbr_avbl = &ps_proc->s_ngbr_avbl;
2152 
2153                 isvce_derive_nghbr_avbl_of_mbs(ps_proc);
2154             }
2155 
2156             /*
2157              * If air says intra, we need to force the following code path to evaluate
2158              * intra The easy way is just to say that the inter cost is too much
2159              */
2160             if(!i4_air_enable_inter)
2161             {
2162                 ps_proc->u4_min_sad_reached = 0;
2163                 ps_proc->i4_mb_cost = INT_MAX;
2164                 ps_proc->i4_mb_distortion = INT_MAX;
2165             }
2166             else if(ps_proc->ps_mb_info->u2_mb_type == PSKIP)
2167             {
2168                 ps_proc->ps_mb_info->u1_base_mode_flag = 0;
2169                 ps_proc->ps_mb_info->u1_residual_prediction_flag = 0;
2170                 goto UPDATE_MB_INFO;
2171             }
2172 
2173             /* If we already have the minimum sad, there is no point in searching for
2174              * sad again */
2175             if((ps_proc->u4_min_sad_reached == 0) ||
2176                (ps_codec->s_cfg.u4_enc_speed_preset != IVE_FASTEST))
2177             {
2178                 /* intra gating in inter slices */
2179                 /* No need of gating if we want to force intra, we need to find the
2180                  * threshold only if inter is enabled by AIR*/
2181                 if((ps_proc->i4_slice_type != ISLICE) &&
2182                    (FORCE_DISTORTION_BASED_INTRA_4X4_GATING ||
2183                     (i4_air_enable_inter && ps_codec->u4_inter_gate)))
2184                 {
2185                     WORD32 i4_distortion[4];
2186 
2187                     if((ps_proc->i4_mb_x > 0) && (ps_proc->i4_mb_y > 0))
2188                     {
2189                         i4_distortion[0] = ps_proc->s_nbr_info.ps_left_mb_info->i4_mb_distortion;
2190 
2191                         i4_distortion[1] = ps_proc->s_nbr_info.ps_top_row_mb_info[ps_proc->i4_mb_x]
2192                                                .i4_mb_distortion;
2193 
2194                         i4_distortion[2] =
2195                             ps_proc->s_nbr_info.ps_top_row_mb_info[ps_proc->i4_mb_x + 1]
2196                                 .i4_mb_distortion;
2197 
2198                         i4_distortion[3] =
2199                             ps_proc->s_nbr_info.ps_top_row_mb_info[ps_proc->i4_mb_x - 1]
2200                                 .i4_mb_distortion;
2201 
2202                         i4_gate_threshold = (i4_distortion[0] + i4_distortion[1] +
2203                                              i4_distortion[2] + i4_distortion[3]) /
2204                                             4;
2205                     }
2206                 }
2207 
2208                 b_enable_intra4x4_eval = true;
2209 
2210                 if(ENABLE_IBL_MODE && (ps_proc->u1_spatial_layer_id > 0) &&
2211                    (ps_proc->s_svc_params.d_spatial_res_ratio == 2.) && !ps_proc->ps_ilp_mv)
2212                 {
2213                     isvce_evaluate_IBL_mode(ps_proc);
2214                 }
2215                 else
2216                 {
2217                     ps_proc->ps_mb_info->u1_base_mode_flag = 0;
2218                 }
2219 
2220                 if(u4_valid_modes & (1 << I16x16))
2221                 {
2222                     isvce_evaluate_intra16x16_modes_for_least_cost_rdoptoff(ps_proc);
2223 
2224                     if(ENABLE_INTRA16X16_BASED_INTRA4X4_GATING &&
2225                        (ps_proc->i4_slice_type != ISLICE) &&
2226                        (ps_proc->ps_mb_info->u2_mb_type == I16x16))
2227                     {
2228                         b_enable_intra4x4_eval = false;
2229                     }
2230                 }
2231 
2232                 if(u4_valid_modes & (1 << I8x8))
2233                 {
2234                     isvce_evaluate_intra8x8_modes_for_least_cost_rdoptoff(ps_proc);
2235                 }
2236 
2237                 if(ENABLE_ILP_BASED_INTRA4X4_GATING && (ps_proc->i4_slice_type != ISLICE))
2238                 {
2239                     b_enable_intra4x4_eval =
2240                         !(ps_proc->ps_ilp_mv && (INVALID_MB_TYPE != ps_proc->ps_ilp_mv->e_mb_type));
2241                 }
2242 
2243                 /* If we are going to force intra we need to evaluate intra irrespective
2244                  * of gating */
2245                 if((!i4_air_enable_inter) ||
2246                    ((i4_gate_threshold + 16 * ((WORD32) ps_proc->u4_lambda)) <
2247                     ps_proc->i4_mb_distortion))
2248                 {
2249                     if(b_enable_intra4x4_eval && (u4_valid_modes & (1 << I4x4)))
2250                     {
2251                         if(!FORCE_FAST_INTRA4X4 &&
2252                            (ps_codec->s_cfg.u4_enc_speed_preset == IVE_SLOWEST))
2253                         {
2254                             isvce_evaluate_intra4x4_modes_for_least_cost_rdopton(ps_proc);
2255                         }
2256                         else
2257                         {
2258                             isvce_evaluate_intra4x4_modes_for_least_cost_rdoptoff(ps_proc);
2259                         }
2260                     }
2261                 }
2262             }
2263         }
2264 
2265         if(ps_proc->ps_mb_info->u2_mb_type == I4x4 || ps_proc->ps_mb_info->u2_mb_type == I16x16 ||
2266            ps_proc->ps_mb_info->u2_mb_type == I8x8)
2267         {
2268             luma_idx = ps_proc->ps_mb_info->u2_mb_type;
2269             chroma_idx = 0;
2270             is_intra = 1;
2271 
2272             isvce_evaluate_chroma_intra8x8_modes_for_least_cost_rdoptoff(ps_proc);
2273         }
2274         else if(ps_proc->ps_mb_info->u2_mb_type == BASE_MODE)
2275         {
2276             luma_idx = 3;
2277             chroma_idx = 1;
2278             is_intra = 1;
2279             ps_proc->u4_min_sad_reached = 0;
2280         }
2281         else
2282         {
2283             luma_idx = 3;
2284             chroma_idx = 1;
2285             is_intra = 0;
2286         }
2287 
2288         ps_proc->ps_mb_info->u1_is_intra = is_intra;
2289 
2290         if(is_intra)
2291         {
2292             ps_proc->ps_mb_info->as_pu->as_me_info[L0].i1_ref_idx = -1;
2293             ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvx = 0;
2294             ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvy = 0;
2295 
2296             ps_proc->ps_mb_info->as_pu->as_me_info[L1].i1_ref_idx = -1;
2297             ps_proc->ps_mb_info->as_pu->as_me_info[L1].s_mv.i2_mvx = 0;
2298             ps_proc->ps_mb_info->as_pu->as_me_info[L1].s_mv.i2_mvy = 0;
2299         }
2300         else
2301         {
2302             isvce_mv_pred(ps_proc, ps_proc->i4_slice_type);
2303         }
2304 
2305         if(ENABLE_RESIDUAL_PREDICTION && !is_intra && (ps_proc->u1_spatial_layer_id > 0) &&
2306            (ps_proc->i4_slice_type == PSLICE) && (ps_proc->ps_mb_info->u2_mb_type != PSKIP))
2307         {
2308             svc_res_pred_ctxt_t *ps_res_pred_ctxt = ps_proc->ps_res_pred_ctxt;
2309 
2310             UWORD32 u4_res_pred_sad;
2311 
2312             isvce_me_ctxt_t *ps_me_ctxt = &ps_proc->s_me_ctxt;
2313             yuv_buf_props_t s_pred = ps_proc->s_src_buf_props;
2314 
2315             if(!(ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvx % 4) &&
2316                !(ps_proc->ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvy % 4))
2317             {
2318                 s_pred.as_component_bufs[Y].pv_data =
2319                     ps_me_ctxt->apu1_ref_buf_luma[L0] +
2320                     (ps_me_ctxt->as_mb_part[L0].s_mv_curr.i2_mvx >> 2) +
2321                     (ps_me_ctxt->as_mb_part[L0].s_mv_curr.i2_mvy >> 2) *
2322                         ps_me_ctxt->ai4_rec_strd[L0];
2323                 s_pred.as_component_bufs[Y].i4_data_stride = ps_me_ctxt->ai4_rec_strd[L0];
2324             }
2325             else
2326             {
2327                 s_pred.as_component_bufs[Y].pv_data = ps_proc->pu1_best_subpel_buf;
2328                 s_pred.as_component_bufs[Y].i4_data_stride = ps_proc->u4_bst_spel_buf_strd;
2329             }
2330 
2331             s_pred.as_component_bufs[U].pv_data = s_pred.as_component_bufs[V].pv_data = NULL;
2332 
2333             ps_res_pred_ctxt->s_res_pred_variables.ps_svc_ilp_data = &ps_codec->s_svc_ilp_data;
2334             ps_res_pred_ctxt->s_res_pred_variables.s_mb_pos.i4_abscissa = ps_proc->i4_mb_x;
2335             ps_res_pred_ctxt->s_res_pred_variables.s_mb_pos.i4_ordinate = ps_proc->i4_mb_y;
2336             ps_res_pred_ctxt->s_res_pred_variables.u1_spatial_layer_id =
2337                 ps_proc->u1_spatial_layer_id;
2338 
2339             if(ps_proc->s_svc_params.d_spatial_res_ratio == 2.)
2340             {
2341                 isvce_get_mb_residual_pred(ps_proc->ps_res_pred_ctxt);
2342             }
2343             else
2344             {
2345                 isvce_get_mb_residual_pred_non_dyadic(ps_proc->ps_res_pred_ctxt);
2346             }
2347 
2348             isvce_residual_pred_eval(ps_proc->ps_res_pred_ctxt, &ps_proc->s_src_buf_props, &s_pred,
2349                                      ps_proc->ps_mb_res_buf, &u4_res_pred_sad,
2350                                      &ps_proc->ps_mb_info->u1_residual_prediction_flag,
2351                                      ps_proc->i4_mb_distortion);
2352 
2353             if(ps_proc->ps_mb_info->u1_residual_prediction_flag)
2354             {
2355                 ps_proc->i4_mb_cost -= ps_proc->i4_mb_distortion;
2356                 ps_proc->i4_mb_cost += (WORD32) u4_res_pred_sad;
2357                 ps_proc->i4_mb_distortion = (WORD32) u4_res_pred_sad;
2358             }
2359         }
2360         else
2361         {
2362             ps_proc->ps_mb_info->u1_residual_prediction_flag = 0;
2363         }
2364 
2365         if(isvce_is_ilp_mv_winning_mv(ps_proc->ps_mb_info, ps_proc->ps_ilp_mv))
2366         {
2367             ps_proc->ps_mb_info->as_pu->as_me_info[L0] = ps_proc->ps_ilp_mv->as_mv[0][L0];
2368             ps_proc->ps_mb_info->as_pu->as_me_info[L1] = ps_proc->ps_ilp_mv->as_mv[0][L1];
2369 
2370             ps_proc->ps_mb_info->u1_base_mode_flag = 1;
2371             ps_proc->ps_mb_info->u2_mb_type = BASE_MODE;
2372         }
2373         else if(ps_proc->ps_mb_info->u2_mb_type != BASE_MODE)
2374         {
2375             ps_proc->ps_mb_info->u1_base_mode_flag = 0;
2376         }
2377 
2378         isvce_mvp_idx_eval(ps_proc->ps_mb_info, ps_proc->ps_pred_mv,
2379                            ps_proc->ps_ilp_mv ? ps_proc->ps_ilp_mv->as_mv[0] : NULL,
2380                            ps_proc->s_me_ctxt.pu1_mv_bits);
2381 
2382         /* 8x8 Tx is not supported, and I8x8 is also unsupported */
2383         ASSERT((luma_idx == 0) || (luma_idx == 1) || (luma_idx == 3));
2384         ps_proc->ps_mb_info->u1_tx_size = 4;
2385 
2386         /* Perform luma mb core coding */
2387         u4_cbp_l = (ps_enc_loop_fxns->apf_luma_energy_compaction)[luma_idx](ps_proc);
2388 
2389         /* Perform chroma mb core coding */
2390         u4_cbp_c = (ps_enc_loop_fxns->apf_chroma_energy_compaction)[chroma_idx](ps_proc);
2391 
2392         ps_proc->u4_cbp = (u4_cbp_c << 4) | u4_cbp_l;
2393         ps_proc->ps_mb_info->u4_cbp = (u4_cbp_c << 4) | u4_cbp_l;
2394         ps_proc->ps_mb_info->u4_csbp = isvce_calculate_csbp(ps_proc);
2395 
2396         if(ps_proc->ps_mb_info->u1_is_intra)
2397         {
2398             switch(ps_proc->ps_mb_info->u2_mb_type)
2399             {
2400                 case I16x16:
2401                 {
2402                     ps_proc->ps_mb_info->s_intra_pu.s_i16x16_mode_data.u1_mode =
2403                         ps_proc->u1_l_i16_mode;
2404 
2405                     break;
2406                 }
2407                 case I4x4:
2408                 {
2409                     WORD32 i;
2410 
2411                     for(i = 0; i < MAX_TU_IN_MB; i++)
2412                     {
2413                         ps_proc->ps_mb_info->s_intra_pu.as_i4x4_mode_data[i].u1_mode =
2414                             ps_proc->au1_intra_luma_mb_4x4_modes[i];
2415                         ps_proc->ps_mb_info->s_intra_pu.as_i4x4_mode_data[i].u1_predicted_mode =
2416                             ps_proc->au1_predicted_intra_luma_mb_4x4_modes[i];
2417                     }
2418 
2419                     break;
2420                 }
2421                 case BASE_MODE:
2422                 {
2423                     break;
2424                 }
2425                 default:
2426                 {
2427                     ASSERT(false);
2428                 }
2429             }
2430 
2431             ps_proc->ps_mb_info->s_intra_pu.u1_chroma_intra_mode = ps_proc->u1_c_i8_mode;
2432         }
2433 
2434         if(!ps_proc->ps_mb_info->u1_is_intra && !ps_proc->ps_mb_info->u1_residual_prediction_flag)
2435         {
2436             if(ps_proc->i4_slice_type == BSLICE)
2437             {
2438                 if(isvce_find_bskip_params(ps_proc, L0))
2439                 {
2440                     ps_proc->ps_mb_info->u2_mb_type = (ps_proc->u4_cbp) ? BDIRECT : BSKIP;
2441                 }
2442             }
2443             else if(!ps_proc->u4_cbp)
2444             {
2445                 if(isvce_find_pskip_params(ps_proc, L0))
2446                 {
2447                     ps_proc->ps_mb_info->u2_mb_type = PSKIP;
2448                 }
2449             }
2450         }
2451 
2452     UPDATE_MB_INFO:
2453         isvce_svc_ilp_buf_update(ps_proc);
2454 
2455         isvce_update_ibl_info(
2456             ps_proc->ps_intra_pred_ctxt, ps_proc->s_svc_params.u1_num_spatial_layers,
2457             ps_proc->u1_spatial_layer_id, ps_proc->ps_mb_info->u2_mb_type, ps_proc->i4_mb_x,
2458             ps_proc->i4_mb_y, ps_proc->ps_mb_info->u1_base_mode_flag);
2459 
2460         isvce_update_res_pred_info(ps_proc);
2461 
2462         /* Update mb sad, mb qp and intra mb cost. Will be used by rate control */
2463         isvce_update_rc_mb_info(&ps_proc->s_frame_info, ps_proc);
2464 
2465         {
2466             svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt = ps_proc->ps_sub_pic_rc_ctxt;
2467             svc_sub_pic_rc_mb_variables_t *ps_sub_pic_rc_variables =
2468                 &ps_sub_pic_rc_ctxt->s_sub_pic_rc_variables.s_mb_variables;
2469 
2470             ps_sub_pic_rc_variables->ps_mb_info = ps_proc->ps_mb_info;
2471             ps_sub_pic_rc_variables->s_mb_pos.i4_abscissa = ps_proc->i4_mb_x;
2472             ps_sub_pic_rc_variables->s_mb_pos.i4_ordinate = ps_proc->i4_mb_y;
2473             ps_sub_pic_rc_variables->u4_cbp = ps_proc->u4_cbp;
2474             ps_sub_pic_rc_variables->aps_mvps[0] = ps_proc->ps_pred_mv;
2475 #if MAX_MVP_IDX == 1
2476             ps_sub_pic_rc_variables->aps_mvps[1] =
2477                 ps_proc->ps_ilp_mv ? ps_proc->ps_ilp_mv->as_mv[0] : NULL;
2478 #endif
2479             ps_sub_pic_rc_variables->apu1_nnzs[Y] = (UWORD8 *) ps_proc->au4_nnz;
2480             ps_sub_pic_rc_variables->apu1_nnzs[UV] = ps_proc->au1_chroma_nnz;
2481 
2482             /* Quant coeffs are arranged TU by TU */
2483             switch(ps_proc->ps_mb_info->u2_mb_type)
2484             {
2485                 case I16x16:
2486                 case I4x4:
2487                 case P16x16:
2488                 case B16x16:
2489                 case BASE_MODE:
2490                 {
2491                     ps_sub_pic_rc_variables->as_quant_coeffs[Y].pv_data =
2492                         ps_proc->pi2_res_buf_intra_4x4;
2493                     ps_sub_pic_rc_variables->as_quant_coeffs[Y].i4_data_stride =
2494                         ps_proc->i4_res_strd;
2495                     ps_sub_pic_rc_variables->as_quant_coeffs[UV].pv_data = ps_proc->pi2_res_buf;
2496                     ps_sub_pic_rc_variables->as_quant_coeffs[UV].i4_data_stride =
2497                         ps_proc->i4_res_strd;
2498 
2499                     break;
2500                 }
2501                 case PSKIP:
2502                 case BSKIP:
2503                 {
2504                     ps_sub_pic_rc_variables->as_quant_coeffs[Y].pv_data = NULL;
2505                     ps_sub_pic_rc_variables->as_quant_coeffs[UV].pv_data = NULL;
2506 
2507                     break;
2508                 }
2509                 default:
2510                 {
2511                     ASSERT(false);
2512 
2513                     break;
2514                 }
2515             }
2516 
2517             isvce_sub_pic_rc_ctxt_update(ps_proc->ps_sub_pic_rc_ctxt);
2518         }
2519 
2520 #if ENABLE_MODE_STAT_VISUALISER
2521         if(ps_proc->u1_spatial_layer_id == (ps_proc->s_svc_params.u1_num_spatial_layers - 1))
2522         {
2523             coordinates_t s_mb_pos = {ps_proc->i4_mb_x, ps_proc->i4_mb_y};
2524 
2525             isvce_msv_set_mode(ps_codec->ps_mode_stat_visualiser, ps_proc->ps_mb_info, &s_mb_pos);
2526         }
2527 #endif
2528 
2529         /**********************************************************************/
2530         /* if disable deblock level is '0' this implies enable deblocking for */
2531         /* all edges of all macroblocks with out any restrictions             */
2532         /*                                                                    */
2533         /* if disable deblock level is '1' this implies disable deblocking for*/
2534         /* all edges of all macroblocks with out any restrictions             */
2535         /*                                                                    */
2536         /* if disable deblock level is '2' this implies enable deblocking for */
2537         /* all edges of all macroblocks except edges overlapping with slice   */
2538         /* boundaries. This option is not currently supported by the encoder  */
2539         /* hence the slice map should be of no significance to perform debloc */
2540         /* king                                                               */
2541         /**********************************************************************/
2542 
2543         if(ps_proc->u4_compute_recon)
2544         {
2545             /* compute blocking strength */
2546             if(ps_proc->u4_disable_deblock_level != 1)
2547             {
2548                 isvce_compute_bs(ps_proc, 0);
2549 
2550                 if(ENABLE_INTRA_BASE_DEBLOCK && (ps_proc->u1_spatial_layer_id <
2551                                                  (ps_proc->s_svc_params.u1_num_spatial_layers - 1)))
2552                 {
2553                     isvce_compute_bs(ps_proc, 1);
2554                 }
2555             }
2556             /* nmb deblocking and hpel and padding */
2557             isvce_dblk_n_mbs(ps_proc, 0);
2558 
2559             if(ENABLE_INTRA_BASE_DEBLOCK &&
2560                (ps_proc->u1_spatial_layer_id < (ps_proc->s_svc_params.u1_num_spatial_layers - 1)))
2561             {
2562                 isvce_intra_base_dblk(ps_proc);
2563             }
2564 
2565             if(ps_proc->i4_mb_x == (ps_proc->i4_wd_mbs - 1) &&
2566                ps_proc->i4_mb_y == (ps_proc->i4_ht_mbs - 1))
2567             {
2568                 isvce_svc_pad_frame(ps_proc);
2569 
2570                 isvce_pad_mb_mode_buf(ps_proc->ps_intra_pred_ctxt, ps_proc->u1_spatial_layer_id,
2571                                       ps_proc->s_svc_params.u1_num_spatial_layers,
2572                                       ps_proc->s_svc_params.d_spatial_res_ratio,
2573                                       ps_codec->s_cfg.u4_wd, ps_codec->s_cfg.u4_ht);
2574             }
2575         }
2576 
2577         /* update the context after for coding next mb */
2578         error_status = isvce_update_proc_ctxt(ps_proc);
2579 
2580         if(error_status != IH264E_SUCCESS)
2581         {
2582             return error_status;
2583         }
2584 
2585         {
2586             UWORD8 u1_new_mb_qp;
2587 
2588             u1_new_mb_qp =
2589                 isvce_sub_pic_rc_get_mb_qp(ps_proc->ps_sub_pic_rc_ctxt, ps_proc->u1_mb_qp);
2590 
2591             if(u1_new_mb_qp != ps_proc->u1_mb_qp)
2592             {
2593                 ps_proc->u1_mb_qp = u1_new_mb_qp;
2594                 ps_proc->u4_lambda = gu1_qp0[u1_new_mb_qp];
2595 
2596                 isvce_init_quant_params(ps_proc, ps_proc->u1_mb_qp);
2597             }
2598         }
2599 
2600         /* Once the last row is processed, mark the buffer status appropriately */
2601         if(ps_proc->i4_ht_mbs == ps_proc->i4_mb_y)
2602         {
2603             /* Pointer to current picture buffer structure */
2604             svc_au_buf_t *ps_cur_pic = ps_proc->ps_cur_pic;
2605 
2606             /* Pointer to current picture's mv buffer structure */
2607             svc_au_data_t *ps_cur_mv_buf = ps_proc->ps_cur_mv_buf;
2608 
2609             /**********************************************************************/
2610             /* if disable deblock level is '0' this implies enable deblocking for */
2611             /* all edges of all macroblocks with out any restrictions             */
2612             /*                                                                    */
2613             /* if disable deblock level is '1' this implies disable deblocking for*/
2614             /* all edges of all macroblocks with out any restrictions             */
2615             /*                                                                    */
2616             /* if disable deblock level is '2' this implies enable deblocking for */
2617             /* all edges of all macroblocks except edges overlapping with slice   */
2618             /* boundaries. This option is not currently supported by the encoder  */
2619             /* hence the slice map should be of no significance to perform debloc */
2620             /* king                                                               */
2621             /**********************************************************************/
2622             error_status = ih264_buf_mgr_release(ps_codec->pv_svc_au_data_store_mgr,
2623                                                  ps_cur_mv_buf->i4_buf_id, BUF_MGR_CODEC);
2624             if(error_status != IH264E_SUCCESS)
2625             {
2626                 return error_status;
2627             }
2628             error_status = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id,
2629                                                  BUF_MGR_CODEC);
2630             if(error_status != IH264E_SUCCESS)
2631             {
2632                 return error_status;
2633             }
2634             if(ps_codec->s_cfg.u4_enable_recon)
2635             {
2636                 /* pic cnt */
2637                 ps_codec->as_rec_buf[ctxt_sel].i4_pic_cnt = ps_proc->i4_pic_cnt;
2638 
2639                 /* rec buffers */
2640                 ps_codec->as_rec_buf[ctxt_sel].s_pic_buf = *ps_proc->ps_cur_pic;
2641 
2642                 /* is last? */
2643                 ps_codec->as_rec_buf[ctxt_sel].u4_is_last = ps_proc->s_entropy.u4_is_last;
2644 
2645                 /* frame time stamp */
2646                 ps_codec->as_rec_buf[ctxt_sel].u4_timestamp_high =
2647                     ps_proc->s_entropy.u4_timestamp_high;
2648                 ps_codec->as_rec_buf[ctxt_sel].u4_timestamp_low =
2649                     ps_proc->s_entropy.u4_timestamp_low;
2650             }
2651         }
2652     }
2653 
2654     DEBUG_HISTOGRAM_DUMP(ps_codec->s_cfg.i4_ht_mbs == ps_proc->i4_mb_y);
2655 
2656     return error_status;
2657 }
2658 
2659 /**
2660 *******************************************************************************
2661 *
2662 * @brief
2663 *  entry point of a spawned encoder thread
2664 *
2665 * @par Description:
2666 *  The encoder thread dequeues a proc/entropy job from the encoder queue and
2667 *  calls necessary routines.
2668 *
2669 * @param[in] pv_proc
2670 *  Process context corresponding to the thread
2671 *
2672 * @returns  error status
2673 *
2674 * @remarks
2675 *
2676 *******************************************************************************
2677 */
isvce_process_thread(void * pv_proc)2678 WORD32 isvce_process_thread(void *pv_proc)
2679 {
2680     job_t s_job;
2681 
2682     isvce_process_ctxt_t *ps_proc = pv_proc;
2683     isvce_codec_t *ps_codec = ps_proc->ps_codec;
2684 
2685     IH264_ERROR_T ret = IH264_SUCCESS;
2686 
2687     WORD32 ctxt_sel = ps_codec->i4_encode_api_call_cnt % MAX_CTXT_SETS;
2688     WORD32 error_status = IH264_SUCCESS;
2689     WORD32 is_blocking = 0;
2690 
2691     ps_proc->i4_error_code = IH264_SUCCESS;
2692 
2693     while(1)
2694     {
2695         /* dequeue a job from the entropy queue */
2696         {
2697             bool b_is_entropy_state_invalid = false;
2698             WORD32 retval = ithread_mutex_lock(ps_codec->pv_entropy_mutex);
2699             volatile ISVCE_ENTROPY_THREAD_STATES_T *pe_entropy_thread_state =
2700                 &ps_codec->ae_entropy_thread_exit_state[ctxt_sel];
2701 
2702             /* have the lock */
2703             if(retval == 0)
2704             {
2705                 if(*pe_entropy_thread_state == INACTIVE)
2706                 {
2707                     /* no entropy threads are active, try dequeuing a job from the entropy
2708                      * queue */
2709                     ret = ih264_list_dequeue(ps_proc->pv_entropy_jobq, &s_job, is_blocking);
2710 
2711                     if(IH264_SUCCESS == ret)
2712                     {
2713                         *pe_entropy_thread_state = IN_PROCESS;
2714                         ithread_mutex_unlock(ps_codec->pv_entropy_mutex);
2715                         goto WORKER;
2716                     }
2717                     else if(is_blocking)
2718                     {
2719                         ithread_mutex_unlock(ps_codec->pv_entropy_mutex);
2720                         break;
2721                     }
2722                 }
2723                 else if(*pe_entropy_thread_state == ERRONEOUS_EXIT)
2724                 {
2725                     b_is_entropy_state_invalid = true;
2726                 }
2727 
2728                 ithread_mutex_unlock(ps_codec->pv_entropy_mutex);
2729             }
2730 
2731             if(b_is_entropy_state_invalid)
2732             {
2733                 ps_proc->i4_error_code = IH264_FAIL;
2734 
2735                 return IH264_FAIL;
2736             }
2737         }
2738 
2739         /* dequeue a job from the process queue */
2740         ret = ih264_list_dequeue(ps_proc->pv_proc_jobq, &s_job, 1);
2741         if(IH264_SUCCESS != ret)
2742         {
2743             if(ps_proc->i4_id)
2744             {
2745                 break;
2746             }
2747             else
2748             {
2749                 is_blocking = 1;
2750                 continue;
2751             }
2752         }
2753 
2754     WORKER:
2755         /* choose appropriate proc context based on proc_base_idx */
2756         switch(s_job.i4_cmd)
2757         {
2758             case CMD_PROCESS:
2759             {
2760                 ps_proc->i4_mb_cnt = s_job.i2_mb_cnt;
2761                 ps_proc->i4_mb_x = s_job.i2_mb_x;
2762                 ps_proc->i4_mb_y = s_job.i2_mb_y;
2763 
2764                 isvce_init_layer_proc_ctxt(ps_proc);
2765 
2766                 error_status = isvce_process(ps_proc);
2767 
2768                 if(error_status != IH264_SUCCESS)
2769                 {
2770                     ps_codec->ae_entropy_thread_exit_state[ctxt_sel] = ERRONEOUS_EXIT;
2771                     ps_proc->i4_error_code = error_status;
2772                     return ret;
2773                 }
2774 
2775                 break;
2776             }
2777             case CMD_ENTROPY:
2778             {
2779                 ps_proc->s_entropy.i4_mb_x = s_job.i2_mb_x;
2780                 ps_proc->s_entropy.i4_mb_y = s_job.i2_mb_y;
2781                 ps_proc->s_entropy.i4_mb_cnt = s_job.i2_mb_cnt;
2782 
2783                 isvce_init_entropy_ctxt(ps_proc);
2784 
2785                 error_status = isvce_entropy(ps_proc);
2786 
2787                 if(error_status != IH264_SUCCESS)
2788                 {
2789                     ps_codec->ae_entropy_thread_exit_state[ctxt_sel] = ERRONEOUS_EXIT;
2790                     ps_proc->i4_error_code = error_status;
2791                     return ret;
2792                 }
2793 
2794                 break;
2795             }
2796             default:
2797             {
2798                 ps_proc->i4_error_code = IH264_FAIL;
2799                 return ret;
2800             }
2801         }
2802     }
2803 
2804     return ret;
2805 }
2806