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