1 /******************************************************************************
2 *
3 * Copyright (C) 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20
21 /*!
22 ******************************************************************************
23 * \file ihevce_frame_process.c
24 *
25 * \brief
26 * This file contains top level functions related Frame processing
27 *
28 * \date
29 * 18/09/2012
30 *
31 * \author
32 * Ittiam
33 *
34 *
35 * List of Functions
36 *
37 *
38 ******************************************************************************
39 */
40
41 /*****************************************************************************/
42 /* File Includes */
43 /*****************************************************************************/
44 /* System include files */
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <assert.h>
49 #include <stdarg.h>
50 #include <math.h>
51 #include <time.h>
52
53 /* User include files */
54 #include "ihevc_typedefs.h"
55 #include "itt_video_api.h"
56 #include "ihevce_api.h"
57
58 #include "rc_cntrl_param.h"
59 #include "rc_frame_info_collector.h"
60 #include "rc_look_ahead_params.h"
61
62 #include "ihevc_defs.h"
63 #include "ihevc_debug.h"
64 #include "ihevc_macros.h"
65 #include "ihevc_structs.h"
66 #include "ihevc_platform_macros.h"
67 #include "ihevc_deblk.h"
68 #include "ihevc_itrans_recon.h"
69 #include "ihevc_chroma_itrans_recon.h"
70 #include "ihevc_chroma_intra_pred.h"
71 #include "ihevc_intra_pred.h"
72 #include "ihevc_inter_pred.h"
73 #include "ihevc_mem_fns.h"
74 #include "ihevc_padding.h"
75 #include "ihevc_weighted_pred.h"
76 #include "ihevc_sao.h"
77 #include "ihevc_resi_trans.h"
78 #include "ihevc_quant_iquant_ssd.h"
79 #include "ihevc_cabac_tables.h"
80 #include "ihevc_common_tables.h"
81
82 #include "ihevce_defs.h"
83 #include "ihevce_buffer_que_interface.h"
84 #include "ihevce_hle_interface.h"
85 #include "ihevce_hle_q_func.h"
86 #include "ihevce_lap_enc_structs.h"
87 #include "ihevce_lap_interface.h"
88 #include "ihevce_multi_thrd_structs.h"
89 #include "ihevce_multi_thrd_funcs.h"
90 #include "ihevce_me_common_defs.h"
91 #include "ihevce_had_satd.h"
92 #include "ihevce_error_checks.h"
93 #include "ihevce_error_codes.h"
94 #include "ihevce_bitstream.h"
95 #include "ihevce_cabac.h"
96 #include "ihevce_rdoq_macros.h"
97 #include "ihevce_function_selector.h"
98 #include "ihevce_enc_structs.h"
99 #include "ihevce_global_tables.h"
100 #include "ihevce_cmn_utils_instr_set_router.h"
101 #include "ihevce_ipe_instr_set_router.h"
102 #include "ihevce_entropy_structs.h"
103 #include "ihevce_enc_loop_structs.h"
104 #include "ihevce_enc_loop_utils.h"
105 #include "ihevce_inter_pred.h"
106 #include "ihevce_common_utils.h"
107 #include "ihevce_sub_pic_rc.h"
108 #include "hme_datatype.h"
109 #include "hme_interface.h"
110 #include "hme_common_defs.h"
111 #include "hme_defs.h"
112 #include "ihevce_enc_loop_pass.h"
113 #include "ihevce_trace.h"
114 #include "ihevce_encode_header.h"
115 #include "ihevce_encode_header_sei_vui.h"
116 #include "ihevce_ipe_structs.h"
117 #include "ihevce_ipe_pass.h"
118 #include "ihevce_dep_mngr_interface.h"
119 #include "ihevce_rc_enc_structs.h"
120 #include "hme_globals.h"
121 #include "ihevce_me_pass.h"
122 #include "ihevce_coarse_me_pass.h"
123 #include "ihevce_frame_process.h"
124 #include "ihevce_rc_interface.h"
125 #include "ihevce_profile.h"
126 #include "ihevce_decomp_pre_intra_structs.h"
127 #include "ihevce_decomp_pre_intra_pass.h"
128 #include "ihevce_frame_process_utils.h"
129
130 #include "cast_types.h"
131 #include "osal.h"
132 #include "osal_defaults.h"
133
134 /*****************************************************************************/
135 /* Constant Macros */
136 /*****************************************************************************/
137
138 #define REF_MOD_STRENGTH 1.0
139 #define REF_MAX_STRENGTH 1.4f
140
141 /*****************************************************************************/
142 /* Extern variables */
143 /*****************************************************************************/
144
145 /**
146 * @var QP2QUANT_MD[]
147 *
148 * @brief Direct Cost Comoparision Table
149 *
150 * @param Comments: Direct cost is compared with 16 * QP2QUANT_MD[Qp]
151 * If direct cost is less than 16 * QP2QUANT_MD[Qp]
152 * than direct cost is assumed to be zero
153 */
154 const WORD16 QP2QUANT_MD[52] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
155 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4,
156 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20,
157 23, 25, 29, 32, 36, 40, 45, 51, 57, 64, 72, 81, 91 };
158
159 /*
160 Gaussian 11x11 window with a sigma of 1.5 - values multiplied by 2048
161 Window made into 9x9 window as most entries were zero
162 The center weight has been reduced by 1 after dropping first row/col and last row/col
163 */
164 UWORD8 g_u1_win_size = 9;
165 UWORD8 g_u1_win_q_shift = 11;
166 UWORD8 au1_g_win[81] = { 0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 3, 8, 16, 20, 16, 8, 3,
167 1, 2, 8, 24, 48, 60, 48, 24, 8, 2, 3, 16, 48, 93, 116, 93, 48,
168 16, 3, 4, 20, 60, 116, 144, 116, 60, 20, 4, 3, 16, 48, 93, 116, 93,
169 48, 16, 3, 2, 8, 24, 48, 60, 48, 24, 8, 2, 1, 3, 8, 16, 20,
170 16, 8, 3, 1, 0, 1, 2, 3, 4, 3, 2, 1, 0 };
171
172 /* lagrange params */
173 const double lamda_modifier_for_I_pic[8] = { 0.85, 0.7471, 0.6646, 0.5913,
174 0.5261, 0.4680, 0.4164, 0.3705 };
175
176 /*****************************************************************************/
177 /* Function Definitions */
178 /*****************************************************************************/
179
180 /*!
181 ******************************************************************************
182 * \if Function name : ihevce_mbr_quality_tool_set_configuration \endif
183 *
184 * \brief
185 * tool set selection for auxilary bitrate. currently only num intra and inter
186 * candidates for auxilary bitrates are controlled
187 *
188 * \param[in] ps_enc_loop_thrd_ctxt : enc ctxt
189 * \param[in] ps_stat_prms: static parameters
190 * \return
191 * None
192 *
193 * \author
194 * Ittiam
195 *
196 *****************************************************************************
197 */
ihevce_mbr_quality_tool_set_configuration(ihevce_enc_loop_ctxt_t * ps_enc_loop_thrd_ctxt,ihevce_static_cfg_params_t * ps_stat_prms)198 void ihevce_mbr_quality_tool_set_configuration(
199 ihevce_enc_loop_ctxt_t *ps_enc_loop_thrd_ctxt, ihevce_static_cfg_params_t *ps_stat_prms)
200 {
201 /* for single bitrate encoder*/
202 switch(ps_stat_prms->s_tgt_lyr_prms.i4_mbr_quality_setting)
203 {
204 case IHEVCE_MBR_HIGH_QUALITY:
205 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 3;
206 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 4;
207 break;
208
209 case IHEVCE_MBR_MEDIUM_SPEED:
210 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 3;
211 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 3;
212 break;
213
214 case IHEVCE_MBR_HIGH_SPEED:
215 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 2;
216 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 2;
217 break;
218
219 case IHEVCE_MBR_EXTREME_SPEED:
220 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_intra = 1;
221 ps_enc_loop_thrd_ctxt->i4_num_modes_to_evaluate_inter = 1;
222 break;
223
224 default:
225 assert(0);
226 break;
227 }
228 }
229
230 /*!
231 ******************************************************************************
232 * \if Function name : ihevce_find_free_indx \endif
233 *
234 * \brief
235 * Pre encode Frame processing slave thread entry point function
236 *
237 * \param[in] Frame processing thread context pointer
238 *
239 * \return
240 * None
241 *
242 * \author
243 * Ittiam
244 *
245 *****************************************************************************
246 */
ihevce_find_free_indx(recon_pic_buf_t ** pps_recon_buf_q,WORD32 i4_num_buf)247 WORD32 ihevce_find_free_indx(recon_pic_buf_t **pps_recon_buf_q, WORD32 i4_num_buf)
248 {
249 WORD32 i4_ctr;
250 WORD32 i4_is_full = 1;
251 WORD32 i4_least_POC = 0x7FFFFFFF;
252 WORD32 i4_least_POC_idx = -1;
253 WORD32 i4_least_GOP_num = 0x7FFFFFFF;
254
255 for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
256 {
257 if(pps_recon_buf_q[i4_ctr]->i4_is_free == 1)
258 {
259 i4_is_full = 0;
260 break;
261 }
262 }
263 if(i4_is_full)
264 {
265 /* remove if any non-reference pictures are present */
266 for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
267 {
268 if(!pps_recon_buf_q[i4_ctr]->i4_is_reference &&
269 pps_recon_buf_q[i4_ctr]->i4_non_ref_free_flag)
270 {
271 i4_least_POC_idx = i4_ctr;
272 break;
273 }
274 }
275 /* if all non reference pictures are removed, then find the least poc
276 in the least gop number*/
277 if(i4_least_POC_idx == -1)
278 {
279 for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
280 {
281 if(i4_least_GOP_num > pps_recon_buf_q[i4_ctr]->i4_idr_gop_num)
282 {
283 i4_least_GOP_num = pps_recon_buf_q[i4_ctr]->i4_idr_gop_num;
284 }
285 }
286 for(i4_ctr = 0; i4_ctr < i4_num_buf; i4_ctr++)
287 {
288 if(i4_least_POC > pps_recon_buf_q[i4_ctr]->i4_poc &&
289 i4_least_GOP_num == pps_recon_buf_q[i4_ctr]->i4_idr_gop_num)
290 {
291 i4_least_POC = pps_recon_buf_q[i4_ctr]->i4_poc;
292 i4_least_POC_idx = i4_ctr;
293 }
294 }
295 }
296 }
297 return i4_least_POC_idx;
298 }
299
300 /*!
301 ******************************************************************************
302 * \if Function name : complexity_RC_reset_marking \endif
303 *
304 * \brief
305 * this function the complexity variation and set the complexity change flag for
306 * rate control to reset the model
307 *
308 * \param[in] ps_enc_loop_thrd_ctxt : enc ctxt
309 * \param[in] ps_stat_prms: static parameters
310 * \return
311 * None
312 *
313 * \author
314 * Ittiam
315 *
316 *****************************************************************************
317 */
complexity_RC_reset_marking(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_cur_ipe_idx,WORD32 i4_end_flag)318 void complexity_RC_reset_marking(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx, WORD32 i4_end_flag)
319 {
320 rc_lap_out_params_t *ps_cur_ipe_lap_out;
321 rc_lap_out_params_t *ps_lap_out_temp;
322 WORD32 i4_max_temporal_layers;
323
324 ps_cur_ipe_lap_out =
325 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out;
326 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_model = 0;
327 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 0;
328
329 i4_max_temporal_layers = ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers;
330
331 /*reset the RC_reset counter at reset points*/
332 if(ps_cur_ipe_lap_out->i4_is_I_only_scd || ps_cur_ipe_lap_out->i4_is_non_I_scd ||
333 ps_cur_ipe_lap_out->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
334 {
335 ps_enc_ctxt->i4_past_RC_reset_count = 0;
336 }
337
338 if(ps_cur_ipe_lap_out->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
339 {
340 ps_enc_ctxt->i4_past_RC_scd_reset_count = 0;
341 }
342 ps_enc_ctxt->i4_past_RC_reset_count++;
343 ps_enc_ctxt->i4_past_RC_scd_reset_count++;
344
345 /*complexity based rate control reset */
346
347 if((ps_cur_ipe_lap_out->i4_rc_pic_type == IV_P_FRAME ||
348 ps_cur_ipe_lap_out->i4_rc_pic_type == IV_I_FRAME) &&
349 (i4_max_temporal_layers > 1) && (!i4_end_flag) &&
350 (ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe > (2 * (1 << i4_max_temporal_layers))))
351 {
352 WORD32 i4_is_cur_pic_high_complex_region =
353 ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx]
354 ->i4_is_high_complex_region;
355 WORD32 i4_next_ipe_idx;
356 WORD32 i4_next_next_ipe_idx;
357 WORD32 i4_temp_ipe_idx;
358 WORD32 i;
359
360 ps_enc_ctxt->i4_future_RC_reset = 0;
361 ps_enc_ctxt->i4_future_RC_scd_reset = 0;
362 ASSERT(i4_is_cur_pic_high_complex_region != -1);
363
364 /*get the next idx of p/i picture */
365 i4_next_ipe_idx =
366 (i4_cur_ipe_idx + 1) % (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1);
367 i4_temp_ipe_idx =
368 (i4_cur_ipe_idx + 1) % (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1);
369 for(i = 0; i < (1 << i4_max_temporal_layers); i++)
370 {
371 ps_lap_out_temp =
372 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_next_ipe_idx]->s_rc_lap_out;
373
374 if(ps_lap_out_temp->i4_rc_pic_type == IV_P_FRAME ||
375 ps_lap_out_temp->i4_rc_pic_type == IV_I_FRAME)
376 {
377 break;
378 }
379 i4_next_ipe_idx = (i4_next_ipe_idx + 1) %
380 (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1);
381 }
382 /* get the next idx of next p/i picture*/
383 i4_next_next_ipe_idx =
384 (i4_next_ipe_idx + 1) % (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1);
385 for(i = 0; i < (1 << i4_max_temporal_layers); i++)
386 {
387 ps_lap_out_temp =
388 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_next_next_ipe_idx]->s_rc_lap_out;
389
390 if(ps_lap_out_temp->i4_rc_pic_type == IV_P_FRAME ||
391 ps_lap_out_temp->i4_rc_pic_type == IV_I_FRAME)
392 {
393 break;
394 }
395 i4_next_next_ipe_idx = (i4_next_next_ipe_idx + 1) %
396 (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1);
397 }
398
399 /*check for any possible RC reset in the future 8 frames*/
400 for(i = 0; i < 8; i++)
401 {
402 ps_lap_out_temp =
403 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_temp_ipe_idx]->s_rc_lap_out;
404
405 if(ps_lap_out_temp->i4_is_I_only_scd || ps_lap_out_temp->i4_is_non_I_scd ||
406 ps_lap_out_temp->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
407 {
408 ps_enc_ctxt->i4_future_RC_reset = 1;
409 }
410 if(ps_cur_ipe_lap_out->i4_rc_scene_type == SCENE_TYPE_SCENE_CUT)
411 {
412 ps_enc_ctxt->i4_future_RC_scd_reset = 1;
413 }
414 i4_temp_ipe_idx = (i4_temp_ipe_idx + 1) %
415 (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1);
416 }
417
418 if((!ps_enc_ctxt->i4_future_RC_reset) && (ps_enc_ctxt->i4_past_RC_reset_count > 8))
419 {
420 /*if the prev two P/I pic is not in high complex region
421 then enable reset RC flag*/
422 if((!ps_enc_ctxt->ai4_is_past_pic_complex[0]) &&
423 (!ps_enc_ctxt->ai4_is_past_pic_complex[1]))
424 {
425 if(i4_is_cur_pic_high_complex_region)
426 {
427 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_model = 1;
428 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
429 ps_enc_ctxt->i4_is_I_reset_done = 0;
430 }
431 }
432
433 /*if the next two P/I pic is not in high complex region
434 then enable reset RC flag*/
435 if((!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_ipe_idx]
436 ->i4_is_high_complex_region) &&
437 (!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_next_ipe_idx]
438 ->i4_is_high_complex_region))
439 {
440 if(i4_is_cur_pic_high_complex_region)
441 {
442 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_model = 1;
443 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
444 ps_enc_ctxt->i4_is_I_reset_done = 0;
445 }
446 }
447 }
448 else if((!ps_enc_ctxt->i4_future_RC_scd_reset) && (ps_enc_ctxt->i4_past_RC_scd_reset_count > 8))
449 {
450 /*if the prev two P/I pic is not in high complex region
451 then enable reset RC flag*/
452 if((!ps_enc_ctxt->ai4_is_past_pic_complex[0]) &&
453 (!ps_enc_ctxt->ai4_is_past_pic_complex[1]))
454 {
455 if(i4_is_cur_pic_high_complex_region)
456 {
457 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
458 }
459 }
460
461 /*if the next two P/I pic is not in high complex region
462 then enable reset RC flag*/
463 if((!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_ipe_idx]
464 ->i4_is_high_complex_region) &&
465 (!ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_next_next_ipe_idx]
466 ->i4_is_high_complex_region))
467 {
468 if(i4_is_cur_pic_high_complex_region)
469 {
470 ps_cur_ipe_lap_out->i4_is_cmplx_change_reset_bits = 1;
471 }
472 }
473 }
474
475 /* forcing I frame reset after complexity change is disable as it gives gain, could be due to that
476 required i reset is already happening on pre Intra SAD*/
477 /*if(!ps_enc_ctxt->i4_is_I_reset_done && (ps_cur_ipe_lap_out->i4_pic_type
478 == IV_I_FRAME))
479 {
480 ps_cur_ipe_lap_out->i4_is_I_only_scd = 1;
481 ps_enc_ctxt->i4_is_I_reset_done = 1;
482 }*/
483
484 ps_enc_ctxt->ai4_is_past_pic_complex[0] = i4_is_cur_pic_high_complex_region;
485
486 ps_enc_ctxt->ai4_is_past_pic_complex[1] = ps_enc_ctxt->ai4_is_past_pic_complex[0];
487 }
488 return;
489 }
490 /*!
491 ******************************************************************************
492 * \if Function name : ihevce_manage_ref_pics \endif
493 *
494 * \brief
495 * Reference picture management based on delta poc array given by LAP
496 * Populates the reference list after removing non used reference pictures
497 * populates the delta poc of reference pics to be signalled in slice header
498 *
499 * \param[in] encoder context pointer
500 * \param[in] current LAP Encoder buffer pointer
501 * \param[in] current frame process and entropy buffer pointer
502 *
503 * \return
504 * None
505 *
506 * \author
507 * Ittiam
508 *
509 *****************************************************************************
510 */
ihevce_pre_enc_manage_ref_pics(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,pre_enc_me_ctxt_t * ps_curr_out,WORD32 i4_ping_pong)511 void ihevce_pre_enc_manage_ref_pics(
512 enc_ctxt_t *ps_enc_ctxt,
513 ihevce_lap_enc_buf_t *ps_curr_inp,
514 pre_enc_me_ctxt_t *ps_curr_out,
515 WORD32 i4_ping_pong)
516 {
517 /* local variables */
518 WORD32 ctr;
519 WORD32 ref_pics;
520 WORD32 ai4_buf_status[HEVCE_MAX_DPB_PICS] = { 0 };
521 WORD32 curr_poc;
522 WORD32 wp_flag = 0;
523 WORD32 num_ref_pics_list0 = 0;
524 WORD32 num_ref_pics_list1 = 0;
525 WORD32 cra_poc = ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc;
526 WORD32 slice_type = ps_curr_out->s_slice_hdr.i1_slice_type;
527 recon_pic_buf_t *(*aps_pre_enc_ref_pic_list)[HEVCE_MAX_REF_PICS * 2];
528 WORD32 i4_inc_L1_active_ref_pic = 0;
529 WORD32 i4_inc_L0_active_ref_pic = 0;
530
531 (void)ps_curr_out;
532 curr_poc = ps_curr_inp->s_lap_out.i4_poc;
533
534 /* Number of reference pics given by LAP should not be greater than max */
535 ASSERT(HEVCE_MAX_REF_PICS >= ps_curr_inp->s_lap_out.i4_num_ref_pics);
536
537 /*derive ref_pic_list based on ping_pong instance */
538 aps_pre_enc_ref_pic_list = ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong];
539
540 /* derive the weighted prediction enable flag based on slice type */
541 if(BSLICE == slice_type)
542 {
543 wp_flag = ps_curr_inp->s_lap_out.i1_weighted_bipred_flag;
544 }
545 else if(PSLICE == slice_type)
546 {
547 wp_flag = ps_curr_inp->s_lap_out.i1_weighted_pred_flag;
548 }
549 else
550 {
551 wp_flag = 0;
552 }
553
554 /*to support diplicate pics*/
555 {
556 WORD32 i, j;
557 for(i = 0; i < 2; i++)
558 {
559 for(j = 0; j < HEVCE_MAX_REF_PICS * 2; j++)
560 {
561 aps_pre_enc_ref_pic_list[i][j] =
562 &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][i][j];
563 }
564 }
565 }
566
567 /* run a loop over the number of reference pics given by LAP */
568 for(ref_pics = 0; ref_pics < ps_curr_inp->s_lap_out.i4_num_ref_pics; ref_pics++)
569 {
570 WORD32 ref_poc;
571 WORD32 i4_loop = 1;
572 WORD32 i4_temp_list;
573
574 ref_poc = curr_poc + ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_ref_pic_delta_poc;
575
576 /* run a loop to check the poc based on delta poc array */
577 for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
578 {
579 /* if the POC is matching with current ref picture*/
580 if((ref_poc == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_poc) &&
581 (0 == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free))
582 {
583 /* mark the buf status as used */
584 ai4_buf_status[ctr] = 1;
585
586 /* populate the reference lists based on delta poc array */
587 if((ref_poc < curr_poc) || (0 == curr_poc))
588 {
589 /* list 0 */
590 memcpy(
591 &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0],
592 ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
593 sizeof(recon_pic_buf_t));
594 i4_temp_list = num_ref_pics_list0;
595
596 /*duplicate pics added to the list*/
597 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
598 .i4_num_duplicate_entries_in_ref_list)
599 {
600 /* list 0 */
601 i4_temp_list++;
602 memcpy(
603 &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][i4_temp_list],
604 ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
605 sizeof(recon_pic_buf_t));
606 i4_loop++;
607 }
608
609 /* populate weights and offsets corresponding to this ref pic */
610 memcpy(
611 &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
612 .s_weight_offset,
613 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
614 sizeof(ihevce_wght_offst_t));
615
616 /* Store the used as ref for current pic flag */
617 ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
618 .i4_used_by_cur_pic_flag =
619 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
620
621 num_ref_pics_list0++;
622 i4_loop = 1;
623 /*duplicate pics added to the list*/
624 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
625 .i4_num_duplicate_entries_in_ref_list)
626 {
627 /* populate weights and offsets corresponding to this ref pic */
628 memcpy(
629 &ps_enc_ctxt
630 ->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
631 .s_weight_offset,
632 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
633 sizeof(ihevce_wght_offst_t));
634
635 /* Store the used as ref for current pic flag */
636 ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_0][num_ref_pics_list0]
637 .i4_used_by_cur_pic_flag =
638 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
639
640 num_ref_pics_list0++;
641 i4_loop++;
642 }
643 }
644 else
645 {
646 /* list 1 */
647 memcpy(
648 &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1],
649 ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
650 sizeof(recon_pic_buf_t));
651
652 i4_temp_list = num_ref_pics_list1;
653 /*duplicate pics added to the list*/
654 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
655 .i4_num_duplicate_entries_in_ref_list)
656 {
657 /* list 1 */
658 i4_temp_list++;
659 memcpy(
660 &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][i4_temp_list],
661 ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr],
662 sizeof(recon_pic_buf_t));
663 i4_loop++;
664 }
665
666 /* populate weights and offsets corresponding to this ref pic */
667 memcpy(
668 &ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
669 .s_weight_offset,
670 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
671 sizeof(ihevce_wght_offst_t));
672
673 /* Store the used as ref for current pic flag */
674 ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
675 .i4_used_by_cur_pic_flag =
676 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
677
678 num_ref_pics_list1++;
679 i4_loop = 1;
680 /*duplicate pics added to the list*/
681 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
682 .i4_num_duplicate_entries_in_ref_list)
683 {
684 /* populate weights and offsets corresponding to this ref pic */
685 memcpy(
686 &ps_enc_ctxt
687 ->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
688 .s_weight_offset,
689 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
690 sizeof(ihevce_wght_offst_t));
691
692 /* Store the used as ref for current pic flag */
693 ps_enc_ctxt->as_pre_enc_ref_lists[i4_ping_pong][LIST_1][num_ref_pics_list1]
694 .i4_used_by_cur_pic_flag =
695 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
696
697 num_ref_pics_list1++;
698 i4_loop++;
699 }
700 }
701 break;
702 }
703 }
704
705 /* if the reference picture is not found then error */
706 ASSERT(ctr != ps_enc_ctxt->i4_pre_enc_num_buf_recon_q);
707 }
708 /* sort the reference pics in List0 in descending order POC */
709 if(num_ref_pics_list0 > 1)
710 {
711 /* run a loop for num ref pics -1 */
712 for(ctr = 0; ctr < num_ref_pics_list0 - 1; ctr++)
713 {
714 WORD32 max_idx = ctr;
715 recon_pic_buf_t *ps_temp;
716 WORD32 i;
717
718 for(i = (ctr + 1); i < num_ref_pics_list0; i++)
719 {
720 /* check for poc greater than current ref poc */
721 if(aps_pre_enc_ref_pic_list[LIST_0][i]->i4_poc >
722 aps_pre_enc_ref_pic_list[LIST_0][max_idx]->i4_poc)
723 {
724 max_idx = i;
725 }
726 }
727
728 /* if max of remaining is not current, swap the pointers */
729 if(max_idx != ctr)
730 {
731 ps_temp = aps_pre_enc_ref_pic_list[LIST_0][max_idx];
732 aps_pre_enc_ref_pic_list[LIST_0][max_idx] = aps_pre_enc_ref_pic_list[LIST_0][ctr];
733 aps_pre_enc_ref_pic_list[LIST_0][ctr] = ps_temp;
734 }
735 }
736 }
737
738 /* sort the reference pics in List1 in ascending order POC */
739 if(num_ref_pics_list1 > 1)
740 {
741 /* run a loop for num ref pics -1 */
742 for(ctr = 0; ctr < num_ref_pics_list1 - 1; ctr++)
743 {
744 WORD32 min_idx = ctr;
745 recon_pic_buf_t *ps_temp;
746 WORD32 i;
747
748 for(i = (ctr + 1); i < num_ref_pics_list1; i++)
749 {
750 /* check for p[oc less than current ref poc */
751 if(aps_pre_enc_ref_pic_list[LIST_1][i]->i4_poc <
752 aps_pre_enc_ref_pic_list[LIST_1][min_idx]->i4_poc)
753 {
754 min_idx = i;
755 }
756 }
757
758 /* if min of remaining is not current, swap the pointers */
759 if(min_idx != ctr)
760 {
761 ps_temp = aps_pre_enc_ref_pic_list[LIST_1][min_idx];
762 aps_pre_enc_ref_pic_list[LIST_1][min_idx] = aps_pre_enc_ref_pic_list[LIST_1][ctr];
763 aps_pre_enc_ref_pic_list[LIST_1][ctr] = ps_temp;
764 }
765 }
766 }
767
768 /* call the ME API to update the DPB of HME pyramids coarse layers */
769 ihevce_coarse_me_frame_dpb_update(
770 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
771 num_ref_pics_list0,
772 num_ref_pics_list1,
773 &aps_pre_enc_ref_pic_list[LIST_0][0],
774 &aps_pre_enc_ref_pic_list[LIST_1][0]);
775
776 /* Default list creation based on uses as ref pic for current pic flag */
777 {
778 WORD32 num_ref_pics_list_final = 0;
779 WORD32 list_idx = 0;
780
781 /* LIST 0 */
782 /* run a loop for num ref pics in list 0 */
783 for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
784 {
785 /* check for used as reference flag */
786 if(1 == aps_pre_enc_ref_pic_list[LIST_0][ctr]->i4_used_by_cur_pic_flag)
787 {
788 /* copy the pointer to the actual valid list idx */
789 aps_pre_enc_ref_pic_list[LIST_0][list_idx] = aps_pre_enc_ref_pic_list[LIST_0][ctr];
790
791 /* increment the valid pic counters and idx */
792 list_idx++;
793 num_ref_pics_list_final++;
794 }
795 }
796
797 /* finally store the number of pictures in List0 */
798 num_ref_pics_list0 = num_ref_pics_list_final;
799 /* LIST 1 */
800 num_ref_pics_list_final = 0;
801 list_idx = 0;
802
803 /* run a loop for num ref pics in list 1 */
804 for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
805 {
806 /* check for used as reference flag */
807 if(1 == aps_pre_enc_ref_pic_list[LIST_1][ctr]->i4_used_by_cur_pic_flag)
808 {
809 /* copy the pointer to the actual valid list idx */
810 aps_pre_enc_ref_pic_list[LIST_1][list_idx] = aps_pre_enc_ref_pic_list[LIST_1][ctr];
811
812 /* increment the valid pic counters and idx */
813 list_idx++;
814 num_ref_pics_list_final++;
815 }
816 }
817
818 /* finally store the number of pictures in List1 */
819 num_ref_pics_list1 = num_ref_pics_list_final;
820 }
821 /*in case of single active ref picture on L0 and L1, then consider one of them weighted
822 and another non-weighted*/
823 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
824 {
825 if(num_ref_pics_list0 > 2)
826 {
827 if(aps_pre_enc_ref_pic_list[LIST_0][0]->i4_poc ==
828 aps_pre_enc_ref_pic_list[LIST_0][1]->i4_poc)
829 {
830 i4_inc_L0_active_ref_pic = 1;
831 }
832 }
833 }
834 else
835 {
836 if(num_ref_pics_list0 >= 2 && num_ref_pics_list1 >= 2)
837 {
838 if(aps_pre_enc_ref_pic_list[LIST_0][0]->i4_poc ==
839 aps_pre_enc_ref_pic_list[LIST_0][1]->i4_poc)
840 {
841 i4_inc_L0_active_ref_pic = 1;
842 }
843 if(aps_pre_enc_ref_pic_list[LIST_1][0]->i4_poc ==
844 aps_pre_enc_ref_pic_list[LIST_1][1]->i4_poc)
845 {
846 i4_inc_L1_active_ref_pic = 1;
847 }
848 }
849 }
850
851 /* append the reference pics in List1 and end of list0 */
852 for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
853 {
854 aps_pre_enc_ref_pic_list[LIST_0][num_ref_pics_list0 + ctr] =
855 aps_pre_enc_ref_pic_list[LIST_1][ctr];
856 }
857
858 /* append the reference pics in List0 and end of list1 */
859 for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
860 {
861 aps_pre_enc_ref_pic_list[LIST_1][num_ref_pics_list1 + ctr] =
862 aps_pre_enc_ref_pic_list[LIST_0][ctr];
863 }
864
865 /* reference list modification for adding duplicate reference */
866 {
867
868 }
869
870 /* popluate the default weights and offsets for disabled cases */
871 {
872 WORD32 i;
873
874 /* populate the weights and offsets for all pics in L0 + L1 */
875 for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
876 {
877 /* populate the weights and offsets if weighted prediction is disabled */
878 if(1 == wp_flag)
879 {
880 /* if weights are disabled then populate default values */
881 if(0 ==
882 aps_pre_enc_ref_pic_list[LIST_0][i]->s_weight_offset.u1_luma_weight_enable_flag)
883 {
884 /* set to default values */
885 aps_pre_enc_ref_pic_list[LIST_0][i]->s_weight_offset.i2_luma_weight =
886 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
887
888 aps_pre_enc_ref_pic_list[LIST_0][i]->s_weight_offset.i2_luma_offset = 0;
889 }
890 }
891 }
892
893 for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
894 {
895 /* populate the weights and offsets if weighted prediction is enabled */
896 if(1 == wp_flag)
897 {
898 /* if weights are disabled then populate default values */
899 if(0 ==
900 aps_pre_enc_ref_pic_list[LIST_1][i]->s_weight_offset.u1_luma_weight_enable_flag)
901 {
902 /* set to default values */
903 aps_pre_enc_ref_pic_list[LIST_1][i]->s_weight_offset.i2_luma_weight =
904 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
905
906 aps_pre_enc_ref_pic_list[LIST_1][i]->s_weight_offset.i2_luma_offset = 0;
907 }
908 }
909 }
910 }
911
912 /* run a loop to free the non used reference pics */
913 for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
914 {
915 /* if not used as reference */
916 if(0 == ai4_buf_status[ctr])
917 {
918 ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free = 1;
919 ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_poc = -1;
920 }
921 }
922
923 /* store the number of reference pics in the list for ME/MC etc */
924 ps_enc_ctxt->i4_pre_enc_num_ref_l0 = num_ref_pics_list0;
925 ps_enc_ctxt->i4_pre_enc_num_ref_l1 = num_ref_pics_list1;
926
927 #define HME_USE_ONLY_2REF
928 #ifndef HME_USE_ONLY_2REF
929 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = num_ref_pics_list0;
930 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = num_ref_pics_list1;
931 #else
932 #if MULTI_REF_ENABLE == 1
933 if(ps_curr_inp->s_lap_out.i4_quality_preset >= IHEVCE_QUALITY_P3)
934 {
935 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
936 {
937 if(IHEVCE_QUALITY_P6 == ps_curr_inp->s_lap_out.i4_quality_preset)
938 {
939 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
940 {
941 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active =
942 MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25 + 1, num_ref_pics_list0);
943 }
944 else
945 {
946 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active =
947 MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25, num_ref_pics_list0);
948 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active += i4_inc_L0_active_ref_pic;
949 }
950
951 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
952 }
953 else
954 {
955 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
956 {
957 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(3, num_ref_pics_list0);
958 }
959 else
960 {
961 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
962 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active += i4_inc_L0_active_ref_pic;
963 }
964
965 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
966 }
967 }
968 else
969 {
970 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
971 {
972 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
973 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
974 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active += i4_inc_L1_active_ref_pic;
975 }
976 else
977 {
978 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(1, num_ref_pics_list0);
979 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
980 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active += i4_inc_L1_active_ref_pic;
981 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active += i4_inc_L0_active_ref_pic;
982 }
983 }
984 }
985 else
986 {
987 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
988 {
989 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
990 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
991 else
992 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
993
994 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
995 }
996 else
997 {
998 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
999 {
1000 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1001 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1002 }
1003 else
1004 {
1005 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1006 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1007 }
1008 }
1009 }
1010 #else
1011 {
1012 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1013 {
1014 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1015 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(3, num_ref_pics_list0);
1016 else
1017 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1018
1019 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = 0;
1020 }
1021 else
1022 {
1023 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1024 {
1025 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1026 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1027 }
1028 else
1029 {
1030 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active = MIN(1, num_ref_pics_list0);
1031 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1032 }
1033 }
1034 }
1035 #endif
1036 #endif
1037
1038 return;
1039 }
1040
1041 /*!
1042 ******************************************************************************
1043 * \if Function name : ihevce_manage_ref_pics \endif
1044 *
1045 * \brief
1046 * Reference picture management based on delta poc array given by LAP
1047 * Populates the reference list after removing non used reference pictures
1048 * populates the delta poc of reference pics to be signalled in slice header
1049 *
1050 * \param[in] encoder context pointer
1051 * \param[in] current LAP Encoder buffer pointer
1052 * \param[in] current frame process and entropy buffer pointer
1053 *
1054 * \return
1055 * None
1056 *
1057 * \author
1058 * Ittiam
1059 *
1060 *****************************************************************************
1061 */
ihevce_manage_ref_pics(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,slice_header_t * ps_slice_header,WORD32 i4_me_frm_id,WORD32 i4_thrd_id,WORD32 i4_bitrate_instance_id)1062 void ihevce_manage_ref_pics(
1063 enc_ctxt_t *ps_enc_ctxt,
1064 ihevce_lap_enc_buf_t *ps_curr_inp,
1065 slice_header_t *ps_slice_header,
1066 WORD32 i4_me_frm_id,
1067 WORD32 i4_thrd_id,
1068 WORD32 i4_bitrate_instance_id)
1069 {
1070 WORD32 ctr;
1071 WORD32 ref_pics;
1072 WORD32 curr_poc, curr_idr_gop_num;
1073 WORD32 wp_flag;
1074 WORD32 num_ref_pics_list0 = 0;
1075 WORD32 num_ref_pics_list1 = 0;
1076 WORD32 cra_poc = ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc;
1077 WORD32 slice_type = ps_slice_header->i1_slice_type;
1078 recon_pic_buf_t *(*aps_ref_list)[HEVCE_MAX_REF_PICS * 2];
1079 recon_pic_buf_t(*aps_ref_list_temp)[HEVCE_MAX_REF_PICS * 2];
1080 WORD32 i4_num_rpics_l0_excl_dup;
1081 WORD32 i4_num_rpics_l1_excl_dup;
1082 WORD32 i4_inc_L1_active_ref_pic = 0;
1083 WORD32 i4_inc_L0_active_ref_pic = 0;
1084 WORD32 i4_bridx = i4_bitrate_instance_id; //bitrate instance index
1085 WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
1086 me_enc_rdopt_ctxt_t *ps_cur_out_me_prms;
1087 recon_pic_buf_t ***ppps_recon_bufs = ps_enc_ctxt->pps_recon_buf_q;
1088 WORD32 i4_num_recon_bufs = ps_enc_ctxt->ai4_num_buf_recon_q[i4_bridx];
1089
1090 ps_cur_out_me_prms = ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id];
1091
1092 /*to support diplicate pics*/
1093 {
1094 WORD32 i, j;
1095 for(i = 0; i < NUM_REF_LISTS; i++)
1096 {
1097 for(j = 0; j < HEVCE_MAX_REF_PICS * 2; j++)
1098 {
1099 ps_cur_out_me_prms->aps_ref_list[i4_bridx][i][j] =
1100 &ps_cur_out_me_prms->as_ref_list[i4_bridx][i][j];
1101 }
1102 }
1103 }
1104
1105 aps_ref_list = ps_cur_out_me_prms->aps_ref_list[i4_bridx];
1106 aps_ref_list_temp = ps_cur_out_me_prms->as_ref_list[i4_bridx];
1107
1108 curr_poc = ps_curr_inp->s_lap_out.i4_poc;
1109 curr_idr_gop_num = ps_curr_inp->s_lap_out.i4_idr_gop_num;
1110
1111 /* Number of reference pics given by LAP should not be greater than max */
1112 ASSERT(HEVCE_MAX_REF_PICS >= ps_curr_inp->s_lap_out.i4_num_ref_pics);
1113
1114 /* derive the weighted prediction enable flag based on slice type */
1115 if(BSLICE == slice_type)
1116 {
1117 wp_flag = ps_curr_inp->s_lap_out.i1_weighted_bipred_flag;
1118 }
1119 else if(PSLICE == slice_type)
1120 {
1121 wp_flag = ps_curr_inp->s_lap_out.i1_weighted_pred_flag;
1122 }
1123 else
1124 {
1125 wp_flag = 0;
1126 }
1127
1128 ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l0 = 0;
1129 ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l1 = 0;
1130 ASSERT(curr_poc != INVALID_POC);
1131
1132 /* run a loop over the number of reference pics given by LAP */
1133 for(ref_pics = 0; ref_pics < ps_curr_inp->s_lap_out.i4_num_ref_pics; ref_pics++)
1134 {
1135 WORD32 ref_poc;
1136 WORD32 i4_loop = 1;
1137 WORD32 i4_temp_list;
1138
1139 ref_poc = curr_poc + ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_ref_pic_delta_poc;
1140 if((0 == curr_poc) && curr_idr_gop_num)
1141 {
1142 curr_idr_gop_num -= 1;
1143 }
1144 ASSERT(ref_poc != INVALID_POC);
1145 /* run a loop to check the poc based on delta poc array */
1146 for(ctr = 0; ctr < i4_num_recon_bufs; ctr++)
1147 {
1148 /* if the POC is matching with current ref picture*/
1149 if((ref_poc == ppps_recon_bufs[i4_bridx][ctr]->i4_poc) &&
1150 (0 == ppps_recon_bufs[i4_bridx][ctr]->i4_is_free) &&
1151 (curr_idr_gop_num == ppps_recon_bufs[i4_bridx][ctr]->i4_idr_gop_num))
1152 {
1153 /* populate the reference lists based on delta poc array */
1154 if((ref_poc < curr_poc) || (0 == curr_poc))
1155 {
1156 /* list 0 */
1157 memcpy(
1158 &aps_ref_list_temp[LIST_0][num_ref_pics_list0],
1159 ppps_recon_bufs[i4_bridx][ctr],
1160 sizeof(recon_pic_buf_t));
1161
1162 i4_temp_list = num_ref_pics_list0;
1163
1164 /*duplicate pics added to the list*/
1165 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1166 .i4_num_duplicate_entries_in_ref_list)
1167 {
1168 i4_temp_list++;
1169 /* list 0 */
1170 memcpy(
1171 &aps_ref_list_temp[LIST_0][i4_temp_list],
1172 ppps_recon_bufs[i4_bridx][ctr],
1173 sizeof(recon_pic_buf_t));
1174 i4_loop++;
1175 }
1176
1177 /* populate weights and offsets corresponding to this ref pic */
1178 memcpy(
1179 &aps_ref_list_temp[LIST_0][num_ref_pics_list0].s_weight_offset,
1180 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
1181 sizeof(ihevce_wght_offst_t));
1182
1183 /* Store the used as ref for current pic flag */
1184 aps_ref_list_temp[LIST_0][num_ref_pics_list0].i4_used_by_cur_pic_flag =
1185 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1186
1187 if(wp_flag)
1188 {
1189 WORD16 i2_luma_weight = (aps_ref_list[LIST_0][num_ref_pics_list0]
1190 ->s_weight_offset.i2_luma_weight);
1191
1192 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1193 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1194
1195 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1196 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1197 }
1198 else
1199 {
1200 WORD16 i2_luma_weight =
1201 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1202
1203 aps_ref_list[LIST_0][num_ref_pics_list0]->s_weight_offset.i2_luma_weight =
1204 i2_luma_weight;
1205
1206 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1207 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1208
1209 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1210 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1211 }
1212
1213 num_ref_pics_list0++;
1214 i4_loop = 1;
1215
1216 /*duplicate pics added to the list*/
1217 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1218 .i4_num_duplicate_entries_in_ref_list)
1219 {
1220 /* populate weights and offsets corresponding to this ref pic */
1221 memcpy(
1222 &aps_ref_list_temp[LIST_0][num_ref_pics_list0].s_weight_offset,
1223 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
1224 sizeof(ihevce_wght_offst_t));
1225
1226 /* Store the used as ref for current pic flag */
1227 aps_ref_list_temp[LIST_0][num_ref_pics_list0].i4_used_by_cur_pic_flag =
1228 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1229
1230 if(wp_flag)
1231 {
1232 WORD16 i2_luma_weight = (aps_ref_list[LIST_0][num_ref_pics_list0]
1233 ->s_weight_offset.i2_luma_weight);
1234
1235 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1236 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1237
1238 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1239 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1240 }
1241 else
1242 {
1243 WORD16 i2_luma_weight =
1244 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1245
1246 aps_ref_list[LIST_0][num_ref_pics_list0]
1247 ->s_weight_offset.i2_luma_weight = i2_luma_weight;
1248
1249 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_inv_luma_wt =
1250 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1251
1252 aps_ref_list[LIST_0][num_ref_pics_list0]->i4_log2_wt_denom =
1253 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1254 }
1255
1256 num_ref_pics_list0++;
1257 i4_loop++;
1258 ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l0 = 1;
1259 ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l1 = 1;
1260 }
1261 }
1262 else
1263 {
1264 /* list 1 */
1265 memcpy(
1266 &aps_ref_list_temp[LIST_1][num_ref_pics_list1],
1267 ppps_recon_bufs[i4_bridx][ctr],
1268 sizeof(recon_pic_buf_t));
1269 i4_temp_list = num_ref_pics_list1;
1270 /*duplicate pics added to the list*/
1271 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1272 .i4_num_duplicate_entries_in_ref_list)
1273 {
1274 i4_temp_list++;
1275 /* list 1 */
1276 memcpy(
1277 &aps_ref_list_temp[LIST_1][i4_temp_list],
1278 ppps_recon_bufs[i4_bridx][ctr],
1279 sizeof(recon_pic_buf_t));
1280 i4_loop++;
1281 }
1282
1283 /* populate weights and offsets corresponding to this ref pic */
1284 memcpy(
1285 &aps_ref_list_temp[LIST_1][num_ref_pics_list1].s_weight_offset,
1286 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[0],
1287 sizeof(ihevce_wght_offst_t));
1288
1289 /* Store the used as ref for current pic flag */
1290 aps_ref_list_temp[LIST_1][num_ref_pics_list1].i4_used_by_cur_pic_flag =
1291 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1292
1293 if(wp_flag)
1294 {
1295 WORD16 i2_luma_weight = (aps_ref_list[LIST_1][num_ref_pics_list1]
1296 ->s_weight_offset.i2_luma_weight);
1297
1298 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1299 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1300
1301 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1302 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1303 }
1304 else
1305 {
1306 WORD16 i2_luma_weight =
1307 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1308
1309 aps_ref_list[LIST_1][num_ref_pics_list1]->s_weight_offset.i2_luma_weight =
1310 i2_luma_weight;
1311
1312 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1313 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1314
1315 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1316 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1317 }
1318
1319 num_ref_pics_list1++;
1320 i4_loop = 1;
1321 /*duplicate pics added to the list*/
1322 while(i4_loop != ps_curr_inp->s_lap_out.as_ref_pics[ref_pics]
1323 .i4_num_duplicate_entries_in_ref_list)
1324 {
1325 /* populate weights and offsets corresponding to this ref pic */
1326 memcpy(
1327 &aps_ref_list_temp[LIST_1][num_ref_pics_list1].s_weight_offset,
1328 &ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].as_wght_off[i4_loop],
1329 sizeof(ihevce_wght_offst_t));
1330
1331 /* Store the used as ref for current pic flag */
1332 aps_ref_list_temp[LIST_1][num_ref_pics_list1].i4_used_by_cur_pic_flag =
1333 ps_curr_inp->s_lap_out.as_ref_pics[ref_pics].i4_used_by_cur_pic_flag;
1334
1335 if(wp_flag)
1336 {
1337 WORD16 i2_luma_weight = (aps_ref_list[LIST_1][num_ref_pics_list1]
1338 ->s_weight_offset.i2_luma_weight);
1339
1340 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1341 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1342
1343 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1344 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1345 }
1346 else
1347 {
1348 WORD16 i2_luma_weight =
1349 (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1350
1351 aps_ref_list[LIST_1][num_ref_pics_list1]
1352 ->s_weight_offset.i2_luma_weight = i2_luma_weight;
1353
1354 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_inv_luma_wt =
1355 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1356
1357 aps_ref_list[LIST_1][num_ref_pics_list1]->i4_log2_wt_denom =
1358 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1359 }
1360
1361 num_ref_pics_list1++;
1362 i4_loop++;
1363 ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l1 = 1;
1364 ps_slice_header->s_rplm.i1_ref_pic_list_modification_flag_l0 = 1;
1365 }
1366 }
1367 break;
1368 }
1369 }
1370
1371 /* if the reference picture is not found then error */
1372 ASSERT(ctr != i4_num_recon_bufs);
1373 }
1374
1375 i4_num_rpics_l0_excl_dup = num_ref_pics_list0;
1376 i4_num_rpics_l1_excl_dup = num_ref_pics_list1;
1377
1378 /* sort the reference pics in List0 in descending order POC */
1379 if(num_ref_pics_list0 > 1)
1380 {
1381 /* run a loop for num ref pics -1 */
1382 for(ctr = 0; ctr < num_ref_pics_list0 - 1; ctr++)
1383 {
1384 WORD32 max_idx = ctr;
1385 recon_pic_buf_t *ps_temp;
1386 WORD32 i;
1387
1388 for(i = (ctr + 1); i < num_ref_pics_list0; i++)
1389 {
1390 /* check for poc greater than current ref poc */
1391 if(aps_ref_list[LIST_0][i]->i4_poc > aps_ref_list[LIST_0][max_idx]->i4_poc)
1392 {
1393 max_idx = i;
1394 }
1395 }
1396
1397 /* if max of remaining is not current, swap the pointers */
1398 if(max_idx != ctr)
1399 {
1400 ps_temp = aps_ref_list[LIST_0][max_idx];
1401 aps_ref_list[LIST_0][max_idx] = aps_ref_list[LIST_0][ctr];
1402 aps_ref_list[LIST_0][ctr] = ps_temp;
1403 }
1404 }
1405 }
1406
1407 /* sort the reference pics in List1 in ascending order POC */
1408 if(num_ref_pics_list1 > 1)
1409 {
1410 /* run a loop for num ref pics -1 */
1411 for(ctr = 0; ctr < num_ref_pics_list1 - 1; ctr++)
1412 {
1413 WORD32 min_idx = ctr;
1414 recon_pic_buf_t *ps_temp;
1415 WORD32 i;
1416
1417 for(i = (ctr + 1); i < num_ref_pics_list1; i++)
1418 {
1419 /* check for p[oc less than current ref poc */
1420 if(aps_ref_list[LIST_1][i]->i4_poc < aps_ref_list[LIST_1][min_idx]->i4_poc)
1421 {
1422 min_idx = i;
1423 }
1424 }
1425
1426 /* if min of remaining is not current, swap the pointers */
1427 if(min_idx != ctr)
1428 {
1429 ps_temp = aps_ref_list[LIST_1][min_idx];
1430 aps_ref_list[LIST_1][min_idx] = aps_ref_list[LIST_1][ctr];
1431 aps_ref_list[LIST_1][ctr] = ps_temp;
1432 }
1433 }
1434 }
1435
1436 /* popluate the slice header parameters to signal delta POCs and use flags */
1437 {
1438 WORD32 i;
1439 WORD32 prev_poc = curr_poc;
1440
1441 ps_slice_header->s_stref_picset.i1_inter_ref_pic_set_prediction_flag = 0;
1442
1443 ps_slice_header->s_stref_picset.i1_num_neg_pics = num_ref_pics_list0;
1444
1445 ps_slice_header->s_stref_picset.i1_num_pos_pics = num_ref_pics_list1;
1446
1447 ps_slice_header->s_stref_picset.i1_num_ref_idc = -1;
1448
1449 /* populate the delta POCs of reference pics */
1450 i = 0;
1451
1452 for(ctr = 0; ctr < i4_num_rpics_l0_excl_dup; ctr++)
1453 {
1454 WORD32 ref_poc_l0 = aps_ref_list[LIST_0][i]->i4_poc;
1455
1456 ps_slice_header->s_stref_picset.ai2_delta_poc[ctr] = prev_poc - ref_poc_l0;
1457 ps_slice_header->s_stref_picset.ai1_used[ctr] =
1458 aps_ref_list[LIST_0][i]->i4_used_by_cur_pic_flag;
1459
1460 /* check if this picture has to be used as reference */
1461 if(1 == ps_slice_header->s_stref_picset.ai1_used[ctr])
1462 {
1463 /* check for CRA poc related use flag signalling */
1464 ps_slice_header->s_stref_picset.ai1_used[ctr] =
1465 (curr_poc > cra_poc) ? (ref_poc_l0 >= cra_poc) : (slice_type != ISLICE);
1466 }
1467 if(!(prev_poc - ref_poc_l0))
1468 {
1469 ctr -= 1;
1470 i4_num_rpics_l0_excl_dup -= 1;
1471 }
1472 prev_poc = ref_poc_l0;
1473
1474 i++;
1475 }
1476
1477 i = 0;
1478 prev_poc = curr_poc;
1479 for(; ctr < (i4_num_rpics_l0_excl_dup + i4_num_rpics_l1_excl_dup); ctr++)
1480 {
1481 WORD32 ref_poc_l1 = aps_ref_list[LIST_1][i]->i4_poc;
1482
1483 ps_slice_header->s_stref_picset.ai2_delta_poc[ctr] = ref_poc_l1 - prev_poc;
1484
1485 ps_slice_header->s_stref_picset.ai1_used[ctr] =
1486 aps_ref_list[LIST_1][i]->i4_used_by_cur_pic_flag;
1487
1488 /* check if this picture has to be used as reference */
1489 if(1 == ps_slice_header->s_stref_picset.ai1_used[ctr])
1490 {
1491 /* check for CRA poc related use flag signalling */
1492 ps_slice_header->s_stref_picset.ai1_used[ctr] =
1493 (curr_poc > cra_poc) ? (ref_poc_l1 >= cra_poc) : (slice_type != ISLICE);
1494 /* (slice_type != ISLICE); */
1495 }
1496 if(!(ref_poc_l1 - prev_poc))
1497 {
1498 ctr -= 1;
1499 i4_num_rpics_l1_excl_dup -= 1;
1500 }
1501 prev_poc = ref_poc_l1;
1502 i++;
1503 }
1504 ps_slice_header->s_stref_picset.i1_num_neg_pics = i4_num_rpics_l0_excl_dup;
1505
1506 ps_slice_header->s_stref_picset.i1_num_pos_pics = i4_num_rpics_l1_excl_dup;
1507
1508 if(IV_IDR_FRAME == ps_curr_inp->s_lap_out.i4_pic_type)
1509 {
1510 ps_slice_header->s_stref_picset.i1_num_neg_pics = 0;
1511 ps_slice_header->s_stref_picset.i1_num_pos_pics = 0;
1512 }
1513
1514 /* not used so set to -1 */
1515 memset(&ps_slice_header->s_stref_picset.ai1_ref_idc[0], -1, MAX_DPB_SIZE);
1516 }
1517 /* call the ME API to update the DPB of HME pyramids
1518 Upadate list for reference bit-rate only */
1519 if(0 == i4_bridx)
1520 {
1521 ihevce_me_frame_dpb_update(
1522 ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
1523 num_ref_pics_list0,
1524 num_ref_pics_list1,
1525 &aps_ref_list[LIST_0][0],
1526 &aps_ref_list[LIST_1][0],
1527 i4_thrd_id);
1528 }
1529
1530 /* Default list creation based on uses as ref pic for current pic flag */
1531 {
1532 WORD32 num_ref_pics_list_final = 0;
1533 WORD32 list_idx = 0;
1534
1535 /* LIST 0 */
1536 /* run a loop for num ref pics in list 0 */
1537 for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
1538 {
1539 /* check for used as reference flag */
1540 if(1 == aps_ref_list[LIST_0][ctr]->i4_used_by_cur_pic_flag)
1541 {
1542 /* copy the pointer to the actual valid list idx */
1543 aps_ref_list[LIST_0][list_idx] = aps_ref_list[LIST_0][ctr];
1544
1545 /* increment the valid pic counters and idx */
1546 list_idx++;
1547 num_ref_pics_list_final++;
1548 }
1549 }
1550
1551 /* finally store the number of pictures in List0 */
1552 num_ref_pics_list0 = num_ref_pics_list_final;
1553
1554 /* LIST 1 */
1555 num_ref_pics_list_final = 0;
1556 list_idx = 0;
1557
1558 /* run a loop for num ref pics in list 1 */
1559 for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
1560 {
1561 /* check for used as reference flag */
1562 if(1 == aps_ref_list[LIST_1][ctr]->i4_used_by_cur_pic_flag)
1563 {
1564 /* copy the pointer to the actual valid list idx */
1565 aps_ref_list[LIST_1][list_idx] = aps_ref_list[LIST_1][ctr];
1566
1567 /* increment the valid pic counters and idx */
1568 list_idx++;
1569 num_ref_pics_list_final++;
1570 }
1571 }
1572
1573 /* finally store the number of pictures in List1 */
1574 num_ref_pics_list1 = num_ref_pics_list_final;
1575 }
1576 /*in case of single active ref picture on L0 and L1, then consider one of them weighted
1577 and another non-weighted*/
1578 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1579 {
1580 if(num_ref_pics_list0 > 2)
1581 {
1582 if(aps_ref_list[LIST_0][0]->i4_poc == aps_ref_list[LIST_0][1]->i4_poc)
1583 {
1584 i4_inc_L0_active_ref_pic = 1;
1585 }
1586 }
1587 }
1588 else
1589 {
1590 if(num_ref_pics_list0 >= 2 && num_ref_pics_list1 >= 2)
1591 {
1592 if(aps_ref_list[LIST_0][0]->i4_poc == aps_ref_list[LIST_0][1]->i4_poc)
1593 {
1594 i4_inc_L0_active_ref_pic = 1;
1595 }
1596
1597 if(aps_ref_list[LIST_1][0]->i4_poc == aps_ref_list[LIST_1][1]->i4_poc)
1598 {
1599 i4_inc_L1_active_ref_pic = 1;
1600 }
1601 }
1602 }
1603 /* append the reference pics in List1 and end of list0 */
1604 for(ctr = 0; ctr < num_ref_pics_list1; ctr++)
1605 {
1606 aps_ref_list[LIST_0][num_ref_pics_list0 + ctr] = aps_ref_list[LIST_1][ctr];
1607 }
1608
1609 /* append the reference pics in List0 and end of list1 */
1610 for(ctr = 0; ctr < num_ref_pics_list0; ctr++)
1611 {
1612 aps_ref_list[LIST_1][num_ref_pics_list1 + ctr] = aps_ref_list[LIST_0][ctr];
1613 }
1614
1615 /* reference list modification for adding duplicate reference */
1616 {
1617 WORD32 i4_latest_idx = 0;
1618 recon_pic_buf_t *ps_ref_list_cur;
1619 recon_pic_buf_t *ps_ref_list_prev;
1620 /*List 0*/
1621 ps_ref_list_cur = aps_ref_list[LIST_0][0];
1622 ps_ref_list_prev = ps_ref_list_cur;
1623 for(ctr = 0; ctr < (num_ref_pics_list0 + num_ref_pics_list1); ctr++)
1624 {
1625 if(ps_ref_list_cur->i4_poc != ps_ref_list_prev->i4_poc)
1626 {
1627 i4_latest_idx++;
1628 }
1629 ps_ref_list_prev = ps_ref_list_cur;
1630 ps_slice_header->s_rplm.i4_ref_poc_l0[ctr] = ps_ref_list_cur->i4_poc;
1631 ps_slice_header->s_rplm.i1_list_entry_l0[ctr] = i4_latest_idx;
1632 if((ctr + 1) < (num_ref_pics_list0 + num_ref_pics_list1))
1633 {
1634 ps_ref_list_cur = aps_ref_list[LIST_0][ctr + 1];
1635 }
1636 } /*end for*/
1637
1638 /*LIST 1*/
1639 i4_latest_idx = 0;
1640 ps_ref_list_cur = aps_ref_list[LIST_1][0];
1641 ps_ref_list_prev = ps_ref_list_cur;
1642 for(ctr = 0; ctr < (num_ref_pics_list0 + num_ref_pics_list1); ctr++)
1643 {
1644 if(ps_ref_list_cur->i4_poc != ps_ref_list_prev->i4_poc)
1645 {
1646 i4_latest_idx++;
1647 }
1648 ps_ref_list_prev = ps_ref_list_cur;
1649 ps_slice_header->s_rplm.i4_ref_poc_l1[ctr] = ps_ref_list_cur->i4_poc;
1650 ps_slice_header->s_rplm.i1_list_entry_l1[ctr] = i4_latest_idx;
1651 if((ctr + 1) < (num_ref_pics_list0 + num_ref_pics_list1))
1652 {
1653 ps_ref_list_cur = aps_ref_list[LIST_1][ctr + 1];
1654 }
1655 } /*end for*/
1656 }
1657
1658 /* set number of active references used for l0 and l1 in slice hdr */
1659 ps_slice_header->i1_num_ref_idx_active_override_flag = 1;
1660 ps_slice_header->i1_num_ref_idx_l0_active = num_ref_pics_list0 + num_ref_pics_list1;
1661 if(BSLICE == slice_type)
1662 {
1663 /* i1_num_ref_idx_l1_active applicable only for B pics */
1664 ps_slice_header->i1_num_ref_idx_l1_active = num_ref_pics_list0 + num_ref_pics_list1;
1665 }
1666 /* popluate the slice header parameters with weights and offsets */
1667 {
1668 WORD32 i;
1669
1670 /* populate the log 2 weight denom if weighted prediction is enabled */
1671 if(1 == wp_flag)
1672 {
1673 ps_slice_header->s_wt_ofst.i1_chroma_log2_weight_denom =
1674 ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom;
1675 ps_slice_header->s_wt_ofst.i1_luma_log2_weight_denom =
1676 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1677 }
1678
1679 /* populate the weights and offsets for all pics in L0 + L1 */
1680 for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
1681 {
1682 /* populate the weights and offsets if weighted prediction is enabled */
1683 if(1 == wp_flag)
1684 {
1685 ps_slice_header->s_wt_ofst.i1_luma_weight_l0_flag[i] =
1686 aps_ref_list[LIST_0][i]->s_weight_offset.u1_luma_weight_enable_flag;
1687
1688 /* if weights are enabled then copy to slice header */
1689 if(1 == ps_slice_header->s_wt_ofst.i1_luma_weight_l0_flag[i])
1690 {
1691 ps_slice_header->s_wt_ofst.i2_luma_weight_l0[i] =
1692 aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_weight;
1693 ps_slice_header->s_wt_ofst.i2_luma_offset_l0[i] =
1694 aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_offset;
1695
1696 {
1697 WORD16 i2_luma_weight =
1698 (aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_weight);
1699
1700 aps_ref_list[LIST_0][i]->i4_inv_luma_wt =
1701 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1702
1703 aps_ref_list[LIST_0][i]->i4_log2_wt_denom =
1704 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1705 }
1706 }
1707 else
1708 {
1709 WORD16 i2_luma_weight = (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1710
1711 /* set to default values */
1712 aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_weight = (i2_luma_weight);
1713
1714 aps_ref_list[LIST_0][i]->s_weight_offset.i2_luma_offset = 0;
1715
1716 aps_ref_list[LIST_0][i]->i4_inv_luma_wt =
1717 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1718
1719 aps_ref_list[LIST_0][i]->i4_log2_wt_denom =
1720 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1721 }
1722
1723 ps_slice_header->s_wt_ofst.i1_chroma_weight_l0_flag[i] =
1724 aps_ref_list[LIST_0][i]->s_weight_offset.u1_chroma_weight_enable_flag;
1725
1726 /* if weights are enabled then copy to slice header */
1727 if(1 == ps_slice_header->s_wt_ofst.i1_chroma_weight_l0_flag[i])
1728 {
1729 ps_slice_header->s_wt_ofst.i2_chroma_weight_l0_cb[i] =
1730 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_weight;
1731 ps_slice_header->s_wt_ofst.i2_chroma_offset_l0_cb[i] =
1732 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_offset;
1733
1734 ps_slice_header->s_wt_ofst.i2_chroma_weight_l0_cr[i] =
1735 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_weight;
1736 ps_slice_header->s_wt_ofst.i2_chroma_offset_l0_cr[i] =
1737 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_offset;
1738 }
1739 else
1740 {
1741 /* set to default values */
1742 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_weight =
1743 (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1744 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_weight =
1745 (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1746 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cb_offset = 0;
1747 aps_ref_list[LIST_0][i]->s_weight_offset.i2_cr_offset = 0;
1748 }
1749 }
1750 }
1751
1752 for(i = 0; i < (num_ref_pics_list0 + num_ref_pics_list1); i++)
1753 {
1754 /* populate the weights and offsets if weighted prediction is enabled */
1755 if(1 == wp_flag)
1756 {
1757 ps_slice_header->s_wt_ofst.i1_luma_weight_l1_flag[i] =
1758 aps_ref_list[LIST_1][i]->s_weight_offset.u1_luma_weight_enable_flag;
1759
1760 /* if weights are enabled then copy to slice header */
1761 if(1 == ps_slice_header->s_wt_ofst.i1_luma_weight_l1_flag[i])
1762 {
1763 ps_slice_header->s_wt_ofst.i2_luma_weight_l1[i] =
1764 aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_weight;
1765 ps_slice_header->s_wt_ofst.i2_luma_offset_l1[i] =
1766 aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_offset;
1767
1768 {
1769 WORD16 i2_luma_weight =
1770 (aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_weight);
1771
1772 aps_ref_list[LIST_1][i]->i4_inv_luma_wt =
1773 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1774
1775 aps_ref_list[LIST_1][i]->i4_log2_wt_denom =
1776 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1777 }
1778 }
1779 else
1780 {
1781 WORD16 i2_luma_weight = (1 << ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom);
1782
1783 /* set to default values */
1784 aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_weight = (i2_luma_weight);
1785
1786 aps_ref_list[LIST_1][i]->s_weight_offset.i2_luma_offset = 0;
1787
1788 aps_ref_list[LIST_1][i]->i4_inv_luma_wt =
1789 ((1 << 15) + (i2_luma_weight >> 1)) / i2_luma_weight;
1790
1791 aps_ref_list[LIST_1][i]->i4_log2_wt_denom =
1792 ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom;
1793 }
1794
1795 ps_slice_header->s_wt_ofst.i1_chroma_weight_l1_flag[i] =
1796 aps_ref_list[LIST_1][i]->s_weight_offset.u1_chroma_weight_enable_flag;
1797
1798 /* if weights are enabled then copy to slice header */
1799 if(1 == ps_slice_header->s_wt_ofst.i1_chroma_weight_l1_flag[i])
1800 {
1801 ps_slice_header->s_wt_ofst.i2_chroma_weight_l1_cb[i] =
1802 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_weight;
1803 ps_slice_header->s_wt_ofst.i2_chroma_offset_l1_cb[i] =
1804 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_offset;
1805
1806 ps_slice_header->s_wt_ofst.i2_chroma_weight_l1_cr[i] =
1807 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_weight;
1808 ps_slice_header->s_wt_ofst.i2_chroma_offset_l1_cr[i] =
1809 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_offset;
1810 }
1811 else
1812 {
1813 /* set to default values */
1814 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_weight =
1815 (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1816 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_weight =
1817 (1 << ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom);
1818 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cb_offset = 0;
1819 aps_ref_list[LIST_1][i]->s_weight_offset.i2_cr_offset = 0;
1820 }
1821 }
1822 }
1823 }
1824
1825 /* store the number of reference pics in the list for ME/MC etc */
1826 ps_enc_ctxt->i4_num_ref_l0 = num_ref_pics_list0;
1827 ps_enc_ctxt->i4_num_ref_l1 = num_ref_pics_list1;
1828
1829 #define HME_USE_ONLY_2REF
1830 #ifndef HME_USE_ONLY_2REF
1831 ps_enc_ctxt->i4_num_ref_l0_active = num_ref_pics_list0;
1832 ps_enc_ctxt->i4_num_ref_l1_active = num_ref_pics_list1;
1833 #else
1834 #if MULTI_REF_ENABLE == 1
1835 if(ps_curr_inp->s_lap_out.i4_quality_preset >= IHEVCE_QUALITY_P3)
1836 {
1837 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1838 {
1839 if(ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6)
1840 {
1841 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1842 {
1843 ps_enc_ctxt->i4_num_ref_l0_active =
1844 MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25 + 1, num_ref_pics_list0);
1845 }
1846 else
1847 {
1848 ps_enc_ctxt->i4_num_ref_l0_active =
1849 MIN(MAX_NUM_REFS_IN_PPICS_IN_XS25, num_ref_pics_list0);
1850
1851 ps_enc_ctxt->i4_num_ref_l0_active += i4_inc_L0_active_ref_pic;
1852 }
1853 }
1854 else
1855 {
1856 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1857 {
1858 ps_enc_ctxt->i4_num_ref_l0_active = MIN(3, num_ref_pics_list0);
1859 }
1860 else
1861 {
1862 ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1863 ps_enc_ctxt->i4_num_ref_l0_active += i4_inc_L0_active_ref_pic;
1864 }
1865 }
1866
1867 ps_enc_ctxt->i4_num_ref_l1_active = 0;
1868 }
1869 else
1870 {
1871 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1872 {
1873 ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1874 ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1875 ps_enc_ctxt->i4_num_ref_l1_active += i4_inc_L1_active_ref_pic;
1876 }
1877 else
1878 {
1879 ps_enc_ctxt->i4_num_ref_l0_active = MIN(1, num_ref_pics_list0);
1880 ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1881
1882 ps_enc_ctxt->i4_num_ref_l1_active += i4_inc_L1_active_ref_pic;
1883 ps_enc_ctxt->i4_num_ref_l0_active += i4_inc_L0_active_ref_pic;
1884 }
1885 }
1886 }
1887 else
1888 {
1889 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1890 {
1891 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1892 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1893 else
1894 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1895
1896 ps_enc_ctxt->i4_num_ref_l1_active = 0;
1897 }
1898 else
1899 {
1900 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1901 {
1902 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1903 ps_enc_ctxt->i4_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1904 }
1905 else
1906 {
1907 ps_enc_ctxt->i4_num_ref_l0_active = MIN(4, num_ref_pics_list0);
1908 ps_enc_ctxt->i4_num_ref_l1_active = MIN(4, num_ref_pics_list1);
1909 }
1910 }
1911 }
1912 #else
1913 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
1914 {
1915 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1916 ps_enc_ctxt->i4_num_ref_l0_active = MIN(3, num_ref_pics_list0);
1917 else
1918 ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1919
1920 ps_enc_ctxt->i4_num_ref_l1_active = 0;
1921 }
1922 else
1923 {
1924 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1925 {
1926 ps_enc_ctxt->i4_num_ref_l0_active = MIN(2, num_ref_pics_list0);
1927 ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1928 }
1929 else
1930 {
1931 ps_enc_ctxt->i4_num_ref_l0_active = MIN(1, num_ref_pics_list0);
1932 ps_enc_ctxt->i4_num_ref_l1_active = MIN(1, num_ref_pics_list1);
1933 }
1934 }
1935 #endif
1936
1937 #endif
1938
1939 ps_slice_header->i1_num_ref_idx_l0_active = MAX(1, ps_enc_ctxt->i4_num_ref_l0_active);
1940 if(BSLICE == slice_type)
1941 {
1942 /* i1_num_ref_idx_l1_active applicable only for B pics */
1943 ps_slice_header->i1_num_ref_idx_l1_active = MAX(1, ps_enc_ctxt->i4_num_ref_l1_active);
1944 }
1945 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
1946 {
1947 /* If Interlace field is enabled, p field following an cra I field should have only one ref frame */
1948 WORD32 cra_second_poc = cra_poc + 1;
1949
1950 if(curr_poc == cra_second_poc)
1951 {
1952 /* set number of active references used for l0 and l1 for me */
1953 ps_enc_ctxt->i4_num_ref_l0_active = 1;
1954 ps_enc_ctxt->i4_num_ref_l1_active = 0;
1955
1956 /* set number of active references used for l0 and l1 in slice hdr */
1957 ps_slice_header->i1_num_ref_idx_active_override_flag = 1;
1958 ps_slice_header->i1_num_ref_idx_l0_active =
1959 ps_enc_ctxt->i4_num_ref_l0 + ps_enc_ctxt->i4_num_ref_l1;
1960 }
1961 }
1962 return;
1963 }
1964
1965 /*!
1966 ******************************************************************************
1967 * \if Function name : ihevce_get_frame_lambda_prms \endif
1968 *
1969 * \brief
1970 * Function whihc calculates the Lambda params for current picture
1971 *
1972 * \param[in] ps_enc_ctxt : encoder ctxt pointer
1973 * \param[in] ps_cur_pic_ctxt : current pic ctxt
1974 * \param[in] i4_cur_frame_qp : current pic QP
1975 * \param[in] first_field : is first field flag
1976 * \param[in] i4_temporal_lyr_id : Current picture layer id
1977 *
1978 * \return
1979 * None
1980 *
1981 * \author
1982 * Ittiam
1983 *
1984 *****************************************************************************
1985 */
ihevce_get_frame_lambda_prms(enc_ctxt_t * ps_enc_ctxt,pre_enc_me_ctxt_t * ps_cur_pic_ctxt,WORD32 i4_cur_frame_qp,WORD32 first_field,WORD32 i4_is_ref_pic,WORD32 i4_temporal_lyr_id,double f_i_pic_lamda_modifier,WORD32 i4_inst_id,WORD32 i4_lambda_type)1986 void ihevce_get_frame_lambda_prms(
1987 enc_ctxt_t *ps_enc_ctxt,
1988 pre_enc_me_ctxt_t *ps_cur_pic_ctxt,
1989 WORD32 i4_cur_frame_qp,
1990 WORD32 first_field,
1991 WORD32 i4_is_ref_pic,
1992 WORD32 i4_temporal_lyr_id,
1993 double f_i_pic_lamda_modifier,
1994 WORD32 i4_inst_id,
1995 WORD32 i4_lambda_type)
1996 {
1997 double lambda_modifier = CONST_LAMDA_MOD_VAL;
1998 double lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
1999 double lambda = 0;
2000 double lambda_uv;
2001 WORD32 i4_use_const_lamda_modifier;
2002
2003 /* initialize lambda based on frm qp, slice type, num b and temporal id */
2004 /* This lamba calculation mimics the jctvc doc (TODO add doc number */
2005
2006 WORD32 num_b_frms =
2007 (1 << ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers) - 1;
2008 WORD32 chroma_qp = (ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format == IV_YUV_422SP_UV)
2009 ? MIN(i4_cur_frame_qp, 51)
2010 : gai1_ihevc_chroma_qp_scale[i4_cur_frame_qp + MAX_QP_BD_OFFSET];
2011
2012 WORD32 i4_qp_bdoffset =
2013 6 * (ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_internal_bit_depth - 8);
2014 WORD32 slice_type = ps_cur_pic_ctxt->s_slice_hdr.i1_slice_type;
2015
2016 (void)first_field;
2017 (void)i4_is_ref_pic;
2018 (void)i4_temporal_lyr_id;
2019 i4_use_const_lamda_modifier = USE_CONSTANT_LAMBDA_MODIFIER;
2020 i4_use_const_lamda_modifier = i4_use_const_lamda_modifier ||
2021 ((ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2022 (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER)) &&
2023 ((ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2024 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) ||
2025 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2026 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_1)) ||
2027 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2028 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_2)) ||
2029 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet &
2030 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_PSYRDOPT_3))));
2031
2032 /* lambda modifier is the dependent on slice type and temporal id */
2033 if(ISLICE == slice_type)
2034 {
2035 double temporal_correction_islice = 1.0 - 0.05 * num_b_frms;
2036 temporal_correction_islice = MAX(0.5, temporal_correction_islice);
2037
2038 lambda_modifier = 0.57 * temporal_correction_islice;
2039 lambda_uv_modifier = lambda_modifier;
2040 if(i4_use_const_lamda_modifier)
2041 {
2042 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = f_i_pic_lamda_modifier;
2043 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = f_i_pic_lamda_modifier;
2044 }
2045 else
2046 {
2047 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = lambda_modifier;
2048 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = lambda_uv_modifier;
2049 }
2050 }
2051 else if(PSLICE == slice_type)
2052 {
2053 if(first_field)
2054 lambda_modifier = 0.442; //0.442*0.8;
2055 else
2056 lambda_modifier = 0.442;
2057 lambda_uv_modifier = lambda_modifier;
2058 if(i4_use_const_lamda_modifier)
2059 {
2060 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = CONST_LAMDA_MOD_VAL;
2061 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
2062 }
2063 else
2064 {
2065 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = lambda_modifier;
2066 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = lambda_uv_modifier;
2067 }
2068 }
2069 else
2070 {
2071 /* BSLICE */
2072 if(1 == i4_is_ref_pic)
2073 {
2074 lambda_modifier = 0.3536;
2075 }
2076 else if(2 == i4_is_ref_pic)
2077 {
2078 lambda_modifier = 0.45;
2079 }
2080 else
2081 {
2082 lambda_modifier = 0.68;
2083 }
2084 lambda_uv_modifier = lambda_modifier;
2085 if(i4_use_const_lamda_modifier)
2086 {
2087 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = CONST_LAMDA_MOD_VAL;
2088 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
2089 }
2090 else
2091 {
2092 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_modifier = lambda_modifier;
2093 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].lambda_uv_modifier = lambda_uv_modifier;
2094 }
2095 /* TODO: Disable lambda modification for interlace encode to match HM runs */
2096 //if(0 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
2097 {
2098 /* modify b lambda further based on temporal id */
2099 if(i4_temporal_lyr_id)
2100 {
2101 lambda_modifier *= CLIP3((((double)(i4_cur_frame_qp - 12)) / 6.0), 2.00, 4.00);
2102 lambda_uv_modifier *= CLIP3((((double)(chroma_qp - 12)) / 6.0), 2.00, 4.00);
2103 }
2104 }
2105 }
2106 if(i4_use_const_lamda_modifier)
2107 {
2108 if(ISLICE == slice_type)
2109 {
2110 lambda_modifier = f_i_pic_lamda_modifier;
2111 lambda_uv_modifier = f_i_pic_lamda_modifier;
2112 }
2113 else
2114 {
2115 lambda_modifier = CONST_LAMDA_MOD_VAL;
2116 lambda_uv_modifier = CONST_LAMDA_MOD_VAL;
2117 }
2118 }
2119
2120 switch(i4_lambda_type)
2121 {
2122 case 0:
2123 {
2124 i4_qp_bdoffset = 0;
2125
2126 lambda = pow(2.0, (((double)(i4_cur_frame_qp + i4_qp_bdoffset - 12)) / 3.0));
2127 lambda_uv = pow(2.0, (((double)(chroma_qp + i4_qp_bdoffset - 12)) / 3.0));
2128
2129 /* modify the base lambda according to lambda modifier */
2130 lambda *= lambda_modifier;
2131 lambda_uv *= lambda_uv_modifier;
2132
2133 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2134 (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2135
2136 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf =
2137 (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2138
2139 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf =
2140 (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2141
2142 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf =
2143 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2144 if(i4_use_const_lamda_modifier)
2145 {
2146 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2147 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2148
2149 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2150 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2151
2152 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2153 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2154 }
2155 else
2156 {
2157 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2158 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2159
2160 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2161 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2162
2163 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2164 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2165 }
2166 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_qf =
2167 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf;
2168
2169 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_chroma_qf =
2170 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf;
2171
2172 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_type2_lambda_qf =
2173 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf;
2174
2175 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2176 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf;
2177
2178 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2179 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf;
2180
2181 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2182 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf;
2183
2184 break;
2185 }
2186 case 1:
2187 {
2188 lambda = pow(2.0, (((double)(i4_cur_frame_qp + i4_qp_bdoffset - 12)) / 3.0));
2189 lambda_uv = pow(2.0, (((double)(chroma_qp + i4_qp_bdoffset - 12)) / 3.0));
2190
2191 /* modify the base lambda according to lambda modifier */
2192 lambda *= lambda_modifier;
2193 lambda_uv *= lambda_uv_modifier;
2194
2195 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2196 (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2197
2198 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf =
2199 (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2200
2201 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf =
2202 (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2203
2204 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf =
2205 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2206 if(i4_use_const_lamda_modifier)
2207 {
2208 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2209 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2210
2211 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2212 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2213
2214 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2215 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2216 }
2217 else
2218 {
2219 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2220 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2221
2222 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2223 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2224
2225 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2226 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2227 }
2228 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_qf =
2229 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf;
2230
2231 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_chroma_qf =
2232 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf;
2233
2234 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_type2_lambda_qf =
2235 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf;
2236
2237 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2238 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf;
2239
2240 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2241 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf;
2242
2243 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2244 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf;
2245
2246 break;
2247 }
2248 case 2:
2249 {
2250 lambda = pow(2.0, (((double)(i4_cur_frame_qp + i4_qp_bdoffset - 12)) / 3.0));
2251 lambda_uv = pow(2.0, (((double)(chroma_qp + i4_qp_bdoffset - 12)) / 3.0));
2252
2253 /* modify the base lambda according to lambda modifier */
2254 lambda *= lambda_modifier;
2255 lambda_uv *= lambda_uv_modifier;
2256
2257 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2258 (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2259
2260 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_qf =
2261 (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2262
2263 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_lambda_chroma_qf =
2264 (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2265
2266 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_lambda_qf =
2267 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2268
2269 if(i4_use_const_lamda_modifier)
2270 {
2271 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2272 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2273
2274 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2275 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2276
2277 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2278 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2279 }
2280 else
2281 {
2282 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_lambda_qf =
2283 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2284
2285 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2286 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2287
2288 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2289 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2290 }
2291 /* lambda corresponding to 8- bit, for metrics based on 8- bit ( Example 8bit SAD in encloop)*/
2292
2293 lambda = pow(2.0, (((double)(i4_cur_frame_qp - 12)) / 3.0));
2294 lambda_uv = pow(2.0, (((double)(chroma_qp - 12)) / 3.0));
2295
2296 /* modify the base lambda according to lambda modifier */
2297 lambda *= lambda_modifier;
2298 lambda_uv *= lambda_uv_modifier;
2299
2300 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].u4_chroma_cost_weighing_factor =
2301 (UWORD32)((lambda / lambda_uv) * (1 << CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT));
2302
2303 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_qf =
2304 (LWORD64)(lambda * (1 << LAMBDA_Q_SHIFT));
2305
2306 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i8_cl_ssd_type2_lambda_chroma_qf =
2307 (LWORD64)(lambda_uv * (1 << LAMBDA_Q_SHIFT));
2308
2309 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_sad_type2_lambda_qf =
2310 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2311 if(i4_use_const_lamda_modifier)
2312 {
2313 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2314 (WORD32)((sqrt(lambda)) * (1 << LAMBDA_Q_SHIFT));
2315
2316 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2317 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2318
2319 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2320 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2321 }
2322 else
2323 {
2324 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_sad_type2_lambda_qf =
2325 (WORD32)((sqrt(lambda) / 1.5) * (1 << LAMBDA_Q_SHIFT));
2326
2327 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_type2_lambda_qf =
2328 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2329
2330 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_type2_lambda_qf =
2331 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2332 }
2333
2334 break;
2335 }
2336 default:
2337 {
2338 /* Intended to be a barren wasteland! */
2339 ASSERT(0);
2340 }
2341 }
2342
2343 /* Assign the final lambdas after up shifting to its q format */
2344
2345 /* closed loop ssd lambda is same as final lambda */
2346
2347 /* --- Initialized the lambda for SATD computations --- */
2348 if(i4_use_const_lamda_modifier)
2349 {
2350 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2351 (WORD32)(sqrt(lambda) * (1 << LAMBDA_Q_SHIFT));
2352
2353 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2354 (WORD32)((sqrt(lambda)) * (1 << (LAMBDA_Q_SHIFT)));
2355 }
2356 else
2357 {
2358 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_cl_satd_lambda_qf =
2359 (WORD32)(sqrt(lambda * 1.5) * (1 << LAMBDA_Q_SHIFT));
2360
2361 ps_cur_pic_ctxt->as_lambda_prms[i4_inst_id].i4_ol_satd_lambda_qf =
2362 (WORD32)((sqrt(lambda * 1.5)) * (1 << (LAMBDA_Q_SHIFT)));
2363 }
2364 }
2365
2366 /*!
2367 ******************************************************************************
2368 * \if Function name : ihevce_update_qp_L1_sad_based \endif
2369 *
2370 * \brief
2371 * Function which recalculates qp in case of scene cut based on L1 satd/act
2372 *
2373 * \param[in] ps_enc_ctxt : encoder ctxt pointer
2374 * \param[in] ps_cur_pic_ctxt : current pic ctxt
2375 * \param[in] i4_cur_frame_qp : current pic QP
2376 * \param[in] first_field : is first field flag
2377 * \param[in] i4_temporal_lyr_id : Current picture layer id
2378 *
2379 * \return
2380 * None
2381 *
2382 * \author
2383 * Ittiam
2384 *
2385 *****************************************************************************
2386 */
ihevce_update_qp_L1_sad_based(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,ihevce_lap_enc_buf_t * ps_prev_inp,pre_enc_me_ctxt_t * ps_curr_out,WORD32 i4_is_last_thread)2387 void ihevce_update_qp_L1_sad_based(
2388 enc_ctxt_t *ps_enc_ctxt,
2389 ihevce_lap_enc_buf_t *ps_curr_inp,
2390 ihevce_lap_enc_buf_t *ps_prev_inp,
2391 pre_enc_me_ctxt_t *ps_curr_out,
2392 WORD32 i4_is_last_thread)
2393 {
2394 WORD32 i4_l1_ht, i4_l1_wd;
2395 ihevce_ed_blk_t *ps_ed_4x4 = ps_curr_out->ps_layer1_buf;
2396 WORD32 best_satd_16x16;
2397 //LWORD64 acc_satd = 0;
2398 LWORD64 acc_sad = 0; /*SAD accumulated to compare with coarse me sad*/
2399 WORD32 i4_tot_4x4block_l1_x, i4_tot_4x4block_l1_y;
2400 WORD32 i4_tot_ctb_l1_x, i4_tot_ctb_l1_y;
2401 WORD32 i;
2402 WORD32 i4_act_factor;
2403 UWORD8 u1_cu_possible_qp;
2404 WORD32 i4_q_scale_mod;
2405 LWORD64 i8_best_satd_16x16;
2406 LWORD64 i8_frame_satd_by_act_L1_accum;
2407 LWORD64 i8_frame_acc_sadt_L1, i8_frame_acc_sadt_L1_squared;
2408 WORD32 i4_new_frame_qp = 0, i4_qp_for_I_pic = 0;
2409 LWORD64 pre_intra_satd_act_evaluated = 0;
2410 ihevce_ed_ctb_l1_t *ps_ed_ctb_l1 = ps_curr_out->ps_ed_ctb_l1;
2411 WORD32 i4_j;
2412 double scale_factor_cmplx_change_detection;
2413 WORD32 i4_cmplx_change_detection_thrsh;
2414 long double ld_frame_avg_satd_L1;
2415
2416 if(i4_is_last_thread)
2417 {
2418 ihevce_decomp_pre_intra_master_ctxt_t *ps_master_ctxt =
2419 (ihevce_decomp_pre_intra_master_ctxt_t *)
2420 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt;
2421 ihevce_decomp_pre_intra_ctxt_t *ps_ctxt = ps_master_ctxt->aps_decomp_pre_intra_thrd_ctxt[0];
2422
2423 i4_l1_wd = ps_ctxt->as_layers[1].i4_actual_wd;
2424 i4_l1_ht = ps_ctxt->as_layers[1].i4_actual_ht;
2425
2426 if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2427 (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2428 {
2429 i8_frame_acc_sadt_L1 = -1;
2430 }
2431 else
2432 {
2433 /*the accumulation of intra satd and calculation of new qp happens for all thread
2434 It must be made sure every thread returns same value of intra satd and qp*/
2435 i8_frame_acc_sadt_L1 = ihevce_decomp_pre_intra_get_frame_satd(
2436 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt, &i4_l1_wd, &i4_l1_ht);
2437 }
2438
2439 #if USE_SQRT_AVG_OF_SATD_SQR
2440 if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2441 (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2442 {
2443 i8_frame_acc_sadt_L1_squared = 0x7fffffff;
2444 }
2445 else
2446 {
2447 i8_frame_acc_sadt_L1_squared = ihevce_decomp_pre_intra_get_frame_satd_squared(
2448 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt, &i4_l1_wd, &i4_l1_ht);
2449 }
2450 #else
2451 i8_frame_acc_sadt_L1_squared = i8_frame_acc_sadt_L1;
2452 #endif
2453 if((i4_l1_wd * i4_l1_ht) > (245760 /*640 * 384*/))
2454 {
2455 scale_factor_cmplx_change_detection =
2456 (double)0.12 * ((i4_l1_wd * i4_l1_ht) / (640.0 * 384.0));
2457 i4_cmplx_change_detection_thrsh =
2458 (WORD32)(HME_HIGH_SAD_BLK_THRESH * (1 - scale_factor_cmplx_change_detection));
2459 }
2460 else
2461 {
2462 scale_factor_cmplx_change_detection =
2463 (double)0.12 * ((640.0 * 384.0) / (i4_l1_wd * i4_l1_ht));
2464 i4_cmplx_change_detection_thrsh =
2465 (WORD32)(HME_HIGH_SAD_BLK_THRESH * (1 + scale_factor_cmplx_change_detection));
2466 }
2467 i4_tot_4x4block_l1_x =
2468 ((i4_l1_wd + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) /
2469 4; //((i4_l1_wd + 31) & 0xFFFFFFE0)/4;//(i4_l1_wd + (i4_l1_wd % 32 )) / 4;
2470 i4_tot_4x4block_l1_y =
2471 ((i4_l1_ht + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) /
2472 4; //((i4_l1_ht + 31) & 0xFFFFFFE0)/4;//(i4_l1_ht + (i4_l1_ht % 32 )) / 4;
2473 ld_frame_avg_satd_L1 =
2474 (WORD32)log(
2475 1 + (long double)i8_frame_acc_sadt_L1_squared /
2476 ((long double)((i4_tot_4x4block_l1_x * i4_tot_4x4block_l1_y) >> 2))) /
2477 log(2.0);
2478 /* L1 satd accumalated for computing qp */
2479 i8_frame_satd_by_act_L1_accum = 0;
2480 i4_tot_ctb_l1_x =
2481 ((i4_l1_wd + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) / (MAX_CTB_SIZE >> 1);
2482 i4_tot_ctb_l1_y =
2483 ((i4_l1_ht + ((MAX_CTB_SIZE >> 1) - 1)) & 0xFFFFFFE0) / (MAX_CTB_SIZE >> 1);
2484
2485 for(i = 0; i < (i4_tot_ctb_l1_x * i4_tot_ctb_l1_y); i += 1)
2486 {
2487 for(i4_j = 0; i4_j < 16; i4_j++)
2488 {
2489 if(ps_ed_ctb_l1->i4_best_satd_8x8[i4_j] != -1)
2490 {
2491 ASSERT(ps_ed_ctb_l1->i4_best_satd_8x8[i4_j] >= 0);
2492 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
2493
2494 if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2495 (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2496 {
2497 best_satd_16x16 = 0;
2498 }
2499 else
2500 {
2501 best_satd_16x16 = ps_ed_ctb_l1->i4_best_satd_8x8[i4_j];
2502 }
2503
2504 acc_sad += (WORD32)ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j];
2505 //acc_satd += (WORD32)best_satd_16x16;
2506 u1_cu_possible_qp = ihevce_cu_level_qp_mod(
2507 32,
2508 best_satd_16x16,
2509 ld_frame_avg_satd_L1,
2510 REF_MOD_STRENGTH, // To be changed later
2511 &i4_act_factor,
2512 &i4_q_scale_mod,
2513 &ps_enc_ctxt->s_rc_quant);
2514 i8_best_satd_16x16 = best_satd_16x16 << QP_LEVEL_MOD_ACT_FACTOR;
2515
2516 if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2517 (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2518 {
2519 i4_act_factor = (1 << QP_LEVEL_MOD_ACT_FACTOR);
2520 }
2521
2522 if(0 != i4_act_factor)
2523 {
2524 i8_frame_satd_by_act_L1_accum +=
2525 ((WORD32)(i8_best_satd_16x16 / i4_act_factor));
2526 /*Accumulate SAD for those regions which will undergo evaluation in L0 stage*/
2527 if(ps_ed_4x4->intra_or_inter != 2)
2528 pre_intra_satd_act_evaluated +=
2529 ((WORD32)(i8_best_satd_16x16 / i4_act_factor));
2530 }
2531 }
2532 ps_ed_4x4 += 4;
2533 }
2534 ps_ed_ctb_l1 += 1;
2535 }
2536 /** store the L1 satd in context struct
2537 Note: this variable is common across all thread. it must be made sure all threads write same value*/
2538 if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
2539 (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
2540 {
2541 i8_frame_satd_by_act_L1_accum = ps_prev_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum;
2542 ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum = i8_frame_satd_by_act_L1_accum;
2543 ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated = -1;
2544 }
2545 else
2546 {
2547 ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum = i8_frame_satd_by_act_L1_accum;
2548 ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated =
2549 pre_intra_satd_act_evaluated;
2550 }
2551
2552 ps_curr_inp->s_rc_lap_out.i8_pre_intra_satd = i8_frame_acc_sadt_L1;
2553 /*accumulate raw intra sad without subtracting non coded sad*/
2554 ps_curr_inp->s_rc_lap_out.i8_raw_pre_intra_sad = acc_sad;
2555 }
2556 /*update pre-enc qp using data from L1 to use better qp in L0 in case of cbr mode*/
2557 if(i4_is_last_thread)
2558 {
2559 /* acquire mutex lock for rate control calls */
2560 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
2561 {
2562 LWORD64 i8_est_L0_satd_by_act;
2563 WORD32 i4_cur_q_scale;
2564 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != CONST_QP)
2565 {
2566 /*RCTODO :This needs to be reviewed in the context of 10/12 bit encoding as the Qp seems to be sub-optimal*/
2567 if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2)
2568 i4_cur_q_scale =
2569 ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
2570 [ps_curr_out->i4_curr_frm_qp]; // + ps_enc_ctxt->s_rc_quant.i1_qp_offset];
2571 else
2572 i4_cur_q_scale = ps_enc_ctxt->s_rc_quant
2573 .pi4_qp_to_qscale[MAX(ps_curr_out->i4_curr_frm_qp, 0)];
2574 }
2575 else
2576 i4_cur_q_scale =
2577 ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
2578 [ps_curr_out->i4_curr_frm_qp + ps_enc_ctxt->s_rc_quant.i1_qp_offset];
2579
2580 i4_cur_q_scale = (i4_cur_q_scale + (1 << (QSCALE_Q_FAC_3 - 1))) >> QSCALE_Q_FAC_3;
2581
2582 i8_est_L0_satd_by_act = ihevce_get_L0_satd_based_on_L1(
2583 i8_frame_satd_by_act_L1_accum,
2584 ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered,
2585 i4_cur_q_scale);
2586 /*HEVC_RC query rate control for qp*/
2587 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
2588 {
2589 i4_new_frame_qp = ihevce_get_L0_est_satd_based_scd_qp(
2590 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
2591 &ps_curr_inp->s_rc_lap_out,
2592 i8_est_L0_satd_by_act,
2593 8.00);
2594 }
2595 else
2596 i4_new_frame_qp = ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms
2597 .as_tgt_params[ps_enc_ctxt->i4_resolution_id]
2598 .ai4_frame_qp[0];
2599 i4_new_frame_qp = CLIP3(i4_new_frame_qp, 1, 51);
2600 i4_qp_for_I_pic = CLIP3(i4_qp_for_I_pic, 1, 51);
2601 ps_curr_inp->s_rc_lap_out.i4_L1_qp = i4_new_frame_qp;
2602 /*I frame qp = qp-3 due to effect of lambda modifier*/
2603 i4_qp_for_I_pic = i4_new_frame_qp - 3;
2604
2605 /*use new qp get possible qp even for inter pictures assuming default offset*/
2606 if(ps_curr_inp->s_lap_out.i4_pic_type != IV_IDR_FRAME &&
2607 ps_curr_inp->s_lap_out.i4_pic_type != IV_I_FRAME)
2608 {
2609 i4_new_frame_qp += ps_curr_inp->s_lap_out.i4_temporal_lyr_id + 1;
2610 }
2611
2612 /*accumulate the L1 ME sad using skip sad value based on qp*/
2613 /*accumulate this only for last thread as it ll be guranteed that L1 ME sad is completely populated*/
2614 /*The lambda modifier in encoder is tuned in such a way that the qp offsets according to lambda modifer are as follows
2615 Note: These qp offset only account for lambda modifier, Hence this should be applied over qp offset that is already there due to picture type
2616 relative lambda scale(these lambda diff are mapped into qp difference which is applied over and obove the qp offset)
2617 Qi = Iqp 1
2618 Qp = Iqp 1
2619 Qb = Iqp + 1.55 1.48
2620 Qb1 = Iqp + 3.1 2.05
2621 Qb2 = Iqp + 3.1 2.05*/
2622
2623 /*ihevce_compute_offsets_from_rc(ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],ai4_offsets,&ps_curr_inp->s_lap_out);*/
2624
2625 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME ||
2626 ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME)
2627 {
2628 i4_new_frame_qp = i4_new_frame_qp - 3;
2629 }
2630 else if(ps_curr_inp->s_lap_out.i4_pic_type == IV_P_FRAME)
2631 {
2632 i4_new_frame_qp = i4_new_frame_qp - 2;
2633 }
2634 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME &&
2635 ps_curr_inp->s_lap_out.i4_temporal_lyr_id == 1)
2636 {
2637 i4_new_frame_qp = i4_new_frame_qp + 2;
2638 }
2639 else if(
2640 ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME &&
2641 ps_curr_inp->s_lap_out.i4_temporal_lyr_id == 2)
2642 {
2643 i4_new_frame_qp = i4_new_frame_qp + 6;
2644 }
2645 else if(
2646 ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME &&
2647 ps_curr_inp->s_lap_out.i4_temporal_lyr_id == 3)
2648 {
2649 i4_new_frame_qp = i4_new_frame_qp + 7;
2650 }
2651
2652 i4_new_frame_qp = CLIP3(i4_new_frame_qp, 1, 51);
2653 i4_qp_for_I_pic = CLIP3(i4_qp_for_I_pic, 1, 51);
2654
2655 {
2656 calc_l1_level_hme_intra_sad_different_qp(
2657 ps_enc_ctxt, ps_curr_out, ps_curr_inp, i4_tot_ctb_l1_x, i4_tot_ctb_l1_y);
2658
2659 /** frame accumulated SAD over entire frame after accounting for dead zone SAD, this is least of intra or inter*/
2660 /*ihevce_accum_hme_sad_subgop_rc(ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],&ps_curr_inp->s_lap_out); */
2661 ihevce_rc_register_L1_analysis_data(
2662 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
2663 &ps_curr_inp->s_rc_lap_out,
2664 i8_est_L0_satd_by_act,
2665 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad
2666 [i4_new_frame_qp], //since the sad passed will be used to calc complexity it should be non coded sad subtracted sad
2667 ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_new_frame_qp]);
2668
2669 ihevce_coarse_me_get_rc_param(
2670 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
2671 &ps_curr_out->i8_acc_frame_coarse_me_cost,
2672 &ps_curr_out->i8_acc_frame_coarse_me_sad,
2673 &ps_curr_out->i8_acc_num_blks_high_sad,
2674 &ps_curr_out->i8_total_blks,
2675 ps_curr_inp->s_lap_out.i4_is_prev_pic_in_Tid0_same_scene);
2676
2677 if(ps_curr_out->i8_total_blks)
2678 {
2679 ps_curr_out->i4_complexity_percentage = (WORD32)(
2680 (ps_curr_out->i8_acc_num_blks_high_sad * 100) /
2681 (ps_curr_out->i8_total_blks));
2682 }
2683 /*not for Const QP mode*/
2684 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
2685 {
2686 if(ps_curr_inp->s_lap_out.i4_is_prev_pic_in_Tid0_same_scene &&
2687 ps_curr_out->i8_total_blks &&
2688 (((float)(ps_curr_out->i8_acc_num_blks_high_sad * 100) /
2689 (ps_curr_out->i8_total_blks)) > (i4_cmplx_change_detection_thrsh)))
2690 {
2691 ps_curr_out->i4_is_high_complex_region = 1;
2692 }
2693 else
2694 {
2695 ps_curr_out->i4_is_high_complex_region = 0;
2696 }
2697 }
2698 ps_curr_inp->s_rc_lap_out.i8_frame_acc_coarse_me_cost =
2699 ps_curr_out->i8_acc_frame_coarse_me_cost;
2700 /*check for I only reset case and Non I SCD*/
2701 ihevce_rc_check_non_lap_scd(
2702 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0], &ps_curr_inp->s_rc_lap_out);
2703 }
2704 }
2705 /* release mutex lock after rate control calls */
2706 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
2707 }
2708 }
2709
2710 /*!
2711 ******************************************************************************
2712 * \if Function name : ihevce_frame_init \endif
2713 *
2714 * \brief
2715 * Pre encode Frame processing slave thread entry point function
2716 *
2717 * \param[in] Frame processing thread context pointer
2718 *
2719 * \return
2720 * None
2721 *
2722 * \author
2723 * Ittiam
2724 *
2725 *****************************************************************************
2726 */
ihevce_frame_init(enc_ctxt_t * ps_enc_ctxt,pre_enc_me_ctxt_t * ps_curr_inp_prms,me_enc_rdopt_ctxt_t * ps_cur_out_me_prms,WORD32 i4_cur_frame_qp,WORD32 i4_me_frm_id,WORD32 i4_thrd_id)2727 void ihevce_frame_init(
2728 enc_ctxt_t *ps_enc_ctxt,
2729 pre_enc_me_ctxt_t *ps_curr_inp_prms,
2730 me_enc_rdopt_ctxt_t *ps_cur_out_me_prms,
2731 WORD32 i4_cur_frame_qp,
2732 WORD32 i4_me_frm_id,
2733 WORD32 i4_thrd_id)
2734 {
2735 ihevce_lap_enc_buf_t *ps_curr_inp;
2736 WORD32 first_field = 1;
2737 me_master_ctxt_t *ps_master_ctxt;
2738
2739 (void)i4_thrd_id;
2740 (void)ps_cur_out_me_prms;
2741 ps_curr_inp = ps_curr_inp_prms->ps_curr_inp;
2742
2743 ps_master_ctxt = (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
2744
2745 /* get frame level lambda params */
2746 ihevce_get_frame_lambda_prms(
2747 ps_enc_ctxt,
2748 ps_curr_inp_prms,
2749 i4_cur_frame_qp,
2750 first_field,
2751 ps_curr_inp->s_lap_out.i4_is_ref_pic,
2752 ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
2753 ps_curr_inp->s_lap_out.f_i_pic_lamda_modifier,
2754 0,
2755 ENC_LAMBDA_TYPE);
2756
2757 if(1 == ps_curr_inp_prms->i4_frm_proc_valid_flag)
2758 {
2759 UWORD8 i1_cu_qp_delta_enabled_flag =
2760 ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_cu_level_rc;
2761
2762 /* picture level init of ME */
2763 ihevce_me_frame_init(
2764 ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
2765 ps_cur_out_me_prms,
2766 ps_enc_ctxt->ps_stat_prms,
2767 &ps_enc_ctxt->s_frm_ctb_prms,
2768 &ps_curr_inp_prms->as_lambda_prms[0],
2769 ps_enc_ctxt->i4_num_ref_l0,
2770 ps_enc_ctxt->i4_num_ref_l1,
2771 ps_enc_ctxt->i4_num_ref_l0_active,
2772 ps_enc_ctxt->i4_num_ref_l1_active,
2773 &ps_cur_out_me_prms->aps_ref_list[0][LIST_0][0],
2774 &ps_cur_out_me_prms->aps_ref_list[0][LIST_1][0],
2775 ps_cur_out_me_prms->aps_ref_list[0],
2776 &ps_enc_ctxt->s_func_selector,
2777 ps_curr_inp,
2778 ps_curr_inp_prms->pv_me_lyr_ctxt,
2779 i4_me_frm_id,
2780 i4_thrd_id,
2781 i4_cur_frame_qp,
2782 ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
2783 i1_cu_qp_delta_enabled_flag,
2784 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]->pv_dep_mngr_encloop_dep_me);
2785
2786 /* -------------------------------------------------------- */
2787 /* Preparing Job Queue for ME and each instance of enc_loop */
2788 /* -------------------------------------------------------- */
2789 ihevce_prepare_job_queue(ps_enc_ctxt, ps_curr_inp, i4_me_frm_id);
2790
2791 /* Dep. Mngr : Reset the num ctb processed in every row for ENC sync */
2792 ihevce_dmgr_rst_row_row_sync(
2793 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]->pv_dep_mngr_encloop_dep_me);
2794 }
2795 }
2796
2797 /****************************************************************************
2798 Function Name : ihevce_rc_close
2799 Description : closing the Rate control by passing the stored data in to the stat file for 2 pass encoding.
2800 Inputs :
2801 Globals :
2802 Processing :
2803 Outputs :
2804 Returns :
2805 Issues :
2806 Revision History:
2807 DD MM YYYY Author(s) Changes (Describe the changes made)
2808 *****************************************************************************/
2809
ihevce_rc_close(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_enc_frm_id_rc,WORD32 i4_store_retrive,WORD32 i4_update_cnt,WORD32 i4_bit_rate_idx)2810 void ihevce_rc_close(
2811 enc_ctxt_t *ps_enc_ctxt,
2812 WORD32 i4_enc_frm_id_rc,
2813 WORD32 i4_store_retrive,
2814 WORD32 i4_update_cnt,
2815 WORD32 i4_bit_rate_idx)
2816 {
2817 rc_bits_sad_t s_rc_frame_stat;
2818 WORD32 out_buf_id;
2819 WORD32 i4_pic_type, k;
2820 WORD32 cur_qp;
2821 ihevce_lap_output_params_t s_lap_out;
2822 rc_lap_out_params_t s_rc_lap_out;
2823
2824 for(k = 0; k < i4_update_cnt; k++) //ELP_RC
2825 {
2826 ihevce_rc_store_retrive_update_info(
2827 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i4_bit_rate_idx],
2828 &s_rc_frame_stat,
2829 i4_enc_frm_id_rc,
2830 i4_bit_rate_idx,
2831 2,
2832 &out_buf_id,
2833 &i4_pic_type,
2834 &cur_qp,
2835 (void *)&s_lap_out,
2836 (void *)&s_rc_lap_out);
2837
2838 ihevce_rc_update_pic_info(
2839 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i4_bit_rate_idx],
2840 (s_rc_frame_stat.u4_total_texture_bits +
2841 s_rc_frame_stat.u4_total_header_bits), //pass total bits
2842 s_rc_frame_stat.u4_total_header_bits,
2843 s_rc_frame_stat.u4_total_sad,
2844 s_rc_frame_stat.u4_total_intra_sad,
2845 (IV_PICTURE_CODING_TYPE_T)i4_pic_type,
2846 cur_qp,
2847 0,
2848 s_rc_frame_stat.i4_qp_normalized_8x8_cu_sum,
2849 s_rc_frame_stat.i4_8x8_cu_sum,
2850 s_rc_frame_stat.i8_sad_by_qscale,
2851 &s_lap_out,
2852 &s_rc_lap_out,
2853 out_buf_id,
2854 s_rc_frame_stat.u4_open_loop_intra_sad,
2855 s_rc_frame_stat.i8_total_ssd_frame,
2856 i4_enc_frm_id_rc); //ps_curr_out->i4_inp_timestamp_low)
2857 i4_enc_frm_id_rc++;
2858 i4_enc_frm_id_rc = (i4_enc_frm_id_rc % ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
2859 }
2860 }
2861
2862 /*!
2863 ******************************************************************************
2864 * \if Function name : ihevce_enc_frm_proc_slave_thrd \endif
2865 *
2866 * \brief
2867 * Enocde Frame processing slave thread entry point function
2868 *
2869 * \param[in] Frame processing thread context pointer
2870 *
2871 * \return
2872 * None
2873 *
2874 * \author
2875 * Ittiam
2876 *
2877 *****************************************************************************
2878 */
ihevce_enc_frm_proc_slave_thrd(void * pv_frm_proc_thrd_ctxt)2879 WORD32 ihevce_enc_frm_proc_slave_thrd(void *pv_frm_proc_thrd_ctxt)
2880 {
2881 frm_proc_thrd_ctxt_t *ps_thrd_ctxt;
2882 enc_ctxt_t *ps_enc_ctxt;
2883 WORD32 i4_me_end_flag, i4_enc_end_flag;
2884 WORD32 i4_thrd_id;
2885 ihevce_hle_ctxt_t *ps_hle_ctxt;
2886 WORD32 i4_num_bitrates; //number of bit-rates instances running
2887 WORD32 i; //ctr
2888 void *pv_dep_mngr_prev_frame_me_done;
2889 void *pv_dep_mngr_prev_frame_done;
2890 WORD32 i4_resolution_id;
2891 WORD32 i4_enc_frm_id_rc = 0;
2892 WORD32 i4_enc_frm_id = 0;
2893 WORD32 i4_me_frm_id = 0;
2894
2895 ps_thrd_ctxt = (frm_proc_thrd_ctxt_t *)pv_frm_proc_thrd_ctxt;
2896 ps_hle_ctxt = ps_thrd_ctxt->ps_hle_ctxt;
2897 ps_enc_ctxt = (enc_ctxt_t *)ps_thrd_ctxt->pv_enc_ctxt; /*Changed for mres*/
2898 i4_thrd_id = ps_thrd_ctxt->i4_thrd_id;
2899 i4_me_end_flag = 0;
2900 i4_enc_end_flag = 0;
2901 i4_num_bitrates = ps_enc_ctxt->i4_num_bitrates;
2902 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
2903
2904 /*pv_dep_mngr_prev_frame_me_done =
2905 ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_me_done;*/
2906
2907 while((0 == i4_me_end_flag) && (0 == i4_enc_end_flag))
2908 {
2909 WORD32 result;
2910 WORD32 ai4_in_buf_id[MAX_NUM_ME_PARALLEL];
2911 me_enc_rdopt_ctxt_t *ps_curr_out_me;
2912
2913 if(1 == ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel)
2914 {
2915 pv_dep_mngr_prev_frame_me_done =
2916 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[0];
2917 }
2918 else
2919 {
2920 pv_dep_mngr_prev_frame_me_done =
2921 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[i4_me_frm_id];
2922 }
2923
2924 /* Wait till the previous frame ME is completly done*/
2925 {
2926 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_me_done, ps_thrd_ctxt->i4_thrd_id);
2927 }
2928
2929 /****** Lock the critical section ******/
2930 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id])
2931 {
2932 result = osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id]);
2933
2934 if(OSAL_SUCCESS != result)
2935 return 0;
2936 }
2937
2938 {
2939 /************************************/
2940 /****** ENTER CRITICAL SECTION ******/
2941 /************************************/
2942
2943 /* First slave getting the mutex lock will act as master and does ME init
2944 * of current frame and other slaves skip it
2945 */
2946 if(ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] == 0)
2947 {
2948 WORD32 i4_ref_cur_qp; //current frame Qp for reference bit-rate instance
2949 ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
2950
2951 if(0 == i4_me_end_flag)
2952 {
2953 /* ------- get the input prms buffer from pre encode que ------------ */
2954 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] =
2955 (pre_enc_me_ctxt_t *)ihevce_q_get_filled_buff(
2956 (void *)ps_enc_ctxt,
2957 IHEVCE_PRE_ENC_ME_Q,
2958 &ai4_in_buf_id[i4_me_frm_id],
2959 BUFF_QUE_BLOCKING_MODE);
2960 /*always buffer must be available*/
2961 ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] != NULL);
2962
2963 ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 0;
2964
2965 /* ------- get the input prms buffer from L0 IPE queue ------------ */
2966 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id] =
2967 (pre_enc_L0_ipe_encloop_ctxt_t *)ihevce_q_get_filled_buff(
2968 (void *)ps_enc_ctxt,
2969 IHEVCE_L0_IPE_ENC_Q,
2970 &ps_enc_ctxt->s_multi_thrd.ai4_in_frm_l0_ipe_id[i4_me_frm_id],
2971 BUFF_QUE_BLOCKING_MODE);
2972
2973 /*always buffer must be available*/
2974 ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id] != NULL);
2975
2976 /* ------- get the free buffer from me_enc que ------------ */
2977 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] =
2978 (me_enc_rdopt_ctxt_t *)ihevce_q_get_free_buff(
2979 ps_enc_ctxt,
2980 IHEVCE_ME_ENC_RDOPT_Q,
2981 &ps_enc_ctxt->s_multi_thrd.ai4_me_out_buf_id[i4_me_frm_id],
2982 BUFF_QUE_BLOCKING_MODE);
2983
2984 /*always buffer must be available*/
2985 ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] != NULL);
2986 }
2987 if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
2988 NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] &&
2989 NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id])
2990 {
2991 ps_curr_inp =
2992 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
2993
2994 ps_curr_out_me = ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id];
2995
2996 ps_curr_out_me->ps_curr_inp_from_l0_ipe_prms =
2997 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id];
2998
2999 /*initialization of curr out me*/
3000 ps_curr_out_me->ps_curr_inp_from_me_prms =
3001 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id];
3002
3003 ps_curr_out_me->curr_inp_from_me_buf_id = ai4_in_buf_id[i4_me_frm_id];
3004
3005 ps_curr_out_me->i4_buf_id =
3006 ps_enc_ctxt->s_multi_thrd.ai4_me_out_buf_id[i4_me_frm_id];
3007
3008 ps_curr_out_me->ps_curr_inp =
3009 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3010
3011 ps_curr_out_me->curr_inp_buf_id =
3012 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->curr_inp_buf_id;
3013
3014 ps_curr_out_me->curr_inp_from_l0_ipe_buf_id =
3015 ps_enc_ctxt->s_multi_thrd.ai4_in_frm_l0_ipe_id[i4_me_frm_id];
3016
3017 ps_curr_out_me->i4_frm_proc_valid_flag =
3018 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3019 ->i4_frm_proc_valid_flag;
3020
3021 ps_curr_out_me->i4_end_flag =
3022 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag;
3023
3024 /* set the parameters for sync b/w entropy thread */
3025
3026 ps_enc_ctxt->s_multi_thrd.me_end_flag =
3027 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag;
3028
3029 /* do the processing if input frm data is valid */
3030 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
3031 {
3032 /* slice header will be populated in pre-enocde stage */
3033 memcpy(
3034 &ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]
3035 ->s_slice_hdr,
3036 &ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3037 ->s_slice_hdr,
3038 sizeof(slice_header_t));
3039
3040 if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3041 ->i4_frm_proc_valid_flag)
3042 {
3043 WORD32 ctr;
3044 recon_pic_buf_t *ps_frm_recon;
3045 for(i = 0; i < i4_num_bitrates; i++)
3046 {
3047 /* run a loop to free the non used reference pics */
3048 /* This is done here because its assured that recon buf
3049 * between app and encode loop is set as produced
3050 */
3051 {
3052 WORD32 i4_free_id;
3053 i4_free_id = ihevce_find_free_indx(
3054 ps_enc_ctxt->pps_recon_buf_q[i],
3055 ps_enc_ctxt->ai4_num_buf_recon_q[i]);
3056
3057 if(i4_free_id != -1)
3058 {
3059 ps_enc_ctxt->pps_recon_buf_q[i][i4_free_id]->i4_is_free = 1;
3060 ps_enc_ctxt->pps_recon_buf_q[i][i4_free_id]->i4_poc = -1;
3061 }
3062 }
3063
3064 ps_frm_recon = NULL;
3065 for(ctr = 0; ctr < ps_enc_ctxt->ai4_num_buf_recon_q[i]; ctr++)
3066 {
3067 if(ps_enc_ctxt->pps_recon_buf_q[i][ctr]->i4_is_free)
3068 {
3069 ps_frm_recon = ps_enc_ctxt->pps_recon_buf_q[i][ctr];
3070 break;
3071 }
3072 }
3073 ASSERT(ps_frm_recon != NULL);
3074
3075 ps_frm_recon->i4_is_free = 0;
3076 ps_frm_recon->i4_non_ref_free_flag = 0;
3077 ps_frm_recon->i4_topfield_first =
3078 ps_curr_inp->s_input_buf.i4_topfield_first;
3079 ps_frm_recon->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
3080 ps_frm_recon->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
3081 ps_frm_recon->i4_display_num =
3082 ps_curr_inp->s_lap_out.i4_display_num;
3083 ps_frm_recon->i4_idr_gop_num =
3084 ps_curr_inp->s_lap_out.i4_idr_gop_num;
3085 ps_frm_recon->i4_bottom_field =
3086 ps_curr_inp->s_input_buf.i4_bottom_field;
3087 ps_frm_recon->i4_is_reference =
3088 ps_curr_inp->s_lap_out.i4_is_ref_pic;
3089
3090 {
3091 WORD32 sei_hash_enabled =
3092 (ps_enc_ctxt->ps_stat_prms->s_out_strm_prms
3093 .i4_sei_enable_flag == 1) &&
3094 (ps_enc_ctxt->ps_stat_prms->s_out_strm_prms
3095 .i4_decoded_pic_hash_sei_flag != 0);
3096
3097 /* Deblock a picture for all reference frames unconditionally. */
3098 /* Deblock non ref if psnr compute or save recon is enabled */
3099 ps_frm_recon->i4_deblk_pad_hpel_cur_pic =
3100 ps_frm_recon->i4_is_reference ||
3101 (ps_enc_ctxt->ps_stat_prms->i4_save_recon) ||
3102 (1 == sei_hash_enabled);
3103 }
3104
3105 ps_frm_recon->s_yuv_buf_desc.i4_y_ht =
3106 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht;
3107 ps_frm_recon->s_yuv_buf_desc.i4_uv_ht =
3108 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht >>
3109 ((ps_enc_ctxt->s_runtime_src_prms.i4_chr_format ==
3110 IV_YUV_422SP_UV)
3111 ? 0
3112 : 1);
3113 ps_frm_recon->s_yuv_buf_desc.i4_y_wd =
3114 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd;
3115 ps_frm_recon->s_yuv_buf_desc.i4_uv_wd =
3116 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd;
3117 ps_frm_recon->s_yuv_buf_desc.i4_y_strd =
3118 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd +
3119 (PAD_HORZ << 1);
3120 ps_frm_recon->s_yuv_buf_desc.i4_uv_strd =
3121 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd +
3122 (PAD_HORZ << 1);
3123
3124 /* reset the row_frm dep mngr for ME reverse sync for reference bitrate */
3125 if(i == 0)
3126 {
3127 ihevce_dmgr_map_rst_sync(ps_frm_recon->pv_dep_mngr_recon);
3128 }
3129
3130 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i] =
3131 ps_frm_recon;
3132 }
3133 }
3134 /* Reference buffer management and reference list creation */
3135 /* This needs to be created for each bit-rate since the reconstructed output is
3136 different for all bit-rates. ME uses only 0th instnace ref list */
3137 for(i = i4_num_bitrates - 1; i >= 0; i--)
3138 {
3139 ihevce_manage_ref_pics(
3140 ps_enc_ctxt,
3141 ps_curr_inp,
3142 &ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id]
3143 ->s_slice_hdr,
3144 i4_me_frm_id,
3145 i4_thrd_id,
3146 i); /* bitrate instance ID */
3147 }
3148 /*query of qp to be moved just before encoding starts*/
3149 i4_ref_cur_qp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3150 ->i4_curr_frm_qp;
3151 /* The Qp populated in Pre enc stage needs to overwritten with Qp
3152 queried from rate control*/
3153 }
3154 else
3155 {
3156 i4_ref_cur_qp = 0;
3157 }
3158
3159 /* call the core encoding loop */
3160 ihevce_frame_init(
3161 ps_enc_ctxt,
3162 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id],
3163 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id],
3164 i4_ref_cur_qp,
3165 i4_me_frm_id,
3166 i4_thrd_id);
3167 }
3168
3169 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 1;
3170 }
3171 }
3172
3173 /************************************/
3174 /****** EXIT CRITICAL SECTION ******/
3175 /************************************/
3176
3177 /****** Unlock the critical section ******/
3178 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id])
3179 {
3180 result = osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i4_me_frm_id]);
3181 if(OSAL_SUCCESS != result)
3182 return 0;
3183 }
3184
3185 if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out) &&
3186 (1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3187 ->ps_curr_inp->s_lap_out.i4_first_frm_new_res))
3188 {
3189 /* Reset the enc frame rc id whenver change in resolution happens */
3190 i4_enc_frm_id_rc = 0;
3191 }
3192
3193 /*update end flag for each thread */
3194 i4_me_end_flag = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_end_flag;
3195 if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
3196 NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] &&
3197 NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id])
3198 {
3199 pre_enc_me_ctxt_t *ps_curr_inp_prms;
3200 pre_enc_L0_ipe_encloop_ctxt_t *ps_curr_L0_IPE_inp_prms;
3201 ihevce_lap_enc_buf_t *ps_curr_inp;
3202
3203 /* get the current buffer pointer */
3204 ps_curr_inp_prms = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id];
3205 ps_curr_L0_IPE_inp_prms =
3206 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id];
3207 ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3208
3209 /* -------------------------------------------------- */
3210 /* Motion estimation (enc layer) of entire frame */
3211 /* -------------------------------------------------- */
3212 if((i4_me_end_flag == 0) &&
3213 (1 ==
3214 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->i4_frm_proc_valid_flag))
3215 {
3216 /* Init i4_is_prev_frame_reference for the next P-frame */
3217 me_master_ctxt_t *ps_master_ctxt =
3218 (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3219
3220 /* get the current thread ctxt pointer */
3221 me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3222
3223 me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3224
3225 if(ISLICE != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3226 ->s_slice_hdr.i1_slice_type)
3227 {
3228 ihevce_me_process(
3229 ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
3230 ps_curr_inp,
3231 ps_curr_inp_prms->ps_ctb_analyse,
3232 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id],
3233 ps_curr_inp_prms->plf_intra_8x8_cost,
3234 ps_curr_L0_IPE_inp_prms->ps_ipe_analyse_ctb,
3235 ps_curr_L0_IPE_inp_prms,
3236 ps_curr_inp_prms->pv_me_lyr_ctxt,
3237 &ps_enc_ctxt->s_multi_thrd,
3238 ((ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel == 1) ? 0 : 1),
3239 i4_thrd_id,
3240 i4_me_frm_id);
3241 }
3242 else
3243
3244 {
3245 /* Init i4_is_prev_frame_reference for the next P-frame */
3246 me_master_ctxt_t *ps_master_ctxt =
3247 (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3248
3249 /* get the current thread ctxt pointer */
3250 me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3251
3252 me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3253
3254 multi_thrd_ctxt_t *ps_multi_thrd_ctxt = &ps_enc_ctxt->s_multi_thrd;
3255
3256 if(ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel != 1)
3257 {
3258 ps_frm_ctxt->i4_is_prev_frame_reference = 0;
3259 }
3260 else
3261 {
3262 ps_frm_ctxt->i4_is_prev_frame_reference =
3263 ps_multi_thrd_ctxt->aps_cur_inp_me_prms[i4_me_frm_id]
3264 ->ps_curr_inp->s_lap_out.i4_is_ref_pic;
3265 }
3266 }
3267 }
3268 }
3269 /************************************/
3270 /****** ENTER CRITICAL SECTION *****/
3271 /************************************/
3272 {
3273 WORD32 result_frame_init;
3274 void *pv_mutex_handle_frame_init;
3275
3276 /* Create mutex for locking non-reentrant sections */
3277 pv_mutex_handle_frame_init =
3278 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i4_me_frm_id];
3279
3280 /****** Lock the critical section ******/
3281 if(NULL != pv_mutex_handle_frame_init)
3282 {
3283 result_frame_init = osal_mutex_lock(pv_mutex_handle_frame_init);
3284
3285 if(OSAL_SUCCESS != result_frame_init)
3286 return 0;
3287 }
3288 }
3289
3290 if(0 == ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id])
3291 {
3292 /* ------- set buffer produced from me_enc que ------------ */
3293 ihevce_q_set_buff_prod(
3294 ps_enc_ctxt,
3295 IHEVCE_ME_ENC_RDOPT_Q,
3296 ps_enc_ctxt->s_multi_thrd.ai4_me_out_buf_id[i4_me_frm_id]);
3297
3298 ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id] = 1;
3299 }
3300 if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] &&
3301 NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id])
3302 {
3303 ihevce_lap_enc_buf_t *ps_curr_inp;
3304
3305 WORD32 first_field = 1;
3306
3307 /* Increment the counter to keep track of no of threads exiting the current mutex*/
3308 ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id]++;
3309
3310 ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]->ps_curr_inp;
3311 /* Last slave thread will reset the master done frame init flag and set the prev
3312 * frame me done flag for curr frame
3313 */
3314 if(ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id] ==
3315 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
3316 {
3317 ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_me_frm_id] = 0;
3318
3319 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 0;
3320
3321 /* Update Dyn. Vert. Search prms for P Pic. */
3322 if(IV_P_FRAME == ps_curr_inp->s_lap_out.i4_pic_type)
3323 {
3324 WORD32 i4_idx_dvsr_p = ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p;
3325 /* Sanity Check */
3326 ASSERT(ps_curr_inp->s_lap_out.i4_pic_type < IV_IP_FRAME);
3327
3328 /* Frame END processing for Dynamic Vertival Search */
3329 ihevce_l0_me_frame_end(
3330 ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
3331 i4_idx_dvsr_p,
3332 ps_curr_inp->s_lap_out.i4_display_num,
3333 i4_me_frm_id);
3334
3335 ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p++;
3336 if(ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p == NUM_SG_INTERLEAVED)
3337 {
3338 ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p = 0;
3339 }
3340 }
3341 if(1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id]
3342 ->i4_frm_proc_valid_flag)
3343 {
3344 /* Init i4_is_prev_frame_reference for the next P-frame */
3345 me_master_ctxt_t *ps_master_ctxt =
3346 (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3347
3348 /* get the current thread ctxt pointer */
3349 me_ctxt_t *ps_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
3350
3351 me_frm_ctxt_t *ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i4_me_frm_id];
3352
3353 ps_frm_ctxt->ps_curr_descr->aps_layers[0]->i4_non_ref_free = 1;
3354 }
3355 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_me_prms[i4_me_frm_id] = NULL;
3356 ps_enc_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_me_frm_id] = NULL;
3357 ps_enc_ctxt->s_multi_thrd.aps_cur_L0_ipe_inp_prms[i4_me_frm_id] = NULL;
3358 ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_me_frm_id] = 0;
3359 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_me_frm_id] = 0;
3360
3361 /* Set me processing done for curr frame in the dependency manager */
3362 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_me_done);
3363 }
3364 }
3365 /************************************/
3366 /****** EXIT CRITICAL SECTION ******/
3367 /************************************/
3368
3369 {
3370 void *pv_mutex_handle_frame_init;
3371
3372 /* Create mutex for locking non-reentrant sections */
3373 pv_mutex_handle_frame_init =
3374 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i4_me_frm_id];
3375 /****** Unlock the critical section ******/
3376 if(NULL != pv_mutex_handle_frame_init)
3377 {
3378 result = osal_mutex_unlock(pv_mutex_handle_frame_init);
3379 if(OSAL_SUCCESS != result)
3380 return 0;
3381 }
3382 }
3383 /* -------------------------------------------- */
3384 /* Encode Loop of entire frame */
3385 /* -------------------------------------------- */
3386 ASSERT(ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel <= MAX_NUM_ENC_LOOP_PARALLEL);
3387
3388 if(1 == ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel)
3389 {
3390 pv_dep_mngr_prev_frame_done = ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[0];
3391 }
3392 else
3393 {
3394 pv_dep_mngr_prev_frame_done =
3395 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[i4_enc_frm_id];
3396 }
3397 /* Wait till the prev frame enc loop is completed*/
3398 {
3399 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_done, ps_thrd_ctxt->i4_thrd_id);
3400 }
3401
3402 /************************************/
3403 /****** ENTER CRITICAL SECTION ******/
3404 /************************************/
3405 {
3406 WORD32 result_frame_init;
3407 void *pv_mutex_handle_frame_init;
3408
3409 /* Create mutex for locking non-reentrant sections */
3410 pv_mutex_handle_frame_init =
3411 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i4_enc_frm_id];
3412
3413 /****** Lock the critical section ******/
3414 if(NULL != pv_mutex_handle_frame_init)
3415 {
3416 result_frame_init = osal_mutex_lock(pv_mutex_handle_frame_init);
3417
3418 if(OSAL_SUCCESS != result_frame_init)
3419 return 0;
3420 }
3421 }
3422
3423 {
3424 ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
3425 pre_enc_me_ctxt_t *ps_curr_inp_from_me = NULL;
3426 me_enc_rdopt_ctxt_t *ps_curr_inp_enc = NULL;
3427 pre_enc_L0_ipe_encloop_ctxt_t *ps_curr_L0_IPE_inp_prms = NULL;
3428 recon_pic_buf_t *(*aps_ref_list)[HEVCE_MAX_REF_PICS * 2];
3429 WORD32 ai4_cur_qp[IHEVCE_MAX_NUM_BITRATES] = { 0 };
3430 WORD32 i4_field_pic = ps_enc_ctxt->s_runtime_src_prms.i4_field_pic;
3431 WORD32 first_field = 1;
3432 WORD32 result_frame_init;
3433 void *pv_mutex_handle_frame_init;
3434
3435 /* Create mutex for locking non-reentrant sections */
3436 pv_mutex_handle_frame_init =
3437 ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i4_enc_frm_id];
3438
3439 //aquire and initialize -> output and recon buffers
3440 if(ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] == 0)
3441 {
3442 WORD32
3443 i4_bitrate_ctr; //bit-rate instance counter (for loop variable) [0->reference bit-rate, 1,2->auxiliarty bit-rates]
3444 /* ------- get the input prms buffer from me que ------------ */
3445 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] =
3446 (me_enc_rdopt_ctxt_t *)ihevce_q_get_filled_buff(
3447 ps_enc_ctxt,
3448 IHEVCE_ME_ENC_RDOPT_Q,
3449 &ps_enc_ctxt->s_multi_thrd.i4_enc_in_buf_id[i4_enc_frm_id],
3450 BUFF_QUE_BLOCKING_MODE);
3451 i4_enc_end_flag =
3452 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->i4_end_flag;
3453
3454 ASSERT(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL);
3455
3456 if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
3457 {
3458 ps_curr_inp =
3459 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->ps_curr_inp;
3460 ps_curr_inp_from_me =
3461 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3462 ->ps_curr_inp_from_me_prms;
3463 ps_curr_inp_enc = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id];
3464 ps_curr_L0_IPE_inp_prms =
3465 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3466 ->ps_curr_inp_from_l0_ipe_prms;
3467
3468 for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates; i4_bitrate_ctr++)
3469 {
3470 iv_enc_recon_data_buffs_t
3471 *ps_recon_out[MAX_NUM_ENC_LOOP_PARALLEL][IHEVCE_MAX_NUM_BITRATES] = {
3472 { NULL }
3473 };
3474 frm_proc_ent_cod_ctxt_t *ps_curr_out[MAX_NUM_ENC_LOOP_PARALLEL]
3475 [IHEVCE_MAX_NUM_BITRATES] = { { NULL } };
3476
3477 /* ------- get free output buffer from Frame buffer que ---------- */
3478 /* There is a separate queue for each bit-rate instnace. The output
3479 buffer is acquired from the corresponding queue based on the
3480 bitrate instnace */
3481 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr] =
3482 (frm_proc_ent_cod_ctxt_t *)ihevce_q_get_free_buff(
3483 (void *)ps_enc_ctxt,
3484 IHEVCE_FRM_PRS_ENT_COD_Q +
3485 i4_bitrate_ctr, /*decides the buffer queue */
3486 &ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
3487 BUFF_QUE_BLOCKING_MODE);
3488 ps_enc_ctxt->s_multi_thrd.is_out_buf_freed[i4_enc_frm_id][i4_bitrate_ctr] =
3489 0;
3490 ps_enc_ctxt->s_multi_thrd
3491 .ps_curr_out_enc_grp[i4_enc_frm_id][i4_bitrate_ctr] =
3492 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr];
3493 //ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_enc_order_num = ps_curr_inp->s_lap_out.i4_enc_order_num;
3494 /*registered User Data Call*/
3495 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_payload_enable_flag)
3496 {
3497 ihevce_fill_sei_payload(
3498 ps_enc_ctxt,
3499 ps_curr_inp,
3500 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]);
3501 }
3502
3503 /*derive end flag and input valid flag in output buffer */
3504 if(NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id])
3505 {
3506 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
3507 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3508 ->i4_end_flag;
3509 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_frm_proc_valid_flag =
3510 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3511 ->i4_frm_proc_valid_flag;
3512
3513 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_out_flush_flag =
3514 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3515 ->ps_curr_inp->s_lap_out.i4_out_flush_flag;
3516 }
3517
3518 /*derive other parameters in output buffer */
3519 if(NULL != ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr] &&
3520 (NULL != ps_curr_inp_from_me) &&
3521 (1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag) &&
3522 (i4_enc_end_flag == 0))
3523 {
3524 /* copy the time stamps from inp to entropy inp */
3525 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_inp_timestamp_low =
3526 ps_curr_inp_from_me->i4_inp_timestamp_low;
3527 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_inp_timestamp_high =
3528 ps_curr_inp_from_me->i4_inp_timestamp_high;
3529 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->pv_app_frm_ctxt =
3530 ps_curr_inp_from_me->pv_app_frm_ctxt;
3531
3532 /*copy slice header params from temp structure to output buffer */
3533 memcpy(
3534 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->s_slice_hdr,
3535 &ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3536 ->s_slice_hdr,
3537 sizeof(slice_header_t));
3538
3539 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3540 ->s_slice_hdr.pu4_entry_point_offset =
3541 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3542 ->ai4_entry_point_offset[0];
3543
3544 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_slice_nal_type =
3545 ps_curr_inp_from_me->i4_slice_nal_type;
3546
3547 /* populate sps, vps and pps pointers for the entropy input params */
3548 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_pps =
3549 &ps_enc_ctxt->as_pps[i4_bitrate_ctr];
3550 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_sps =
3551 &ps_enc_ctxt->as_sps[i4_bitrate_ctr];
3552 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->ps_vps =
3553 &ps_enc_ctxt->as_vps[i4_bitrate_ctr];
3554
3555 /* SEI header will be populated in pre-enocde stage */
3556 memcpy(
3557 &ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->s_sei,
3558 &ps_curr_inp_from_me->s_sei,
3559 sizeof(sei_params_t));
3560
3561 /*AUD and EOS presnt flags are populated*/
3562 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i1_aud_present_flag =
3563 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_aud_enable_flags;
3564
3565 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i1_eos_present_flag =
3566 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_eos_enable_flags;
3567
3568 /* Information required for SEI Picture timing info */
3569 {
3570 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_display_num =
3571 ps_curr_inp->s_lap_out.i4_display_num;
3572 }
3573
3574 /* The Qp populated in Pre enc stage needs to overwritten with Qp
3575 queried from rate control*/
3576 ps_curr_out[i4_enc_frm_id][i4_bitrate_ctr]
3577 ->s_slice_hdr.i1_slice_qp_delta =
3578 (WORD8)ps_curr_inp_from_me->i4_curr_frm_qp -
3579 ps_enc_ctxt->as_pps[i4_bitrate_ctr].i1_pic_init_qp;
3580 }
3581
3582 /* ------- get a filled descriptor from output Que ------------ */
3583 if(/*(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag) &&*/
3584 (ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0))
3585 {
3586 /*swaping of buf_id for 0th and reference bitrate location, as encoder
3587 assumes always 0th loc for reference bitrate and app must receive in
3588 the configured order*/
3589 WORD32 i4_recon_buf_id = i4_bitrate_ctr;
3590 if(i4_bitrate_ctr == 0)
3591 {
3592 i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
3593 }
3594 else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
3595 {
3596 i4_recon_buf_id = 0;
3597 }
3598
3599 /* ------- get free Recon buffer from Frame buffer que ---------- */
3600 /* There is a separate queue for each bit-rate instnace. The recon
3601 buffer is acquired from the corresponding queue based on the
3602 bitrate instnace */
3603 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
3604 (iv_enc_recon_data_buffs_t *)ihevce_q_get_filled_buff(
3605 (void *)ps_enc_ctxt,
3606 IHEVCE_RECON_DATA_Q +
3607 i4_recon_buf_id, /*decides the buffer queue */
3608 &ps_enc_ctxt->s_multi_thrd
3609 .recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
3610 BUFF_QUE_BLOCKING_MODE);
3611
3612 ps_enc_ctxt->s_multi_thrd
3613 .is_recon_dumped[i4_enc_frm_id][i4_bitrate_ctr] = 0;
3614 ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
3615 ps_enc_ctxt->s_multi_thrd
3616 .ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr];
3617
3618 ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
3619 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3620 ->i4_end_flag;
3621 }
3622
3623 } //bitrate ctr
3624 }
3625 }
3626 if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
3627 {
3628 ps_curr_inp =
3629 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]->ps_curr_inp;
3630 ps_curr_inp_from_me = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3631 ->ps_curr_inp_from_me_prms;
3632 ps_curr_inp_enc = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id];
3633 ps_curr_L0_IPE_inp_prms =
3634 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3635 ->ps_curr_inp_from_l0_ipe_prms;
3636 }
3637 if((NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]) &&
3638 ((1 == ps_curr_inp_enc->i4_frm_proc_valid_flag) &&
3639 (ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] == 0)))
3640 {
3641 for(i = 0; i < i4_num_bitrates; i++)
3642 {
3643 aps_ref_list = ps_curr_inp_enc->aps_ref_list[i];
3644 /* acquire mutex lock for rate control calls */
3645 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
3646
3647 /*utlize the satd data from pre enc stage to get more accurate estimate SAD for I pic*/
3648 if(ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME ||
3649 ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME)
3650 {
3651 ihevce_rc_update_cur_frm_intra_satd(
3652 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3653 ps_curr_inp_from_me->i8_frame_acc_satd_cost,
3654 ps_enc_ctxt->i4_active_enc_frame_id);
3655 }
3656
3657 /*pels assuming satd/act is obtained for entire frame*/
3658 ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered =
3659 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
3660 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
3661
3662 /*Service pending request to change average bitrate if any*/
3663 {
3664 LWORD64 i8_new_bitrate =
3665 ihevce_rc_get_new_bitrate(ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3666 LWORD64 i8_new_peak_bitrate = ihevce_rc_get_new_peak_bitrate(
3667 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3668 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3669 ->i8_buf_level_bitrate_change = -1;
3670 if((i8_new_bitrate != -1) &&
3671 (i8_new_peak_bitrate != -1)) /*-1 indicates no pending request*/
3672 {
3673 LWORD64 buffer_level = ihevce_rc_change_avg_bitrate(
3674 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3675 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3676 ->i8_buf_level_bitrate_change = buffer_level;
3677 }
3678 }
3679
3680 if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out) &&
3681 (1 == ps_curr_inp->s_lap_out.i4_first_frm_new_res))
3682 {
3683 /* Whenver change in resolution happens change the buffer level */
3684 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3685 ->i8_buf_level_bitrate_change = 0;
3686 }
3687 #if 1 //KISH ELP
3688 {
3689 rc_bits_sad_t as_rc_frame_stat[IHEVCE_MAX_NUM_BITRATES];
3690
3691 if(ps_enc_ctxt->ai4_rc_query[i] ==
3692 ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc) //KISH
3693 {
3694 WORD32 out_buf_id[IHEVCE_MAX_NUM_BITRATES];
3695 WORD32 i4_pic_type;
3696 WORD32 cur_qp[IHEVCE_MAX_NUM_BITRATES];
3697 ihevce_lap_output_params_t s_lap_out;
3698
3699 rc_lap_out_params_t s_rc_lap_out;
3700 WORD32 i4_suppress_bpic_update;
3701
3702 ihevce_rc_store_retrive_update_info(
3703 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3704 &as_rc_frame_stat[i],
3705 ps_enc_ctxt->i4_active_enc_frame_id,
3706 i,
3707 2,
3708 &out_buf_id[i],
3709 &i4_pic_type,
3710 &cur_qp[i],
3711 (void *)&s_lap_out,
3712 (void *)&s_rc_lap_out);
3713
3714 i4_suppress_bpic_update =
3715 (WORD32)(s_rc_lap_out.i4_rc_temporal_lyr_id > 1);
3716 /*RC inter face update before update to happen only for ELP disabled */
3717 if(1 == ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
3718 {
3719 /* SGI & Enc Loop Parallelism related changes*/
3720 ihevce_rc_interface_update(
3721 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3722 (IV_PICTURE_CODING_TYPE_T)s_rc_lap_out.i4_rc_pic_type,
3723 &s_rc_lap_out,
3724 cur_qp[i],
3725 i4_enc_frm_id_rc);
3726 }
3727
3728 ihevce_rc_update_pic_info(
3729 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3730 (as_rc_frame_stat[i].u4_total_texture_bits +
3731 as_rc_frame_stat[i].u4_total_header_bits), //pass total bits
3732 as_rc_frame_stat[i].u4_total_header_bits,
3733 as_rc_frame_stat[i].u4_total_sad,
3734 as_rc_frame_stat[i].u4_total_intra_sad,
3735 (IV_PICTURE_CODING_TYPE_T)i4_pic_type,
3736 cur_qp[i],
3737 i4_suppress_bpic_update,
3738 as_rc_frame_stat[i].i4_qp_normalized_8x8_cu_sum,
3739 as_rc_frame_stat[i].i4_8x8_cu_sum,
3740 as_rc_frame_stat[i].i8_sad_by_qscale,
3741 &s_lap_out,
3742 &s_rc_lap_out,
3743 out_buf_id[i],
3744 as_rc_frame_stat[i].u4_open_loop_intra_sad,
3745 as_rc_frame_stat[i].i8_total_ssd_frame,
3746 ps_enc_ctxt
3747 ->i4_active_enc_frame_id); //ps_curr_out->i4_inp_timestamp_low)
3748
3749 //DBG_PRINTF("\n Sad = %d \t total bits = %d ", s_rc_frame_stat.u4_total_sad, (s_rc_frame_stat.u4_total_texture_bits + s_rc_frame_stat.u4_total_header_bits));
3750 /*populate qp for pre enc*/
3751
3752 //g_count--;
3753 ps_enc_ctxt->ai4_rc_query[i]--;
3754
3755 if(i == (i4_num_bitrates - 1))
3756 {
3757 ihevce_rc_cal_pre_enc_qp(
3758 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0]);
3759
3760 ps_enc_ctxt->i4_active_enc_frame_id++;
3761 ps_enc_ctxt->i4_active_enc_frame_id =
3762 (ps_enc_ctxt->i4_active_enc_frame_id %
3763 ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
3764 }
3765 }
3766 }
3767 #endif
3768 if(ps_enc_ctxt->ai4_rc_query[i] < ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
3769 {
3770 /*HEVC_RC query rate control for qp*/
3771 ai4_cur_qp[i] = ihevce_rc_get_pic_quant(
3772 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3773 &ps_curr_inp->s_rc_lap_out,
3774 ENC_GET_QP,
3775 i4_enc_frm_id_rc,
3776 0,
3777 &ps_curr_inp->s_lap_out.ai4_frame_bits_estimated[i]);
3778
3779 ps_curr_inp->s_rc_lap_out.i4_orig_rc_qp = ai4_cur_qp[i];
3780
3781 ps_enc_ctxt->s_multi_thrd.i4_in_frame_rc_enabled = 0;
3782 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3783 ->i4_sub_pic_level_rc = 0;
3784 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3785 ->ai4_frame_bits_estimated =
3786 ps_curr_inp->s_lap_out.ai4_frame_bits_estimated[i];
3787
3788 {
3789 ps_enc_ctxt->ai4_rc_query[i]++;
3790 }
3791 }
3792
3793 /* SGI & Enc Loop Parallelism related changes*/
3794 ihevce_rc_interface_update(
3795 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
3796 (IV_PICTURE_CODING_TYPE_T)ps_curr_inp->s_lap_out.i4_pic_type,
3797 &ps_curr_inp->s_rc_lap_out,
3798 ai4_cur_qp[i],
3799 i4_enc_frm_id_rc);
3800
3801 //DBG_PRINTF("HEVC_QP = %d MPEG2_QP = %d\n",cur_qp,gu1_HEVCToMpeg2Quant[cur_qp]);//i_model_print
3802
3803 /* release mutex lock after rate control calls */
3804 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
3805
3806 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3807 ->s_slice_hdr.i1_slice_qp_delta =
3808 (WORD8)ai4_cur_qp[i] - ps_enc_ctxt->as_pps[i].i1_pic_init_qp;
3809
3810 ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i] = ai4_cur_qp[i];
3811
3812 /* For interlace pictures, first_field depends on topfield_first and bottom field */
3813 if(i4_field_pic)
3814 {
3815 first_field =
3816 (ps_curr_inp->s_input_buf.i4_topfield_first ^
3817 ps_curr_inp->s_input_buf.i4_bottom_field);
3818 }
3819 /* get frame level lambda params */
3820 ihevce_get_frame_lambda_prms(
3821 ps_enc_ctxt,
3822 ps_curr_inp_from_me,
3823 ai4_cur_qp[i],
3824 first_field,
3825 ps_curr_inp->s_lap_out.i4_is_ref_pic,
3826 ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
3827 ps_curr_inp->s_lap_out.f_i_pic_lamda_modifier,
3828 i,
3829 ENC_LOOP_LAMBDA_TYPE);
3830
3831 #if ADAPT_COLOCATED_FROM_L0_FLAG
3832 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i]->i4_frame_qp =
3833 ai4_cur_qp[i];
3834 #endif
3835 } //bitrate counter ends
3836
3837 /* Reset the Dependency Mngrs local to EncLoop., ie CU_TopRight and Dblk */
3838 ihevce_enc_loop_dep_mngr_frame_reset(
3839 ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt, i4_enc_frm_id);
3840 }
3841
3842 {
3843 /*Set the master done flag for frame init so that other
3844 * threads can skip it
3845 */
3846 ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 1;
3847 }
3848
3849 /************************************/
3850 /****** EXIT CRITICAL SECTION ******/
3851 /************************************/
3852
3853 /****** Unlock the critical section ******/
3854 if(NULL != pv_mutex_handle_frame_init)
3855 {
3856 result_frame_init = osal_mutex_unlock(pv_mutex_handle_frame_init);
3857 if(OSAL_SUCCESS != result_frame_init)
3858 return 0;
3859 }
3860 ps_enc_ctxt->s_multi_thrd.i4_encode = 1;
3861 ps_enc_ctxt->s_multi_thrd.i4_num_re_enc = 0;
3862 /************************************/
3863 /****** Do Enc loop process ******/
3864 /************************************/
3865 /* Each thread will run the enc-loop.
3866 Each thread will initialize it's own enc_loop context and do the processing.
3867 Each thread will run all the bit-rate instances one after another */
3868 if((i4_enc_end_flag == 0) &&
3869 (NULL != ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]) &&
3870 (1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3871 ->i4_frm_proc_valid_flag))
3872 {
3873 while(1)
3874 {
3875 ctb_enc_loop_out_t *ps_ctb_enc_loop_frm[IHEVCE_MAX_NUM_BITRATES];
3876 cu_enc_loop_out_t *ps_cu_enc_loop_frm[IHEVCE_MAX_NUM_BITRATES];
3877 tu_enc_loop_out_t *ps_tu_frm[IHEVCE_MAX_NUM_BITRATES];
3878 pu_t *ps_pu_frm[IHEVCE_MAX_NUM_BITRATES];
3879 UWORD8 *pu1_frm_coeffs[IHEVCE_MAX_NUM_BITRATES];
3880 me_master_ctxt_t *ps_master_me_ctxt =
3881 (me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_me_ctxt;
3882 ihevce_enc_loop_master_ctxt_t *ps_master_ctxt =
3883 (ihevce_enc_loop_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt;
3884
3885 for(i = 0; i < i4_num_bitrates; i++)
3886 {
3887 if(i4_thrd_id == 0)
3888 {
3889 PROFILE_START(
3890 &ps_hle_ctxt->profile_enc[ps_enc_ctxt->i4_resolution_id][i]);
3891 }
3892 if(NULL != ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id])
3893 {
3894 ps_ctb_enc_loop_frm[i] =
3895 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3896 ->ps_frm_ctb_data;
3897 ps_cu_enc_loop_frm[i] =
3898 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3899 ->ps_frm_cu_data;
3900 ps_tu_frm[i] =
3901 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3902 ->ps_frm_tu_data;
3903 ps_pu_frm[i] =
3904 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3905 ->ps_frm_pu_data;
3906 pu1_frm_coeffs[i] = (UWORD8 *)ps_enc_ctxt->s_multi_thrd
3907 .ps_curr_out_enc_grp[i4_enc_frm_id][i]
3908 ->pv_coeff_data;
3909 }
3910 /*derive reference picture list based on ping or pong instnace */
3911 aps_ref_list = ps_curr_inp_enc->aps_ref_list[i];
3912
3913 /* Always consider chroma cost when computing cost for derived instance */
3914 ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id]->i4_consider_chroma_cost =
3915 1;
3916
3917 /*************************
3918 * MULTI BITRATE CODE START
3919 **************************/
3920 if(i4_num_bitrates > 1)
3921 {
3922 ihevce_mbr_quality_tool_set_configuration(
3923 ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id],
3924 ps_enc_ctxt->ps_stat_prms);
3925 }
3926 /************************
3927 * MULTI BITRATE CODE END
3928 *************************/
3929 /* picture level init of Encode loop module */
3930 ihevce_enc_loop_frame_init(
3931 ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
3932 ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i],
3933 aps_ref_list,
3934 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i],
3935 &ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
3936 ->s_slice_hdr,
3937 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_pps,
3938 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_sps,
3939 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->ps_vps,
3940 ps_curr_inp_enc->ps_curr_inp->s_lap_out.i1_weighted_pred_flag,
3941 ps_curr_inp_enc->ps_curr_inp->s_lap_out.i1_weighted_bipred_flag,
3942 ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_log2_luma_wght_denom,
3943 ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_log2_chroma_wght_denom,
3944 ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_poc,
3945 ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_display_num,
3946 ps_enc_ctxt,
3947 ps_curr_inp_enc,
3948 i,
3949 i4_thrd_id,
3950 i4_enc_frm_id, // update this to enc_loop_ctxt struct
3951 i4_num_bitrates,
3952 ps_curr_inp_enc->ps_curr_inp->s_lap_out.i4_quality_preset,
3953 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
3954 ->pv_dep_mngr_encloop_dep_me);
3955
3956 ihevce_enc_loop_process(
3957 ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
3958 ps_curr_inp,
3959 ps_curr_inp_from_me->ps_ctb_analyse,
3960 ps_curr_L0_IPE_inp_prms->ps_ipe_analyse_ctb,
3961 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i],
3962 ps_curr_inp_enc->ps_cur_ctb_cu_tree,
3963 ps_ctb_enc_loop_frm[i],
3964 ps_cu_enc_loop_frm[i],
3965 ps_tu_frm[i],
3966 ps_pu_frm[i],
3967 pu1_frm_coeffs[i],
3968 &ps_enc_ctxt->s_frm_ctb_prms,
3969 &ps_curr_inp_from_me->as_lambda_prms[i],
3970 &ps_enc_ctxt->s_multi_thrd,
3971 i4_thrd_id,
3972 i4_enc_frm_id,
3973 ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass);
3974 if(i4_thrd_id == 0)
3975 {
3976 PROFILE_STOP(
3977 &ps_hle_ctxt->profile_enc[ps_enc_ctxt->i4_resolution_id][i], NULL);
3978 }
3979 } //loop over bitrate ends
3980 {
3981 break;
3982 }
3983 } /*end of while(ps_enc_ctxt->s_multi_thrd.ai4_encode[i4_enc_frm_id] == 1)*/
3984 }
3985
3986 /************************************/
3987 /****** ENTER CRITICAL SECTION ******/
3988 /************************************/
3989
3990 /****** Lock the critical section ******/
3991 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
3992 {
3993 result = osal_mutex_lock(
3994 ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
3995
3996 if(OSAL_SUCCESS != result)
3997 return 0;
3998 }
3999 if(ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] != NULL)
4000 {
4001 /* Increment the counter to keep track of no of threads exiting the current mutex*/
4002 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id]++;
4003
4004 /* If the end frame is reached force the last slave to enter the next critical section*/
4005 if(i4_enc_end_flag == 1)
4006 {
4007 if(ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4008 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds - 1)
4009 {
4010 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] =
4011 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds;
4012 }
4013 }
4014
4015 {
4016 /*Last slave thread comming out of enc loop will execute next critical section*/
4017 if(ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] ==
4018 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
4019 {
4020 iv_enc_recon_data_buffs_t *ps_recon_out_temp = NULL;
4021 recon_pic_buf_t *ps_frm_recon_temp = NULL;
4022 ihevce_lap_enc_buf_t *ps_curr_inp;
4023 rc_lap_out_params_t *ps_rc_lap_out_next_encode;
4024
4025 WORD32 ai4_act_qp[IHEVCE_MAX_NUM_BITRATES];
4026 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] = 0;
4027
4028 ps_curr_inp = ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
4029 ->ps_curr_inp;
4030
4031 for(i = 0; i < i4_num_bitrates; i++)
4032 {
4033 {
4034 WORD32 j, i4_avg_QP;
4035 ihevce_enc_loop_master_ctxt_t *ps_master_ctxt =
4036 (ihevce_enc_loop_master_ctxt_t *)
4037 ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt;
4038 ihevce_enc_loop_ctxt_t *ps_ctxt, *ps_ctxt_temp;
4039 ihevce_enc_loop_ctxt_t *ps_ctxt_last_thrd;
4040 LWORD64 i8_total_cu_bits_into_qscale = 0, i8_total_cu_bits = 0;
4041 UWORD32 total_frame_intra_sad = 0;
4042 UWORD32 total_frame_inter_sad = 0;
4043 UWORD32 total_frame_sad = 0;
4044
4045 LWORD64 total_frame_intra_cost = 0;
4046 LWORD64 total_frame_inter_cost = 0;
4047 LWORD64 total_frame_cost = 0;
4048
4049 ps_ctxt_last_thrd =
4050 ps_master_ctxt->aps_enc_loop_thrd_ctxt[i4_thrd_id];
4051 if(ps_enc_ctxt->s_multi_thrd.i4_in_frame_rc_enabled)
4052 {
4053 WORD32 i4_total_ctb =
4054 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4055 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert;
4056
4057 ai4_act_qp[i] =
4058 ps_enc_ctxt->s_multi_thrd
4059 .ai4_curr_qp_acc[ps_ctxt_last_thrd->i4_enc_frm_id][i] /
4060 i4_total_ctb;
4061 }
4062 else
4063 {
4064 ai4_act_qp[i] =
4065 ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4066 }
4067
4068 ps_enc_ctxt->s_multi_thrd
4069 .ai4_curr_qp_acc[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4070
4071 /*Reset all the values of sub pic rc to default after the frame is completed */
4072 {
4073 ps_enc_ctxt->s_multi_thrd
4074 .ai4_acc_ctb_ctr[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4075 ps_enc_ctxt->s_multi_thrd
4076 .ai4_ctb_ctr[ps_ctxt_last_thrd->i4_enc_frm_id][i] = 0;
4077
4078 ps_enc_ctxt->s_multi_thrd
4079 .ai4_threshold_reached[ps_ctxt_last_thrd->i4_enc_frm_id][i] =
4080 0;
4081
4082 ps_enc_ctxt->s_multi_thrd
4083 .ai4_curr_qp_estimated[ps_ctxt_last_thrd->i4_enc_frm_id][i] =
4084 (1 << QP_LEVEL_MOD_ACT_FACTOR);
4085
4086 ps_enc_ctxt->s_multi_thrd
4087 .af_acc_hdr_bits_scale_err[ps_ctxt_last_thrd->i4_enc_frm_id]
4088 [i] = 0;
4089 }
4090 for(j = 0; j < ps_master_ctxt->i4_num_proc_thrds; j++)
4091 {
4092 /* ENC_LOOP state structure */
4093 ps_ctxt = ps_master_ctxt->aps_enc_loop_thrd_ctxt[j];
4094
4095 total_frame_intra_sad +=
4096 ps_ctxt
4097 ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4098 ->i4_enc_frm_id][i]
4099 ->u4_frame_intra_sad_acc;
4100 total_frame_inter_sad +=
4101 ps_ctxt
4102 ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4103 ->i4_enc_frm_id][i]
4104 ->u4_frame_inter_sad_acc;
4105 total_frame_sad +=
4106 ps_ctxt
4107 ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4108 ->i4_enc_frm_id][i]
4109 ->u4_frame_sad_acc;
4110
4111 total_frame_intra_cost +=
4112 ps_ctxt
4113 ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4114 ->i4_enc_frm_id][i]
4115 ->i8_frame_intra_cost_acc;
4116 total_frame_inter_cost +=
4117 ps_ctxt
4118 ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4119 ->i4_enc_frm_id][i]
4120 ->i8_frame_inter_cost_acc;
4121 total_frame_cost +=
4122 ps_ctxt
4123 ->aaps_enc_loop_rc_params[ps_ctxt_last_thrd
4124 ->i4_enc_frm_id][i]
4125 ->i8_frame_cost_acc;
4126 /*Reset thrd id flag once the frame is completed */
4127 ps_enc_ctxt->s_multi_thrd
4128 .ai4_thrd_id_valid_flag[ps_ctxt_last_thrd->i4_enc_frm_id][i]
4129 [j] = -1;
4130 }
4131 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4132 ->s_pic_level_info.u4_frame_sad = total_frame_sad;
4133 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4134 ->s_pic_level_info.u4_frame_intra_sad = total_frame_intra_sad;
4135 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4136 ->s_pic_level_info.u4_frame_inter_sad = total_frame_inter_sad;
4137
4138 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4139 ->s_pic_level_info.i8_frame_cost = total_frame_cost;
4140 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4141 ->s_pic_level_info.i8_frame_intra_cost = total_frame_intra_cost;
4142 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4143 ->s_pic_level_info.i8_frame_inter_cost = total_frame_inter_cost;
4144 }
4145 ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] = 1;
4146 ps_recon_out_temp =
4147 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i];
4148 ps_frm_recon_temp =
4149 ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_enc_frm_id][i];
4150
4151 /* end of frame processing only if current input is valid */
4152 if(1 == ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id]
4153 ->i4_frm_proc_valid_flag)
4154 {
4155 /* Calculate the SEI Hash if enabled */
4156 if(0 !=
4157 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4158 ->s_sei.i1_decoded_pic_hash_sei_flag)
4159 {
4160 void *pv_y_buf;
4161 void *pv_u_buf;
4162
4163 {
4164 pv_y_buf = ps_frm_recon_temp->s_yuv_buf_desc.pv_y_buf;
4165 pv_u_buf = ps_frm_recon_temp->s_yuv_buf_desc.pv_u_buf;
4166 }
4167
4168 ihevce_populate_hash_sei(
4169 &ps_enc_ctxt->s_multi_thrd
4170 .ps_curr_out_enc_grp[i4_enc_frm_id][i]
4171 ->s_sei,
4172 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms
4173 .i4_internal_bit_depth,
4174 pv_y_buf,
4175 ps_frm_recon_temp->s_yuv_buf_desc.i4_y_wd,
4176 ps_frm_recon_temp->s_yuv_buf_desc.i4_y_ht,
4177 ps_frm_recon_temp->s_yuv_buf_desc.i4_y_strd,
4178 pv_u_buf,
4179 ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_wd,
4180 ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_ht,
4181 ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_strd,
4182 0,
4183 0);
4184 }
4185 /* Sending qp, poc and pic-type to entropy thread for printing on console */
4186 if(ps_enc_ctxt->ps_stat_prms->i4_log_dump_level != 0)
4187 {
4188 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4189 ->i4_qp =
4190 ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4191 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4192 ->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
4193 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4194 ->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
4195 }
4196
4197 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4198 ->i4_is_I_scenecut =
4199 ((ps_curr_inp->s_lap_out.i4_scene_type == 1) &&
4200 (ps_curr_inp->s_lap_out.i4_pic_type == IV_IDR_FRAME ||
4201 ps_curr_inp->s_lap_out.i4_pic_type == IV_I_FRAME));
4202
4203 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4204 ->i4_is_non_I_scenecut =
4205 ((ps_curr_inp->s_lap_out.i4_scene_type ==
4206 SCENE_TYPE_SCENE_CUT) &&
4207 (ps_enc_ctxt->s_multi_thrd
4208 .ps_curr_out_enc_grp[i4_enc_frm_id][i]
4209 ->i4_is_I_scenecut == 0));
4210
4211 /*ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->i4_is_I_only_scd = ps_curr_inp->s_lap_out.i4_is_I_only_scd;
4212 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->i4_is_non_I_scd = ps_curr_inp->s_lap_out.i4_is_non_I_scd;
4213
4214 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]->i4_is_model_valid = ps_curr_inp->s_lap_out.i4_is_model_valid;*/
4215
4216 /* -------------------------------------------- */
4217 /* MSE Computation for PSNR */
4218 /* -------------------------------------------- */
4219 if(ps_enc_ctxt->ps_stat_prms->i4_log_dump_level != 0)
4220 {
4221 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4222 ->i4_qp =
4223 ps_enc_ctxt->s_multi_thrd.cur_qp[i4_enc_frm_id][i];
4224 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4225 ->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
4226 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4227 ->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
4228 }
4229
4230 /* if non reference B picture */
4231 if(0 == ps_frm_recon_temp->i4_is_reference)
4232 {
4233 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i]
4234 ->i4_pic_type += 2;
4235 }
4236
4237 #define FORCE_EXT_REF_PIC 0
4238
4239 /* -------------------------------------------- */
4240 /* Dumping of recon to App Queue */
4241 /* -------------------------------------------- */
4242 if(1 == ps_enc_ctxt->ps_stat_prms->i4_save_recon)
4243 {
4244 {
4245 WORD32 i, j;
4246 UWORD8 *pu1_recon;
4247 UWORD8 *pu1_chrm_buf_u;
4248 UWORD8 *pu1_chrm_buf_v;
4249 UWORD8 *pu1_curr_recon;
4250
4251 pu1_recon =
4252 (UWORD8 *)ps_frm_recon_temp->s_yuv_buf_desc.pv_y_buf;
4253
4254 /** Copying Luma into recon buffer **/
4255 pu1_curr_recon = (UWORD8 *)ps_recon_out_temp->pv_y_buf;
4256
4257 for(j = 0; j < ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht;
4258 j++)
4259 {
4260 memcpy(
4261 pu1_curr_recon,
4262 pu1_recon,
4263 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd);
4264
4265 pu1_recon +=
4266 ps_frm_recon_temp->s_yuv_buf_desc.i4_y_strd;
4267 pu1_curr_recon +=
4268 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
4269 }
4270
4271 /* recon chroma is converted from Semiplanar to Planar for dumping */
4272 pu1_recon =
4273 (UWORD8 *)ps_frm_recon_temp->s_yuv_buf_desc.pv_u_buf;
4274 pu1_chrm_buf_u = (UWORD8 *)ps_recon_out_temp->pv_cb_buf;
4275 pu1_chrm_buf_v =
4276 pu1_chrm_buf_u +
4277 ((ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd >> 1) *
4278 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht);
4279
4280 for(j = 0; j < ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht;
4281 j++)
4282 {
4283 for(i = 0;
4284 i<ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd>> 1;
4285 i++)
4286 {
4287 *pu1_chrm_buf_u++ = *pu1_recon++;
4288 *pu1_chrm_buf_v++ = *pu1_recon++;
4289 }
4290
4291 pu1_recon -=
4292 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd;
4293 pu1_recon +=
4294 ps_frm_recon_temp->s_yuv_buf_desc.i4_uv_strd;
4295 }
4296
4297 /* set the POC and number of bytes in Y & UV buf */
4298 ps_recon_out_temp->i4_poc = ps_frm_recon_temp->i4_poc;
4299 ps_recon_out_temp->i4_y_pixels =
4300 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
4301 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
4302 ps_recon_out_temp->i4_uv_pixels =
4303 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd *
4304 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht;
4305 }
4306 }
4307 ps_frm_recon_temp->i4_non_ref_free_flag = 1;
4308 /* -------------------------------------------- */
4309 /* End of picture updates */
4310 /* -------------------------------------------- */
4311 }
4312
4313 /* After the MSE (or PSNR) computation is done we will update
4314 these data in output buffer structure and then signal entropy
4315 thread that the buffer is produced. */
4316 if(ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] == 1)
4317 {
4318 /* set the output buffer as produced */
4319 ihevce_q_set_buff_prod(
4320 (void *)ps_enc_ctxt,
4321 IHEVCE_FRM_PRS_ENT_COD_Q + i,
4322 ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i]);
4323
4324 ps_enc_ctxt->s_multi_thrd.is_out_buf_freed[i4_enc_frm_id][i] = 1;
4325 ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_enc_frm_id][i] = 0;
4326 }
4327
4328 } //bit-rate counter ends
4329 /* -------------------------------------------- */
4330 /* Frame level RC update */
4331 /* -------------------------------------------- */
4332 /* Query enc_loop to get the Parameters for Rate control */
4333 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
4334 {
4335 frm_proc_ent_cod_ctxt_t *ps_curr_out = NULL;
4336 /*HEVC_RC*/
4337 rc_bits_sad_t as_rc_frame_stat[IHEVCE_MAX_NUM_BITRATES];
4338 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4339
4340 for(i = 0; i < i4_num_bitrates; i++)
4341 {
4342 /*each bit-rate RC params are collated by master thread */
4343 ihevce_enc_loop_get_frame_rc_prms(
4344 ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt,
4345 &as_rc_frame_stat[i],
4346 i,
4347 i4_enc_frm_id);
4348
4349 /*update bits estimate on rd opt thread so that mismatch between rdopt and entropy can be taken care of*/
4350 ps_curr_out =
4351 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i];
4352
4353 ps_rc_lap_out_next_encode =
4354 (rc_lap_out_params_t *)
4355 ps_curr_inp->s_rc_lap_out.ps_rc_lap_out_next_encode;
4356
4357 ps_curr_out->i4_is_end_of_idr_gop = 0;
4358
4359 if(NULL != ps_rc_lap_out_next_encode)
4360 {
4361 if(ps_rc_lap_out_next_encode->i4_rc_pic_type == IV_IDR_FRAME)
4362 {
4363 /*If the next pic is IDR, then signal end of gopf for current frame*/
4364 ps_curr_out->i4_is_end_of_idr_gop = 1;
4365 }
4366 }
4367 else if(NULL == ps_rc_lap_out_next_encode)
4368 {
4369 /*If the lap out next is NULL, then end of sequence reached*/
4370 ps_curr_out->i4_is_end_of_idr_gop = 1;
4371 }
4372
4373 if(NULL == ps_curr_out)
4374 {
4375 DBG_PRINTF("error in getting curr out in encode loop\n");
4376 }
4377
4378 //DBG_PRINTF("\nRDOPT head = %d RDOPT text = %d\n",s_rc_frame_stat.u4_total_header_bits,s_rc_frame_stat.u4_total_texture_bits);
4379 /* acquire mutex lock for rate control calls */
4380
4381 /* Note : u4_total_intra_sad coming out of enc_loop */
4382 /* will not be accurate becos of intra gating */
4383 /* need to access the importance of this sad in RC */
4384
4385 //Store the rc update parameters for deterministic Enc loop parallelism
4386
4387 {
4388 ihevce_rc_store_retrive_update_info(
4389 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4390 &as_rc_frame_stat[i],
4391 i4_enc_frm_id_rc,
4392 i,
4393 1,
4394 &ps_enc_ctxt->s_multi_thrd.out_buf_id[i4_enc_frm_id][i],
4395 &ps_curr_inp->s_lap_out.i4_pic_type,
4396 &ai4_act_qp[i],
4397 (void *)&ps_curr_inp->s_lap_out,
4398 (void *)&ps_curr_inp->s_rc_lap_out); // STORE
4399 }
4400 }
4401
4402 /* release mutex lock after rate control calls */
4403 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4404 }
4405 if((ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0) /*&&
4406 (1 == ps_curr_inp->s_input_buf.s_input_buf.i4_inp_frm_data_valid_flag)*/)
4407 {
4408 WORD32 i4_bitrate_ctr;
4409 for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates;
4410 i4_bitrate_ctr++)
4411 {
4412 /*swaping of buf_id for 0th and reference bitrate location, as encoder
4413 assumes always 0th loc for reference bitrate and app must receive in
4414 the configured order*/
4415 WORD32 i4_recon_buf_id = i4_bitrate_ctr;
4416 if(i4_bitrate_ctr == 0)
4417 {
4418 i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
4419 }
4420 else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
4421 {
4422 i4_recon_buf_id = 0;
4423 }
4424
4425 /* Call back to Apln. saying recon buffer is produced */
4426 ps_hle_ctxt->ihevce_output_recon_fill_done(
4427 ps_hle_ctxt->pv_recon_cb_handle,
4428 ps_enc_ctxt->s_multi_thrd
4429 .ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr],
4430 i4_recon_buf_id, /* br instance */
4431 i4_resolution_id /* res_intance */);
4432
4433 /* --- release the current recon buffer ---- */
4434 ihevce_q_rel_buf(
4435 (void *)ps_enc_ctxt,
4436 (IHEVCE_RECON_DATA_Q + i4_recon_buf_id),
4437 ps_enc_ctxt->s_multi_thrd
4438 .recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr]);
4439
4440 ps_enc_ctxt->s_multi_thrd
4441 .is_recon_dumped[i4_enc_frm_id][i4_bitrate_ctr] = 1;
4442 }
4443 }
4444
4445 if(i4_enc_end_flag == 1)
4446 {
4447 if(ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] == 0)
4448 {
4449 /* release the pre_enc/enc queue buffer */
4450 ihevce_q_rel_buf(
4451 (void *)ps_enc_ctxt,
4452 IHEVCE_PRE_ENC_ME_Q,
4453 ps_curr_inp_enc->curr_inp_from_me_buf_id);
4454
4455 ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 1;
4456 }
4457 }
4458 /* release encoder owned input buffer*/
4459 ihevce_q_rel_buf(
4460 (void *)ps_enc_ctxt,
4461 IHEVCE_INPUT_DATA_CTRL_Q,
4462 ps_curr_inp_enc->curr_inp_buf_id);
4463 /* release the pre_enc/enc queue buffer */
4464 ihevce_q_rel_buf(
4465 ps_enc_ctxt,
4466 IHEVCE_PRE_ENC_ME_Q,
4467 ps_curr_inp_enc->curr_inp_from_me_buf_id);
4468
4469 ps_enc_ctxt->s_multi_thrd.is_in_buf_freed[i4_enc_frm_id] = 1;
4470
4471 /* release the pre_enc/enc queue buffer */
4472 ihevce_q_rel_buf(
4473 ps_enc_ctxt,
4474 IHEVCE_L0_IPE_ENC_Q,
4475 ps_curr_inp_enc->curr_inp_from_l0_ipe_buf_id);
4476
4477 ps_enc_ctxt->s_multi_thrd.is_L0_ipe_in_buf_freed[i4_enc_frm_id] = 1;
4478 /* release the me/enc queue buffer */
4479 ihevce_q_rel_buf(
4480 ps_enc_ctxt,
4481 IHEVCE_ME_ENC_RDOPT_Q,
4482 ps_enc_ctxt->s_multi_thrd.i4_enc_in_buf_id[i4_enc_frm_id]);
4483
4484 /* reset the pointers to NULL */
4485 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] = NULL;
4486 ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 0;
4487 for(i = 0; i < i4_num_bitrates; i++)
4488 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i] = NULL;
4489
4490 /* Set the prev_frame_done variable to 1 to indicate that
4491 *prev frame is done */
4492 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_done);
4493 }
4494 }
4495 }
4496 else
4497 {
4498 /* Increment the counter to keep track of no of threads exiting the current mutex*/
4499 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id]++;
4500 /*Last slave thread comming out of enc loop will execute next critical section*/
4501 if(ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] ==
4502 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds)
4503 {
4504 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_enc_frm_id] = 0;
4505
4506 /* reset the pointers to NULL */
4507 ps_enc_ctxt->s_multi_thrd.aps_cur_inp_enc_prms[i4_enc_frm_id] = NULL;
4508
4509 ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_enc_frm_id] = 0;
4510
4511 for(i = 0; i < i4_num_bitrates; i++)
4512 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_enc_frm_id][i] = NULL;
4513
4514 /* Set the prev_frame_done variable to 1 to indicate that
4515 *prev frame is done
4516 */
4517 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_done);
4518 }
4519 }
4520
4521 /* Toggle the ping pong flag of the thread exiting curr frame*/
4522 /*ps_enc_ctxt->s_multi_thrd.ping_pong[ps_thrd_ctxt->i4_thrd_id] =
4523 !ps_enc_ctxt->s_multi_thrd.ping_pong[ps_thrd_ctxt->i4_thrd_id];*/
4524 }
4525
4526 /************************************/
4527 /****** EXIT CRITICAL SECTION ******/
4528 /************************************/
4529 /****** Unlock the critical section ******/
4530 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4531 {
4532 result = osal_mutex_unlock(
4533 ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4534 if(OSAL_SUCCESS != result)
4535 return 0;
4536 }
4537
4538 if((0 == i4_me_end_flag) && (0 == i4_enc_end_flag))
4539 {
4540 i4_enc_frm_id++;
4541 i4_enc_frm_id_rc++;
4542
4543 if(i4_enc_frm_id == NUM_ME_ENC_BUFS)
4544 {
4545 i4_enc_frm_id = 0;
4546 }
4547
4548 if(i4_enc_frm_id_rc == ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc)
4549 {
4550 i4_enc_frm_id_rc = 0;
4551 }
4552 i4_me_frm_id++;
4553
4554 if(i4_me_frm_id == NUM_ME_ENC_BUFS)
4555 i4_me_frm_id = 0;
4556 }
4557 if(1 == ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
4558 {
4559 i4_me_end_flag = 1;
4560 i4_enc_end_flag = 1;
4561 }
4562 }
4563
4564 /****** Lock the critical section ******/
4565
4566 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4567 {
4568 WORD32 result;
4569
4570 result =
4571 osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4572
4573 if(OSAL_SUCCESS != result)
4574 return 0;
4575 }
4576
4577 if(ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4578 (ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds - 1))
4579 {
4580 if(1 != ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
4581 {
4582 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4583 for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4584 {
4585 ihevce_rc_close(
4586 ps_enc_ctxt,
4587 ps_enc_ctxt->i4_active_enc_frame_id,
4588 2,
4589 MIN(ps_enc_ctxt->ai4_rc_query[i], ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc),
4590 i);
4591 }
4592 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4593 }
4594 }
4595
4596 ps_enc_ctxt->s_multi_thrd.num_thrds_done++;
4597
4598 /****** UnLock the critical section ******/
4599 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4600 {
4601 WORD32 result;
4602
4603 result =
4604 osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4605
4606 if(OSAL_SUCCESS != result)
4607 return 0;
4608 }
4609
4610 /****** Lock the critical section ******/
4611 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4612 {
4613 WORD32 result;
4614 result =
4615 osal_mutex_lock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4616
4617 if(OSAL_SUCCESS != result)
4618 return 0;
4619 }
4620 if((ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4621 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) &&
4622 (ps_enc_ctxt->s_multi_thrd.i4_force_end_flag))
4623 {
4624 WORD32 num_bufs_preenc_me_que, num_bufs_L0_ipe_enc;
4625 WORD32 buf_id_ctr, frm_id_ctr;
4626 frm_proc_ent_cod_ctxt_t *ps_curr_out_enc_ent[IHEVCE_MAX_NUM_BITRATES];
4627 WORD32 out_buf_id_enc_ent[IHEVCE_MAX_NUM_BITRATES];
4628
4629 if(ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel > 1)
4630 {
4631 num_bufs_preenc_me_que = (MAX_L0_IPE_ENC_STAGGER - 1) + MIN_L1_L0_STAGGER_NON_SEQ +
4632 NUM_BUFS_DECOMP_HME +
4633 ps_enc_ctxt->ps_stat_prms->s_lap_prms.i4_rc_look_ahead_pics;
4634
4635 num_bufs_L0_ipe_enc = MAX_L0_IPE_ENC_STAGGER;
4636 }
4637 else
4638 {
4639 num_bufs_preenc_me_que = (MIN_L0_IPE_ENC_STAGGER - 1) + MIN_L1_L0_STAGGER_NON_SEQ +
4640 NUM_BUFS_DECOMP_HME +
4641 ps_enc_ctxt->ps_stat_prms->s_lap_prms.i4_rc_look_ahead_pics;
4642
4643 num_bufs_L0_ipe_enc = MIN_L0_IPE_ENC_STAGGER;
4644 }
4645 for(buf_id_ctr = 0; buf_id_ctr < num_bufs_preenc_me_que; buf_id_ctr++)
4646 {
4647 /* release encoder owned input buffer*/
4648 ihevce_q_rel_buf((void *)ps_enc_ctxt, IHEVCE_PRE_ENC_ME_Q, buf_id_ctr);
4649 }
4650 for(buf_id_ctr = 0; buf_id_ctr < num_bufs_L0_ipe_enc; buf_id_ctr++)
4651 {
4652 /* release encoder owned input buffer*/
4653 ihevce_q_rel_buf((void *)ps_enc_ctxt, IHEVCE_L0_IPE_ENC_Q, buf_id_ctr);
4654 }
4655 for(frm_id_ctr = 0; frm_id_ctr < NUM_ME_ENC_BUFS; frm_id_ctr++)
4656 {
4657 for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4658 {
4659 if(NULL != ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i])
4660 {
4661 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i]
4662 ->i4_frm_proc_valid_flag = 0;
4663 ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[frm_id_ctr][i]->i4_end_flag = 1;
4664 /* set the output buffer as produced */
4665 ihevce_q_set_buff_prod(
4666 (void *)ps_enc_ctxt,
4667 IHEVCE_FRM_PRS_ENT_COD_Q + i,
4668 ps_enc_ctxt->s_multi_thrd.out_buf_id[frm_id_ctr][i]);
4669 }
4670 }
4671 }
4672 for(buf_id_ctr = 0; buf_id_ctr < NUM_FRMPROC_ENTCOD_BUFS;
4673 buf_id_ctr++) /*** Set buffer produced for NUM_FRMPROC_ENTCOD_BUFS buffers for entropy to exit ***/
4674 {
4675 for(i = 0; i < ps_enc_ctxt->i4_num_bitrates; i++)
4676 {
4677 ps_curr_out_enc_ent[i] = (frm_proc_ent_cod_ctxt_t *)ihevce_q_get_free_buff(
4678 (void *)ps_enc_ctxt,
4679 IHEVCE_FRM_PRS_ENT_COD_Q + i, /*decides the buffer queue */
4680 &out_buf_id_enc_ent[i],
4681 BUFF_QUE_NON_BLOCKING_MODE);
4682 if(NULL != ps_curr_out_enc_ent[i])
4683 {
4684 ps_curr_out_enc_ent[i]->i4_frm_proc_valid_flag = 0;
4685 ps_curr_out_enc_ent[i]->i4_end_flag = 1;
4686 /* set the output buffer as produced */
4687 ihevce_q_set_buff_prod(
4688 (void *)ps_enc_ctxt, IHEVCE_FRM_PRS_ENT_COD_Q + i, out_buf_id_enc_ent[i]);
4689 }
4690 }
4691 }
4692 }
4693
4694 /* The last thread coming out of Enc. Proc. */
4695 /* Release all the Recon buffers the application might have queued in */
4696 if((ps_enc_ctxt->s_multi_thrd.num_thrds_done ==
4697 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) &&
4698 (ps_enc_ctxt->ps_stat_prms->i4_save_recon != 0) &&
4699 (ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done == 0))
4700 {
4701 WORD32 i4_bitrate_ctr;
4702
4703 for(i4_bitrate_ctr = 0; i4_bitrate_ctr < i4_num_bitrates; i4_bitrate_ctr++)
4704 {
4705 WORD32 end_flag = 0;
4706 while(0 == end_flag)
4707 {
4708 /*swaping of buf_id for 0th and reference bitrate location, as encoder
4709 assumes always 0th loc for reference bitrate and app must receive in
4710 the configured order*/
4711 WORD32 i4_recon_buf_id = i4_bitrate_ctr;
4712 if(i4_bitrate_ctr == 0)
4713 {
4714 i4_recon_buf_id = ps_enc_ctxt->i4_ref_mbr_id;
4715 }
4716 else if(i4_bitrate_ctr == ps_enc_ctxt->i4_ref_mbr_id)
4717 {
4718 i4_recon_buf_id = 0;
4719 }
4720
4721 /* ------- get free Recon buffer from Frame buffer que ---------- */
4722 /* There is a separate queue for each bit-rate instnace. The recon
4723 buffer is acquired from the corresponding queue based on the
4724 bitrate instnace */
4725 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr] =
4726 (iv_enc_recon_data_buffs_t *)ihevce_q_get_filled_buff(
4727 (void *)ps_enc_ctxt,
4728 IHEVCE_RECON_DATA_Q + i4_recon_buf_id, /*decides the buffer queue */
4729 &ps_enc_ctxt->s_multi_thrd.recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr],
4730 BUFF_QUE_BLOCKING_MODE);
4731
4732 /* Update the end_flag from application */
4733 end_flag = ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]
4734 ->i4_is_last_buf;
4735
4736 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_end_flag =
4737 1;
4738 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_y_pixels =
4739 0;
4740 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr]->i4_uv_pixels =
4741 0;
4742
4743 /* Call back to Apln. saying recon buffer is produced */
4744 ps_hle_ctxt->ihevce_output_recon_fill_done(
4745 ps_hle_ctxt->pv_recon_cb_handle,
4746 ps_enc_ctxt->s_multi_thrd.ps_recon_out[i4_enc_frm_id][i4_bitrate_ctr],
4747 i4_recon_buf_id, /* br instance */
4748 i4_resolution_id /* res_intance */);
4749
4750 /* --- release the current recon buffer ---- */
4751 ihevce_q_rel_buf(
4752 (void *)ps_enc_ctxt,
4753 (IHEVCE_RECON_DATA_Q + i4_recon_buf_id),
4754 ps_enc_ctxt->s_multi_thrd.recon_buf_id[i4_enc_frm_id][i4_bitrate_ctr]);
4755 }
4756 }
4757 /* Set the recon free done flag */
4758 ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done = 1;
4759 }
4760
4761 /****** UnLock the critical section ******/
4762 if(NULL != ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id])
4763 {
4764 WORD32 result;
4765 result =
4766 osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i4_enc_frm_id]);
4767
4768 if(OSAL_SUCCESS != result)
4769 return 0;
4770 }
4771
4772 return (0);
4773 }
4774
4775 /*!
4776 ******************************************************************************
4777 * \if Function name : ihevce_set_pre_enc_prms \endif
4778 *
4779 * \brief
4780 * Set CTB parameters
4781 * Set ME params
4782 * Set pps, sps, vps, vui params
4783 * Do RC init
4784 *
4785 * \param[in] Encoder context pointer
4786 *
4787 * \return
4788 * None
4789 *
4790 * \author
4791 * Ittiam
4792 *
4793 *****************************************************************************
4794 */
ihevce_set_pre_enc_prms(enc_ctxt_t * ps_enc_ctxt)4795 void ihevce_set_pre_enc_prms(enc_ctxt_t *ps_enc_ctxt)
4796 {
4797 WORD32 i;
4798 WORD32 i4_num_instance,
4799 i4_resolution_id = ps_enc_ctxt->i4_resolution_id; //number of bit-rate instances
4800
4801 i4_num_instance = ps_enc_ctxt->i4_num_bitrates;
4802
4803 #if PIC_ALIGN_CTB_SIZE
4804
4805 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd =
4806 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
4807 SET_CTB_ALIGN(
4808 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width,
4809 ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
4810
4811 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4812 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4813
4814 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht =
4815 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
4816 SET_CTB_ALIGN(
4817 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height,
4818 ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
4819
4820 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4821 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4822 #else // PIC_ALIGN_CTB_SIZE
4823 /* Allign the frame width to min CU size */
4824 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd =
4825 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
4826 SET_CTB_ALIGN(
4827 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width,
4828 ps_enc_ctxt->s_frm_ctb_prms.i4_min_cu_size);
4829
4830 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4831 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4832
4833 if((ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd %
4834 ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size) != 0)
4835 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz =
4836 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz + 1;
4837
4838 /* Allign the frame hieght to min CU size */
4839 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht =
4840 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
4841 SET_CTB_ALIGN(
4842 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height,
4843 ps_enc_ctxt->s_frm_ctb_prms.i4_min_cu_size);
4844
4845 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4846 ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht / ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size;
4847
4848 if((ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht %
4849 ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size) != 0)
4850 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert =
4851 ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert + 1;
4852
4853 #endif // PIC_ALIGN_CTB_SIZE
4854
4855 ps_enc_ctxt->s_frm_ctb_prms.i4_max_cus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4856 ps_enc_ctxt->s_frm_ctb_prms.i4_num_cus_in_ctb;
4857
4858 ps_enc_ctxt->s_frm_ctb_prms.i4_max_pus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4859 ps_enc_ctxt->s_frm_ctb_prms.i4_num_pus_in_ctb;
4860
4861 ps_enc_ctxt->s_frm_ctb_prms.i4_max_tus_in_row = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz *
4862 ps_enc_ctxt->s_frm_ctb_prms.i4_num_tus_in_ctb;
4863 ihevce_coarse_me_set_resolution(
4864 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
4865 1,
4866 &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd,
4867 &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht);
4868
4869 /*if Resolution need to be changed dynamically then needs to go to encode group */
4870 ihevce_me_set_resolution(
4871 ps_enc_ctxt->s_module_ctxt.pv_me_ctxt,
4872 1,
4873 &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd,
4874 &ps_enc_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht);
4875 i4_num_instance = ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id]
4876 .i4_num_bitrate_instances;
4877 for(i = 0; i < i4_num_instance; i++)
4878 {
4879 WORD32 i4_id;
4880 /*swaping of buf_id for 0th and reference bitrate location, as encoder
4881 assumes always 0th loc for reference bitrate and app must receive in
4882 the configured order*/
4883 if(i == 0)
4884 {
4885 i4_id = ps_enc_ctxt->i4_ref_mbr_id;
4886 }
4887 else if(i == ps_enc_ctxt->i4_ref_mbr_id)
4888 {
4889 i4_id = 0;
4890 }
4891 else
4892 {
4893 i4_id = i;
4894 }
4895 /* populate vps based on encoder configuration and tools */
4896 ihevce_populate_vps(
4897 ps_enc_ctxt,
4898 &ps_enc_ctxt->as_vps[i],
4899 &ps_enc_ctxt->s_runtime_src_prms,
4900 &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4901 &ps_enc_ctxt->s_runtime_coding_prms,
4902 &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4903 ps_enc_ctxt->ps_stat_prms,
4904 i4_resolution_id);
4905
4906 /* populate sps based on encoder configuration and tools */
4907 ihevce_populate_sps(
4908 ps_enc_ctxt,
4909 &ps_enc_ctxt->as_sps[i],
4910 &ps_enc_ctxt->as_vps[i],
4911 &ps_enc_ctxt->s_runtime_src_prms,
4912 &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4913 &ps_enc_ctxt->s_runtime_coding_prms,
4914 &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4915 &ps_enc_ctxt->s_frm_ctb_prms,
4916 ps_enc_ctxt->ps_stat_prms,
4917 i4_resolution_id);
4918
4919 /* populate pps based on encoder configuration and tools */
4920 ihevce_populate_pps(
4921 &ps_enc_ctxt->as_pps[i],
4922 &ps_enc_ctxt->as_sps[i],
4923 &ps_enc_ctxt->s_runtime_src_prms,
4924 &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms,
4925 &ps_enc_ctxt->s_runtime_coding_prms,
4926 &ps_enc_ctxt->ps_stat_prms->s_config_prms,
4927 ps_enc_ctxt->ps_stat_prms,
4928 i4_id,
4929 i4_resolution_id,
4930 ps_enc_ctxt->ps_tile_params_base,
4931 &ps_enc_ctxt->ai4_column_width_array[0],
4932 &ps_enc_ctxt->ai4_row_height_array[0]);
4933
4934 // if(ps_enc_ctxt->as_sps[i].i1_vui_parameters_present_flag == 1)
4935 {
4936 ihevce_populate_vui(
4937 &ps_enc_ctxt->as_sps[i].s_vui_parameters,
4938 &ps_enc_ctxt->as_sps[i],
4939 &ps_enc_ctxt->s_runtime_src_prms,
4940 &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms,
4941 i4_resolution_id,
4942 &ps_enc_ctxt->s_runtime_tgt_params,
4943 ps_enc_ctxt->ps_stat_prms,
4944 i4_id);
4945 }
4946 }
4947
4948 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4949 /* run the loop over all bit-rate instnaces */
4950 for(i = 0; i < i4_num_instance; i++)
4951 {
4952 /*HEVC_RC Do one time initialization of rate control*/
4953 ihevce_rc_init(
4954 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4955 &ps_enc_ctxt->s_runtime_src_prms,
4956 &ps_enc_ctxt->s_runtime_tgt_params,
4957 &ps_enc_ctxt->s_rc_quant,
4958 &ps_enc_ctxt->ps_stat_prms->s_sys_api,
4959 &ps_enc_ctxt->ps_stat_prms->s_lap_prms,
4960 ps_enc_ctxt->i4_max_fr_enc_loop_parallel_rc);
4961
4962 ihevce_vbv_complaince_init_level(
4963 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[i],
4964 &ps_enc_ctxt->as_sps[i].s_vui_parameters);
4965 }
4966 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
4967 }
4968
4969 /*!
4970 ******************************************************************************
4971 * \if Function name : ihevce_pre_enc_init \endif
4972 *
4973 * \brief
4974 * set out_buf params
4975 * Calculate end_flag if flushmode on
4976 * Slice initialization
4977 * Populate SIE params
4978 * reference list creation
4979 *
4980 * \param[in] Encoder context pointer
4981 *
4982 * \return
4983 * None
4984 *
4985 * \author
4986 * Ittiam
4987 *
4988 *****************************************************************************
4989 */
ihevce_pre_enc_init(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,pre_enc_me_ctxt_t * ps_curr_out,WORD32 * pi4_end_flag_ret,WORD32 * pi4_cur_qp_ret,WORD32 * pi4_decomp_lyr_idx,WORD32 i4_ping_pong)4990 void ihevce_pre_enc_init(
4991 enc_ctxt_t *ps_enc_ctxt,
4992 ihevce_lap_enc_buf_t *ps_curr_inp,
4993 pre_enc_me_ctxt_t *ps_curr_out,
4994 WORD32 *pi4_end_flag_ret,
4995 WORD32 *pi4_cur_qp_ret,
4996 WORD32 *pi4_decomp_lyr_idx,
4997 WORD32 i4_ping_pong)
4998 {
4999 WORD32 end_flag = 0;
5000 WORD32 cur_qp;
5001 //recon_pic_buf_t *ps_frm_recon;
5002 WORD32 first_field = 1;
5003 WORD32 i4_field_pic = ps_enc_ctxt->s_runtime_src_prms.i4_field_pic;
5004 WORD32 i4_decomp_lyrs_idx = 0;
5005 WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
5006 WORD32 slice_type = ISLICE;
5007 WORD32 nal_type;
5008 WORD32 min_cu_size;
5009
5010 WORD32 stasino_enabled;
5011
5012 /* copy the time stamps from inp to entropy inp */
5013 ps_curr_out->i4_inp_timestamp_low = ps_curr_inp->s_input_buf.i4_inp_timestamp_low;
5014 ps_curr_out->i4_inp_timestamp_high = ps_curr_inp->s_input_buf.i4_inp_timestamp_high;
5015 ps_curr_out->pv_app_frm_ctxt = ps_curr_inp->s_input_buf.pv_app_frm_ctxt;
5016
5017 /* get the min cu size from config params */
5018 min_cu_size = ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_min_log2_cu_size;
5019
5020 min_cu_size = 1 << min_cu_size;
5021
5022 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd =
5023 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd +
5024 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd, min_cu_size);
5025
5026 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht =
5027 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht +
5028 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht, min_cu_size);
5029
5030 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd =
5031 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd +
5032 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_wd, min_cu_size);
5033
5034 if(IV_YUV_420SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5035 {
5036 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5037 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5038 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, (min_cu_size >> 1));
5039 }
5040 else if(IV_YUV_422SP_UV == ps_enc_ctxt->ps_stat_prms->s_src_prms.i4_chr_format)
5041 {
5042 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht =
5043 ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht +
5044 SET_CTB_ALIGN(ps_curr_inp->s_lap_out.s_input_buf.i4_uv_ht, min_cu_size);
5045 }
5046
5047 /* update the END flag from LAP out */
5048 end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
5049 ps_curr_out->i4_end_flag = end_flag;
5050 ps_enc_ctxt->s_multi_thrd.i4_last_pic_flag = end_flag;
5051
5052 /* ----------------------------------------------------------------------*/
5053 /* Slice initialization for current frame; Required for entropy context */
5054 /* ----------------------------------------------------------------------*/
5055 {
5056 WORD32 cur_poc = ps_curr_inp->s_lap_out.i4_poc;
5057
5058 /* max merge candidates derived based on quality preset for now */
5059 WORD32 max_merge_candidates = 2;
5060
5061 /* pocs less than random acess poc tagged for discard as they */
5062 /* could be refering to pics before the cra. */
5063
5064 /* CRA case: as the leading pictures can refer the picture precedes the associated
5065 IRAP(CRA) in decoding order, hence make it Random access skipped leading pictures (RASL)*/
5066
5067 if((1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability) &&
5068 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5069 ps_curr_inp->s_lap_out.i4_temporal_lyr_id)) //TEMPORALA_SCALABILITY CHANGES
5070 {
5071 if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5072 {
5073 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5074 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RASL_R : NAL_RASL_N)
5075 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5076 }
5077 /* IDR case: as the leading pictures can't refer the picture precedes the associated
5078 IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5079 else
5080 {
5081 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5082 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5083 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TSA_R : NAL_TSA_N);
5084 }
5085 }
5086 else
5087 {
5088 if(ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5089 {
5090 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5091 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RASL_R : NAL_RASL_N)
5092 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5093 }
5094 /* IDR case: as the leading pictures can't refer the picture precedes the associated
5095 IRAP(IDR) in decoding order, hence make it Random access decodable leading pictures (RADL)*/
5096 else
5097 {
5098 nal_type = (cur_poc < ps_curr_inp->s_lap_out.i4_assoc_IRAP_poc)
5099 ? (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_RADL_R : NAL_RADL_N)
5100 : (ps_curr_inp->s_lap_out.i4_is_ref_pic ? NAL_TRAIL_R : NAL_TRAIL_N);
5101 }
5102 }
5103
5104 switch(ps_curr_inp->s_lap_out.i4_pic_type)
5105 {
5106 case IV_IDR_FRAME:
5107 /* IDR pic */
5108 slice_type = ISLICE;
5109 nal_type = NAL_IDR_W_LP;
5110 cur_poc = 0;
5111 ps_enc_ctxt->i4_cra_poc = cur_poc;
5112 break;
5113
5114 case IV_I_FRAME:
5115 slice_type = ISLICE;
5116
5117 if(ps_curr_inp->s_lap_out.i4_is_cra_pic)
5118 {
5119 nal_type = NAL_CRA;
5120 }
5121
5122 ps_enc_ctxt->i4_cra_poc = cur_poc;
5123 break;
5124
5125 case IV_P_FRAME:
5126 slice_type = PSLICE;
5127 break;
5128
5129 case IV_B_FRAME:
5130 /* TODO : Mark the nal type as NAL_TRAIL_N for non ref pics */
5131 slice_type = BSLICE;
5132 break;
5133
5134 default:
5135 /* This should never occur */
5136 ASSERT(0);
5137 }
5138
5139 /* number of merge candidates and error metric chosen based on quality preset */
5140 switch(ps_curr_inp->s_lap_out.i4_quality_preset)
5141 {
5142 case IHEVCE_QUALITY_P0:
5143 max_merge_candidates = 5;
5144 break;
5145
5146 case IHEVCE_QUALITY_P2:
5147 max_merge_candidates = 5;
5148 break;
5149
5150 case IHEVCE_QUALITY_P3:
5151 max_merge_candidates = 3;
5152 break;
5153
5154 case IHEVCE_QUALITY_P4:
5155 case IHEVCE_QUALITY_P5:
5156 case IHEVCE_QUALITY_P6:
5157 max_merge_candidates = 2;
5158 break;
5159
5160 default:
5161 ASSERT(0);
5162 }
5163
5164 /* acquire mutex lock for rate control calls */
5165 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5166 {
5167 ps_curr_inp->s_rc_lap_out.i4_num_pels_in_frame_considered =
5168 ps_curr_inp->s_lap_out.s_input_buf.i4_y_ht *
5169 ps_curr_inp->s_lap_out.s_input_buf.i4_y_wd;
5170
5171 /*initialize the frame info stat inside LAP out, Data inside this will be populated in ihevce_rc_get_bpp_based_frame_qp call*/
5172 ps_curr_inp->s_rc_lap_out.ps_frame_info = &ps_curr_inp->s_frame_info;
5173
5174 ps_curr_inp->s_rc_lap_out.i4_is_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5175 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode == 3)
5176 {
5177 /*for constant qp use same qp*/
5178 /*HEVC_RC query rate control for qp*/
5179 cur_qp = ihevce_rc_pre_enc_qp_query(
5180 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
5181 &ps_curr_inp->s_rc_lap_out,
5182 0);
5183 }
5184 else
5185 {
5186 cur_qp = ihevce_rc_get_bpp_based_frame_qp(
5187 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0], &ps_curr_inp->s_rc_lap_out);
5188 }
5189 }
5190 /* release mutex lock after rate control calls */
5191 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
5192
5193 /* store the QP in output prms */
5194 /* The same qp is also used in enc thread only for ME*/
5195 ps_curr_out->i4_curr_frm_qp = cur_qp;
5196
5197 /* slice header entropy syn memory is not valid in pre encode stage */
5198 ps_curr_out->s_slice_hdr.pu4_entry_point_offset = NULL;
5199
5200 /* derive the flag which indicates if stasino is enabled */
5201 stasino_enabled = (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5202 (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION)) &&
5203 (ps_enc_ctxt->s_runtime_coding_prms.i4_vqet &
5204 (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER));
5205
5206 /* initialize the slice header */
5207 ihevce_populate_slice_header(
5208 &ps_curr_out->s_slice_hdr,
5209 &ps_enc_ctxt->as_pps[0],
5210 &ps_enc_ctxt->as_sps[0],
5211 nal_type,
5212 slice_type,
5213 0,
5214 0,
5215 ps_curr_inp->s_lap_out.i4_poc,
5216 cur_qp,
5217 max_merge_candidates,
5218 ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass,
5219 ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id]
5220 .i4_quality_preset,
5221 stasino_enabled);
5222
5223 ps_curr_out->i4_slice_nal_type = nal_type;
5224
5225 ps_curr_out->s_slice_hdr.u4_nuh_temporal_id = 0;
5226
5227 if(1 == ps_enc_ctxt->ps_stat_prms->s_tgt_lyr_prms.i4_enable_temporal_scalability)
5228 {
5229 ps_curr_out->s_slice_hdr.u4_nuh_temporal_id =
5230 (ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_max_temporal_layers ==
5231 ps_curr_inp->s_lap_out.i4_temporal_lyr_id); //TEMPORALA_SCALABILITY CHANGES
5232 }
5233
5234 /* populate sps, vps and pps pointers for the entropy input params */
5235 ps_curr_out->ps_pps = &ps_enc_ctxt->as_pps[0];
5236 ps_curr_out->ps_sps = &ps_enc_ctxt->as_sps[0];
5237 ps_curr_out->ps_vps = &ps_enc_ctxt->as_vps[0];
5238 }
5239
5240 /* By default, Sei messages are set to 0, to avoid unintialised memory access */
5241 memset(&ps_curr_out->s_sei, 0, sizeof(sei_params_t));
5242
5243 /* VUI, SEI flags reset */
5244 ps_curr_out->s_sei.i1_sei_parameters_present_flag = 0;
5245 ps_curr_out->s_sei.i1_buf_period_params_present_flag = 0;
5246 ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 0;
5247 ps_curr_out->s_sei.i1_recovery_point_params_present_flag = 0;
5248 ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag = 0;
5249 ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags = 0;
5250
5251 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_enable_flag == 1)
5252 {
5253 /* insert buffering period, display volume, recovery point only at irap points */
5254 WORD32 insert_per_irap =
5255 ((slice_type == ISLICE) &&
5256 (((NAL_IDR_N_LP == nal_type) || (NAL_CRA == nal_type)) || (NAL_IDR_W_LP == nal_type)));
5257
5258 ps_curr_out->s_sei.i1_sei_parameters_present_flag = 1;
5259
5260 /* populate Sei buffering period based on encoder configuration and tools */
5261 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_buffer_period_flags == 1)
5262 {
5263 ihevce_populate_buffering_period_sei(
5264 &ps_curr_out->s_sei,
5265 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5266 &ps_enc_ctxt->as_sps[0],
5267 &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5268
5269 ps_curr_out->s_sei.i1_buf_period_params_present_flag = insert_per_irap;
5270
5271 ihevce_populate_active_parameter_set_sei(
5272 &ps_curr_out->s_sei, &ps_enc_ctxt->as_vps[0], &ps_enc_ctxt->as_sps[0]);
5273 }
5274
5275 /* populate Sei picture timing based on encoder configuration and tools */
5276 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_pic_timing_flags == 1)
5277 {
5278 ihevce_populate_picture_timing_sei(
5279 &ps_curr_out->s_sei,
5280 &ps_enc_ctxt->as_sps[0].s_vui_parameters,
5281 &ps_enc_ctxt->s_runtime_src_prms,
5282 ps_curr_inp->s_input_buf.i4_bottom_field);
5283 ps_curr_out->s_sei.i1_pic_timing_params_present_flag = 1;
5284 }
5285
5286 /* populate Sei recovery point based on encoder configuration and tools */
5287 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_recovery_point_flags == 1)
5288 {
5289 ihevce_populate_recovery_point_sei(
5290 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_vui_sei_prms);
5291 ps_curr_out->s_sei.i1_recovery_point_params_present_flag = insert_per_irap;
5292 }
5293
5294 /* populate mastering_display_colour_volume parameters */
5295 if(ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_sei_mastering_disp_colour_vol_flags == 1)
5296 {
5297 ihevce_populate_mastering_disp_col_vol_sei(
5298 &ps_curr_out->s_sei, &ps_enc_ctxt->ps_stat_prms->s_out_strm_prms);
5299
5300 ps_curr_out->s_sei.i4_sei_mastering_disp_colour_vol_params_present_flags =
5301 insert_per_irap;
5302 }
5303
5304 /* populate SEI Hash Flag based on encoder configuration */
5305 if(0 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag)
5306 {
5307 /* Sanity checks */
5308 ASSERT(0 != ps_enc_ctxt->as_sps[0].i1_chroma_format_idc);
5309
5310 ASSERT(
5311 (0 < ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag) &&
5312 (4 > ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag));
5313
5314 /* MD5 is not supported now! picture_md5[cIdx][i] pblm */
5315 ASSERT(1 != ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag);
5316
5317 ps_curr_out->s_sei.i1_decoded_pic_hash_sei_flag =
5318 ps_enc_ctxt->ps_stat_prms->s_out_strm_prms.i4_decoded_pic_hash_sei_flag;
5319 }
5320 }
5321
5322 /* For interlace pictures, first_field depends on topfield_first and bottom field */
5323 if(i4_field_pic)
5324 {
5325 first_field =
5326 (ps_curr_inp->s_input_buf.i4_topfield_first ^ ps_curr_inp->s_input_buf.i4_bottom_field);
5327 }
5328
5329 /* get frame level lambda params */
5330 ihevce_get_frame_lambda_prms(
5331 ps_enc_ctxt,
5332 ps_curr_out,
5333 cur_qp,
5334 first_field,
5335 ps_curr_inp->s_lap_out.i4_is_ref_pic,
5336 ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
5337 lamda_modifier_for_I_pic[4] /*mean TRF*/,
5338 0,
5339 PRE_ENC_LAMBDA_TYPE);
5340 /* Coarse ME and Decomp buffers sharing */
5341 {
5342 UWORD8 *apu1_lyr_bufs[MAX_NUM_HME_LAYERS];
5343 WORD32 ai4_lyr_buf_strd[MAX_NUM_HME_LAYERS];
5344
5345 /* get the Decomposition frame buffer from ME */
5346 i4_decomp_lyrs_idx = ihevce_coarse_me_get_lyr_buf_desc(
5347 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt, &apu1_lyr_bufs[0], &ai4_lyr_buf_strd[0]);
5348 /* register the buffers with decomp module along with frame init */
5349 ihevce_decomp_pre_intra_frame_init(
5350 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5351 &apu1_lyr_bufs[0],
5352 &ai4_lyr_buf_strd[0],
5353 ps_curr_out->ps_layer1_buf,
5354 ps_curr_out->ps_layer2_buf,
5355 ps_curr_out->ps_ed_ctb_l1,
5356 ps_curr_out->as_lambda_prms[0].i4_ol_sad_lambda_qf,
5357 ps_curr_out->s_slice_hdr.i1_slice_type,
5358 ps_curr_out->ps_ctb_analyse);
5359 }
5360
5361 /* -------------------------------------------------------- */
5362 /* Preparing Pre encode Passes Job Queue */
5363 /* -------------------------------------------------------- */
5364 ihevce_prepare_pre_enc_job_queue(ps_enc_ctxt, ps_curr_inp, i4_ping_pong);
5365
5366 /*assign return variables */
5367 *pi4_end_flag_ret = end_flag;
5368 *pi4_cur_qp_ret = cur_qp;
5369 *pi4_decomp_lyr_idx = i4_decomp_lyrs_idx;
5370 //*pps_frm_recon_ret = ps_frm_recon;
5371 }
5372
5373 /*!
5374 ******************************************************************************
5375 * \if Function name : ihevce_pre_enc_process_frame \endif
5376 *
5377 * \brief
5378 * Frame processing main function
5379 *
5380 * \param[in] Encoder context pointer
5381 * \param[in] Current input buffer params pointer
5382 * \param[out] Current output buffer params pointer
5383 * \param[in] Current frame QP
5384 *
5385 * \return
5386 * None
5387 *
5388 * \author
5389 * Ittiam
5390 *
5391 *****************************************************************************
5392 */
ihevce_pre_enc_process_frame(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,pre_enc_me_ctxt_t * ps_curr_out,WORD32 i4_cur_frame_qp,WORD32 i4_thrd_id,WORD32 i4_ping_pong)5393 void ihevce_pre_enc_process_frame(
5394 enc_ctxt_t *ps_enc_ctxt,
5395 ihevce_lap_enc_buf_t *ps_curr_inp,
5396 pre_enc_me_ctxt_t *ps_curr_out,
5397 WORD32 i4_cur_frame_qp,
5398 WORD32 i4_thrd_id,
5399 WORD32 i4_ping_pong)
5400 {
5401 if(1 == ps_curr_out->i4_frm_proc_valid_flag)
5402 {
5403 /* ------------------------------------------------------------ */
5404 /* Layer Decomp and Intra 4x4 Analysis */
5405 /* ------------------------------------------------------------ */
5406 ihevce_decomp_pre_intra_process(
5407 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5408 &ps_curr_inp->s_lap_out,
5409 &ps_enc_ctxt->s_frm_ctb_prms,
5410 &ps_enc_ctxt->s_multi_thrd,
5411 i4_thrd_id,
5412 i4_ping_pong,
5413 ps_curr_out->ps_layer0_cur_satd,
5414 ps_curr_out->ps_layer0_cur_mean);
5415
5416 /* ------------------------------------------------------------ */
5417 /* Coarse Motion estimation and early intra-inter decision */
5418 /* ------------------------------------------------------------ */
5419 ihevce_coarse_me_process(
5420 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5421 ps_curr_inp,
5422 &ps_enc_ctxt->s_multi_thrd,
5423 i4_thrd_id,
5424 i4_ping_pong);
5425
5426 /* ------------------------------------------------------------ */
5427 /* Update qp used in based in L1 satd/act in case of scene cut */
5428 /* ------------------------------------------------------------ */
5429 //ihevce_update_qp_L1_sad_based(ps_enc_ctxt,ps_curr_inp,ps_curr_out);
5430
5431 /* Calculate the average activity values from the previous frame and
5432 these would be used by the current frame*/
5433 /*ihevce_decomp_pre_intra_curr_frame_pre_intra_deinit(
5434 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
5435 ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
5436 i4_thrd_id);*/
5437 }
5438 }
5439
5440 /*!
5441 ******************************************************************************
5442 * \if Function name : ihevce_pre_enc_coarse_me_init \endif
5443 *
5444 * \brief
5445 * set out_buf params
5446 * Calculate end_flag if flushmode on
5447 * Slice initialization
5448 * Populate SIE params
5449 * reference list creation
5450 *
5451 * \param[in] Encoder context pointer
5452 *
5453 * \return
5454 * None
5455 *
5456 * \author
5457 * Ittiam
5458 *
5459 *****************************************************************************
5460 */
ihevce_pre_enc_coarse_me_init(enc_ctxt_t * ps_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,pre_enc_me_ctxt_t * ps_curr_out,recon_pic_buf_t ** pps_frm_recon_ret,WORD32 i4_decomp_lyrs_idx,WORD32 i4_cur_qp,WORD32 i4_ping_pong)5461 void ihevce_pre_enc_coarse_me_init(
5462 enc_ctxt_t *ps_enc_ctxt,
5463 ihevce_lap_enc_buf_t *ps_curr_inp,
5464 pre_enc_me_ctxt_t *ps_curr_out,
5465 recon_pic_buf_t **pps_frm_recon_ret,
5466 WORD32 i4_decomp_lyrs_idx,
5467 WORD32 i4_cur_qp,
5468 WORD32 i4_ping_pong)
5469
5470 {
5471 /* local variables */
5472 recon_pic_buf_t *ps_frm_recon;
5473 coarse_me_master_ctxt_t *ps_ctxt = NULL;
5474 ps_ctxt = (coarse_me_master_ctxt_t *)ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt;
5475 /* Reference buffer management and reference list creation for pre enc group */
5476 ihevce_pre_enc_manage_ref_pics(ps_enc_ctxt, ps_curr_inp, ps_curr_out, i4_ping_pong);
5477
5478 /* get a free recon buffer for current picture */
5479 {
5480 WORD32 ctr;
5481
5482 ps_frm_recon = NULL;
5483 for(ctr = 0; ctr < ps_enc_ctxt->i4_pre_enc_num_buf_recon_q; ctr++)
5484 {
5485 if(1 == ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr]->i4_is_free)
5486 {
5487 ps_frm_recon = ps_enc_ctxt->pps_pre_enc_recon_buf_q[ctr];
5488 break;
5489 }
5490 }
5491 }
5492 /* should not be NULL */
5493 ASSERT(ps_frm_recon != NULL);
5494
5495 /* populate reference /recon params based on LAP output */
5496 ps_frm_recon->i4_is_free = 0;
5497 /* top first field is set to 1 by application */
5498 ps_frm_recon->i4_topfield_first = ps_curr_inp->s_input_buf.i4_topfield_first;
5499 ps_frm_recon->i4_poc = ps_curr_inp->s_lap_out.i4_poc;
5500 ps_frm_recon->i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
5501 ps_frm_recon->i4_display_num = ps_curr_inp->s_lap_out.i4_display_num;
5502 /* bottom field is toggled for every field by application */
5503 ps_frm_recon->i4_bottom_field = ps_curr_inp->s_input_buf.i4_bottom_field;
5504
5505 /* Reference picture property is given by LAP */
5506 ps_frm_recon->i4_is_reference = ps_curr_inp->s_lap_out.i4_is_ref_pic;
5507
5508 /* Deblock a picture for all reference frames unconditionally. */
5509 /* Deblock non ref if psnr compute or save recon is enabled */
5510 ps_frm_recon->i4_deblk_pad_hpel_cur_pic = ps_frm_recon->i4_is_reference ||
5511 (ps_enc_ctxt->ps_stat_prms->i4_save_recon);
5512
5513 /* set the width, height and stride to defalut values */
5514 ps_frm_recon->s_yuv_buf_desc.i4_y_ht = 0;
5515 ps_frm_recon->s_yuv_buf_desc.i4_uv_ht = 0;
5516 ps_frm_recon->s_yuv_buf_desc.i4_y_wd = 0;
5517 ps_frm_recon->s_yuv_buf_desc.i4_uv_wd = 0;
5518 ps_frm_recon->s_yuv_buf_desc.i4_y_strd = 0;
5519 ps_frm_recon->s_yuv_buf_desc.i4_uv_strd = 0;
5520
5521 /* register the Layer1 MV bank pointer with ME module */
5522 ihevce_coarse_me_set_lyr1_mv_bank(
5523 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5524 ps_curr_inp,
5525 ps_curr_out->pv_me_mv_bank,
5526 ps_curr_out->pv_me_ref_idx,
5527 i4_decomp_lyrs_idx);
5528
5529 /* Coarse picture level init of ME */
5530 ihevce_coarse_me_frame_init(
5531 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
5532 ps_enc_ctxt->ps_stat_prms,
5533 &ps_enc_ctxt->s_frm_ctb_prms,
5534 &ps_curr_out->as_lambda_prms[0],
5535 ps_enc_ctxt->i4_pre_enc_num_ref_l0,
5536 ps_enc_ctxt->i4_pre_enc_num_ref_l1,
5537 ps_enc_ctxt->i4_pre_enc_num_ref_l0_active,
5538 ps_enc_ctxt->i4_pre_enc_num_ref_l1_active,
5539 &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_0][0],
5540 &ps_enc_ctxt->aps_pre_enc_ref_lists[i4_ping_pong][LIST_1][0],
5541 ps_curr_inp,
5542 i4_cur_qp,
5543 ps_curr_out->ps_layer1_buf,
5544 ps_curr_out->ps_ed_ctb_l1,
5545 ps_curr_out->pu1_me_reverse_map_info,
5546 ps_curr_inp->s_lap_out.i4_temporal_lyr_id);
5547
5548 /*assign return variables */
5549 *pps_frm_recon_ret = ps_frm_recon;
5550 }
5551
5552 #define MAX_64BIT_VAL 0x7fffffffffffffff
5553
5554 /*!
5555 ******************************************************************************
5556 * \if Function name : ihevce_variance_calc_acc_activity \endif
5557 *
5558 * \brief
5559 * Function to calculate modulation based on spatial variance across lap period
5560 *
5561 * \param[in] pv_ctxt : pointer to IPE module
5562 *
5563 * \return
5564 * None
5565 *
5566 * \author
5567 * Ittiam
5568 *
5569 *****************************************************************************
5570 */
ihevce_variance_calc_acc_activity(enc_ctxt_t * ps_enc_ctxt,WORD32 i4_cur_ipe_idx)5571 void ihevce_variance_calc_acc_activity(enc_ctxt_t *ps_enc_ctxt, WORD32 i4_cur_ipe_idx)
5572 {
5573 WORD32 j, i4_k;
5574 WORD32 i = 0;
5575 WORD32 is_i_frame =
5576 ((ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_pic_type ==
5577 IV_I_FRAME) ||
5578 (ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_pic_type ==
5579 IV_IDR_FRAME));
5580
5581 WORD32 is_p_frame =
5582 (ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_pic_type ==
5583 IV_P_FRAME);
5584
5585 WORD32 i4_delay_loop = (ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe + 1);
5586 pre_enc_me_ctxt_t *ps_pre_enc_me_ctxt_t;
5587 pre_enc_me_ctxt_t *ps_curr_out = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx];
5588 rc_lap_out_params_t *ps_temp_ipe_rc_lap_out;
5589 UWORD8 is_no_scene_change = 1;
5590 WORD32 loop_lap2, i4_pass_num;
5591 UWORD32 u4_scene_num;
5592 i4_pass_num = ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass;
5593 ps_temp_ipe_rc_lap_out =
5594 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out;
5595 ps_curr_out->i8_acc_frame_8x8_sum_act_sqr = 0;
5596 ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength = 0;
5597 for(i4_k = 0; i4_k < 2; i4_k++)
5598 {
5599 ps_curr_out->i8_acc_frame_8x8_sum_act[i4_k] = 0;
5600 ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k] = 0;
5601
5602 ps_curr_out->i8_acc_frame_16x16_sum_act[i4_k] = 0;
5603 ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k] = 0;
5604
5605 ps_curr_out->i8_acc_frame_32x32_sum_act[i4_k] = 0;
5606 ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k] = 0;
5607 }
5608 ps_curr_out->i8_acc_frame_16x16_sum_act[i4_k] = 0;
5609 ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k] = 0;
5610
5611 ps_curr_out->i8_acc_frame_32x32_sum_act[i4_k] = 0;
5612 ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k] = 0;
5613
5614 u4_scene_num =
5615 ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.u4_scene_num;
5616
5617 //ps_curr_out->i4_acc_frame_median_sum_act = 0;
5618
5619 #if MODULATION_OVER_LAP
5620 if(ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe - 1 <= 0)
5621 loop_lap2 = 1;
5622 else
5623 loop_lap2 = ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe - 1;
5624 #else
5625 loop_lap2 = 1;
5626 #endif
5627
5628 if(ps_temp_ipe_rc_lap_out->ps_rc_lap_out_next_encode == NULL ||
5629 ps_temp_ipe_rc_lap_out->i4_is_non_I_scd)
5630 {
5631 is_no_scene_change = 0;
5632 }
5633
5634 /*Loop over complete lap2 struct ad make sure no scene change occurs in the lap2 frmaes */
5635 for(i = 1; i < loop_lap2; i++)
5636 {
5637 WORD32 i4_temp_ipe_idx = (i4_cur_ipe_idx + i) % i4_delay_loop;
5638 if(0 == is_no_scene_change)
5639 {
5640 loop_lap2 = i;
5641 break;
5642 }
5643 ps_temp_ipe_rc_lap_out =
5644 &ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_temp_ipe_idx]->s_rc_lap_out;
5645
5646 /*check if the current frame scene num is same as previous frame scene num */
5647 is_no_scene_change = (u4_scene_num == ps_temp_ipe_rc_lap_out->u4_rc_scene_num);
5648
5649 if(ps_temp_ipe_rc_lap_out->ps_rc_lap_out_next_encode == NULL ||
5650 ps_temp_ipe_rc_lap_out->i4_is_non_I_scd)
5651 {
5652 is_no_scene_change = 0;
5653 loop_lap2 = i;
5654 break;
5655 }
5656 }
5657
5658 /*Only if there is no scene change then process the lap2 for modulation index calcuation */
5659 if(((1 == is_i_frame) || (1 == is_p_frame)) &&
5660 (1 == is_no_scene_change || (ps_enc_ctxt->i4_active_scene_num != (WORD32)u4_scene_num)))
5661 {
5662 //do
5663 ps_enc_ctxt->i4_active_scene_num = u4_scene_num;
5664 for(i = 0; i < loop_lap2; i++)
5665 {
5666 WORD32 i4_temp_ipe_idx = (i4_cur_ipe_idx + i) % i4_delay_loop;
5667 UWORD8 i_frame =
5668 ((ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_temp_ipe_idx]
5669 ->s_lap_out.i4_pic_type == IV_I_FRAME) ||
5670 (ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_temp_ipe_idx]
5671 ->s_lap_out.i4_pic_type == IV_IDR_FRAME));
5672 UWORD8 p_frame =
5673 (ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_temp_ipe_idx]
5674 ->s_lap_out.i4_pic_type == IV_P_FRAME);
5675
5676 ps_pre_enc_me_ctxt_t = ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_temp_ipe_idx];
5677
5678 if(1 == (p_frame || i_frame))
5679 {
5680 ps_curr_out->i8_acc_frame_8x8_sum_act_sqr +=
5681 ps_pre_enc_me_ctxt_t->u8_curr_frame_8x8_sum_act_sqr;
5682 ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength +=
5683 ps_pre_enc_me_ctxt_t->i4_curr_frame_8x8_sum_act_for_strength[0];
5684 for(i4_k = 0; i4_k < 2; i4_k++)
5685 {
5686 ps_curr_out->i8_acc_frame_8x8_sum_act[i4_k] +=
5687 ps_pre_enc_me_ctxt_t->i8_curr_frame_8x8_sum_act[i4_k];
5688 ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k] +=
5689 ps_pre_enc_me_ctxt_t->i4_curr_frame_8x8_num_blks[i4_k];
5690
5691 ps_curr_out->i8_acc_frame_16x16_sum_act[i4_k] +=
5692 ps_pre_enc_me_ctxt_t->i8_curr_frame_16x16_sum_act[i4_k];
5693 ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k] +=
5694 ps_pre_enc_me_ctxt_t->i4_curr_frame_16x16_num_blks[i4_k];
5695
5696 ps_curr_out->i8_acc_frame_32x32_sum_act[i4_k] +=
5697 ps_pre_enc_me_ctxt_t->i8_curr_frame_32x32_sum_act[i4_k];
5698 ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k] +=
5699 ps_pre_enc_me_ctxt_t->i4_curr_frame_32x32_num_blks[i4_k];
5700 }
5701
5702 ps_curr_out->i8_acc_frame_16x16_sum_act[i4_k] +=
5703 ps_pre_enc_me_ctxt_t->i8_curr_frame_16x16_sum_act[i4_k];
5704 ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k] +=
5705 ps_pre_enc_me_ctxt_t->i4_curr_frame_16x16_num_blks[i4_k];
5706
5707 ps_curr_out->i8_acc_frame_32x32_sum_act[i4_k] +=
5708 ps_pre_enc_me_ctxt_t->i8_curr_frame_32x32_sum_act[i4_k];
5709 ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k] +=
5710 ps_pre_enc_me_ctxt_t->i4_curr_frame_32x32_num_blks[i4_k];
5711
5712 //ps_curr_out->i4_acc_frame_median_sum_act += ps_lap_out->i4_curr_frame_median_sum_act;
5713 //ps_curr_out->i4_acc_frame_median_num_blks += ps_lap_out->i4_curr_frame_median_num_blks;
5714 }
5715
5716 //ps_is_next_frame_available = (ihevce_lap_output_params_t *)ps_is_next_frame_available->ps_lap_out_next_encode;
5717 if(NULL == ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_temp_ipe_idx]
5718 ->s_rc_lap_out.ps_rc_lap_out_next_encode)
5719 break;
5720 } //while(NULL != ps_is_next_frame_available);
5721
5722 /*calculate corr. average, overwrite frame avg by acc. avergae*/
5723 {
5724 for(i4_k = 0; i4_k < 2; i4_k++)
5725 {
5726 if(1 == is_i_frame)
5727 {
5728 ASSERT(0 != ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k]);
5729 ASSERT(0 != ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k]);
5730 ASSERT(0 != ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k]);
5731 }
5732
5733 /*In P frame, if no occlusion is present, tehn accumalted avg can be 0*/
5734 /*In that case, modulation index is made 1*/
5735 if(0 == ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k])
5736 {
5737 ps_curr_out->i8_curr_frame_8x8_avg_act[i4_k] = 0;
5738 }
5739 else
5740 {
5741 ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength =
5742 (ps_curr_out->i8_acc_frame_8x8_sum_act_for_strength +
5743 (ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k] >> 1)) /
5744 ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k];
5745 ps_curr_out->i8_curr_frame_8x8_avg_act[i4_k] =
5746 (ps_curr_out->i8_acc_frame_8x8_sum_act[i4_k] +
5747 (ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k] >> 1)) /
5748 ps_curr_out->i4_acc_frame_8x8_num_blks[i4_k];
5749 ps_curr_out->ld_curr_frame_8x8_log_avg[i4_k] =
5750 (log(1 + (long double)ps_curr_out->i8_curr_frame_8x8_avg_act[i4_k]) /
5751 log(2.0));
5752 }
5753
5754 if(0 == ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k])
5755 {
5756 ps_curr_out->i8_curr_frame_16x16_avg_act[i4_k] = 0;
5757 }
5758 else
5759 {
5760 ps_curr_out->i8_curr_frame_16x16_avg_act[i4_k] =
5761 (ps_curr_out->i8_acc_frame_16x16_sum_act[i4_k] +
5762 (ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k] >> 1)) /
5763 ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k];
5764 ps_curr_out->ld_curr_frame_16x16_log_avg[i4_k] =
5765 (log(1 + (long double)ps_curr_out->i8_curr_frame_16x16_avg_act[i4_k]) /
5766 log(2.0));
5767 }
5768
5769 if(0 == ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k])
5770 {
5771 ps_curr_out->i8_curr_frame_32x32_avg_act[i4_k] = 0;
5772 }
5773 else
5774 {
5775 ps_curr_out->i8_curr_frame_32x32_avg_act[i4_k] =
5776 (ps_curr_out->i8_acc_frame_32x32_sum_act[i4_k] +
5777 (ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k] >> 1)) /
5778 ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k];
5779 ps_curr_out->ld_curr_frame_32x32_log_avg[i4_k] =
5780 (log(1 + (long double)ps_curr_out->i8_curr_frame_32x32_avg_act[i4_k]) /
5781 log(2.0));
5782 }
5783 }
5784
5785 if(1 == is_i_frame)
5786 {
5787 ASSERT(0 != ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k]);
5788 ASSERT(0 != ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k]);
5789 //ASSERT(0 != ps_curr_out->i4_acc_frame_median_num_blks);
5790 }
5791 if(0 == ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k])
5792 {
5793 ps_curr_out->i8_curr_frame_16x16_avg_act[i4_k] = 0;
5794 }
5795 else
5796 {
5797 ps_curr_out->i8_curr_frame_16x16_avg_act[i4_k] =
5798 (ps_curr_out->i8_acc_frame_16x16_sum_act[i4_k] +
5799 (ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k] >> 1)) /
5800 ps_curr_out->i4_acc_frame_16x16_num_blks[i4_k];
5801 ps_curr_out->ld_curr_frame_16x16_log_avg[i4_k] =
5802 (log(1 + (long double)ps_curr_out->i8_curr_frame_16x16_avg_act[i4_k]) /
5803 log(2.0));
5804 }
5805
5806 if(0 == ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k])
5807 {
5808 ps_curr_out->i8_curr_frame_32x32_avg_act[i4_k] = 0;
5809 }
5810 else
5811 {
5812 ps_curr_out->i8_curr_frame_32x32_avg_act[i4_k] =
5813 (ps_curr_out->i8_acc_frame_32x32_sum_act[i4_k] +
5814 (ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k] >> 1)) /
5815 ps_curr_out->i4_acc_frame_32x32_num_blks[i4_k];
5816 ps_curr_out->ld_curr_frame_32x32_log_avg[i4_k] =
5817 (log(1 + (long double)ps_curr_out->i8_curr_frame_32x32_avg_act[i4_k]) /
5818 log(2.0));
5819 }
5820 }
5821 /*store the avg activity for B pictures*/
5822 {
5823 #if POW_OPT
5824 ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0] =
5825 ps_curr_out->ld_curr_frame_8x8_log_avg[0];
5826 ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1] =
5827 ps_curr_out->ld_curr_frame_8x8_log_avg[1];
5828
5829 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0] =
5830 ps_curr_out->ld_curr_frame_16x16_log_avg[0];
5831 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1] =
5832 ps_curr_out->ld_curr_frame_16x16_log_avg[1];
5833 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2] =
5834 ps_curr_out->ld_curr_frame_16x16_log_avg[2];
5835
5836 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0] =
5837 ps_curr_out->ld_curr_frame_32x32_log_avg[0];
5838 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1] =
5839 ps_curr_out->ld_curr_frame_32x32_log_avg[1];
5840 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2] =
5841 ps_curr_out->ld_curr_frame_32x32_log_avg[2];
5842 #else
5843 ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0] =
5844 ps_curr_out->i8_curr_frame_8x8_avg_act[0];
5845 ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1] =
5846 ps_curr_out->i8_curr_frame_8x8_avg_act[1];
5847
5848 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0] =
5849 ps_curr_out->i8_curr_frame_16x16_avg_act[0];
5850 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1] =
5851 ps_curr_out->i8_curr_frame_16x16_avg_act[1];
5852 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2] =
5853 ps_curr_out->i8_curr_frame_16x16_avg_act[2];
5854
5855 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0] =
5856 ps_curr_out->i8_curr_frame_32x32_avg_act[0];
5857 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1] =
5858 ps_curr_out->i8_curr_frame_32x32_avg_act[1];
5859 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2] =
5860 ps_curr_out->i8_curr_frame_32x32_avg_act[2];
5861 #endif
5862 }
5863 /*Calculte modulation index */
5864 {
5865 LWORD64 i8_mean, i8_mean_sqr, i8_variance;
5866 LWORD64 i8_deviation;
5867 WORD32 i4_mod_factor;
5868 float f_strength;
5869
5870 if(ps_curr_out->i4_acc_frame_8x8_num_blks[0] > 0)
5871 {
5872 #if STRENGTH_BASED_ON_CURR_FRM
5873 i8_mean_sqr =
5874 ((ps_curr_out->i8_curr_frame_8x8_sum_act_sqr +
5875 (ps_curr_out->i4_curr_frame_8x8_num_blks[0] >> 1)) /
5876 ps_curr_out->i4_curr_frame_8x8_num_blks[0]);
5877 #else
5878 i8_mean_sqr =
5879 ((ps_curr_out->i8_acc_frame_8x8_sum_act_sqr +
5880 (ps_curr_out->i4_acc_frame_8x8_num_blks[0] >> 1)) /
5881 ps_curr_out->i4_acc_frame_8x8_num_blks[0]);
5882 #endif
5883 i8_mean = (ps_curr_out->i8_curr_frame_8x8_sum_act_for_strength);
5884
5885 i8_variance = i8_mean_sqr - (i8_mean * i8_mean);
5886 i8_deviation = (LWORD64)sqrt((long double)i8_variance);
5887 #if STRENGTH_BASED_ON_DEVIATION
5888
5889 if(((float)i8_deviation) <= (REF_MOD_DEVIATION))
5890 {
5891 f_strength =
5892 (float)((((float)i8_deviation - (BELOW_REF_DEVIATION)) * REF_MOD_STRENGTH) / ((REF_MOD_DEVIATION) - (BELOW_REF_DEVIATION)));
5893 }
5894 else
5895 {
5896 f_strength =
5897 (float)((((float)i8_deviation - (ABOVE_REF_DEVIATION)) * REF_MOD_STRENGTH) / ((REF_MOD_DEVIATION) - (ABOVE_REF_DEVIATION)));
5898 }
5899
5900 #else
5901 f_strength = (((float)((float)i8_mean_sqr / (float)(i8_mean * i8_mean)) - 1.0)) *
5902 REF_MOD_STRENGTH / REF_MOD_VARIANCE;
5903 #endif
5904 i4_mod_factor = (WORD32)(i8_deviation / 60);
5905
5906 f_strength = (float)CLIP3(f_strength, 0.0, REF_MAX_STRENGTH);
5907 }
5908 else
5909 {
5910 /*If not sufficient blocks are present, turn modulation index to 1 */
5911 i4_mod_factor = 1;
5912 f_strength = 0;
5913 }
5914 ps_curr_out->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5915 ps_curr_out->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5916 ps_curr_out->f_strength = f_strength;
5917
5918 if(1 == ps_enc_ctxt->s_runtime_src_prms.i4_field_pic)
5919 {
5920 /*For Interlace period, store mod factor and strenght if only first field*/
5921 if(1 == ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]
5922 ->s_lap_out.i4_first_field)
5923 {
5924 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5925 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5926 ps_enc_ctxt->f_strength = f_strength;
5927 }
5928 }
5929 else
5930 {
5931 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0] = i4_mod_factor;
5932 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1] = i4_mod_factor;
5933 ps_enc_ctxt->f_strength = f_strength;
5934 }
5935 }
5936 }
5937 else
5938 {
5939 ps_curr_out->ai4_mod_factor_derived_by_variance[0] =
5940 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[0];
5941 ps_curr_out->ai4_mod_factor_derived_by_variance[1] =
5942 ps_enc_ctxt->ai4_mod_factor_derived_by_variance[1];
5943 ps_curr_out->f_strength = ps_enc_ctxt->f_strength;
5944 /*copy the prev avg activity from Tid 0 for B pictures*/
5945 {
5946 #if POW_OPT
5947 ps_curr_out->ld_curr_frame_8x8_log_avg[0] =
5948 ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[0];
5949 ps_curr_out->ld_curr_frame_8x8_log_avg[1] =
5950 ps_enc_ctxt->ald_lap2_8x8_log_avg_act_from_T0[1];
5951
5952 ps_curr_out->ld_curr_frame_16x16_log_avg[0] =
5953 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[0];
5954 ps_curr_out->ld_curr_frame_16x16_log_avg[1] =
5955 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[1];
5956 ps_curr_out->ld_curr_frame_16x16_log_avg[2] =
5957 ps_enc_ctxt->ald_lap2_16x16_log_avg_act_from_T0[2];
5958
5959 ps_curr_out->ld_curr_frame_32x32_log_avg[0] =
5960 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[0];
5961 ps_curr_out->ld_curr_frame_32x32_log_avg[1] =
5962 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[1];
5963 ps_curr_out->ld_curr_frame_32x32_log_avg[2] =
5964 ps_enc_ctxt->ald_lap2_32x32_log_avg_act_from_T0[2];
5965 #else
5966 ps_curr_out->i8_curr_frame_8x8_avg_act[0] =
5967 ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[0];
5968 ps_curr_out->i8_curr_frame_8x8_avg_act[1] =
5969 ps_enc_ctxt->ai8_lap2_8x8_avg_act_from_T0[1];
5970
5971 ps_curr_out->i8_curr_frame_16x16_avg_act[0] =
5972 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[0];
5973 ps_curr_out->i8_curr_frame_16x16_avg_act[1] =
5974 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[1];
5975 ps_curr_out->i8_curr_frame_16x16_avg_act[2] =
5976 ps_enc_ctxt->ai8_lap2_16x16_avg_act_from_T0[2];
5977
5978 ps_curr_out->i8_curr_frame_32x32_avg_act[0] =
5979 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[0];
5980 ps_curr_out->i8_curr_frame_32x32_avg_act[1] =
5981 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[1];
5982 ps_curr_out->i8_curr_frame_32x32_avg_act[2] =
5983 ps_enc_ctxt->ai8_lap2_32x32_avg_act_from_T0[2];
5984 #endif
5985 }
5986 }
5987
5988 /*If Compenated block, then CLIP qp to max of frame qp and modulated qp*/
5989 {
5990 WORD32 ctb_ctr, vert_ctr;
5991 WORD32 ctb_ctr_blks = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_horz;
5992 WORD32 vert_ctr_blks = ps_enc_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert;
5993 ihevce_ed_ctb_l1_t *ps_ed_ctb_pic_l1 =
5994 ps_enc_ctxt->s_multi_thrd.aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ed_ctb_l1;
5995 WORD32 i4_pic_type =
5996 ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_pic_type;
5997 for(vert_ctr = 0; vert_ctr < vert_ctr_blks; vert_ctr++)
5998 {
5999 ihevce_ed_ctb_l1_t *ps_ed_ctb_row_l1 = ps_ed_ctb_pic_l1 + vert_ctr * ctb_ctr_blks;
6000
6001 for(ctb_ctr = 0; ctb_ctr < ctb_ctr_blks; ctb_ctr++)
6002 {
6003 ihevce_ed_ctb_l1_t *ps_ed_ctb_curr_l1 = ps_ed_ctb_row_l1 + ctb_ctr;
6004
6005 WORD32 is_min_block_comensated_in_l32x32 = 0;
6006
6007 /*Populate avg satd to calculate MI and activity factors*/
6008 for(i = 0; i < 4; i++)
6009 {
6010 WORD32 is_min_block_comensated_in_l116x16 = 0;
6011
6012 for(j = 0; j < 4; j++)
6013 {
6014 /*Accumulate the sum of 8*8 activities in the current layer (16*16 CU in L0)*/
6015 if(ps_ed_ctb_curr_l1->i4_sum_4x4_satd[i * 4 + j] != -1)
6016 {
6017 WORD32 is_skipped = 0;
6018 if((i4_pic_type != IV_I_FRAME) && (i4_pic_type != IV_IDR_FRAME) &&
6019 (1 == is_skipped))
6020 {
6021 is_min_block_comensated_in_l116x16 += 1;
6022 is_min_block_comensated_in_l32x32 += 1;
6023
6024 if(ps_ed_ctb_curr_l1->i4_8x8_satd[i * 4 + j][0] <
6025 ps_curr_out->i8_curr_frame_8x8_avg_act[0])
6026 ps_ed_ctb_curr_l1->i4_8x8_satd[i * 4 + j][0] = -1;
6027
6028 if(ps_ed_ctb_curr_l1->i4_8x8_satd[i * 4 + j][1] <
6029 ps_curr_out->i8_curr_frame_8x8_avg_act[1])
6030 ps_ed_ctb_curr_l1->i4_8x8_satd[i * 4 + j][1] = -1;
6031 }
6032 }
6033 }
6034
6035 if(4 == is_min_block_comensated_in_l116x16)
6036 {
6037 if(ps_ed_ctb_curr_l1->i4_16x16_satd[i][0] <
6038 ps_curr_out->i8_curr_frame_16x16_avg_act[0])
6039 ps_ed_ctb_curr_l1->i4_16x16_satd[i][0] = -1;
6040
6041 if(ps_ed_ctb_curr_l1->i4_16x16_satd[i][1] <
6042 ps_curr_out->i8_curr_frame_16x16_avg_act[1])
6043 ps_ed_ctb_curr_l1->i4_16x16_satd[i][1] = -1;
6044
6045 if(ps_ed_ctb_curr_l1->i4_16x16_satd[i][2] <
6046 ps_curr_out->i8_curr_frame_16x16_avg_act[2])
6047 ps_ed_ctb_curr_l1->i4_16x16_satd[i][2] = -1;
6048 }
6049 }
6050
6051 if((16 == is_min_block_comensated_in_l32x32))
6052 {
6053 if(ps_ed_ctb_curr_l1->i4_32x32_satd[0][0] <
6054 ps_curr_out->i8_curr_frame_32x32_avg_act[0])
6055 ps_ed_ctb_curr_l1->i4_32x32_satd[0][0] = -1;
6056
6057 if(ps_ed_ctb_curr_l1->i4_32x32_satd[0][1] <
6058 ps_curr_out->i8_curr_frame_32x32_avg_act[1])
6059 ps_ed_ctb_curr_l1->i4_32x32_satd[0][1] = -1;
6060
6061 if(ps_ed_ctb_curr_l1->i4_32x32_satd[0][2] <
6062 ps_curr_out->i8_curr_frame_32x32_avg_act[2])
6063 ps_ed_ctb_curr_l1->i4_32x32_satd[0][2] = -1;
6064 }
6065 }
6066 }
6067 }
6068
6069 /**/
6070 return;
6071 }
6072
6073 /*!
6074 ******************************************************************************
6075 * \if Function name : ihevce_pre_enc_process_frame_thrd \endif
6076 *
6077 * \brief
6078 * Pre-Encode Frame processing thread interface function
6079 *
6080 * \param[in] High level encoder context pointer
6081 *
6082 * \return
6083 * None
6084 *
6085 * \author
6086 * Ittiam
6087 *
6088 *****************************************************************************
6089 */
ihevce_pre_enc_process_frame_thrd(void * pv_frm_proc_thrd_ctxt)6090 WORD32 ihevce_pre_enc_process_frame_thrd(void *pv_frm_proc_thrd_ctxt)
6091 {
6092 frm_proc_thrd_ctxt_t *ps_thrd_ctxt = (frm_proc_thrd_ctxt_t *)pv_frm_proc_thrd_ctxt;
6093 ihevce_hle_ctxt_t *ps_hle_ctxt = ps_thrd_ctxt->ps_hle_ctxt;
6094 enc_ctxt_t *ps_enc_ctxt = (enc_ctxt_t *)ps_thrd_ctxt->pv_enc_ctxt;
6095 multi_thrd_ctxt_t *ps_multi_thrd = &ps_enc_ctxt->s_multi_thrd;
6096 WORD32 i4_thrd_id = ps_thrd_ctxt->i4_thrd_id;
6097 WORD32 i4_resolution_id = ps_enc_ctxt->i4_resolution_id;
6098 WORD32 i4_end_flag = 0;
6099 WORD32 i4_out_flush_flag = 0;
6100 WORD32 i4_cur_decomp_idx = 0;
6101 WORD32 i4_cur_coarse_me_idx = 0;
6102 WORD32 i4_cur_ipe_idx = 0;
6103 ihevce_lap_enc_buf_t *ps_lap_inp_buf = NULL;
6104 void *pv_dep_mngr_prev_frame_pre_enc_l1 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l1;
6105 void *pv_dep_mngr_prev_frame_pre_enc_l0 = ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_l0;
6106 void *pv_dep_mngr_prev_frame_pre_enc_coarse_me =
6107 ps_multi_thrd->pv_dep_mngr_prev_frame_pre_enc_coarse_me;
6108 WORD32 i4_num_buf_prod_for_l0_ipe = 0;
6109 WORD32 i4_decomp_end_flag = 0;
6110
6111 (void)ps_hle_ctxt;
6112 (void)i4_resolution_id;
6113 if(i4_thrd_id == 0)
6114 {
6115 PROFILE_START(&ps_hle_ctxt->profile_pre_enc[i4_resolution_id]);
6116 }
6117
6118 /* ---------- Processing Loop until Flush command is received --------- */
6119 while(0 == i4_end_flag)
6120 {
6121 /* Wait till previous frame(instance)'s decomp_intra is processed */
6122 {
6123 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1, i4_thrd_id);
6124 }
6125
6126 /* ----------------------------------------------------------- */
6127 /* decomp pre_intra init */
6128 /* ----------------------------------------------------------- */
6129
6130 /****** Lock the critical section for decomp pre_intra init ******/
6131 {
6132 WORD32 i4_status;
6133
6134 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
6135 if(OSAL_SUCCESS != i4_status)
6136 return 0;
6137 }
6138
6139 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_decomp_idx] = 0;
6140
6141 /* init */
6142 if((ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] == 0) &&
6143 (0 == i4_decomp_end_flag))
6144 {
6145 ihevce_lap_enc_buf_t *ps_curr_inp = NULL;
6146 pre_enc_me_ctxt_t *ps_curr_out = NULL;
6147 WORD32 in_buf_id;
6148 WORD32 out_buf_id;
6149
6150 do
6151 {
6152 ps_lap_inp_buf = NULL;
6153 if(0 == ps_multi_thrd->i4_last_inp_buf)
6154 {
6155 /* ------- get input buffer input data que ---------- */
6156 ps_lap_inp_buf = (ihevce_lap_enc_buf_t *)ihevce_q_get_filled_buff(
6157 (void *)ps_enc_ctxt,
6158 IHEVCE_INPUT_DATA_CTRL_Q,
6159 &in_buf_id,
6160 BUFF_QUE_BLOCKING_MODE);
6161 ps_multi_thrd->i4_last_inp_buf = ihevce_check_last_inp_buf(
6162 (WORD32 *)ps_lap_inp_buf->s_input_buf.pv_synch_ctrl_bufs);
6163 }
6164
6165 ps_curr_inp =
6166 ihevce_lap_process(ps_enc_ctxt->pv_lap_interface_ctxt, ps_lap_inp_buf);
6167
6168 } while(NULL == ps_curr_inp);
6169
6170 /* set the flag saying init is done so that other cores dont do it */
6171 ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 1;
6172
6173 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx] = ps_curr_inp;
6174 ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_decomp_idx] =
6175 ps_curr_inp->s_input_buf.i4_buf_id;
6176
6177 /* ------- get free output buffer from pre-enc/enc buffer que ---------- */
6178 ps_curr_out = (pre_enc_me_ctxt_t *)ihevce_q_get_free_buff(
6179 (void *)ps_enc_ctxt, IHEVCE_PRE_ENC_ME_Q, &out_buf_id, BUFF_QUE_BLOCKING_MODE);
6180 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx] = ps_curr_out;
6181 ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_decomp_idx] = out_buf_id;
6182
6183 if((NULL != ps_curr_inp) && (NULL != ps_curr_out))
6184 {
6185 /* by default last picture to be encoded flag is set to 0 */
6186 /* this flag will be used by slave threads to exit at the end */
6187 ps_multi_thrd->i4_last_pic_flag = 0;
6188
6189 /* store the buffer id */
6190 ps_curr_out->i4_buf_id = out_buf_id;
6191
6192 ps_curr_out->i8_acc_num_blks_high_sad = 0;
6193 ps_curr_out->i8_total_blks = 0;
6194 ps_curr_out->i4_is_high_complex_region = -1;
6195
6196 /* set the parameters for sync b/w pre-encode and encode threads */
6197 ps_curr_out->i4_end_flag = ps_curr_inp->s_lap_out.i4_end_flag;
6198 ps_curr_out->i4_frm_proc_valid_flag = 1;
6199 if(ps_curr_out->i4_end_flag)
6200 {
6201 ps_curr_out->i4_frm_proc_valid_flag =
6202 ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
6203 ps_multi_thrd->i4_last_pic_flag = 1;
6204 ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
6205 }
6206 if(ps_curr_inp->s_lap_out.i4_out_flush_flag)
6207 {
6208 ps_curr_out->i4_frm_proc_valid_flag =
6209 ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag;
6210 }
6211
6212 /* do the init processing if input frm data is valid */
6213 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6214 {
6215 WORD32 end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
6216 WORD32 cur_qp = 0, count;
6217
6218 ihevce_pre_enc_init(
6219 ps_enc_ctxt,
6220 ps_curr_inp,
6221 ps_curr_out,
6222 &end_flag,
6223 &cur_qp,
6224 &ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_decomp_idx],
6225 i4_cur_decomp_idx);
6226
6227 ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = end_flag;
6228 ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_decomp_idx] = cur_qp;
6229
6230 for(count = 0; count < ((HEVCE_MAX_HEIGHT >> 1) / 8); count++)
6231 {
6232 ps_multi_thrd->aai4_l1_pre_intra_done[i4_cur_decomp_idx][count] = 0;
6233 }
6234 }
6235 }
6236 }
6237 else if(1 == i4_decomp_end_flag)
6238 {
6239 /* Once end is reached all subsequent flags are set to 1 to indicate end */
6240 ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx] = 1;
6241 }
6242
6243 /****** UnLock the critical section after decomp pre_intra init ******/
6244 {
6245 WORD32 i4_status;
6246 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_init);
6247
6248 if(OSAL_SUCCESS != i4_status)
6249 return 0;
6250 }
6251
6252 /* ------------------------------------------------------------ */
6253 /* Layer Decomp and Pre Intra Analysis */
6254 /* ------------------------------------------------------------ */
6255 if(0 == i4_decomp_end_flag)
6256 {
6257 pre_enc_me_ctxt_t *ps_curr_out = ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_decomp_idx];
6258
6259 if(1 == ps_curr_out->i4_frm_proc_valid_flag)
6260 {
6261 ihevce_decomp_pre_intra_process(
6262 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
6263 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_decomp_idx]->s_lap_out,
6264 &ps_enc_ctxt->s_frm_ctb_prms,
6265 ps_multi_thrd,
6266 i4_thrd_id,
6267 i4_cur_decomp_idx,
6268 ps_curr_out->ps_layer0_cur_satd,
6269 ps_curr_out->ps_layer0_cur_mean);
6270 }
6271 }
6272
6273 /* ------------------------------------------------------------ */
6274 /* Layer Decomp and Pre Intra Deinit */
6275 /* ------------------------------------------------------------ */
6276
6277 /****** Lock the critical section for decomp deinit ******/
6278 {
6279 WORD32 i4_status;
6280 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
6281
6282 if(OSAL_SUCCESS != i4_status)
6283 return 0;
6284 }
6285
6286 ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx]++;
6287 i4_decomp_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_decomp_idx];
6288
6289 /* check for last thread condition */
6290 if(ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] ==
6291 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6292 {
6293 ps_multi_thrd->ai4_num_thrds_processed_decomp[i4_cur_decomp_idx] = 0;
6294
6295 /* reset the init flag so that init happens by the first thread for the next frame
6296 of same ping_pong instance */
6297 ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_decomp_idx] = 0;
6298
6299 /* update the pre enc l1 done in dep manager */
6300 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l1);
6301 }
6302
6303 /* index increment */
6304 i4_cur_decomp_idx = i4_cur_decomp_idx + 1;
6305
6306 /* wrap around case */
6307 if(i4_cur_decomp_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME))
6308 {
6309 i4_cur_decomp_idx = 0;
6310 }
6311
6312 /****** UnLock the critical section after decomp pre_intra deinit ******/
6313 {
6314 WORD32 i4_status;
6315 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_decomp_deinit);
6316
6317 if(OSAL_SUCCESS != i4_status)
6318 return 0;
6319 }
6320
6321 /* ------------------------------------------------------------ */
6322 /* HME Init */
6323 /* ------------------------------------------------------------ */
6324
6325 /* Wait till previous frame(instance)'s coarse_me is processed */
6326 {
6327 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me, i4_thrd_id);
6328 }
6329
6330 /****** Lock the critical section for hme init ******/
6331 {
6332 WORD32 i4_status;
6333
6334 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
6335 if(OSAL_SUCCESS != i4_status)
6336 return 0;
6337 }
6338
6339 if(0 == ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx])
6340 {
6341 /* do the init processing if input frm data is valid */
6342 if(1 ==
6343 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6344 {
6345 recon_pic_buf_t *ps_frm_recon = NULL;
6346
6347 /* DPB management for coarse me + HME init */
6348 ihevce_pre_enc_coarse_me_init(
6349 ps_enc_ctxt,
6350 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6351 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6352 &ps_frm_recon,
6353 ps_multi_thrd->ai4_decomp_lyr_buf_idx[i4_cur_coarse_me_idx],
6354 ps_multi_thrd->ai4_cur_frame_qp_pre_enc[i4_cur_coarse_me_idx],
6355 i4_cur_coarse_me_idx);
6356
6357 /* store the recon buffer pointer */
6358 ps_multi_thrd->aps_frm_recon_pre_enc[i4_cur_coarse_me_idx] = ps_frm_recon;
6359 }
6360
6361 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 1;
6362 }
6363
6364 /****** Unlock the critical section for hme init ******/
6365 {
6366 WORD32 i4_status;
6367
6368 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_init);
6369 if(OSAL_SUCCESS != i4_status)
6370 return 0;
6371 }
6372
6373 /* ------------------------------------------------------------ */
6374 /* Coarse Motion estimation and early intra-inter decision */
6375 /* ------------------------------------------------------------ */
6376 if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6377 {
6378 ihevce_coarse_me_process(
6379 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6380 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6381 &ps_enc_ctxt->s_multi_thrd,
6382 i4_thrd_id,
6383 i4_cur_coarse_me_idx);
6384 }
6385
6386 /* update the end flag */
6387 i4_end_flag = ps_multi_thrd->ai4_end_flag_pre_enc[i4_cur_coarse_me_idx];
6388 i4_out_flush_flag =
6389 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx]->s_lap_out.i4_out_flush_flag;
6390
6391 /****** Lock the critical section for hme deinit ******/
6392 {
6393 WORD32 i4_status;
6394 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_hme_deinit);
6395
6396 if(OSAL_SUCCESS != i4_status)
6397 return 0;
6398 }
6399
6400 /* last thread finishing pre_enc_process will update the flag indicating
6401 decomp and coarse ME is done. So that the next frame (next ping_pong instance)
6402 can start immediately after finishing current frame's IPE */
6403 if(1 == ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->i4_frm_proc_valid_flag)
6404 {
6405 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6406
6407 /* ------------------------------------------------------------ */
6408 /* Update qp used in based in L1 satd/act in case of scene cut */
6409 /* ------------------------------------------------------------ */
6410 {
6411 ihevce_lap_enc_buf_t *ps_curr_inp =
6412 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6413
6414 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6415 {
6416 WORD32 i4_prev_coarse_me_idx;
6417
6418 /* wrap around case */
6419 if(i4_cur_coarse_me_idx == 0)
6420 {
6421 i4_prev_coarse_me_idx = MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME - 1;
6422 }
6423 else
6424 {
6425 i4_prev_coarse_me_idx = i4_cur_coarse_me_idx - 1;
6426 }
6427
6428 ihevce_update_qp_L1_sad_based(
6429 ps_enc_ctxt,
6430 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx],
6431 ps_multi_thrd->aps_curr_inp_pre_enc[i4_prev_coarse_me_idx],
6432 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6433 ((ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6434 ps_multi_thrd->i4_num_pre_enc_proc_thrds)));
6435 }
6436 }
6437 /* check for last thread condition */
6438 if(ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6439 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6440 {
6441 ihevce_lap_enc_buf_t *ps_curr_inp =
6442 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_coarse_me_idx];
6443
6444 /* Frame END processing */
6445 ihevce_coarse_me_frame_end(ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt);
6446
6447 if(1 == ps_curr_inp->s_input_buf.i4_inp_frm_data_valid_flag)
6448 {
6449 WORD32 i4_enable_noise_detection = 0;
6450 WORD32 i4_vqet = ps_enc_ctxt->ps_stat_prms->s_coding_tools_prms.i4_vqet;
6451
6452 if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_CONTROL_TOGGLER))
6453 {
6454 if(i4_vqet & (1 << BITPOS_IN_VQ_TOGGLE_FOR_ENABLING_NOISE_PRESERVATION))
6455 {
6456 i4_enable_noise_detection = 1;
6457 }
6458 }
6459
6460 if(1 != ((ps_curr_inp->s_lap_out.i4_pic_type == IV_B_FRAME) &&
6461 (ps_enc_ctxt->s_lap_stat_prms.ai4_quality_preset[i4_resolution_id] ==
6462 IHEVCE_QUALITY_P6)))
6463 {
6464 ihevce_decomp_pre_intra_curr_frame_pre_intra_deinit(
6465 ps_enc_ctxt->s_module_ctxt.pv_decomp_pre_intra_ctxt,
6466 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx],
6467 1,
6468 &ps_enc_ctxt->s_frm_ctb_prms,
6469 ps_curr_inp->s_lap_out.i4_temporal_lyr_id,
6470 i4_enable_noise_detection);
6471 }
6472 }
6473
6474 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6475
6476 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6477
6478 /* get the layer 1 ctxt to be passed on to encode group */
6479 ihevce_coarse_me_get_lyr1_ctxt(
6480 ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
6481 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_ctxt,
6482 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_coarse_me_idx]->pv_me_lyr_bnk_ctxt);
6483
6484 /* reset the init flag so that init happens by the first thread for the next frame
6485 of same ping_pong instance */
6486 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6487
6488 /* update the pre enc l1 done in dep manager */
6489 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6490 }
6491
6492 i4_num_buf_prod_for_l0_ipe++;
6493
6494 /* index increment */
6495 i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6496
6497 /* wrap around case */
6498 if(i4_cur_coarse_me_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME))
6499 {
6500 i4_cur_coarse_me_idx = 0;
6501 }
6502 }
6503 else
6504 {
6505 /* for invalid frame set the processed flag to 1 for L0 IPE */
6506 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6507
6508 if(1 == i4_out_flush_flag)
6509 {
6510 /* update the num thrds who have finished pre-enc processing */
6511 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx]++;
6512
6513 if(ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] ==
6514 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6515 {
6516 ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_coarse_me_idx] = 1;
6517
6518 /* reset num thread finished counter */
6519 ps_multi_thrd->ai4_num_thrds_processed_coarse_me[i4_cur_coarse_me_idx] = 0;
6520
6521 ps_multi_thrd->ai4_pre_enc_hme_init_done[i4_cur_coarse_me_idx] = 0;
6522
6523 /* update flag indicating coarse_me and decomp is done */
6524 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_coarse_me);
6525 }
6526 }
6527
6528 i4_num_buf_prod_for_l0_ipe++;
6529
6530 /* index increment */
6531 i4_cur_coarse_me_idx = i4_cur_coarse_me_idx + 1;
6532
6533 /* wrap around case */
6534 if(i4_cur_coarse_me_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME))
6535 {
6536 i4_cur_coarse_me_idx = 0;
6537 }
6538 }
6539
6540 /****** UnLock the critical section after hme deinit ******/
6541 {
6542 WORD32 i4_status;
6543 i4_status =
6544 osal_mutex_unlock(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit);
6545
6546 if(OSAL_SUCCESS != i4_status)
6547 return 0;
6548 }
6549
6550 /* ----------------------------------------------------------- */
6551 /* IPE init and process */
6552 /* ----------------------------------------------------------- */
6553
6554 if(i4_num_buf_prod_for_l0_ipe >= ps_multi_thrd->i4_delay_pre_me_btw_l0_ipe || i4_end_flag ||
6555 i4_out_flush_flag)
6556 {
6557 do
6558 {
6559 /* Wait till previous frame(instance)'s IPE is processed */
6560 {
6561 ihevce_dmgr_chk_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0, i4_thrd_id);
6562 }
6563
6564 /* Wait till current frame(instance)'s L1 and below layers are processed */
6565 {
6566 volatile WORD32 *pi4_cur_l1_complete =
6567 &ps_multi_thrd->ai4_decomp_coarse_me_complete_flag[i4_cur_ipe_idx];
6568
6569 while(1)
6570 {
6571 if(*pi4_cur_l1_complete)
6572 break;
6573 }
6574 }
6575
6576 /* ----------------------------------------------------------- */
6577 /* L0 IPE qp init */
6578 /* ----------------------------------------------------------- */
6579
6580 /****** Lock the critical section for init ******/
6581 {
6582 WORD32 i4_status;
6583 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6584
6585 if(OSAL_SUCCESS != i4_status)
6586 return 0;
6587 }
6588
6589 /* first thread that enters will calculate qp and write that to shared variable
6590 that will be accessed by other threads */
6591 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6592 {
6593 volatile WORD32 i4_is_qp_valid = -1;
6594 WORD32 i4_update_qp;
6595 WORD32 i4_cur_q_scale;
6596
6597 i4_cur_q_scale =
6598 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp;
6599 i4_cur_q_scale = ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale[i4_cur_q_scale];
6600 i4_cur_q_scale = (i4_cur_q_scale + (1 << (QSCALE_Q_FAC_3 - 1))) >>
6601 QSCALE_Q_FAC_3;
6602 /* Get free buffer to store L0 IPE output to enc loop */
6603 ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc =
6604 (pre_enc_L0_ipe_encloop_ctxt_t *)ihevce_q_get_free_buff(
6605 (void *)ps_enc_ctxt,
6606 IHEVCE_L0_IPE_ENC_Q,
6607 &ps_multi_thrd->i4_L0_IPE_out_buf_id,
6608 BUFF_QUE_BLOCKING_MODE);
6609 if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2 &&
6610 ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6611 {
6612 complexity_RC_reset_marking(
6613 ps_enc_ctxt, i4_cur_ipe_idx, (i4_end_flag || i4_out_flush_flag));
6614 }
6615 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6616 ->s_input_buf.i4_inp_frm_data_valid_flag)
6617 {
6618 while(i4_is_qp_valid == -1)
6619 {
6620 /*this rate control call is outside mutex lock to avoid deadlock. If this acquires mutex lock enc will not be able to
6621 populate qp*/
6622 i4_is_qp_valid = ihevce_rc_check_is_pre_enc_qp_valid(
6623 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6624 (volatile WORD32 *)&ps_enc_ctxt->s_multi_thrd.i4_force_end_flag);
6625 if(1 == ps_enc_ctxt->s_multi_thrd.i4_force_end_flag)
6626 {
6627 /*** For force end condition break from this loop ***/
6628 i4_is_qp_valid = 1;
6629 break;
6630 }
6631 }
6632
6633 /*lock rate control context*/
6634 osal_mutex_lock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6635
6636 /* Qp query has to happen irrespective of using it or not since producer consumer logic will be disturbed */
6637 i4_update_qp = ihevce_rc_pre_enc_qp_query(
6638 (void *)ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6639 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out,
6640 0);
6641
6642 if(ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6643 {
6644 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6645 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1 =
6646 ihevce_get_L0_satd_based_on_L1(
6647 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6648 ->s_rc_lap_out.i8_frame_satd_by_act_L1_accum,
6649 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6650 ->s_rc_lap_out.i4_num_pels_in_frame_considered,
6651 i4_cur_q_scale);
6652
6653 if(ps_enc_ctxt->ps_stat_prms->s_pass_prms.i4_pass != 2)
6654 {
6655 if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6656 ->s_rc_lap_out.i4_rc_scene_type ==
6657 SCENE_TYPE_SCENE_CUT ||
6658 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6659 ->s_rc_lap_out.i4_is_I_only_scd ||
6660 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6661 ->s_rc_lap_out.i4_is_non_I_scd == 1)
6662 {
6663 float i_to_avg_rest_ratio;
6664 WORD32 i4_count = 0;
6665
6666 while(1)
6667 {
6668 i_to_avg_rest_ratio = ihevce_get_i_to_avg_ratio(
6669 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6670 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6671 ->s_rc_lap_out,
6672 1,
6673 0,
6674 0,
6675 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6676 ->s_rc_lap_out.ai4_offsets,
6677 0);
6678 /* HEVC_RC query rate control for qp */
6679 i4_update_qp = ihevce_get_L0_est_satd_based_scd_qp(
6680 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6681 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6682 ->s_rc_lap_out,
6683 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6684 ->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1,
6685 i_to_avg_rest_ratio);
6686
6687 ihevce_set_L0_scd_qp(
6688 ps_enc_ctxt->s_module_ctxt.apv_rc_ctxt[0],
6689 i4_update_qp);
6690
6691 if(ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6692 ->s_lap_out.i4_pic_type != IV_IDR_FRAME &&
6693 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6694 ->s_lap_out.i4_pic_type != IV_I_FRAME)
6695 {
6696 i4_update_qp +=
6697 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6698 ->s_lap_out.i4_temporal_lyr_id +
6699 1;
6700
6701 i4_update_qp =
6702 CLIP3(i4_update_qp, MIN_HEVC_QP, MAX_HEVC_QP);
6703 }
6704
6705 i4_count++;
6706 if((i4_update_qp ==
6707 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6708 ->s_rc_lap_out.i4_L0_qp) ||
6709 i4_count > 4)
6710 break;
6711
6712 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6713 ->s_rc_lap_out.i4_L0_qp = i4_update_qp;
6714 }
6715 }
6716 }
6717 else
6718 {
6719 //i4_update_qp = ihevce_get_first_pass_qp(ps_enc_ctxt->s_multi_thrd.aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.pv_frame_info);
6720 i4_update_qp = ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6721 ->s_rc_lap_out.ps_frame_info->i4_rc_hevc_qp;
6722 }
6723 }
6724
6725 {
6726 WORD32 i4_index = 0;
6727 rc_lap_out_params_t *ps_rc_lap_temp =
6728 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_rc_lap_out;
6729 WORD32 i4_offset;
6730
6731 if(ps_rc_lap_temp->i4_rc_pic_type != IV_IDR_FRAME &&
6732 ps_rc_lap_temp->i4_rc_pic_type != IV_I_FRAME)
6733 {
6734 i4_index = ps_rc_lap_temp->i4_rc_temporal_lyr_id + 1;
6735 }
6736 i4_offset = ps_rc_lap_temp->ai4_offsets[i4_index];
6737 ASSERT(i4_offset >= 0);
6738 /* Map the current frame Qp to L0 Qp */
6739 ps_rc_lap_temp->i4_L0_qp = i4_update_qp - i4_offset;
6740 }
6741 osal_mutex_unlock(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
6742 ASSERT(ps_multi_thrd->i4_qp_update_l0_ipe == -1);
6743 ps_multi_thrd->i4_qp_update_l0_ipe = i4_update_qp;
6744 ps_multi_thrd->i4_rc_l0_qp = i4_update_qp;
6745 }
6746 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6747 ->s_lap_out.f_i_pic_lamda_modifier = CONST_LAMDA_MOD_VAL;
6748 }
6749 /* update qp only if it is not scene cut since it has already been
6750 populated in L1 for scene cut frames */
6751 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6752 ->s_input_buf.i4_inp_frm_data_valid_flag &&
6753 ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_rate_control_mode != 3)
6754 {
6755 /*get relevant lambda params*/
6756 ihevce_get_frame_lambda_prms(
6757 ps_enc_ctxt,
6758 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6759 ps_multi_thrd->i4_qp_update_l0_ipe,
6760 ps_enc_ctxt->s_runtime_src_prms.i4_field_pic,
6761 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out.i4_is_ref_pic,
6762 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6763 ->s_lap_out.i4_temporal_lyr_id,
6764 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6765 ->s_lap_out.f_i_pic_lamda_modifier,
6766 0,
6767 PRE_ENC_LAMBDA_TYPE);
6768
6769 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp =
6770 ps_multi_thrd->i4_qp_update_l0_ipe;
6771 }
6772 /* Compute accumulated activity and strength */
6773 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6774 ->s_input_buf.i4_inp_frm_data_valid_flag &&
6775 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] == 0)
6776 {
6777 ihevce_variance_calc_acc_activity(ps_enc_ctxt, i4_cur_ipe_idx);
6778 }
6779
6780 /* Mark qp as read by last thread */
6781 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx]++;
6782 if(ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] ==
6783 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6784 {
6785 ps_multi_thrd->ai4_num_thrds_processed_L0_ipe_qp_init[i4_cur_ipe_idx] = 0;
6786 ps_multi_thrd->i4_qp_update_l0_ipe = -1;
6787 }
6788
6789 /****** UnLock the critical section after deinit ******/
6790 {
6791 WORD32 i4_status;
6792 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_l0_ipe_init);
6793
6794 if(OSAL_SUCCESS != i4_status)
6795 return 0;
6796 }
6797
6798 if(1 == ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6799 ->s_input_buf.i4_inp_frm_data_valid_flag)
6800 {
6801 WORD32 i4_slice_type =
6802 (WORD32)ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]
6803 ->s_slice_hdr.i1_slice_type;
6804 WORD32 i4_quality_preset =
6805 (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6806 ->s_lap_out.i4_quality_preset;
6807 WORD32 i4_temporal_layer_id =
6808 (WORD32)ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]
6809 ->s_lap_out.i4_temporal_lyr_id;
6810 #if DISABLE_L0_IPE_INTRA_IN_BPICS
6811 if(1 != ((i4_quality_preset == IHEVCE_QUALITY_P6) &&
6812 (i4_temporal_layer_id > TEMPORAL_LAYER_DISABLE)))
6813 #endif
6814 {
6815 UWORD8 i1_cu_qp_delta_enabled_flag =
6816 ps_enc_ctxt->ps_stat_prms->s_config_prms.i4_cu_level_rc;
6817
6818 ihevce_populate_ipe_frame_init(
6819 ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6820 ps_enc_ctxt->ps_stat_prms,
6821 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->i4_curr_frm_qp,
6822 i4_slice_type,
6823 i4_thrd_id,
6824 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx],
6825 i1_cu_qp_delta_enabled_flag,
6826 &ps_enc_ctxt->s_rc_quant,
6827 i4_quality_preset,
6828 i4_temporal_layer_id,
6829 &ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx]->s_lap_out);
6830
6831 ihevce_ipe_process(
6832 ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6833 &ps_enc_ctxt->s_frm_ctb_prms,
6834 &ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->as_lambda_prms[0],
6835 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx],
6836 ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc,
6837 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ctb_analyse,
6838 ps_multi_thrd->ps_L0_IPE_curr_out_pre_enc->ps_ipe_analyse_ctb,
6839 &ps_enc_ctxt->s_multi_thrd,
6840 i4_slice_type,
6841 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer1_buf,
6842 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_layer2_buf,
6843 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx]->ps_ed_ctb_l1,
6844 i4_thrd_id,
6845 i4_cur_ipe_idx);
6846 }
6847 }
6848
6849 /* ----------------------------------------------------------- */
6850 /* pre-enc de-init */
6851 /* ----------------------------------------------------------- */
6852
6853 /****** Lock the critical section for deinit ******/
6854 {
6855 WORD32 i4_status;
6856 i4_status = osal_mutex_lock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6857
6858 if(OSAL_SUCCESS != i4_status)
6859 return 0;
6860 }
6861
6862 ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx]++;
6863 if(ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] ==
6864 ps_multi_thrd->i4_num_pre_enc_proc_thrds)
6865 {
6866 ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 0;
6867 ps_multi_thrd->ai4_num_thrds_processed_pre_enc[i4_cur_ipe_idx] = 0;
6868
6869 /* reset the init flag so that init happens by the first thread for the
6870 next frame of same ping_pnog instnace */
6871 ps_multi_thrd->ai4_pre_enc_init_done[i4_cur_ipe_idx] = 0;
6872 }
6873
6874 /* de-init */
6875 if(0 == ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx])
6876 {
6877 ihevce_lap_enc_buf_t *ps_curr_inp =
6878 ps_multi_thrd->aps_curr_inp_pre_enc[i4_cur_ipe_idx];
6879 pre_enc_me_ctxt_t *ps_curr_out =
6880 ps_multi_thrd->aps_curr_out_pre_enc[i4_cur_ipe_idx];
6881
6882 /* set the flag saying de init is done so that other cores dont do it */
6883 ps_multi_thrd->ai4_pre_enc_deinit_done[i4_cur_ipe_idx] = 1;
6884
6885 if(1 == ps_curr_out->i4_frm_proc_valid_flag)
6886 {
6887 LWORD64 frame_acc_satd_by_modqp;
6888 float L1_full_processed_ratio;
6889
6890 if(ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated)
6891 {
6892 L1_full_processed_ratio =
6893 ((float)ps_curr_inp->s_rc_lap_out.i8_frame_satd_by_act_L1_accum /
6894 ps_curr_inp->s_rc_lap_out.i8_satd_by_act_L1_accum_evaluated);
6895 }
6896 else
6897 {
6898 L1_full_processed_ratio = 1.0;
6899 }
6900 /* Get frame-level satd cost and mode bit cost from IPE */
6901 ps_curr_out->i8_frame_acc_satd_cost = ihevce_ipe_get_frame_intra_satd_cost(
6902 ps_enc_ctxt->s_module_ctxt.pv_ipe_ctxt,
6903 &frame_acc_satd_by_modqp,
6904 &ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits,
6905 &ps_curr_inp->s_lap_out.i8_frame_level_activity_fact,
6906 &ps_curr_inp->s_lap_out.i8_frame_l0_acc_satd);
6907
6908 if((ps_curr_inp->s_lap_out.i4_quality_preset == IHEVCE_QUALITY_P6) &&
6909 (ps_curr_inp->s_lap_out.i4_temporal_lyr_id > TEMPORAL_LAYER_DISABLE))
6910 {
6911 ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = -1;
6912 }
6913
6914 {
6915 WORD32 i4_cur_q_scale = (ps_enc_ctxt->s_rc_quant.pi4_qp_to_qscale
6916 [ps_enc_ctxt->s_multi_thrd.i4_rc_l0_qp +
6917 ps_enc_ctxt->s_rc_quant.i1_qp_offset] +
6918 (1 << (QSCALE_Q_FAC_3 - 1))) >>
6919 QSCALE_Q_FAC_3;
6920
6921 /* calculate satd/act_fac = satd/qm * (qp_used_at_L0_analysis) */
6922 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6923 frame_acc_satd_by_modqp * i4_cur_q_scale;
6924 }
6925
6926 /* Because of early intra inter decision, L0 intra analysis might not happen for entire frame, correct the error
6927 based on L1 data */
6928 ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits = (LWORD64)(
6929 ps_curr_inp->s_rc_lap_out.i8_est_I_pic_header_bits *
6930 L1_full_processed_ratio);
6931
6932 if(L1_full_processed_ratio < 1.5)
6933 {
6934 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum = (LWORD64)(
6935 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum *
6936 L1_full_processed_ratio);
6937 }
6938 else
6939 {
6940 /* This is the case when too many candidates would not have gone through intra analysis, scaling based on L1 is found to be inappropriate,
6941 Hence directly estimating L0 satd from L1 satd */
6942 ps_curr_inp->s_rc_lap_out.i8_frame_satd_act_accum =
6943 ps_curr_inp->s_rc_lap_out.i8_frm_satd_act_accum_L0_frm_L1;
6944 }
6945 }
6946
6947 /* register the current input buffer to be cnosumed by encode group threads */
6948 ps_curr_out->curr_inp_buf_id =
6949 ps_multi_thrd->ai4_in_buf_id_pre_enc[i4_cur_ipe_idx];
6950 ps_curr_out->ps_curr_inp = ps_curr_inp;
6951
6952 /* set the output buffer as produced */
6953 ihevce_q_set_buff_prod(
6954 (void *)ps_enc_ctxt,
6955 IHEVCE_PRE_ENC_ME_Q,
6956 ps_multi_thrd->ai4_out_buf_id_pre_enc[i4_cur_ipe_idx]);
6957
6958 /* set the output buffer of L0 IPE as produced */
6959 ihevce_q_set_buff_prod(
6960 (void *)ps_enc_ctxt,
6961 IHEVCE_L0_IPE_ENC_Q,
6962 ps_multi_thrd->i4_L0_IPE_out_buf_id);
6963
6964 /* update flag indicating ipe is done */
6965 ihevce_dmgr_update_frm_frm_sync(pv_dep_mngr_prev_frame_pre_enc_l0);
6966 }
6967
6968 {
6969 /* index increment */
6970 i4_cur_ipe_idx = i4_cur_ipe_idx + 1;
6971
6972 /* wrap around case */
6973 if(i4_cur_ipe_idx == (MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME))
6974 {
6975 i4_cur_ipe_idx = 0;
6976 }
6977 i4_num_buf_prod_for_l0_ipe--;
6978 }
6979 /*NOTE: update of above indices should mark end if ipe.do not access below this*/
6980
6981 /****** UnLock the critical section after deinit ******/
6982 {
6983 WORD32 i4_status;
6984 i4_status = osal_mutex_unlock(ps_multi_thrd->pv_mutex_hdl_pre_enc_deinit);
6985
6986 if(OSAL_SUCCESS != i4_status)
6987 return 0;
6988 }
6989
6990 if(1 == ps_multi_thrd->i4_force_end_flag)
6991 {
6992 i4_end_flag = 1;
6993 break;
6994 }
6995 } while((i4_end_flag || i4_out_flush_flag) && i4_num_buf_prod_for_l0_ipe);
6996 }
6997 }
6998 if(i4_thrd_id == 0)
6999 {
7000 PROFILE_STOP(&ps_hle_ctxt->profile_pre_enc[i4_resolution_id], NULL);
7001 }
7002
7003 return 0;
7004 }
7005
calc_l1_level_hme_intra_sad_different_qp(enc_ctxt_t * ps_enc_ctxt,pre_enc_me_ctxt_t * ps_curr_out,ihevce_lap_enc_buf_t * ps_curr_inp,WORD32 i4_tot_ctb_l1_x,WORD32 i4_tot_ctb_l1_y)7006 void calc_l1_level_hme_intra_sad_different_qp(
7007 enc_ctxt_t *ps_enc_ctxt,
7008 pre_enc_me_ctxt_t *ps_curr_out,
7009 ihevce_lap_enc_buf_t *ps_curr_inp,
7010 WORD32 i4_tot_ctb_l1_x,
7011 WORD32 i4_tot_ctb_l1_y)
7012 {
7013 ihevce_ed_ctb_l1_t *ps_ed_ctb_l1;
7014 WORD32 i4_qp_counter, i4_qp_start = 0, i4_qp_end = 0, i, i4_j, i4_new_frame_qp;
7015 LWORD64 i8_l1_intra_sad_nc_accounted = 0, cur_intra_sad, raw_hme_sad = 0;
7016 LWORD64 cur_hme_sad = 0, cur_hme_sad_for_offset = 0, acc_hme_l1_sad = 0,
7017 acc_hme_l1_sad_for_offset = 0;
7018 i4_qp_start = 1;
7019 i4_qp_end = 51;
7020
7021 for(i4_qp_counter = i4_qp_start; i4_qp_counter <= i4_qp_end; i4_qp_counter = i4_qp_counter + 3)
7022 {
7023 i8_l1_intra_sad_nc_accounted = 0;
7024 cur_intra_sad = 0;
7025 raw_hme_sad = 0;
7026 cur_hme_sad = 0;
7027 cur_hme_sad_for_offset = 0;
7028 acc_hme_l1_sad = 0;
7029 ps_ed_ctb_l1 = ps_curr_out->ps_ed_ctb_l1;
7030 i4_new_frame_qp = i4_qp_counter;
7031 acc_hme_l1_sad = 0;
7032
7033 for(i = 0; i < (i4_tot_ctb_l1_x * i4_tot_ctb_l1_y); i += 1)
7034 {
7035 for(i4_j = 0; i4_j < 16; i4_j++)
7036 {
7037 if(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] != -1)
7038 {
7039 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
7040 if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_I_FRAME &&
7041 ps_curr_inp->s_rc_lap_out.i4_rc_pic_type != IV_IDR_FRAME)
7042 {
7043 /*When l1 is disabled for B pics i4_best_sad_8x8_l1_ipe is set to max value always,
7044 so will enter this path even for incomplete ctb, hence the assert holdsto good only for P pic */
7045 if(ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6)
7046 {
7047 if(ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_P_FRAME)
7048 {
7049 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
7050 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
7051 }
7052 }
7053 else
7054 {
7055 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] >= 0);
7056 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_me_for_decide[i4_j] >= 0);
7057 }
7058
7059 #if 1 //DISABLE_L1_L2_IPE_INTRA_IN_BPICS && RC_DEPENDENCY_FOR_BPIC
7060 if((ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] != -1))
7061 #endif
7062 {
7063 cur_hme_sad = ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j] -
7064 (QP2QUANT_MD[i4_new_frame_qp] << 3);
7065 }
7066 raw_hme_sad += ps_ed_ctb_l1->i4_best_sad_8x8_l1_me[i4_j];
7067
7068 if(cur_hme_sad > 0)
7069 acc_hme_l1_sad += cur_hme_sad;
7070 }
7071 if(cur_hme_sad_for_offset > 0)
7072 {
7073 acc_hme_l1_sad_for_offset += cur_hme_sad_for_offset;
7074 }
7075 ASSERT(ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] >= 0);
7076 /*intra sad is scaled by 1.17 to be account for 1/3 vs 1/6th rounding*/
7077 cur_intra_sad = (LWORD64)(
7078 (ps_ed_ctb_l1->i4_best_sad_8x8_l1_ipe[i4_j] * 1.17) -
7079 (QP2QUANT_MD[i4_new_frame_qp] << 3));
7080
7081 if(cur_intra_sad > 0)
7082 i8_l1_intra_sad_nc_accounted += cur_intra_sad;
7083 }
7084 }
7085 ps_ed_ctb_l1 += 1;
7086 }
7087 if((ps_curr_inp->s_rc_lap_out.i4_rc_quality_preset == IHEVCE_QUALITY_P6) &&
7088 (ps_curr_inp->s_rc_lap_out.i4_rc_pic_type == IV_B_FRAME))
7089 {
7090 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] = -1;
7091 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] = -1;
7092 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] = -1;
7093 }
7094 else
7095 {
7096 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter] =
7097 i8_l1_intra_sad_nc_accounted;
7098 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 1] =
7099 i8_l1_intra_sad_nc_accounted;
7100 ps_curr_inp->s_rc_lap_out.ai8_pre_intra_sad[i4_qp_counter + 2] =
7101 i8_l1_intra_sad_nc_accounted;
7102 }
7103 ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter] = acc_hme_l1_sad;
7104 ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 1] = acc_hme_l1_sad;
7105 ps_curr_inp->s_rc_lap_out.ai8_frame_acc_coarse_me_sad[i4_qp_counter + 2] = acc_hme_l1_sad;
7106 ps_curr_inp->s_rc_lap_out.i8_raw_l1_coarse_me_sad = raw_hme_sad;
7107 }
7108 }
7109