• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright (C) 2022 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 
21 /**
22 *******************************************************************************
23 * @file
24 *  ih264e_svc_utils.c
25 *
26 * @brief
27 *  Contains utility functions used for SVC encoding
28 *
29 * @author
30 *  ittiam
31 *
32 * @par List of Functions:
33 *  - ih264e_svc_ref_list_refresh()
34 *  - ih264e_svc_inp_params_validate()
35 *
36 * @remarks
37 *  None
38 *
39 *******************************************************************************
40 */
41 #include <math.h>
42 #include <limits.h>
43 
44 #include "ih264_typedefs.h"
45 
46 /* Dependencies of ih264_buf_mgr.h */
47 /* Dependencies of ih264_list.h */
48 #include "ih264_error.h"
49 
50 #include "ih264_buf_mgr.h"
51 #include "ih264_list.h"
52 #include "ih264_trans_data.h"
53 #include "ih264_size_defs.h"
54 
55 /* Dependencies of ih264_common_tables.h */
56 #include "ih264_defs.h"
57 #include "ih264_structs.h"
58 
59 #include "ih264_common_tables.h"
60 
61 /* Dependencies of ih264e_bitstream.h */
62 #include "ih264e_error.h"
63 
64 /* Dependencies of ih264e_cabac_structs.h */
65 #include "ih264_cabac_tables.h"
66 
67 /* Dependencies of ime_structs.h */
68 #include "ime_defs.h"
69 #include "ime_distortion_metrics.h"
70 
71 /* Dependencies of ih264e_structs.h */
72 #include "iv2.h"
73 #include "ive2.h"
74 #include "ih264_defs.h"
75 #include "ih264_deblk_edge_filters.h"
76 #include "ih264_inter_pred_filters.h"
77 #include "ih264_structs.h"
78 #include "ih264_trans_quant_itrans_iquant.h"
79 #include "ih264e_bitstream.h"
80 #include "ih264e_cabac_structs.h"
81 #include "ime_statistics.h"
82 #include "ime_structs.h"
83 /* Dependencies of 'irc_picture_type.h' */
84 #include "irc_cntrl_param.h"
85 #include "irc_frame_info_collector.h"
86 #include "irc_mem_req_and_acq.h"
87 /* Dependencies of 'irc_rate_control_api_structs' */
88 #include "irc_picture_type.h"
89 #include "irc_rd_model.h"
90 #include "irc_vbr_storage_vbv.h"
91 #include "irc_est_sad.h"
92 #include "irc_bit_allocation.h"
93 #include "irc_mb_model_based.h"
94 #include "irc_cbr_buffer_control.h"
95 #include "irc_vbr_str_prms.h"
96 #include "irc_common.h"
97 #include "irc_rate_control_api_structs.h"
98 #include "irc_rate_control_api.h"
99 #include "irc_svc_rate_control_api.h"
100 /* Dependencies of 'ih264e_utils.h' */
101 #include "ih264e_defs.h"
102 #include "ih264e_structs.h"
103 /* Dependencies of 'ih264e_utils.h' */
104 #include "ih264e_rc_mem_interface.h"
105 #include "ih264e_time_stamp.h"
106 #include "ih264e_utils.h"
107 #include "ime.h"
108 #include "isvc_macros.h"
109 #include "isvce_cabac.h"
110 #include "isvce_core_coding.h"
111 #include "isvce_defs.h"
112 #include "isvce_error.h"
113 #include "isvce_me.h"
114 #include "isvce_utils.h"
115 #include "isvce_downscaler.h"
116 #include "isvce_encode_header.h"
117 #include "isvce_rate_control.h"
118 #include "isvce_sub_pic_rc.h"
119 
120 static const UWORD32 gu4_downscaler_blk_size = 96;
121 
isvce_get_downscaler_blk_dims(UWORD32 u4_frame_dim,UWORD32 u4_blk_pos,UWORD32 u4_default_blk_size)122 static FORCEINLINE UWORD32 isvce_get_downscaler_blk_dims(UWORD32 u4_frame_dim, UWORD32 u4_blk_pos,
123                                                          UWORD32 u4_default_blk_size)
124 {
125     return ((u4_frame_dim - u4_blk_pos * u4_default_blk_size) < u4_default_blk_size)
126                ? (u4_frame_dim - u4_blk_pos * u4_default_blk_size)
127                : u4_default_blk_size;
128 }
129 
130 /**
131 *******************************************************************************
132 *
133 * @brief
134 *  Reference and MV bank Buffer Manager for SVC
135 *
136 * @par Description:
137 *  Here we will
138 *      1) Find the correct ref pics for the current frame
139 *      2) Free the ref pics that are not going to be used anymore
140 *
141 *  1) Finding correct ref pic
142 *      All pics needed for future are arranged in a picture list called
143 *      ps_codec->as_ref_set. Each picture in this will have a pic buffer and
144 *      MV buffer that is marked appropriately as BUF_MGR_REF, BUF_MGR_IO or
145 *      BUF_MGR_CODEC. pic_cnt, poc, and temporal_id will also be present.
146 *      The strategy is to pick the closest references that belongs to the
147 *      same temporal_id or lesser. The closeness is measured via the
148 *      smallest absolute difference between ref and cur pocs.
149 *
150 *      Note that i4_pic_cnt == -1 is used to filter uninitialised ref pics.
151 *      Now since we only have max two ref pics, we will always find max 2
152 *      ref pics.
153 *
154 *  2) Self explanatory
155 *
156 * @param[in] ps_codec
157 *  Pointer to codeec context
158 *
159 * @param[in] pps_ref_pics
160 *  Array of pointers to refPicBufs
161 *
162 * @param[in] pps_mv_bufs
163 *  Array of pointers to refMVBufs
164 *
165 * @param[in] e_pic_type
166 *  Picture type
167 *
168 * @returns Nothing
169 *
170 *******************************************************************************
171 */
isvce_ref_list_refresh(isvce_codec_t * ps_codec,svc_au_buf_t ** pps_ref_pics,svc_au_data_t ** pps_mv_bufs,WORD32 * pi4_ref_set_id,PIC_TYPE_T e_pic_type)172 static WORD32 isvce_ref_list_refresh(isvce_codec_t *ps_codec, svc_au_buf_t **pps_ref_pics,
173                                      svc_au_data_t **pps_mv_bufs, WORD32 *pi4_ref_set_id,
174                                      PIC_TYPE_T e_pic_type)
175 {
176     typedef struct
177     {
178         WORD32 i4_buf_id;
179 
180         WORD32 i4_abs_poc_diff;
181 
182         WORD8 i1_temporal_id;
183     } ref_pic_props_t;
184 
185     ref_pic_props_t s_ref_pic_props = {0, 0, -1};
186 
187     WORD32 i, buf_status;
188 
189     WORD32 i4_cur_pic_poc = ps_codec->i4_poc;
190     WORD32 i4_cur_pic_temporal_id = isvce_svc_temporal_id_compute(
191         ps_codec->i4_poc, ps_codec->s_cfg.s_svc_params.u1_num_temporal_layers, e_pic_type);
192 
193     if(e_pic_type == PIC_B)
194     {
195         return IH264E_FAIL;
196     }
197 
198     ASSERT(1 == MAX_LAYER_REFERENCE_PICS);
199 
200     /* Pick a ref_pic for the current picture */
201     if(e_pic_type != PIC_IDR)
202     {
203         for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
204         {
205             WORD32 i4_abs_poc_diff;
206             WORD8 i1_temporal_id;
207 
208             if(ps_codec->as_ref_set[i].i4_pic_cnt == -1)
209             {
210                 continue;
211             }
212 
213             buf_status = ih264_buf_mgr_get_status(ps_codec->pv_ref_buf_mgr,
214                                                   ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
215 
216             if(buf_status & BUF_MGR_REF)
217             {
218                 i4_abs_poc_diff = ABS(ps_codec->as_ref_set[i].i4_poc - i4_cur_pic_poc);
219                 i1_temporal_id = ps_codec->as_ref_set[i].ps_pic_buf->i1_temporal_id;
220 
221                 if(s_ref_pic_props.i1_temporal_id > -1)
222                 {
223                     if((i1_temporal_id <= i4_cur_pic_temporal_id) &&
224                        (s_ref_pic_props.i4_abs_poc_diff > i4_abs_poc_diff))
225                     {
226                         s_ref_pic_props.i4_abs_poc_diff = i4_abs_poc_diff;
227                         s_ref_pic_props.i1_temporal_id = i1_temporal_id;
228                         s_ref_pic_props.i4_buf_id = i;
229                     }
230                 }
231                 else if(i1_temporal_id <= i4_cur_pic_temporal_id)
232                 {
233                     s_ref_pic_props.i4_abs_poc_diff = i4_abs_poc_diff;
234                     s_ref_pic_props.i1_temporal_id = i1_temporal_id;
235                     s_ref_pic_props.i4_buf_id = i;
236                 }
237             }
238         }
239 
240         if(s_ref_pic_props.i1_temporal_id < 0)
241         {
242             return IH264E_FAIL;
243         }
244 
245         pps_ref_pics[0] = pps_ref_pics[1] =
246             ps_codec->as_ref_set[s_ref_pic_props.i4_buf_id].ps_pic_buf;
247         pps_mv_bufs[0] = pps_mv_bufs[1] =
248             ps_codec->as_ref_set[s_ref_pic_props.i4_buf_id].ps_svc_au_data;
249 
250         /* Pick all ref pic_bufs to be freed. */
251         for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
252         {
253             if(ps_codec->as_ref_set[i].i4_pic_cnt == -1)
254             {
255                 continue;
256             }
257 
258             buf_status = ih264_buf_mgr_get_status(ps_codec->pv_ref_buf_mgr,
259                                                   ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
260 
261             if((buf_status & (BUF_MGR_REF | BUF_MGR_CODEC | BUF_MGR_IO)) == 0)
262             {
263                 ps_codec->as_ref_set[i].i4_pic_cnt = -1;
264                 ps_codec->as_ref_set[i].i4_poc = 32768;
265 
266                 continue;
267             }
268 
269             if(buf_status & BUF_MGR_REF)
270             {
271                 if((i4_cur_pic_temporal_id <= ps_codec->as_ref_set[i].ps_pic_buf->i1_temporal_id) &&
272                    (pps_ref_pics[0]->i4_frame_num !=
273                     ps_codec->as_ref_set[i].ps_pic_buf->i4_frame_num) &&
274                    (pps_ref_pics[0]->i4_frame_num !=
275                     ps_codec->as_ref_set[i].ps_pic_buf->i4_frame_num))
276                 {
277                     ih264_buf_mgr_release(ps_codec->pv_svc_au_data_store_mgr,
278                                           ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id,
279                                           BUF_MGR_REF);
280 
281                     ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr,
282                                           ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id,
283                                           BUF_MGR_REF);
284                 }
285             }
286         }
287     }
288     else
289     {
290         for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
291         {
292             if(ps_codec->as_ref_set[i].i4_pic_cnt == -1)
293             {
294                 continue;
295             }
296 
297             buf_status = ih264_buf_mgr_get_status(ps_codec->pv_ref_buf_mgr,
298                                                   ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
299 
300             if((buf_status & (BUF_MGR_REF | BUF_MGR_CODEC | BUF_MGR_IO)) == 0)
301             {
302                 ps_codec->as_ref_set[i].i4_pic_cnt = -1;
303                 ps_codec->as_ref_set[i].i4_poc = 32768;
304 
305                 continue;
306             }
307 
308             if(buf_status & BUF_MGR_REF)
309             {
310                 ih264_buf_mgr_release(ps_codec->pv_svc_au_data_store_mgr,
311                                       ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id, BUF_MGR_REF);
312 
313                 ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr,
314                                       ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id, BUF_MGR_REF);
315             }
316         }
317     }
318 
319     /*
320      * Mark all reference pic with unused buffers to be free
321      * We need this step since each one, ie ref, recon io etc only unset their
322      * respective flags. Hence we need to combine togather and mark the ref set
323      * accordingly
324      */
325     pi4_ref_set_id[0] = -1;
326 
327     for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
328     {
329         if(ps_codec->as_ref_set[i].i4_pic_cnt == -1)
330         {
331             pi4_ref_set_id[0] = i;
332             continue;
333         }
334 
335         buf_status = ih264_buf_mgr_get_status(ps_codec->pv_ref_buf_mgr,
336                                               ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
337 
338         if((buf_status & (BUF_MGR_REF | BUF_MGR_CODEC | BUF_MGR_IO)) == 0)
339         {
340             ps_codec->as_ref_set[i].i4_pic_cnt = -1;
341             ps_codec->as_ref_set[i].i4_poc = 32768;
342 
343             pi4_ref_set_id[0] = i;
344         }
345     }
346 
347     /* An asssert failure here means we donot have any free buffs */
348     if(pi4_ref_set_id[0] < 0)
349     {
350         return IH264E_FAIL;
351     }
352 
353     return IH264E_SUCCESS;
354 }
355 
356 /**
357 *******************************************************************************
358 *
359 * @brief
360 *  Validates SVC AU properties
361 *
362 * @param[in] ps_cfg
363 *  Cfg parameters
364 *
365 * @returns  error code in conformance with 'IH264E_ERROR_T'
366 *
367 *******************************************************************************
368 */
isvce_svc_au_props_validate(svc_inp_params_t * ps_svc_inp_params,UWORD32 u4_inp_wd,UWORD32 u4_inp_ht,UWORD32 u4_svc_comp_wd,UWORD32 u4_svc_comp_ht)369 WORD32 isvce_svc_au_props_validate(svc_inp_params_t *ps_svc_inp_params, UWORD32 u4_inp_wd,
370                                    UWORD32 u4_inp_ht, UWORD32 u4_svc_comp_wd,
371                                    UWORD32 u4_svc_comp_ht)
372 {
373     typedef struct
374     {
375         DOUBLE d_spatial_res_ratio;
376 
377         UWORD8 u1_max_num_spatial_layers;
378     } spatial_layer_props_t;
379 
380     UWORD8 i;
381     UWORD32 au4_svc_wd[MAX_NUM_SPATIAL_LAYERS];
382     UWORD32 au4_svc_ht[MAX_NUM_SPATIAL_LAYERS];
383 
384     DOUBLE d_scaling_factor = ps_svc_inp_params->d_spatial_res_ratio;
385     UWORD8 u1_num_spatial_layers = ps_svc_inp_params->u1_num_spatial_layers;
386     const spatial_layer_props_t gas_valid_spatial_layer_props[] = {{1.5, 2}, {2, 3}};
387     UWORD32 u4_error_code = IV_SUCCESS;
388     const UWORD8 u1_min_num_temporal_layers = 1;
389     const UWORD8 u1_min_num_spatial_layers = 1;
390     const UWORD8 u1_max_num_temporal_layers = MAX_NUM_TEMPORAL_LAYERS;
391     const UWORD8 u1_max_num_spatial_layers = MAX_NUM_SPATIAL_LAYERS;
392     const UWORD8 u1_num_valid_spatial_layer_props =
393         sizeof(gas_valid_spatial_layer_props) / sizeof(gas_valid_spatial_layer_props[0]);
394 
395     if((ps_svc_inp_params->u1_num_temporal_layers < u1_min_num_temporal_layers) ||
396        (ps_svc_inp_params->u1_num_temporal_layers > u1_max_num_temporal_layers))
397     {
398         u4_error_code |= IH264E_INVALID_SVC_PARAMS | IH264E_INVALID_NUM_TEMPORAL_LAYERS;
399     }
400 
401     if((ps_svc_inp_params->u1_num_spatial_layers < u1_min_num_spatial_layers) ||
402        (ps_svc_inp_params->u1_num_spatial_layers > u1_max_num_spatial_layers))
403     {
404         u4_error_code |= IH264E_INVALID_SVC_PARAMS | IH264E_INVALID_NUM_SPATIAL_LAYERS;
405     }
406 
407     {
408         UWORD8 u1_is_input_ratio_valid = 0;
409 
410         for(i = 0; i < u1_num_valid_spatial_layer_props; i++)
411         {
412             if(ps_svc_inp_params->d_spatial_res_ratio ==
413                gas_valid_spatial_layer_props[i].d_spatial_res_ratio)
414             {
415                 u1_is_input_ratio_valid = 1;
416 
417                 if(ps_svc_inp_params->u1_num_spatial_layers >
418                    gas_valid_spatial_layer_props[i].u1_max_num_spatial_layers)
419                 {
420                     u4_error_code |= IH264E_INVALID_SVC_PARAMS | IH264E_INVALID_NUM_SPATIAL_LAYERS;
421                 }
422 
423                 break;
424             }
425         }
426 
427         if(!u1_is_input_ratio_valid)
428         {
429             u4_error_code |= IH264E_INVALID_SVC_PARAMS | IH264E_INVALID_SPATIAL_RES_RATIO;
430         }
431     }
432 
433     if((u4_svc_comp_wd > SVCE_MAX_INP_DIM) || (u4_svc_comp_ht > SVCE_MAX_INP_DIM) ||
434        ((u4_svc_comp_wd * u4_svc_comp_ht) > SVCE_MAX_INP_FRAME_SIZE) ||
435        (u4_svc_comp_wd % 16 != 0) || (u4_svc_comp_ht % 16 != 0))
436     {
437         u4_error_code |= IH264E_INVALID_SVC_INPUT_DIMENSIONS;
438     }
439 
440     /* Constraint from padding intrinsics */
441     if((u4_svc_comp_wd - u4_inp_wd) % 16)
442     {
443         u4_error_code |= IH264E_INVALID_SVC_INPUT_DIMENSIONS;
444     }
445 
446     /* Constraint from 420p to 420sp conversion */
447     if((u4_svc_comp_ht - u4_inp_ht) % 4)
448     {
449         u4_error_code |= IH264E_INVALID_SVC_INPUT_DIMENSIONS;
450     }
451 
452     au4_svc_wd[u1_num_spatial_layers - 1] = u4_svc_comp_wd;
453     au4_svc_ht[u1_num_spatial_layers - 1] = u4_svc_comp_ht;
454 
455     for(i = (u1_num_spatial_layers - 1); i > 0; i--)
456     {
457         au4_svc_wd[i - 1] = au4_svc_wd[i] / d_scaling_factor;
458         au4_svc_ht[i - 1] = au4_svc_ht[i] / d_scaling_factor;
459 
460         if((au4_svc_wd[i - 1] * d_scaling_factor != au4_svc_wd[i]) ||
461            (au4_svc_ht[i - 1] * d_scaling_factor != au4_svc_ht[i]) ||
462            (au4_svc_ht[i - 1] % 16 != 0) || (au4_svc_ht[i - 1] % 16 != 0))
463         {
464             u4_error_code |= IH264E_INVALID_SVC_INPUT_DIMENSIONS;
465         }
466     }
467 
468     return u4_error_code;
469 }
470 
471 /**
472 *******************************************************************************
473 *
474 * @brief
475 *  Validates SVC input params
476 *
477 * @param[in] ps_cfg
478 *  Cfg parameters
479 *
480 * @returns  error code in conformance with 'IH264E_ERROR_T'
481 *
482 *******************************************************************************
483 */
isvce_svc_inp_params_validate(isvce_init_ip_t * ps_ip,isvce_cfg_params_t * ps_cfg)484 WORD32 isvce_svc_inp_params_validate(isvce_init_ip_t *ps_ip, isvce_cfg_params_t *ps_cfg)
485 {
486     UWORD32 u4_error_code = isvce_svc_au_props_validate(&ps_ip->s_svc_inp_params, ps_ip->u4_wd,
487                                                         ps_ip->u4_ht, ps_cfg->u4_wd, ps_cfg->u4_ht);
488 
489     if(ps_cfg->u4_enable_alt_ref)
490     {
491         u4_error_code |= IH264E_INVALID_ALT_REF_OPTION;
492     }
493 
494     if(ps_cfg->u4_num_bframes)
495     {
496         u4_error_code |= IH264E_BFRAMES_NOT_SUPPORTED;
497     }
498 
499     if(ps_cfg->e_slice_mode != IVE_SLICE_MODE_NONE)
500     {
501         u4_error_code |= IH264E_SLICE_TYPE_INPUT_INVALID;
502     }
503 
504     if(ps_cfg->e_content_type != IV_PROGRESSIVE)
505     {
506         u4_error_code |= IH264E_CONTENT_TYPE_NOT_SUPPORTED;
507     }
508 
509     if(ps_cfg->u4_weighted_prediction)
510     {
511         u4_error_code |= IH264E_WEIGHTED_PRED_NOT_SUPPORTED;
512     }
513 
514     return u4_error_code;
515 }
516 
517 /**
518 *******************************************************************************
519 *
520 * @brief
521 *  Used to get reference picture buffer size for a given level and
522 *  and padding used
523 *
524 * @param[in] ps_svc_inp_params
525 *  Struct containing SVC specific input params
526 *
527 * @param[in] i4_pic_size
528 *  Number of luma samples (Width * Height)
529 *
530 * @param[in] i4_level
531 *  Level
532 *
533 * @param[in] i4_horz_pad
534 *  Total padding used in horizontal direction
535 *
536 * @param[in] i4_vert_pad
537 *  Total padding used in vertical direction
538 *
539 * @param[in] i4_num_ref_frames
540 *  Num Reference Frames
541 *
542 * @param[in] i4_num_reorder_frames
543 *  Num Reorder Frames
544 *
545 * @returns  Total picture buffer size
546 *
547 *******************************************************************************
548 */
isvce_get_total_svc_au_buf_size(svc_inp_params_t * ps_svc_inp_params,WORD32 i4_pic_size,WORD32 i4_level,WORD32 i4_horz_pad,WORD32 i4_vert_pad,WORD32 i4_num_ref_frames,WORD32 i4_num_reorder_frames)549 WORD32 isvce_get_total_svc_au_buf_size(svc_inp_params_t *ps_svc_inp_params, WORD32 i4_pic_size,
550                                        WORD32 i4_level, WORD32 i4_horz_pad, WORD32 i4_vert_pad,
551                                        WORD32 i4_num_ref_frames, WORD32 i4_num_reorder_frames)
552 {
553     WORD32 i;
554     WORD32 size;
555     WORD32 num_luma_samples;
556     WORD32 lvl_idx;
557     WORD32 max_wd, min_ht;
558     WORD32 num_samples;
559     WORD32 max_num_bufs;
560 
561     WORD32 pad = MAX(i4_horz_pad, i4_vert_pad);
562     DOUBLE d_svc_size_multiplier = 1;
563 
564     for(i = 1; i < ps_svc_inp_params->u1_num_spatial_layers; i++)
565     {
566         d_svc_size_multiplier += 1. / pow(ps_svc_inp_params->d_spatial_res_ratio, i);
567     }
568 
569     /*
570      * If i4_num_ref_frames and num_reorder_frmaes is specified
571      * Use minimum value
572      */
573     max_num_bufs = (i4_num_ref_frames + i4_num_reorder_frames + MAX_CTXT_SETS +
574                     ps_svc_inp_params->u1_num_temporal_layers);
575 
576     /* Get i4_level index */
577     lvl_idx = ih264e_get_lvl_idx(i4_level);
578 
579     /* Maximum number of luma samples in a picture at given i4_level */
580     num_luma_samples = gai4_ih264_max_luma_pic_size[lvl_idx];
581     num_luma_samples = MAX(num_luma_samples, i4_pic_size);
582 
583     /* Account for chroma */
584     num_samples = num_luma_samples * 3 / 2;
585 
586     /* Maximum width of luma samples in a picture at given i4_level */
587     max_wd = gai4_ih264_max_wd_ht[lvl_idx];
588 
589     /* Minimum height of luma samples in a picture at given i4_level */
590     min_ht = gai4_ih264_min_wd_ht[lvl_idx];
591 
592     /* Allocation is required for
593      * (Wd + i4_horz_pad) * (Ht + i4_vert_pad) * (2 * max_dpb_size + 1)
594      *
595      * Above expanded as
596      * ((Wd * Ht) + (i4_horz_pad * i4_vert_pad) + Wd * i4_vert_pad + Ht *
597      * i4_horz_pad) * (2 * max_dpb_size + 1) (Wd * Ht) * (2 * max_dpb_size + 1) +
598      * ((i4_horz_pad * i4_vert_pad) + Wd * i4_vert_pad + Ht * i4_horz_pad) * (2 *
599      * max_dpb_size + 1) Now max_dpb_size increases with smaller Wd and Ht, but Wd
600      * * ht * max_dpb_size will still be lesser or equal to max_wd * max_ht *
601      * dpb_size
602      *
603      * In the above equation (Wd * Ht) * (2 * max_dpb_size + 1) is accounted by
604      * using num_samples * (2 * max_dpb_size + 1) below
605      *
606      * For the padded area use MAX(i4_horz_pad, i4_vert_pad) as pad
607      * ((pad * pad) + pad * (Wd + Ht)) * (2 * max_dpb_size + 1) has to accounted
608      * from the above for padding
609      *
610      * Since Width and Height can change worst Wd + Ht is when One of the
611      * dimensions is max and other is min So use max_wd and min_ht
612      */
613 
614     /* Number of bytes in reference pictures */
615     size = num_samples * max_num_bufs;
616 
617     /* Account for Spatial Layers */
618     size = (WORD32) (size * d_svc_size_multiplier + 0.99);
619 
620     /* Account for padding area */
621     size += ((pad * pad) + pad * (max_wd + min_ht)) * 3 / 2 * max_num_bufs *
622             ps_svc_inp_params->u1_num_spatial_layers;
623 
624     size += ps_svc_inp_params->u1_num_spatial_layers * sizeof(yuv_buf_props_t);
625 
626     return size;
627 }
628 
629 /**
630 *******************************************************************************
631 *
632 * @brief
633 *  Used to get size of buffers used for storing prediction data
634 *
635 * @param[in] ps_svc_inp_params
636 *  Struct containing SVC specific input params
637 *
638 * @param[in] i4_num_luma_samples
639 *  Number of luma samples (Width * Height)
640 *
641 * @returns  Size of buffers used for storing prediction data
642 *
643 *******************************************************************************
644 */
isvce_get_total_svc_au_data_size(WORD32 i4_num_luma_samples,UWORD8 u1_num_spatial_layers,DOUBLE d_spatial_res_ratio)645 UWORD32 isvce_get_total_svc_au_data_size(WORD32 i4_num_luma_samples, UWORD8 u1_num_spatial_layers,
646                                          DOUBLE d_spatial_res_ratio)
647 {
648     WORD32 i;
649 
650     UWORD32 u4_svc_au_data_size = 0;
651 
652     u4_svc_au_data_size += u1_num_spatial_layers * sizeof(svc_layer_data_t);
653 
654     for(i = 0; i < u1_num_spatial_layers; i++)
655     {
656         WORD32 i4_layer_luma_samples =
657             ((DOUBLE) i4_num_luma_samples) / pow(pow(d_spatial_res_ratio, i), 2) + 0.99;
658         WORD32 i4_num_mbs = i4_layer_luma_samples / (MB_SIZE * MB_SIZE);
659 
660         /* isvce_mb_info_t */
661         u4_svc_au_data_size += i4_num_mbs * sizeof(isvce_mb_info_t);
662 
663         /* pu4_num_pus_in_mb */
664         u4_svc_au_data_size += i4_num_mbs * sizeof(UWORD32);
665     }
666 
667     return u4_svc_au_data_size;
668 }
669 
670 /**
671 *******************************************************************************
672 *
673 * @brief Function to add buffers to SVC AU Data Store Manager
674 *
675 * @param[in] ps_codec
676 *  Pointer to codec context
677 *
678 * @returns  error status
679 *
680 *******************************************************************************
681 */
isvce_svc_au_data_mgr_add_bufs(isvce_codec_t * ps_codec)682 IH264E_ERROR_T isvce_svc_au_data_mgr_add_bufs(isvce_codec_t *ps_codec)
683 {
684     IH264_ERROR_T ret;
685 
686     WORD32 i, j;
687     UWORD8 *pu1_buf;
688 
689     svc_au_data_t *ps_svc_au_data = ps_codec->ps_svc_au_data_base;
690 
691     WORD32 i4_max_dpb_size = ps_codec->i4_ref_buf_cnt;
692     WORD64 i8_alloc_mem_size = ps_codec->i4_svc_au_data_size;
693     WORD32 i4_num_luma_samples = ALIGN16(ps_codec->s_cfg.u4_wd) * ALIGN16(ps_codec->s_cfg.u4_ht);
694     UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
695     DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio;
696 
697     ps_codec->ps_svc_au_data = ps_svc_au_data;
698     pu1_buf = (UWORD8 *) ps_svc_au_data;
699     pu1_buf += BUF_MGR_MAX_CNT * sizeof(ps_svc_au_data[0]);
700 
701     i8_alloc_mem_size -= (BUF_MGR_MAX_CNT * sizeof(ps_svc_au_data[0]));
702 
703     i = 0;
704 
705     while(i < i4_max_dpb_size)
706     {
707         ps_svc_au_data->ps_svc_layer_data = (svc_layer_data_t *) pu1_buf;
708         pu1_buf += u1_num_spatial_layers * sizeof(ps_svc_au_data->ps_svc_layer_data[0]);
709         i8_alloc_mem_size -= u1_num_spatial_layers * sizeof(ps_svc_au_data->ps_svc_layer_data[0]);
710 
711         for(j = u1_num_spatial_layers - 1; j >= 0; j--)
712         {
713             WORD32 i4_layer_luma_samples =
714                 ((DOUBLE) i4_num_luma_samples) /
715                     pow(pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j), 2) +
716                 0.99;
717             WORD32 i4_num_mbs = i4_layer_luma_samples / (MB_SIZE * MB_SIZE);
718 
719             ps_svc_au_data->ps_svc_layer_data[j].pu4_num_pus_in_mb = (UWORD32 *) pu1_buf;
720             pu1_buf +=
721                 i4_num_mbs * sizeof(ps_svc_au_data->ps_svc_layer_data[j].pu4_num_pus_in_mb[0]);
722             i8_alloc_mem_size -=
723                 i4_num_mbs * sizeof(ps_svc_au_data->ps_svc_layer_data[j].pu4_num_pus_in_mb[0]);
724 
725             ps_svc_au_data->ps_svc_layer_data[j].ps_mb_info = (isvce_mb_info_t *) pu1_buf;
726             pu1_buf += i4_num_mbs * sizeof(ps_svc_au_data->ps_svc_layer_data[j].ps_mb_info[0]);
727             i8_alloc_mem_size -=
728                 i4_num_mbs * sizeof(ps_svc_au_data->ps_svc_layer_data[j].ps_mb_info[0]);
729 
730             ASSERT(i8_alloc_mem_size >= 0);
731         }
732 
733         if(i8_alloc_mem_size < 0)
734         {
735             ps_codec->i4_error_code = IH264E_INSUFFICIENT_MEM_MVBANK;
736 
737             return IH264E_INSUFFICIENT_MEM_MVBANK;
738         }
739 
740         ret =
741             ih264_buf_mgr_add((buf_mgr_t *) ps_codec->pv_svc_au_data_store_mgr, ps_svc_au_data, i);
742 
743         if(IH264_SUCCESS != ret)
744         {
745             ps_codec->i4_error_code = IH264E_BUF_MGR_ERROR;
746 
747             return IH264E_BUF_MGR_ERROR;
748         }
749 
750         ps_svc_au_data++;
751         i++;
752     }
753 
754     return IH264E_SUCCESS;
755 }
756 
757 /**
758 *******************************************************************************
759 *
760 * @brief
761 *  Function to initialize svc_au_buf_t structs add au buffers to
762 *  buffer manager in case of non-shared mode
763 *
764 * @param[in] ps_codec
765 *  Pointer to codec context
766 *
767 * @returns  error status
768 *
769 *******************************************************************************
770 */
isvce_svc_au_buf_mgr_add_bufs(isvce_codec_t * ps_codec)771 IH264E_ERROR_T isvce_svc_au_buf_mgr_add_bufs(isvce_codec_t *ps_codec)
772 {
773     WORD32 i, j;
774     WORD32 buf_ret;
775 
776     svc_au_buf_t *ps_pic_buf = ps_codec->ps_pic_buf;
777 
778     IH264E_ERROR_T ret = IH264E_SUCCESS;
779 
780     WORD32 i4_max_dpb_size = ps_codec->i4_ref_buf_cnt;
781     WORD64 i8_alloc_mem_size =
782         ps_codec->i4_total_pic_buf_size - BUF_MGR_MAX_CNT * sizeof(ps_pic_buf[0]);
783     UWORD8 *pu1_buf = (UWORD8 *) ps_codec->ps_pic_buf;
784     UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
785     DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio;
786 
787     pu1_buf += BUF_MGR_MAX_CNT * sizeof(svc_au_buf_t);
788 
789     for(i = 0; i < i4_max_dpb_size; i++)
790     {
791         WORD32 i4_total_fpel_mem_size = 0;
792 
793         ps_pic_buf->ps_layer_yuv_buf_props = (yuv_buf_props_t *) pu1_buf;
794         pu1_buf += u1_num_spatial_layers * sizeof(ps_pic_buf->ps_layer_yuv_buf_props[0]);
795         i8_alloc_mem_size -= u1_num_spatial_layers * sizeof(ps_pic_buf->ps_layer_yuv_buf_props[0]);
796 
797         if(i8_alloc_mem_size < 0)
798         {
799             ps_codec->i4_error_code = IH264E_INSUFFICIENT_MEM_PICBUF;
800             return IH264E_INSUFFICIENT_MEM_PICBUF;
801         }
802 
803         for(j = u1_num_spatial_layers - 1; j >= 0; j--)
804         {
805             WORD32 i4_layer_luma_wd = ((DOUBLE) ps_codec->s_cfg.u4_wd /
806                                        pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) +
807                                       0.99;
808             WORD32 i4_layer_luma_ht = ((DOUBLE) ps_codec->s_cfg.u4_ht /
809                                        pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) +
810                                       0.99;
811             WORD32 i4_layer_luma_samples =
812                 (ALIGN16(i4_layer_luma_wd) + PAD_WD) * (i4_layer_luma_ht + PAD_HT);
813             WORD32 i4_layer_uv_wd = i4_layer_luma_wd;
814             WORD32 i4_layer_uv_ht = i4_layer_luma_ht / 2.0 + 0.99;
815             WORD32 i4_layer_uv_samples =
816                 (ALIGN16(i4_layer_uv_wd) + PAD_WD) * (i4_layer_uv_ht + PAD_HT);
817 
818             ps_pic_buf->ps_layer_yuv_buf_props[j].as_component_bufs[0].i4_data_stride =
819                 ALIGN16(i4_layer_luma_wd) + PAD_WD;
820             ps_pic_buf->ps_layer_yuv_buf_props[j].as_component_bufs[0].pv_data =
821                 pu1_buf +
822                 ps_pic_buf->ps_layer_yuv_buf_props[j].as_component_bufs[0].i4_data_stride *
823                     PAD_TOP +
824                 PAD_LEFT;
825 
826             pu1_buf += i4_layer_luma_samples;
827 
828             ps_pic_buf->ps_layer_yuv_buf_props[j].as_component_bufs[1].i4_data_stride =
829                 ALIGN16(i4_layer_uv_wd) + PAD_WD;
830             ps_pic_buf->ps_layer_yuv_buf_props[j].as_component_bufs[1].pv_data =
831                 pu1_buf +
832                 ps_pic_buf->ps_layer_yuv_buf_props[j].as_component_bufs[1].i4_data_stride *
833                     (PAD_TOP / 2) +
834                 PAD_LEFT;
835 
836             pu1_buf += i4_layer_uv_samples;
837 
838             ps_pic_buf->ps_layer_yuv_buf_props[j].u4_width = i4_layer_luma_wd;
839             ps_pic_buf->ps_layer_yuv_buf_props[j].u4_height = i4_layer_luma_ht;
840             ps_pic_buf->ps_layer_yuv_buf_props[j].u1_bit_depth = 8;
841             ps_pic_buf->ps_layer_yuv_buf_props[j].e_color_format = IV_YUV_420SP_UV;
842 
843             i8_alloc_mem_size -= i4_layer_luma_samples + i4_layer_uv_samples;
844             i4_total_fpel_mem_size += i4_layer_luma_samples + i4_layer_uv_samples;
845 
846             if(i8_alloc_mem_size < 0)
847             {
848                 ps_codec->i4_error_code = IH264E_INSUFFICIENT_MEM_PICBUF;
849                 return IH264E_INSUFFICIENT_MEM_PICBUF;
850             }
851         }
852 
853         buf_ret = ih264_buf_mgr_add((buf_mgr_t *) ps_codec->pv_ref_buf_mgr, ps_pic_buf, i);
854 
855         if(0 != buf_ret)
856         {
857             ps_codec->i4_error_code = IH264E_BUF_MGR_ERROR;
858             return IH264E_BUF_MGR_ERROR;
859         }
860 
861         pu1_buf += (HPEL_PLANES_CNT - 1) * i4_total_fpel_mem_size;
862         ps_pic_buf++;
863     }
864 
865     return ret;
866 }
867 
868 /**
869 *******************************************************************************
870 *
871 * @brief
872 *  Returns size of buffers for storing SVC input data
873 *
874 * @param[in] u1_num_spatial_layers
875 *  Num Spatial Layers
876 *
877 * @param[in] d_spatial_res_ratio
878 *  Resolution Ratio b/w spatial layers
879 *
880 * @param[in] u4_wd
881 *  Input Width
882 *
883 * @param[in] u4_ht
884 *  Input Height
885 *
886 * @returns  Size of buffers
887 *
888 *******************************************************************************
889 */
isvce_get_svc_inp_buf_size(UWORD8 u1_num_spatial_layers,DOUBLE d_spatial_res_ratio,UWORD32 u4_wd,UWORD32 u4_ht)890 UWORD32 isvce_get_svc_inp_buf_size(UWORD8 u1_num_spatial_layers, DOUBLE d_spatial_res_ratio,
891                                    UWORD32 u4_wd, UWORD32 u4_ht)
892 {
893     padding_dims_t s_pad_dims;
894 
895     UWORD32 i;
896     UWORD8 u1_filter_padding_size_x, u1_filter_padding_size_y;
897 
898     UWORD32 u4_size = 0;
899 
900     isvce_get_downscaler_padding_dims(&s_pad_dims);
901 
902     u1_filter_padding_size_x = s_pad_dims.u1_left_pad_size + s_pad_dims.u1_right_pad_size;
903 
904     u1_filter_padding_size_y = s_pad_dims.u1_top_pad_size + s_pad_dims.u1_bottom_pad_size;
905 
906     for(i = 0; i < u1_num_spatial_layers; i++)
907     {
908         WORD32 i4_layer_luma_wd = ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, i)) + 0.99;
909         WORD32 i4_layer_luma_ht = ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, i)) + 0.99;
910         WORD32 i4_layer_luma_samples =
911             (ALIGN16(i4_layer_luma_wd) + PAD_WD + u1_filter_padding_size_x) *
912             (i4_layer_luma_ht + PAD_HT + u1_filter_padding_size_y);
913         WORD32 i4_layer_uv_wd = i4_layer_luma_wd;
914         WORD32 i4_layer_uv_ht = i4_layer_luma_ht / 2.0 + 0.99;
915         /* u1_filter_padding_size_x * 2 because U and V
916         both need same amount of padding */
917         WORD32 i4_layer_uv_samples =
918             (ALIGN16(i4_layer_uv_wd) + PAD_WD + u1_filter_padding_size_x * 2) *
919             (i4_layer_uv_ht + PAD_HT + u1_filter_padding_size_y);
920 
921         u4_size += (i4_layer_luma_samples + i4_layer_uv_samples) * sizeof(UWORD8);
922     }
923 
924     return SVC_MAX_NUM_INP_FRAMES * u4_size;
925 }
926 
927 /**
928 *******************************************************************************
929 *
930 * @brief
931 *  Function to initialize svc input buffers
932 *
933 * @param[in] ps_codec
934 *  Pointer to codec context
935 *
936 * @param[in] ps_mem_rec
937 *  Pointer to memory allocated for input buffers
938 *
939 *******************************************************************************
940 */
isvce_svc_inp_buf_init(isvce_codec_t * ps_codec,iv_mem_rec_t * ps_mem_rec)941 void isvce_svc_inp_buf_init(isvce_codec_t *ps_codec, iv_mem_rec_t *ps_mem_rec)
942 {
943     padding_dims_t s_pad_dims;
944 
945     WORD32 i, j;
946     UWORD8 u1_filter_padding_size_x, u1_filter_padding_size_y;
947 
948     DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio;
949     UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
950     UWORD32 u4_wd = ps_codec->s_cfg.u4_wd;
951     UWORD32 u4_ht = ps_codec->s_cfg.u4_ht;
952     UWORD8 *pu1_buf = ps_mem_rec->pv_base;
953     WORD64 i8_alloc_mem_size =
954         isvce_get_svc_inp_buf_size(u1_num_spatial_layers, d_spatial_res_ratio, u4_wd, u4_ht);
955 
956     isvce_get_downscaler_padding_dims(&s_pad_dims);
957 
958     u1_filter_padding_size_x = s_pad_dims.u1_left_pad_size + s_pad_dims.u1_right_pad_size;
959 
960     u1_filter_padding_size_y = s_pad_dims.u1_top_pad_size + s_pad_dims.u1_bottom_pad_size;
961 
962     for(i = 0; i < SVC_MAX_NUM_INP_FRAMES; i++)
963     {
964         ps_codec->as_inp_list[i].s_svc_params = ps_codec->s_cfg.s_svc_params;
965 
966         for(j = u1_num_spatial_layers - 1; j >= 0; j--)
967         {
968             WORD32 i4_layer_luma_wd =
969                 ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) + 0.99;
970             WORD32 i4_layer_luma_ht =
971                 ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) + 0.99;
972             WORD32 i4_layer_luma_samples =
973                 (ALIGN16(i4_layer_luma_wd) + PAD_WD + u1_filter_padding_size_x) *
974                 (i4_layer_luma_ht + PAD_HT + u1_filter_padding_size_y);
975             WORD32 i4_layer_uv_wd = i4_layer_luma_wd;
976             WORD32 i4_layer_uv_ht = i4_layer_luma_ht / 2.0 + 0.99;
977             /* u1_filter_padding_size_x * 2 because U and V
978             both need same amount of padding */
979             WORD32 i4_layer_uv_samples =
980                 (ALIGN16(i4_layer_uv_wd) + PAD_WD + u1_filter_padding_size_x * 2) *
981                 (i4_layer_uv_ht + PAD_HT + u1_filter_padding_size_y);
982 
983             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].as_component_bufs[Y].i4_data_stride =
984                 ALIGN16(i4_layer_luma_wd) + PAD_WD + u1_filter_padding_size_x;
985             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].as_component_bufs[Y].pv_data =
986                 pu1_buf +
987                 ps_codec->as_inp_list[i]
988                         .as_layer_yuv_buf_props[j]
989                         .as_component_bufs[Y]
990                         .i4_data_stride *
991                     (PAD_TOP + s_pad_dims.u1_top_pad_size) +
992                 (PAD_LEFT + s_pad_dims.u1_left_pad_size);
993             pu1_buf += i4_layer_luma_samples * sizeof(UWORD8);
994             i8_alloc_mem_size -= i4_layer_luma_samples * sizeof(UWORD8);
995 
996             ps_codec->as_inp_list[i]
997                 .as_layer_yuv_buf_props[j]
998                 .as_component_bufs[UV]
999                 .i4_data_stride = ALIGN16(i4_layer_uv_wd) + PAD_WD + u1_filter_padding_size_x * 2;
1000             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].as_component_bufs[UV].pv_data =
1001                 pu1_buf +
1002                 ps_codec->as_inp_list[i]
1003                         .as_layer_yuv_buf_props[j]
1004                         .as_component_bufs[UV]
1005                         .i4_data_stride *
1006                     (PAD_TOP + s_pad_dims.u1_top_pad_size) +
1007                 (PAD_LEFT + s_pad_dims.u1_left_pad_size * 2);
1008             pu1_buf += i4_layer_uv_samples * sizeof(UWORD8);
1009             i8_alloc_mem_size -= i4_layer_uv_samples * sizeof(UWORD8);
1010 
1011             /* Chroma is always stored interleaved */
1012             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].as_component_bufs[V].pv_data = NULL;
1013 
1014             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].u1_bit_depth = 8;
1015             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].e_color_format = IV_YUV_420SP_UV;
1016             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].u4_width = i4_layer_luma_wd;
1017             ps_codec->as_inp_list[i].as_layer_yuv_buf_props[j].u4_height = i4_layer_luma_ht;
1018 
1019             ASSERT(i8_alloc_mem_size >= 0);
1020         }
1021     }
1022 }
1023 
isvce_init_svc_dimension(isvce_inp_buf_t * ps_inp)1024 void isvce_init_svc_dimension(isvce_inp_buf_t *ps_inp)
1025 {
1026     WORD32 i;
1027 
1028     UWORD8 u1_num_spatial_layers = ps_inp->s_svc_params.u1_num_spatial_layers;
1029     DOUBLE d_spatial_res_ratio = ps_inp->s_svc_params.d_spatial_res_ratio;
1030     UWORD32 u4_wd = ps_inp->s_inp_props.s_raw_buf.au4_wd[Y];
1031     UWORD32 u4_ht = ps_inp->s_inp_props.s_raw_buf.au4_ht[Y];
1032 
1033     for(i = 0; i < u1_num_spatial_layers; i++)
1034     {
1035         ps_inp->as_layer_yuv_buf_props[i].u4_width =
1036             ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
1037         ps_inp->as_layer_yuv_buf_props[i].u4_height =
1038             ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
1039     }
1040 }
1041 
1042 /**
1043 *******************************************************************************
1044 *
1045 * @brief
1046 *  Pads input buf as assumed by the downscaler filter
1047 *
1048 * @param[in] ps_codec
1049 *  Pointer to codec ctxt
1050 *
1051 * @param[in] ps_inp
1052 *  Pointer to svc input buffer
1053 *
1054 * @param[in] u1_svc_layer_index
1055 *  SVC layer index of the buffer
1056 *
1057 *******************************************************************************
1058 */
1059 
isvce_pad_buf_for_filtering(isvce_codec_t * ps_codec,isvce_inp_buf_t * ps_inp,UWORD8 u1_svc_layer_index)1060 static void isvce_pad_buf_for_filtering(isvce_codec_t *ps_codec, isvce_inp_buf_t *ps_inp,
1061                                         UWORD8 u1_svc_layer_index)
1062 {
1063     padding_dims_t s_pad_dims;
1064 
1065     UWORD8 *pu1_buf;
1066     UWORD32 u4_buf_width, u4_buf_height;
1067 
1068     UWORD8 u1_pad_left_size;
1069     UWORD8 u1_pad_right_size;
1070     UWORD8 u1_pad_top_size;
1071     UWORD8 u1_pad_bottom_size;
1072     UWORD8 u1_filter_padding_size_x;
1073     UWORD8 u1_filter_padding_size_chroma_x;
1074 
1075     ASSERT(ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].e_color_format == IV_YUV_420SP_UV);
1076 
1077     isvce_get_downscaler_padding_dims(&s_pad_dims);
1078 
1079     u1_pad_left_size = s_pad_dims.u1_left_pad_size;
1080     u1_pad_right_size = s_pad_dims.u1_right_pad_size;
1081     u1_pad_top_size = s_pad_dims.u1_top_pad_size;
1082     u1_pad_bottom_size = s_pad_dims.u1_bottom_pad_size;
1083     u1_filter_padding_size_x = u1_pad_left_size + u1_pad_right_size;
1084     u1_filter_padding_size_chroma_x = u1_filter_padding_size_x * 2;
1085 
1086     u4_buf_width = ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].u4_width;
1087 
1088     u4_buf_height = ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].u4_height;
1089 
1090     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1091                               .as_component_bufs[0]
1092                               .pv_data);
1093 
1094     ps_codec->pf_pad_left_luma(
1095         pu1_buf,
1096         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[0].i4_data_stride,
1097         u4_buf_height, u1_pad_left_size);
1098 
1099     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1100                               .as_component_bufs[0]
1101                               .pv_data);
1102 
1103     pu1_buf += u4_buf_width;
1104 
1105     ps_codec->pf_pad_right_luma(
1106         pu1_buf,
1107         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[0].i4_data_stride,
1108         u4_buf_height, u1_pad_right_size);
1109 
1110     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1111                               .as_component_bufs[1]
1112                               .pv_data);
1113 
1114     ps_codec->pf_pad_left_chroma(
1115         pu1_buf,
1116         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[1].i4_data_stride,
1117         u4_buf_height / 2, u1_pad_left_size * 2);
1118 
1119     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1120                               .as_component_bufs[1]
1121                               .pv_data);
1122 
1123     pu1_buf += u4_buf_width;
1124 
1125     ps_codec->pf_pad_right_chroma(
1126         pu1_buf,
1127         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[1].i4_data_stride,
1128         u4_buf_height / 2, u1_pad_right_size * 2);
1129 
1130     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1131                               .as_component_bufs[0]
1132                               .pv_data) -
1133               u1_pad_left_size;
1134 
1135     ps_codec->pf_pad_top(
1136         pu1_buf,
1137         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[0].i4_data_stride,
1138         (u4_buf_width + u1_filter_padding_size_x), u1_pad_top_size);
1139 
1140     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1141                               .as_component_bufs[0]
1142                               .pv_data) -
1143               u1_pad_left_size;
1144 
1145     pu1_buf +=
1146         (u4_buf_height *
1147          ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[0].i4_data_stride);
1148 
1149     ps_codec->pf_pad_bottom(
1150         pu1_buf,
1151         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[0].i4_data_stride,
1152         (u4_buf_width + u1_filter_padding_size_x), u1_pad_bottom_size);
1153 
1154     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1155                               .as_component_bufs[1]
1156                               .pv_data) -
1157               u1_pad_left_size * 2;
1158 
1159     ps_codec->pf_pad_top(
1160         pu1_buf,
1161         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[1].i4_data_stride,
1162         (u4_buf_width + u1_filter_padding_size_chroma_x), u1_pad_top_size);
1163 
1164     pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index]
1165                               .as_component_bufs[1]
1166                               .pv_data) -
1167               u1_pad_left_size * 2;
1168 
1169     pu1_buf +=
1170         ((u4_buf_height / 2) *
1171          ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[1].i4_data_stride);
1172 
1173     ps_codec->pf_pad_bottom(
1174         pu1_buf,
1175         ps_inp->as_layer_yuv_buf_props[u1_svc_layer_index].as_component_bufs[1].i4_data_stride,
1176         (u4_buf_width + u1_filter_padding_size_chroma_x), u1_pad_bottom_size);
1177 }
1178 
1179 /**
1180 *******************************************************************************
1181 *
1182 * @brief
1183 *  Pads raw input to satisfy SVC compliant input dimensions
1184 *
1185 * @param[in] ps_codec
1186 *  Pointer to codec ctxt
1187 *
1188 * @param[in] ps_inp
1189 *  Pointer to svc input buffer
1190 *
1191 *******************************************************************************
1192 */
1193 
isvce_pad_input_to_svc_compliant_dims(isvce_codec_t * ps_codec,isvce_inp_buf_t * ps_inp)1194 static void isvce_pad_input_to_svc_compliant_dims(isvce_codec_t *ps_codec, isvce_inp_buf_t *ps_inp)
1195 {
1196     UWORD8 *pu1_buf;
1197     UWORD32 u4_raw_input_wd, u4_raw_input_ht, u4_padded_width, u4_padded_height, u4_width_delta,
1198         u4_height_delta;
1199     UWORD8 u1_num_layers = ps_inp->s_svc_params.u1_num_spatial_layers;
1200 
1201     ASSERT(ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].e_color_format == IV_YUV_420SP_UV);
1202 
1203     u4_padded_width = ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].u4_width;
1204     u4_padded_height = ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].u4_height;
1205     u4_raw_input_wd = ps_inp->s_inp_props.s_raw_buf.au4_wd[0];
1206     u4_raw_input_ht = ps_inp->s_inp_props.s_raw_buf.au4_ht[0];
1207     u4_width_delta = u4_padded_width - u4_raw_input_wd;
1208     u4_height_delta = u4_padded_height - u4_raw_input_ht;
1209 
1210     ASSERT(!(u4_width_delta & 1));
1211     ASSERT(!(u4_height_delta & 1));
1212 
1213     if(u4_width_delta)
1214     {
1215         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1216                                   .as_component_bufs[0]
1217                                   .pv_data);
1218 
1219         pu1_buf += ((u4_width_delta / 2) + (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1220                                                 .as_component_bufs[0]
1221                                                 .i4_data_stride) *
1222                                                (u4_height_delta / 2));
1223 
1224         ps_codec->pf_pad_left_luma(
1225             pu1_buf,
1226             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[0].i4_data_stride,
1227             u4_padded_height, u4_width_delta / 2);
1228 
1229         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1230                                   .as_component_bufs[0]
1231                                   .pv_data);
1232 
1233         pu1_buf += ((u4_width_delta / 2) + (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1234                                                 .as_component_bufs[0]
1235                                                 .i4_data_stride) *
1236                                                (u4_height_delta / 2));
1237 
1238         pu1_buf += u4_raw_input_wd;
1239 
1240         ps_codec->pf_pad_right_luma(
1241             pu1_buf,
1242             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[0].i4_data_stride,
1243             u4_padded_height, u4_width_delta / 2);
1244 
1245         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1246                                   .as_component_bufs[1]
1247                                   .pv_data);
1248 
1249         pu1_buf += ((u4_width_delta / 2) + (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1250                                                 .as_component_bufs[1]
1251                                                 .i4_data_stride) *
1252                                                (u4_height_delta / 4));
1253 
1254         ps_codec->pf_pad_left_chroma(
1255             pu1_buf,
1256             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[1].i4_data_stride,
1257             u4_padded_height / 2, u4_width_delta / 2);
1258 
1259         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1260                                   .as_component_bufs[1]
1261                                   .pv_data);
1262 
1263         pu1_buf += ((u4_width_delta / 2) + (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1264                                                 .as_component_bufs[1]
1265                                                 .i4_data_stride) *
1266                                                (u4_height_delta / 4));
1267 
1268         pu1_buf += u4_raw_input_wd;
1269 
1270         ps_codec->pf_pad_right_chroma(
1271             pu1_buf,
1272             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[1].i4_data_stride,
1273             u4_padded_height / 2, u4_width_delta / 2);
1274     }
1275 
1276     if(u4_height_delta)
1277     {
1278         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1279                                   .as_component_bufs[0]
1280                                   .pv_data);
1281 
1282         pu1_buf += ((ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1283                          .as_component_bufs[0]
1284                          .i4_data_stride) *
1285                     (u4_height_delta / 2));
1286 
1287         ps_codec->pf_pad_top(
1288             pu1_buf,
1289             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[0].i4_data_stride,
1290             u4_padded_width, u4_height_delta / 2);
1291 
1292         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1293                                   .as_component_bufs[0]
1294                                   .pv_data);
1295 
1296         pu1_buf += ((ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1297                          .as_component_bufs[0]
1298                          .i4_data_stride) *
1299                     (u4_height_delta / 2));
1300 
1301         pu1_buf +=
1302             (u4_raw_input_ht *
1303              ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[0].i4_data_stride);
1304 
1305         ps_codec->pf_pad_bottom(
1306             pu1_buf,
1307             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[0].i4_data_stride,
1308             u4_padded_width, u4_height_delta / 2);
1309 
1310         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1311                                   .as_component_bufs[1]
1312                                   .pv_data);
1313 
1314         pu1_buf += ((ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1315                          .as_component_bufs[1]
1316                          .i4_data_stride) *
1317                     (u4_height_delta / 4));
1318 
1319         ps_codec->pf_pad_top(
1320             pu1_buf,
1321             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[1].i4_data_stride,
1322             u4_padded_width, u4_height_delta / 4);
1323 
1324         pu1_buf = (UWORD8 *) (ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1325                                   .as_component_bufs[1]
1326                                   .pv_data);
1327 
1328         pu1_buf += ((ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1]
1329                          .as_component_bufs[1]
1330                          .i4_data_stride) *
1331                     (u4_height_delta / 4));
1332 
1333         pu1_buf +=
1334             ((u4_raw_input_ht / 2) *
1335              ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[1].i4_data_stride);
1336 
1337         ps_codec->pf_pad_bottom(
1338             pu1_buf,
1339             ps_inp->as_layer_yuv_buf_props[u1_num_layers - 1].as_component_bufs[1].i4_data_stride,
1340             u4_padded_width, u4_height_delta / 4);
1341     }
1342 }
1343 
1344 /**
1345 *******************************************************************************
1346 *
1347 * @brief
1348 *  Format conversion and downsampling for deriving spatial layer inputs
1349 *
1350 * @param[in] ps_inp
1351 *  Pointer to input buffer
1352 *
1353 *******************************************************************************
1354 */
isvce_svc_inp_buf_populate(isvce_codec_t * ps_codec,isvce_inp_buf_t * ps_inp)1355 void isvce_svc_inp_buf_populate(isvce_codec_t *ps_codec, isvce_inp_buf_t *ps_inp)
1356 {
1357     yuv_buf_props_t s_src_buf_props, s_dst_buf_props;
1358 
1359     UWORD32 i;
1360     UWORD32 u4_blk_x, u4_blk_y;
1361     UWORD8 *pu1_planar_y, *pu1_planar_u, *pu1_planar_v, *pu1_semi_planar_y, *pu1_semi_planar_uv;
1362     UWORD8 *pu1_src_luma, *pu1_src_chroma, *pu1_dst_luma, *pu1_dst_chroma;
1363     UWORD32 u4_num_blocks_x, u4_num_blocks_y;
1364     UWORD32 u4_scaled_block_wd, u4_scaled_block_ht;
1365     UWORD32 u4_blk_wd_luma, u4_blk_ht_luma;
1366 
1367     downscaler_ctxt_t *ps_scaler = &ps_codec->s_scaler;
1368     isa_dependent_fxns_t *ps_isa_dependent_fxns = &ps_codec->s_isa_dependent_fxns;
1369     mem_fxns_t *ps_mem_fxns = &ps_isa_dependent_fxns->s_mem_fxns;
1370 
1371     const UWORD8 u1_num_yuv_components_420sp = NUM_SP_COMPONENTS;
1372     UWORD8 u1_num_spatial_layers = ps_inp->s_svc_params.u1_num_spatial_layers;
1373     UWORD32 u4_padded_width = ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1].u4_width;
1374     UWORD32 u4_padded_height = ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1].u4_height;
1375     UWORD32 u4_raw_input_wd = ps_inp->s_inp_props.s_raw_buf.au4_wd[0];
1376     UWORD32 u4_raw_input_ht = ps_inp->s_inp_props.s_raw_buf.au4_ht[0];
1377     UWORD32 u4_width_delta = u4_padded_width - u4_raw_input_wd;
1378     UWORD32 u4_height_delta = u4_padded_height - u4_raw_input_ht;
1379 
1380     ASSERT(!(u4_width_delta & 1));
1381     ASSERT(!(u4_height_delta & 1));
1382 
1383     ASSERT((ps_inp->s_inp_props.s_raw_buf.e_color_fmt == IV_YUV_420P) ||
1384            (ps_inp->s_inp_props.s_raw_buf.e_color_fmt == IV_YUV_420SP_UV));
1385 
1386     /* Check is input is valid */
1387     if(!(ps_inp->s_inp_props.s_raw_buf.apv_bufs[0]))
1388     {
1389         ASSERT(0);
1390 
1391         return;
1392     }
1393 
1394     /* Convert the input into semi-planar in case of other formats */
1395     if(ps_inp->s_inp_props.s_raw_buf.e_color_fmt == IV_YUV_420P)
1396     {
1397         pu1_planar_y = (UWORD8 *) ps_inp->s_inp_props.s_raw_buf.apv_bufs[0];
1398         pu1_planar_u = (UWORD8 *) ps_inp->s_inp_props.s_raw_buf.apv_bufs[1];
1399         pu1_planar_v = (UWORD8 *) ps_inp->s_inp_props.s_raw_buf.apv_bufs[2];
1400 
1401         pu1_semi_planar_y = (UWORD8 *) ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1402                                 .as_component_bufs[0]
1403                                 .pv_data;
1404 
1405         pu1_semi_planar_uv = (UWORD8 *) ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1406                                  .as_component_bufs[1]
1407                                  .pv_data;
1408 
1409         pu1_semi_planar_y +=
1410             ((u4_width_delta / 2) + (ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1411                                          .as_component_bufs[0]
1412                                          .i4_data_stride) *
1413                                         (u4_height_delta / 2));
1414 
1415         pu1_semi_planar_uv +=
1416             ((u4_width_delta / 2) + (ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1417                                          .as_component_bufs[1]
1418                                          .i4_data_stride) *
1419                                         (u4_height_delta / 4));
1420 
1421         ps_codec->pf_ih264e_conv_420p_to_420sp(
1422             pu1_planar_y, pu1_planar_u, pu1_planar_v, pu1_semi_planar_y, pu1_semi_planar_uv,
1423             ps_inp->s_inp_props.s_raw_buf.au4_ht[0], ps_inp->s_inp_props.s_raw_buf.au4_wd[0],
1424             ps_inp->s_inp_props.s_raw_buf.au4_strd[0], ps_inp->s_inp_props.s_raw_buf.au4_strd[1],
1425             ps_inp->s_inp_props.s_raw_buf.au4_strd[2],
1426             ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1427                 .as_component_bufs[0]
1428                 .i4_data_stride,
1429             ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1430                 .as_component_bufs[1]
1431                 .i4_data_stride,
1432             0);
1433     }
1434     else
1435     {
1436         UWORD32 u4_wd, u4_ht;
1437         UWORD8 u1_comp;
1438         UWORD32 au4_arr_dims[4];
1439         UWORD8 *pu1_src, *pu1_dst;
1440 
1441         au4_arr_dims[0] = ps_inp->s_inp_props.s_raw_buf.au4_wd[0];
1442         au4_arr_dims[1] = ps_inp->s_inp_props.s_raw_buf.au4_ht[0];
1443         au4_arr_dims[2] = ps_inp->s_inp_props.s_raw_buf.au4_wd[1];
1444         au4_arr_dims[3] = ps_inp->s_inp_props.s_raw_buf.au4_ht[1];
1445 
1446         for(u1_comp = 0; u1_comp < u1_num_yuv_components_420sp; u1_comp++)
1447         {
1448             u4_wd = au4_arr_dims[u1_comp * 2];
1449             u4_ht = au4_arr_dims[(u1_comp * 2) + 1];
1450 
1451             pu1_dst = (UWORD8 *) ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1452                           .as_component_bufs[u1_comp]
1453                           .pv_data;
1454 
1455             pu1_dst +=
1456                 ((u4_width_delta / 2) + (ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1457                                              .as_component_bufs[u1_comp]
1458                                              .i4_data_stride) *
1459                                             ((u4_height_delta / 2) / (u1_comp + 1)));
1460 
1461             pu1_src = ps_inp->s_inp_props.s_raw_buf.apv_bufs[u1_comp];
1462 
1463             ps_mem_fxns->pf_copy_2d(pu1_dst,
1464                                     ps_inp->as_layer_yuv_buf_props[u1_num_spatial_layers - 1]
1465                                         .as_component_bufs[u1_comp]
1466                                         .i4_data_stride,
1467                                     pu1_src, ps_inp->s_inp_props.s_raw_buf.au4_strd[u1_comp], u4_wd,
1468                                     u4_ht);
1469         }
1470     }
1471 
1472     /* Padding input to satisfy SVC constraints */
1473     isvce_pad_input_to_svc_compliant_dims(ps_codec, ps_inp);
1474 
1475     /* Downscaling */
1476     for(i = u1_num_spatial_layers - 1; i > 0; i--)
1477     {
1478         const UWORD32 u4_default_scaled_blk_wd =
1479             gu4_downscaler_blk_size / ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio + 0.5;
1480         const UWORD32 u4_default_scaled_blk_ht =
1481             gu4_downscaler_blk_size / ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio + 0.5;
1482 
1483         isvce_pad_buf_for_filtering(ps_codec, ps_inp, i);
1484 
1485         s_src_buf_props = ps_inp->as_layer_yuv_buf_props[i];
1486         s_dst_buf_props = ps_inp->as_layer_yuv_buf_props[i - 1];
1487 
1488         u4_num_blocks_x =
1489             (s_src_buf_props.u4_width + (gu4_downscaler_blk_size - 1)) / gu4_downscaler_blk_size;
1490 
1491         u4_num_blocks_y =
1492             (s_src_buf_props.u4_height + (gu4_downscaler_blk_size - 1)) / gu4_downscaler_blk_size;
1493 
1494         pu1_src_luma = (UWORD8 *) s_src_buf_props.as_component_bufs[Y].pv_data;
1495         pu1_src_chroma = (UWORD8 *) s_src_buf_props.as_component_bufs[U].pv_data;
1496         pu1_dst_luma = (UWORD8 *) s_dst_buf_props.as_component_bufs[Y].pv_data;
1497         pu1_dst_chroma = (UWORD8 *) s_dst_buf_props.as_component_bufs[U].pv_data;
1498 
1499         for(u4_blk_x = 0; u4_blk_x < u4_num_blocks_x; u4_blk_x++)
1500         {
1501             for(u4_blk_y = 0; u4_blk_y < u4_num_blocks_y; u4_blk_y++)
1502             {
1503                 u4_blk_wd_luma = isvce_get_downscaler_blk_dims(s_src_buf_props.u4_width, u4_blk_x,
1504                                                                gu4_downscaler_blk_size);
1505 
1506                 u4_blk_ht_luma = isvce_get_downscaler_blk_dims(s_src_buf_props.u4_height, u4_blk_y,
1507                                                                gu4_downscaler_blk_size);
1508 
1509                 u4_scaled_block_wd = isvce_get_downscaler_blk_dims(
1510                     s_dst_buf_props.u4_width, u4_blk_x, u4_default_scaled_blk_wd);
1511 
1512                 u4_scaled_block_ht = isvce_get_downscaler_blk_dims(
1513                     s_dst_buf_props.u4_height, u4_blk_y, u4_default_scaled_blk_ht);
1514 
1515                 s_src_buf_props.as_component_bufs[Y].pv_data =
1516                     pu1_src_luma + (u4_blk_x * gu4_downscaler_blk_size +
1517                                     u4_blk_y * gu4_downscaler_blk_size *
1518                                         s_src_buf_props.as_component_bufs[Y].i4_data_stride);
1519 
1520                 s_src_buf_props.as_component_bufs[U].pv_data =
1521                     pu1_src_chroma + (u4_blk_x * gu4_downscaler_blk_size +
1522                                       u4_blk_y * (gu4_downscaler_blk_size / 2) *
1523                                           s_src_buf_props.as_component_bufs[U].i4_data_stride);
1524 
1525                 s_dst_buf_props.as_component_bufs[Y].pv_data =
1526                     pu1_dst_luma + (u4_blk_x * u4_default_scaled_blk_wd +
1527                                     u4_blk_y * u4_default_scaled_blk_ht *
1528                                         s_dst_buf_props.as_component_bufs[Y].i4_data_stride);
1529 
1530                 s_dst_buf_props.as_component_bufs[U].pv_data =
1531                     pu1_dst_chroma + (u4_blk_x * u4_default_scaled_blk_wd +
1532                                       u4_blk_y * (u4_default_scaled_blk_ht / 2) *
1533                                           s_dst_buf_props.as_component_bufs[U].i4_data_stride);
1534 
1535                 ASSERT(!(u4_scaled_block_wd & 1));
1536                 ASSERT(!(u4_scaled_block_ht & 1));
1537 
1538                 isvce_process_downscaler(ps_scaler, &s_src_buf_props, &s_dst_buf_props,
1539                                          u4_blk_wd_luma, u4_blk_ht_luma);
1540             }
1541         }
1542     }
1543 
1544     UNUSED(u4_scaled_block_wd);
1545     UNUSED(u4_scaled_block_ht);
1546 }
1547 
1548 /**
1549 *******************************************************************************
1550 *
1551 * @brief
1552 *  calculates the greatest common divisor between the two parameters.
1553 *
1554 *******************************************************************************
1555 */
1556 
isvce_get_GCD(DOUBLE a,DOUBLE b)1557 static DOUBLE isvce_get_GCD(DOUBLE a, DOUBLE b)
1558 {
1559     if(b == 0)
1560     {
1561         return a;
1562     }
1563 
1564     return isvce_get_GCD(b, fmod(a, b));
1565 }
1566 
1567 /**
1568 *******************************************************************************
1569 *
1570 * @brief
1571 *  calculates the least common multiple between the two parameters
1572 *
1573 *******************************************************************************
1574 */
1575 
isvce_get_LCM(DOUBLE a,DOUBLE b)1576 static DOUBLE isvce_get_LCM(DOUBLE a, DOUBLE b) { return (a / isvce_get_GCD(a, b)) * b; }
1577 
1578 /**
1579 *******************************************************************************
1580 *
1581 * @brief
1582 *  sets the width and height in config structure to SVC compliant width and
1583 *   height
1584 *
1585 * @param[in] ps_cfg
1586 *  Pointer to config struct
1587 *
1588 * @param[in] u4_app_wd
1589 *  width of the YUV as read by the app
1590 *
1591 * @param[in] u4_app_ht
1592 *  height of the YUV as read by the app
1593 *
1594 *******************************************************************************
1595 */
1596 
isvce_get_svc_compliant_dimensions(UWORD8 u1_num_spatial_layers,DOUBLE d_scaling_factor,UWORD32 u4_wd,UWORD32 u4_ht,UWORD32 * pu4_svc_comp_wd,UWORD32 * pu4_svc_comp_ht)1597 void isvce_get_svc_compliant_dimensions(UWORD8 u1_num_spatial_layers, DOUBLE d_scaling_factor,
1598                                         UWORD32 u4_wd, UWORD32 u4_ht, UWORD32 *pu4_svc_comp_wd,
1599                                         UWORD32 *pu4_svc_comp_ht)
1600 {
1601     DOUBLE d_scaling_factor_power_num_layers_minus1 = 0;
1602     UWORD32 u4_constraint_offset = 0;
1603 
1604     d_scaling_factor_power_num_layers_minus1 = pow(d_scaling_factor, u1_num_spatial_layers - 1);
1605 
1606     if(fmod(16, d_scaling_factor_power_num_layers_minus1))
1607     {
1608         u4_constraint_offset =
1609             (UWORD32) isvce_get_LCM(16, d_scaling_factor_power_num_layers_minus1);
1610     }
1611     else
1612     {
1613         u4_constraint_offset = (UWORD32) (16 * d_scaling_factor_power_num_layers_minus1);
1614     }
1615 
1616     if(u4_wd % u4_constraint_offset)
1617     {
1618         *pu4_svc_comp_wd = u4_wd - ((u4_wd) % u4_constraint_offset) + u4_constraint_offset;
1619     }
1620     else
1621     {
1622         *pu4_svc_comp_wd = u4_wd;
1623     }
1624 
1625     if(u4_ht % u4_constraint_offset)
1626     {
1627         *pu4_svc_comp_ht = u4_ht - ((u4_ht) % u4_constraint_offset) + u4_constraint_offset;
1628     }
1629     else
1630     {
1631         *pu4_svc_comp_ht = u4_ht;
1632     }
1633 }
1634 
1635 /**
1636 *******************************************************************************
1637 *
1638 * @brief
1639 *  Returns size of buffers for storing SVC layer nbr info
1640 *
1641 * @param[in] u1_num_spatial_layers
1642 *  Num Spatial Layers
1643 *
1644 * @param[in] d_spatial_res_ratio
1645 *  Resolution Ratio b/w spatial layers
1646 *
1647 * @param[in] u4_wd
1648 *  Input Width
1649 *
1650 * @returns  Size of buffers
1651 *
1652 *******************************************************************************
1653 */
isvce_get_svc_nbr_info_buf_size(UWORD8 u1_num_spatial_layers,DOUBLE d_spatial_res_ratio,UWORD32 u4_wd,UWORD32 u4_ht)1654 UWORD32 isvce_get_svc_nbr_info_buf_size(UWORD8 u1_num_spatial_layers, DOUBLE d_spatial_res_ratio,
1655                                         UWORD32 u4_wd, UWORD32 u4_ht)
1656 {
1657     UWORD32 i;
1658 
1659     UWORD32 u4_size = 0;
1660 
1661     ASSERT(1 == MAX_CTXT_SETS);
1662 
1663     u4_size += MAX_PROCESS_CTXT * u1_num_spatial_layers * sizeof(nbr_info_t);
1664 
1665     for(i = 0; i < u1_num_spatial_layers; i++)
1666     {
1667         WORD32 i4_layer_luma_wd = ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, i)) + 0.99;
1668         WORD32 i4_layer_luma_ht = ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, i)) + 0.99;
1669         WORD32 i4_num_mbs_in_row = i4_layer_luma_wd / MB_SIZE;
1670         WORD32 i4_num_mbs_in_col = i4_layer_luma_ht / MB_SIZE;
1671 
1672         /* ps_top_row_mb_info */
1673         u4_size += (i4_num_mbs_in_row + 1) * i4_num_mbs_in_col * sizeof(isvce_mb_info_t);
1674 
1675         /* ps_left_mb_info */
1676         u4_size += MAX_PROCESS_CTXT * sizeof(isvce_mb_info_t);
1677 
1678         /* ps_top_mb_intra_modes */
1679         u4_size += (i4_num_mbs_in_row + 1) * i4_num_mbs_in_col * sizeof(mb_intra_modes_t);
1680 
1681         /* ps_left_mb_intra_modes */
1682         u4_size += MAX_PROCESS_CTXT * sizeof(mb_intra_modes_t);
1683     }
1684 
1685     return u4_size;
1686 }
1687 
1688 /**
1689 *******************************************************************************
1690 *
1691 * @brief
1692 *  Function to initialize svc nbr info buffers
1693 *
1694 * @param[in] ps_codec
1695 *  Pointer to codec context
1696 *
1697 * @param[in] ps_mem_rec
1698 *  Pointer to memory allocated for input buffers
1699 *
1700 *******************************************************************************
1701 */
isvce_svc_nbr_info_buf_init(isvce_codec_t * ps_codec,iv_mem_rec_t * ps_mem_rec)1702 void isvce_svc_nbr_info_buf_init(isvce_codec_t *ps_codec, iv_mem_rec_t *ps_mem_rec)
1703 {
1704     WORD32 i, j;
1705 
1706     DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio;
1707     UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
1708     UWORD32 u4_wd = ps_codec->s_cfg.u4_wd;
1709     UWORD32 u4_ht = ps_codec->s_cfg.u4_ht;
1710 
1711     UWORD8 *pu1_buf = ps_mem_rec->pv_base;
1712     WORD64 i8_alloc_mem_size =
1713         isvce_get_svc_nbr_info_buf_size(u1_num_spatial_layers, d_spatial_res_ratio, u4_wd, u4_ht);
1714 
1715     ASSERT(1 == MAX_CTXT_SETS);
1716 
1717     for(i = 0; i < MAX_PROCESS_CTXT; i++)
1718     {
1719         ps_codec->as_process[i].s_nbr_info_base.ps_layer_nbr_info = (nbr_info_t *) pu1_buf;
1720         pu1_buf += u1_num_spatial_layers *
1721                    sizeof(ps_codec->as_process[i].s_nbr_info_base.ps_layer_nbr_info[0]);
1722         i8_alloc_mem_size -= u1_num_spatial_layers *
1723                              sizeof(ps_codec->as_process[i].s_nbr_info_base.ps_layer_nbr_info[0]);
1724 
1725         for(j = u1_num_spatial_layers - 1; j >= 0; j--)
1726         {
1727             ps_codec->as_process[i].s_nbr_info_base.ps_layer_nbr_info[j].ps_left_mb_info =
1728                 (isvce_mb_info_t *) pu1_buf;
1729             ps_codec->as_process[i].s_nbr_info.ps_left_mb_info = (isvce_mb_info_t *) pu1_buf;
1730             pu1_buf += sizeof(ps_codec->as_process[i].s_nbr_info.ps_left_mb_info[0]);
1731             i8_alloc_mem_size -= sizeof(ps_codec->as_process[i].s_nbr_info.ps_left_mb_info[0]);
1732 
1733             ps_codec->as_process[i].s_nbr_info_base.ps_layer_nbr_info[j].ps_left_mb_intra_modes =
1734                 (mb_intra_modes_t *) pu1_buf;
1735             ps_codec->as_process[i].s_nbr_info.ps_left_mb_intra_modes =
1736                 (mb_intra_modes_t *) pu1_buf;
1737             pu1_buf += sizeof(ps_codec->as_process[i].s_nbr_info.ps_left_mb_intra_modes[0]);
1738             i8_alloc_mem_size -=
1739                 sizeof(ps_codec->as_process[i].s_nbr_info.ps_left_mb_intra_modes[0]);
1740         }
1741 
1742         ASSERT(i8_alloc_mem_size >= 0);
1743     }
1744 
1745     for(i = u1_num_spatial_layers - 1; i >= 0; i--)
1746     {
1747         isvce_mb_info_t *ps_top_mb_info;
1748         mb_intra_modes_t *ps_top_intra_modes;
1749 
1750         WORD32 i4_layer_luma_wd =
1751             ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
1752         WORD32 i4_layer_luma_ht =
1753             ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
1754         WORD32 i4_num_mbs_in_row = i4_layer_luma_wd / MB_SIZE;
1755         WORD32 i4_num_mbs_in_col = i4_layer_luma_ht / MB_SIZE;
1756 
1757         ps_top_mb_info = (isvce_mb_info_t *) pu1_buf;
1758         pu1_buf += (i4_num_mbs_in_row + 1) * i4_num_mbs_in_col * sizeof(ps_top_mb_info[0]);
1759         i8_alloc_mem_size -=
1760             (i4_num_mbs_in_row + 1) * i4_num_mbs_in_col * sizeof(ps_top_mb_info[0]);
1761 
1762         ps_top_intra_modes = (mb_intra_modes_t *) pu1_buf;
1763         pu1_buf += (i4_num_mbs_in_row + 1) * i4_num_mbs_in_col * sizeof(ps_top_intra_modes[0]);
1764         i8_alloc_mem_size -=
1765             (i4_num_mbs_in_row + 1) * i4_num_mbs_in_col * sizeof(ps_top_intra_modes[0]);
1766 
1767         for(j = 0; j < MAX_PROCESS_CTXT; j++)
1768         {
1769             ps_codec->as_process[j].s_nbr_info_base.ps_layer_nbr_info[i].ps_top_row_mb_info =
1770                 ps_top_mb_info;
1771             ps_codec->as_process[j].s_nbr_info.ps_top_row_mb_info = NULL;
1772 
1773             ps_codec->as_process[j].s_nbr_info_base.ps_layer_nbr_info[i].ps_top_mb_intra_modes =
1774                 ps_top_intra_modes;
1775             ps_codec->as_process[j].s_nbr_info.ps_top_mb_intra_modes = NULL;
1776         }
1777 
1778         ASSERT(i8_alloc_mem_size >= 0);
1779     }
1780 }
1781 
1782 /**
1783 *******************************************************************************
1784 *
1785 * @brief
1786 *  isvce_codec_t and proc_t initialisations for an Access Unit
1787 *
1788 * @par Description:
1789 *  Before beginning to encode the frame, the current function initializes all
1790 *  the ctxts (proc, entropy, me, ...) basing on the input configured params.
1791 *  It locates space for storing recon in the encoder picture buffer set, fetches
1792 *  reference frame from encoder picture buffer set. Calls RC pre-enc to get
1793 *  qp and pic type for the current frame. Queues proc jobs so that
1794 *  the other threads can begin encoding. In brief, this function sets up the
1795 *  tone for the entire encoder.
1796 *
1797 * @param[in] ps_codec
1798 *  Pointer to codec context
1799 *
1800 * @param[in] ps_inp_buf
1801 *  Pointer to input buffer context
1802 *
1803 * @returns  error_status
1804 *
1805 * @remarks
1806 *
1807 *
1808 *******************************************************************************
1809 */
isvce_svc_au_init(isvce_codec_t * ps_codec,isvce_inp_buf_t * ps_inp_buf)1810 IH264E_ERROR_T isvce_svc_au_init(isvce_codec_t *ps_codec, isvce_inp_buf_t *ps_inp_buf)
1811 {
1812     svc_au_buf_t *ps_cur_pic;
1813 
1814     WORD32 cur_mv_bank_buf_id;
1815     WORD32 cur_pic_buf_id;
1816     WORD32 ref_set_id;
1817     WORD32 i, j;
1818 
1819     svc_au_data_t *ps_mv_buf = NULL;
1820     svc_au_buf_t *aps_ref_pic[MAX_REF_PIC_CNT] = {NULL, NULL};
1821     svc_au_data_t *aps_mv_buf[MAX_REF_PIC_CNT] = {NULL, NULL};
1822 
1823     IH264E_ERROR_T error_status = IH264E_SUCCESS;
1824     PIC_TYPE_T *pic_type = &ps_codec->pic_type;
1825 
1826     UWORD32 u4_timestamp_high = ps_inp_buf->s_inp_props.u4_timestamp_high;
1827     UWORD32 u4_timestamp_low = ps_inp_buf->s_inp_props.u4_timestamp_low;
1828     WORD32 ctxt_sel = ps_codec->i4_encode_api_call_cnt % MAX_CTXT_SETS;
1829     /* Diamond search Iteration Max Cnt */
1830     UWORD32 u4_num_layers =
1831         (ps_codec->s_cfg.u4_enc_speed_preset == IVE_FASTEST) ? (NUM_LAYERS >> 2) : NUM_LAYERS;
1832     UWORD32 u4_enable_fast_sad = ps_codec->s_cfg.u4_enable_fast_sad;
1833 
1834     if((PIC_I == *pic_type) || (PIC_IDR == *pic_type))
1835     {
1836         ps_codec->i4_slice_type = ISLICE;
1837     }
1838     else if(PIC_P == *pic_type)
1839     {
1840         ps_codec->i4_slice_type = PSLICE;
1841     }
1842     else if(PIC_B == *pic_type)
1843     {
1844         ps_codec->i4_slice_type = BSLICE;
1845     }
1846 
1847     ps_codec->u4_is_curr_frm_ref = 0;
1848     ps_codec->u4_is_curr_frm_ref = (*pic_type != PIC_B);
1849 
1850     if(ps_codec->s_cfg.u4_enable_alt_ref && (*pic_type == PIC_P) &&
1851        (ps_codec->i4_pic_cnt % (ps_codec->s_cfg.u4_enable_alt_ref + 1)))
1852     {
1853         ps_codec->u4_is_curr_frm_ref = 0;
1854     }
1855 
1856     ps_codec->u4_is_idr = 0;
1857 
1858     if(PIC_IDR == *pic_type)
1859     {
1860         ps_codec->u4_is_idr = 1;
1861 
1862         ps_codec->i4_frame_num = 0;
1863 
1864         ps_codec->i4_idr_pic_id++;
1865     }
1866 
1867     ps_codec->u4_disable_deblock_level = 1;
1868 
1869     if(ps_codec->s_cfg.u4_disable_deblock_level == DISABLE_DEBLK_LEVEL_0)
1870     {
1871         ps_codec->u4_disable_deblock_level = 0;
1872     }
1873     else if(ps_codec->s_cfg.u4_disable_deblock_level == DISABLE_DEBLK_LEVEL_2)
1874     {
1875         if(ps_codec->u4_disable_deblock_level_cnt == DISABLE_DEBLOCK_INTERVAL ||
1876            ps_codec->i4_slice_type == ISLICE)
1877         {
1878             ps_codec->u4_disable_deblock_level = 0;
1879         }
1880     }
1881     else if(ps_codec->s_cfg.u4_disable_deblock_level == DISABLE_DEBLK_LEVEL_3)
1882     {
1883         if(ps_codec->i4_slice_type == ISLICE)
1884         {
1885             ps_codec->u4_disable_deblock_level = 0;
1886         }
1887     }
1888 
1889     if(ps_codec->u4_disable_deblock_level)
1890     {
1891         ps_codec->u4_disable_deblock_level_cnt++;
1892     }
1893     else
1894     {
1895         ps_codec->u4_disable_deblock_level_cnt = 0;
1896     }
1897 
1898     if(ps_codec->u4_disable_deblock_level == 0)
1899     {
1900         if(ps_codec->s_cfg.e_slice_mode != IVE_SLICE_MODE_NONE)
1901         {
1902             ps_codec->i4_error_code = IH264E_SLICE_TYPE_INPUT_INVALID;
1903 
1904             return IH264E_SLICE_TYPE_INPUT_INVALID;
1905         }
1906     }
1907 
1908     ps_codec->i4_error_code = IH264E_SUCCESS;
1909 
1910     if(ps_codec->i4_gen_header)
1911     {
1912         sps_t *ps_sps = NULL;
1913         pps_t *ps_pps = NULL;
1914         subset_sps_t *ps_subset_sps = NULL;
1915         UWORD8 u1_profile_idc = IH264_PROFILE_BASELINE;
1916 
1917         if(ps_codec->as_process[ctxt_sel * MAX_PROCESS_THREADS].u1_spatial_layer_id > 0)
1918         {
1919             u1_profile_idc = IH264_SCALABLE_BASELINE;
1920         }
1921 
1922         ps_sps = ps_codec->ps_sps_base;
1923         isvce_populate_sps(ps_codec, ps_sps, 0, u1_profile_idc, ps_inp_buf, 0);
1924 
1925         ps_pps = ps_codec->ps_pps_base;
1926         isvce_populate_pps(ps_codec, ps_pps, 0, 0, 0);
1927 
1928         for(i = 1; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
1929         {
1930             ps_subset_sps = ps_codec->ps_subset_sps_base + i;
1931             isvce_populate_subset_sps(ps_codec, ps_subset_sps, i, ps_inp_buf, i);
1932 
1933             /* populate pps header */
1934             ps_pps = ps_codec->ps_pps_base + i;
1935             isvce_populate_pps(ps_codec, ps_pps, i, i, i);
1936         }
1937     }
1938 
1939     if(IH264E_SUCCESS !=
1940        isvce_ref_list_refresh(ps_codec, aps_ref_pic, aps_mv_buf, &ref_set_id, pic_type[0]))
1941     {
1942         ps_codec->i4_error_code = IH264E_NO_FREE_PICBUF;
1943 
1944         return IH264E_NO_FREE_PICBUF;
1945     }
1946 
1947     {
1948         ps_mv_buf = (svc_au_data_t *) ih264_buf_mgr_get_next_free(
1949             (buf_mgr_t *) ps_codec->pv_svc_au_data_store_mgr, &cur_mv_bank_buf_id);
1950 
1951         if(NULL == ps_mv_buf)
1952         {
1953             ps_codec->i4_error_code = IH264E_NO_FREE_MVBANK;
1954 
1955             return IH264E_NO_FREE_MVBANK;
1956         }
1957 
1958         if(ps_codec->u4_is_curr_frm_ref)
1959         {
1960             ih264_buf_mgr_set_status(ps_codec->pv_svc_au_data_store_mgr, cur_mv_bank_buf_id,
1961                                      BUF_MGR_REF);
1962         }
1963 
1964         ps_mv_buf->i4_abs_poc = ps_codec->i4_abs_pic_order_cnt;
1965         ps_mv_buf->i4_buf_id = cur_mv_bank_buf_id;
1966     }
1967 
1968     {
1969         ps_cur_pic = (svc_au_buf_t *) ih264_buf_mgr_get_next_free(
1970             (buf_mgr_t *) ps_codec->pv_ref_buf_mgr, &cur_pic_buf_id);
1971 
1972         if(NULL == ps_cur_pic)
1973         {
1974             ps_codec->i4_error_code = IH264E_NO_FREE_PICBUF;
1975 
1976             return IH264E_NO_FREE_PICBUF;
1977         }
1978 
1979         if(ps_codec->u4_is_curr_frm_ref)
1980         {
1981             ih264_buf_mgr_set_status(ps_codec->pv_ref_buf_mgr, cur_pic_buf_id, BUF_MGR_REF);
1982         }
1983 
1984         if(1 == ps_codec->s_cfg.u4_enable_recon)
1985         {
1986             ih264_buf_mgr_set_status(ps_codec->pv_ref_buf_mgr, cur_pic_buf_id, BUF_MGR_IO);
1987         }
1988 
1989         ps_cur_pic->u4_timestamp_high = ps_inp_buf->s_inp_props.u4_timestamp_high;
1990         ps_cur_pic->u4_timestamp_low = ps_inp_buf->s_inp_props.u4_timestamp_low;
1991 
1992         ps_cur_pic->i4_abs_poc = ps_codec->i4_poc;
1993         ps_cur_pic->i4_poc_lsb = ps_codec->i4_pic_order_cnt_lsb;
1994         ps_cur_pic->i4_frame_num = ps_codec->i4_frame_num;
1995 
1996         ps_cur_pic->i4_buf_id = cur_pic_buf_id;
1997 
1998         ps_cur_pic->i1_temporal_id = isvce_svc_temporal_id_compute(
1999             ps_codec->i4_poc, ps_codec->s_cfg.s_svc_params.u1_num_temporal_layers, pic_type[0]);
2000     }
2001 
2002     /*
2003      * Add the current picture to ref list independent of the fact that it is used
2004      * as reference or not. This is because, now recon is not in sync with output
2005      * hence we may need the current recon after some delay. By adding it to ref
2006      * list we can retrieve the recon any time we want. The information that it is
2007      * used for ref can still be found by checking the buffer status of pic buf.
2008      */
2009     ps_codec->as_ref_set[ref_set_id].i4_pic_cnt = ps_codec->i4_pic_cnt;
2010     ps_codec->as_ref_set[ref_set_id].i4_poc = ps_codec->i4_poc;
2011     ps_codec->as_ref_set[ref_set_id].ps_svc_au_data = ps_mv_buf;
2012     ps_codec->as_ref_set[ref_set_id].ps_pic_buf = ps_cur_pic;
2013 
2014     ps_codec->s_svc_ilp_data.ps_svc_au_data = ps_mv_buf;
2015 
2016     {
2017         isvce_process_ctxt_t *ps_proc = NULL;
2018 
2019         j = ctxt_sel * MAX_PROCESS_THREADS;
2020 
2021         for(i = j; i < (j + MAX_PROCESS_THREADS); i++)
2022         {
2023             ps_proc = &ps_codec->as_process[i];
2024 
2025             ps_proc->s_svc_params = ps_codec->s_cfg.s_svc_params;
2026 
2027             ps_proc->i4_frame_num = ps_codec->i4_frame_num;
2028             ps_proc->u4_is_idr = ps_codec->u4_is_idr;
2029             ps_proc->u4_idr_pic_id = ps_codec->i4_idr_pic_id;
2030             ps_proc->i4_slice_type = ps_codec->i4_slice_type;
2031 
2032             ps_proc->u4_half_x_offset = 0;
2033             ps_proc->u4_half_y_offset = 0;
2034             ps_proc->u4_half_xy_offset = 0;
2035 
2036             ps_proc->u4_disable_deblock_level = ps_codec->u4_disable_deblock_level;
2037 
2038             ps_proc->i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id;
2039             ps_proc->ps_cur_pic = ps_cur_pic;
2040             ps_proc->ps_cur_mv_buf = ps_mv_buf;
2041 
2042             /*
2043              * pointer to ref picture
2044              * 0    : Temporal back reference
2045              * 1    : Temporal forward reference
2046              */
2047             ps_proc->aps_ref_pic[L0] = aps_ref_pic[L0];
2048             ps_proc->aps_ref_pic[L1] = aps_ref_pic[L1];
2049             if(ps_codec->pic_type == PIC_B)
2050             {
2051                 ps_proc->aps_mv_buf[L0] = aps_mv_buf[L0];
2052                 ps_proc->aps_mv_buf[L1] = aps_mv_buf[L1];
2053             }
2054             else
2055             {
2056                 /*
2057                  * Else is dummy since for non B pic we does not need this
2058                  * But an assignment here will help in not having a segfault
2059                  * when we calcualte colpic in P slices
2060                  */
2061                 ps_proc->aps_mv_buf[L0] = ps_mv_buf;
2062                 ps_proc->aps_mv_buf[L1] = ps_mv_buf;
2063             }
2064 
2065             ps_proc->s_inp_buf = ps_inp_buf[0];
2066 
2067             ps_proc->i4_encode_api_call_cnt = ps_codec->i4_encode_api_call_cnt;
2068 
2069             ps_proc->i4_pic_cnt = ps_codec->i4_pic_cnt;
2070 
2071             ps_proc->i4_error_code = 0;
2072 
2073             {
2074                 isvce_entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy;
2075 
2076                 ps_entropy->i4_sof = 0;
2077                 ps_entropy->i4_eof = 0;
2078                 ps_entropy->ps_sps_base = ps_codec->ps_sps_base;
2079                 ps_entropy->ps_pps_base = ps_codec->ps_pps_base;
2080                 ps_entropy->pu1_slice_idx = ps_proc->pu1_slice_idx;
2081                 ps_entropy->ps_svc_nalu_ext_base = ps_proc->ps_svc_nalu_ext_base;
2082                 ps_entropy->ps_subset_sps_base = ps_proc->ps_subset_sps_base;
2083                 ps_entropy->ps_slice_hdr_base = ps_proc->ps_slice_hdr_base;
2084                 ps_entropy->ps_svc_slice_hdr_base = ps_proc->ps_svc_slice_hdr_base;
2085                 ps_entropy->i4_abs_pic_order_cnt = ps_codec->i4_poc;
2086 
2087                 ps_entropy->i1_transform_8x8_mode_flag = 0;
2088 
2089                 ps_entropy->i4_error_code = IH264E_SUCCESS;
2090                 ps_proc->s_entropy.u4_is_last = ps_inp_buf->s_inp_props.u4_is_last;
2091                 ps_proc->s_entropy.i4_pic_cnt = ps_codec->i4_pic_cnt;
2092 
2093                 ps_entropy->u4_timestamp_low = u4_timestamp_low;
2094                 ps_entropy->u4_timestamp_high = u4_timestamp_high;
2095             }
2096 
2097             {
2098                 isvce_me_ctxt_t *ps_me_ctxt = &ps_proc->s_me_ctxt;
2099 
2100                 ps_me_ctxt->ai2_srch_boundaries[0] = ps_codec->s_cfg.u4_srch_rng_x;
2101                 ps_me_ctxt->ai2_srch_boundaries[1] = ps_codec->s_cfg.u4_srch_rng_y;
2102 
2103                 ps_me_ctxt->u4_half_x_offset = ps_proc->u4_half_x_offset;
2104                 ps_me_ctxt->u4_half_y_offset = ps_proc->u4_half_y_offset;
2105                 ps_me_ctxt->u4_half_xy_offset = ps_proc->u4_half_xy_offset;
2106 
2107                 ps_me_ctxt->u4_enable_fast_sad = u4_enable_fast_sad;
2108                 ps_me_ctxt->u4_enable_hpel = ps_codec->s_cfg.u4_enable_hpel;
2109                 ps_me_ctxt->u4_num_layers = u4_num_layers;
2110                 ps_me_ctxt->u4_me_speed_preset = ps_codec->s_cfg.u4_me_speed_preset;
2111 
2112                 if((i == j) && (0 == ps_codec->i4_poc))
2113                 {
2114                     isvce_init_mv_bits(ps_me_ctxt);
2115                 }
2116             }
2117 
2118             ps_proc->ps_ngbr_avbl = &(ps_proc->s_ngbr_avbl);
2119         }
2120     }
2121 
2122     return error_status;
2123 }
2124 
isvce_init_quant_params(isvce_process_ctxt_t * ps_proc,WORD32 qp)2125 void isvce_init_quant_params(isvce_process_ctxt_t *ps_proc, WORD32 qp)
2126 {
2127     isvce_codec_t *ps_codec = ps_proc->ps_codec;
2128     /* quant params */
2129     quant_params_t *ps_qp_params;
2130 
2131     /* ptr to forward quant threshold matrix */
2132     const UWORD16 *pu2_thres_mat = NULL;
2133 
2134     /* ptr to forward scale matrix */
2135     const UWORD16 *pu2_scale_mat = gu2_quant_scale_matrix_4x4;
2136 
2137     /* ptr to inverse scale matrix */
2138     const UWORD16 *pu2_iscale_mat = gau2_ih264_iquant_scale_matrix_4x4;
2139 
2140     /* temp var */
2141     UWORD32 u4_qp[3], u4_qp_div6, u4_qp_mod6;
2142     COMPONENT_TYPE plane;
2143     WORD32 i;
2144     UWORD32 u4_satdq_t;
2145     const UWORD16 *pu2_smat;
2146 
2147     /********************************************************************/
2148     /* init quant params for all planes Y, U and V                      */
2149     /********************************************************************/
2150     /* luma qp */
2151     u4_qp[Y] = qp;
2152 
2153     /* chroma qp
2154      * TODO_LATER : just in case if the chroma planes use different qp's this
2155      * needs to be corrected accordingly.
2156      */
2157     u4_qp[U] = gu1_qpc_fqpi[qp];
2158     u4_qp[V] = gu1_qpc_fqpi[qp];
2159 
2160     plane = Y;
2161     while(plane <= V)
2162     {
2163         u4_qp_div6 = (u4_qp[plane] / 6);
2164         u4_qp_mod6 = (u4_qp[plane] % 6);
2165 
2166         ps_qp_params = ps_proc->ps_qp_params[plane];
2167 
2168         /* mb qp */
2169         ps_qp_params->u1_mb_qp = u4_qp[plane];
2170 
2171         /* mb qp / 6 */
2172         ps_qp_params->u1_qp_div = u4_qp_div6;
2173 
2174         /* mb qp % 6 */
2175         ps_qp_params->u1_qp_rem = u4_qp_mod6;
2176 
2177         /* QP bits */
2178         ps_qp_params->u1_qbits = QP_BITS_h264_4x4 + u4_qp_div6;
2179 
2180         /* forward scale matrix */
2181         ps_qp_params->pu2_scale_mat = pu2_scale_mat + (u4_qp_mod6 * 16);
2182 
2183         /* threshold matrix & weight for quantization */
2184         pu2_thres_mat = gu2_forward_quant_threshold_4x4 + (u4_qp_mod6 * 16);
2185         for(i = 0; i < 16; i++)
2186         {
2187             ps_qp_params->pu2_thres_mat[i] = pu2_thres_mat[i] >> (8 - u4_qp_div6);
2188             ps_qp_params->pu2_weigh_mat[i] = 16;
2189         }
2190 
2191         /* qp dependent rounding constant */
2192         ps_qp_params->u4_dead_zone = gu4_forward_quant_round_factor_4x4[u4_qp_div6];
2193 
2194         /* slice dependent rounding constant */
2195         if(ps_proc->i4_slice_type != ISLICE && ps_proc->i4_slice_type != SISLICE)
2196         {
2197             ps_qp_params->u4_dead_zone >>= 1;
2198         }
2199 
2200         /* SATQD threshold for zero block prediction */
2201         if(ps_codec->s_cfg.u4_enable_satqd)
2202         {
2203             pu2_smat = ps_qp_params->pu2_scale_mat;
2204 
2205             u4_satdq_t = ((1 << (ps_qp_params->u1_qbits)) - ps_qp_params->u4_dead_zone);
2206 
2207             ps_qp_params->pu2_sad_thrsh[0] = u4_satdq_t / MAX(pu2_smat[3], pu2_smat[11]);
2208             ps_qp_params->pu2_sad_thrsh[1] = u4_satdq_t / MAX(pu2_smat[1], pu2_smat[9]);
2209             ps_qp_params->pu2_sad_thrsh[2] = u4_satdq_t / pu2_smat[15];
2210             ps_qp_params->pu2_sad_thrsh[3] = u4_satdq_t / pu2_smat[7];
2211             ps_qp_params->pu2_sad_thrsh[4] = u4_satdq_t / MAX(pu2_smat[12], pu2_smat[14]);
2212             ps_qp_params->pu2_sad_thrsh[5] = u4_satdq_t / MAX(pu2_smat[4], pu2_smat[6]);
2213             ps_qp_params->pu2_sad_thrsh[6] = u4_satdq_t / pu2_smat[13];
2214             ps_qp_params->pu2_sad_thrsh[7] = u4_satdq_t / pu2_smat[5];
2215             ps_qp_params->pu2_sad_thrsh[8] =
2216                 u4_satdq_t / MAX(MAX3(pu2_smat[0], pu2_smat[2], pu2_smat[8]), pu2_smat[10]);
2217         }
2218 
2219         /* inverse scale matrix */
2220         ps_qp_params->pu2_iscale_mat = pu2_iscale_mat + (u4_qp_mod6 * 16);
2221 
2222         plane += 1;
2223     }
2224 }
2225 
2226 /**
2227 *******************************************************************************
2228 *
2229 * @brief
2230 *  isvce_codec_t and proc_t initialisations for an Access Unit
2231 *
2232 * @par Description:
2233 *  Before beginning to encode the frame, the current function initializes all
2234 *  the ctxts (proc, entropy, me, ...) basing on the input configured params.
2235 *  It locates space for storing recon in the encoder picture buffer set, fetches
2236 *  reference frame from encoder picture buffer set. Calls RC pre-enc to get
2237 *  qp and pic type for the current frame. Queues proc jobs so that
2238 *  the other threads can begin encoding. In brief, this function sets up the
2239 *  tone for the entire encoder.
2240 *
2241 * @param[in] ps_codec
2242 *  Pointer to codec context
2243 *
2244 * @param[in] ps_inp_buf
2245 *  Pointer to input buffer context
2246 *
2247 * @param[in] u1_spatial_layer_id
2248 *  Spatial Layer IDl 0 => Base layer
2249 *
2250 * @returns  error_status
2251 *
2252 * @remarks
2253 *
2254 *
2255 *******************************************************************************
2256 */
isvce_svc_layer_pic_init(isvce_codec_t * ps_codec,isvce_inp_buf_t * ps_inp_buf,UWORD8 u1_spatial_layer_id)2257 IH264E_ERROR_T isvce_svc_layer_pic_init(isvce_codec_t *ps_codec, isvce_inp_buf_t *ps_inp_buf,
2258                                         UWORD8 u1_spatial_layer_id)
2259 {
2260     WORD32 i;
2261 
2262     IH264E_ERROR_T error_status = IH264E_SUCCESS;
2263     IH264_ERROR_T ret = IH264_SUCCESS;
2264     PIC_TYPE_T e_pic_type = ps_codec->pic_type;
2265 
2266     ASSERT(MAX_CTXT_SETS == 1);
2267 
2268     for(i = 0; i < MAX_PROCESS_THREADS; i++)
2269     {
2270         isvce_process_ctxt_t *ps_proc = &ps_codec->as_process[i];
2271         isvce_entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy;
2272         isvce_deblk_ctxt_t *ps_deblk = &ps_proc->s_deblk_ctxt;
2273         isvce_me_ctxt_t *ps_me_ctxt = &ps_proc->s_me_ctxt;
2274         svc_au_buf_t *ps_cur_pic = ps_proc->ps_cur_pic;
2275         svc_au_buf_t *aps_ref_pic[MAX_REF_PIC_CNT] = {ps_proc->aps_ref_pic[L0],
2276                                                       ps_proc->aps_ref_pic[L1]};
2277 
2278         ps_proc->u1_spatial_layer_id = u1_spatial_layer_id;
2279 
2280         ps_proc->s_src_pic_buf_props = ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id];
2281 
2282         ps_proc->s_rec_pic_buf_props = ps_cur_pic->ps_layer_yuv_buf_props[u1_spatial_layer_id];
2283 
2284         ASSERT(0 == (ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_width % MB_SIZE));
2285         ASSERT(0 == (ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_height % MB_SIZE));
2286 
2287         ps_proc->i4_wd_mbs =
2288             ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_width / MB_SIZE;
2289         ps_proc->i4_ht_mbs =
2290             ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_height / MB_SIZE;
2291 
2292         ps_proc->u1_frame_qp = ps_codec->au4_frame_qp[u1_spatial_layer_id];
2293 
2294         ps_proc->u1_mb_qp = ps_proc->u1_frame_qp;
2295         ps_entropy->ps_mb_qp_ctxt->u1_cur_mb_qp = ps_proc->u1_frame_qp;
2296 
2297         isvce_init_quant_params(ps_proc, ps_proc->u1_frame_qp);
2298 
2299         memset(&ps_proc->s_frame_info, 0, sizeof(frame_info_t));
2300 
2301         /* row '-1' */
2302         memset(ps_proc->pu1_proc_map - ps_proc->i4_wd_mbs, 1,
2303                ps_proc->i4_wd_mbs * sizeof(ps_proc->pu1_proc_map[0]));
2304 
2305         /* row 0 to ht in mbs */
2306         memset(ps_proc->pu1_proc_map, 0,
2307                ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs * sizeof(ps_proc->pu1_proc_map[0]));
2308 
2309         /* row '-1' */
2310         memset(ps_proc->pu1_deblk_map - ps_proc->i4_wd_mbs, 1,
2311                ps_proc->i4_wd_mbs * sizeof(ps_proc->pu1_deblk_map[0]));
2312 
2313         /* row 0 to ht in mbs */
2314         memset(ps_proc->pu1_deblk_map, 0,
2315                ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs * sizeof(ps_proc->pu1_deblk_map[0]));
2316 
2317         /* row '-1' */
2318         memset(ps_proc->pu1_me_map - ps_proc->i4_wd_mbs, 1,
2319                ps_proc->i4_wd_mbs * sizeof(ps_proc->pu1_me_map[0]));
2320 
2321         /* row 0 to ht in mbs */
2322         memset(ps_proc->pu1_me_map, 0,
2323                ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs * sizeof(ps_proc->pu1_me_map[0]));
2324 
2325         if(IVE_AIR_MODE_NONE != ps_codec->s_cfg.e_air_mode)
2326         {
2327             ps_codec->i4_air_pic_cnt =
2328                 (ps_codec->i4_air_pic_cnt + 1) % ps_codec->s_cfg.u4_air_refresh_period;
2329 
2330             if(!ps_codec->i4_air_pic_cnt)
2331             {
2332                 memset(ps_proc->pu1_is_intra_coded, 0,
2333                        ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs *
2334                            sizeof(ps_proc->pu1_is_intra_coded[0]));
2335             }
2336         }
2337 
2338         if(ps_codec->s_cfg.e_slice_mode == IVE_SLICE_MODE_NONE)
2339         {
2340             memset(ps_proc->pu1_slice_idx, 0,
2341                    ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs * sizeof(ps_proc->pu1_slice_idx[0]));
2342         }
2343         else if(ps_codec->s_cfg.e_slice_mode == IVE_SLICE_MODE_BLOCKS)
2344         {
2345             UWORD8 *pu1_slice_idx = ps_proc->pu1_slice_idx;
2346             WORD32 i4_mb_y = 0, slice_idx = 0, cnt;
2347 
2348             while(i4_mb_y < ps_proc->i4_ht_mbs)
2349             {
2350                 if(i4_mb_y + (WORD32) ps_codec->s_cfg.u4_slice_param < ps_proc->i4_ht_mbs)
2351                 {
2352                     cnt = ps_codec->s_cfg.u4_slice_param * ps_proc->i4_wd_mbs;
2353                     i4_mb_y += ps_codec->s_cfg.u4_slice_param;
2354                 }
2355                 else
2356                 {
2357                     cnt = (ps_proc->i4_ht_mbs - i4_mb_y) * ps_proc->i4_wd_mbs;
2358                     i4_mb_y += (ps_proc->i4_ht_mbs - i4_mb_y);
2359                 }
2360 
2361                 memset(pu1_slice_idx, slice_idx, cnt * sizeof(pu1_slice_idx[0]));
2362 
2363                 slice_idx++;
2364                 pu1_slice_idx += cnt;
2365             }
2366         }
2367 
2368         if((e_pic_type != PIC_IDR) && (e_pic_type != PIC_I))
2369         {
2370             ps_proc->as_ref_pic_buf_props[L0] =
2371                 aps_ref_pic[L0]->ps_layer_yuv_buf_props[u1_spatial_layer_id];
2372             ps_proc->as_ref_pic_buf_props[L1] =
2373                 aps_ref_pic[L1]->ps_layer_yuv_buf_props[u1_spatial_layer_id];
2374         }
2375 
2376         ps_entropy->i4_gen_header = ps_codec->i4_gen_header && (0 == u1_spatial_layer_id);
2377         ps_entropy->i4_gen_subset_sps =
2378             (ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers > 1) && ps_codec->i4_gen_header;
2379 
2380         /* row '-1' */
2381         memset(ps_entropy->pu1_entropy_map - ps_proc->i4_wd_mbs, 1,
2382                ps_proc->i4_wd_mbs * sizeof(ps_entropy->pu1_entropy_map[0]));
2383 
2384         /* row 0 to ht in mbs */
2385         memset(ps_entropy->pu1_entropy_map, 0,
2386                ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs * sizeof(ps_entropy->pu1_entropy_map[0]));
2387 
2388         isvce_init_cabac_table(ps_entropy);
2389 
2390         ps_entropy->i4_wd_mbs = ps_proc->i4_wd_mbs;
2391         ps_entropy->i4_ht_mbs = ps_proc->i4_ht_mbs;
2392 
2393         ps_entropy->u1_entropy_coding_mode_flag =
2394             ((ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers > 1) && (0 == u1_spatial_layer_id))
2395                 ? CAVLC
2396                 : ps_codec->s_cfg.u4_entropy_coding_mode;
2397 
2398         ps_proc->s_entropy.pi4_mb_skip_run[0] = 0;
2399 
2400         ps_entropy->u4_header_bits[MB_TYPE_INTRA] = 0;
2401         ps_entropy->u4_header_bits[MB_TYPE_INTER] = 0;
2402         ps_entropy->u4_residue_bits[MB_TYPE_INTRA] = 0;
2403         ps_entropy->u4_residue_bits[MB_TYPE_INTER] = 0;
2404 
2405         ps_entropy->u1_spatial_layer_id = ps_proc->u1_spatial_layer_id;
2406 
2407         ps_deblk->pu1_slice_idx = ps_proc->pu1_slice_idx;
2408 
2409         ps_me_ctxt->u1_mb_qp = ps_codec->au4_frame_qp[u1_spatial_layer_id];
2410 
2411         {
2412             UWORD8 u1_min_qp;
2413             UWORD8 u1_max_qp;
2414 
2415             svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt = ps_proc->ps_sub_pic_rc_ctxt;
2416             svc_sub_pic_rc_layer_variables_t *ps_layer_variables =
2417                 &ps_sub_pic_rc_ctxt->s_sub_pic_rc_variables.s_layer_variables;
2418 
2419             switch(ps_proc->i4_slice_type)
2420             {
2421                 case ISLICE:
2422                 {
2423                     u1_min_qp = ps_codec->s_cfg.au4_i_qp_min[u1_spatial_layer_id];
2424                     u1_max_qp = ps_codec->s_cfg.au4_i_qp_max[u1_spatial_layer_id];
2425 
2426                     break;
2427                 }
2428                 case PSLICE:
2429                 {
2430                     u1_min_qp = ps_codec->s_cfg.au4_p_qp_min[u1_spatial_layer_id];
2431                     u1_max_qp = ps_codec->s_cfg.au4_p_qp_max[u1_spatial_layer_id];
2432 
2433                     break;
2434                 }
2435                 default:
2436                 {
2437                     u1_min_qp = ps_codec->s_cfg.au4_b_qp_min[u1_spatial_layer_id];
2438                     u1_max_qp = ps_codec->s_cfg.au4_b_qp_max[u1_spatial_layer_id];
2439 
2440                     break;
2441                 }
2442             }
2443 
2444             ps_layer_variables->i4_max_num_reference_frames = ps_codec->i4_max_num_reference_frames;
2445             ps_layer_variables->i4_slice_type = ps_proc->i4_slice_type;
2446             ps_layer_variables->i4_frame_num = ps_proc->i4_frame_num;
2447             ps_layer_variables->u1_frame_qp = ps_proc->u1_frame_qp;
2448             ps_layer_variables->u1_spatial_layer_id = u1_spatial_layer_id;
2449             ps_layer_variables->u1_min_qp = u1_min_qp;
2450             ps_layer_variables->u1_max_qp = u1_max_qp;
2451 
2452             isvce_sub_pic_rc_ctxt_layer_init(ps_proc->ps_sub_pic_rc_ctxt);
2453         }
2454     }
2455 
2456     {
2457         job_t s_job;
2458 
2459         s_job.i4_cmd = CMD_PROCESS;
2460         s_job.i2_mb_cnt =
2461             ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_width / MB_SIZE;
2462         s_job.i2_mb_x = 0;
2463 
2464         for(i = 0; i < (WORD32) (ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_height /
2465                                  MB_SIZE);
2466             i++)
2467         {
2468             s_job.i2_mb_y = i;
2469 
2470             ret = ih264_list_queue(ps_codec->pv_proc_jobq, &s_job, 1);
2471 
2472             if(ret != IH264_SUCCESS)
2473             {
2474                 ps_codec->i4_error_code = ret;
2475 
2476                 return IH264E_FAIL;
2477             }
2478         }
2479 
2480         /* Once all the jobs are queued, terminate the queue */
2481         /* Since the threads are created and deleted in each call, terminating
2482         here is not an issue */
2483         ih264_list_terminate(ps_codec->pv_proc_jobq);
2484     }
2485 
2486     ps_codec->i4_gen_header = 0;
2487 
2488     return error_status;
2489 }
2490 
2491 /**
2492 *******************************************************************************
2493 *
2494 * @brief   initialize process context.
2495 *
2496 * @par Description:
2497 *  Before dispatching the current job to process thread, the process context
2498 *  associated with the job is initialized. Usually every job aims to encode one
2499 *  row of mb's. Basing on the row indices provided by the job, the process
2500 *  context's buffer ptrs, slice indices and other elements that are necessary
2501 *  during core-coding are initialized.
2502 *
2503 * @param[in] ps_proc
2504 *  Pointer to the current process context
2505 *
2506 * @returns error status
2507 *
2508 * @remarks none
2509 *
2510 *******************************************************************************
2511 */
isvce_init_layer_proc_ctxt(isvce_process_ctxt_t * ps_proc)2512 IH264E_ERROR_T isvce_init_layer_proc_ctxt(isvce_process_ctxt_t *ps_proc)
2513 {
2514     WORD32 i4_mb_x, i4_mb_y;
2515 
2516     isvce_codec_t *ps_codec = ps_proc->ps_codec;
2517     n_mb_process_ctxt_t *ps_n_mb_ctxt = &ps_proc->s_n_mb_ctxt;
2518     quant_params_t *ps_qp_params = ps_proc->ps_qp_params[0];
2519     isvce_deblk_ctxt_t *ps_deblk = &ps_proc->s_deblk_ctxt;
2520     isvce_bs_ctxt_t *ps_bs = &(ps_deblk->s_bs_ctxt);
2521     svc_au_data_t *ps_cur_mv_buf = ps_proc->ps_cur_mv_buf;
2522 
2523     i4_mb_x = ps_proc->i4_mb_x;
2524     i4_mb_y = ps_proc->i4_mb_y;
2525 
2526     ASSERT((ps_codec->s_cfg.u4_wd - ps_codec->s_cfg.u4_disp_wd) == 0);
2527     ASSERT((ps_codec->s_cfg.u4_ht - ps_codec->s_cfg.u4_disp_ht) == 0);
2528 
2529     ps_proc->i4_nmb_ntrpy = ps_proc->i4_wd_mbs;
2530     ps_proc->u4_nmb_me = 1;
2531 
2532     ps_proc->s_src_buf_props = ps_proc->s_src_pic_buf_props;
2533     ps_proc->s_rec_buf_props = ps_proc->s_rec_pic_buf_props;
2534     ps_proc->as_ref_buf_props[0] = ps_proc->as_ref_pic_buf_props[0];
2535     ps_proc->as_ref_buf_props[1] = ps_proc->as_ref_pic_buf_props[1];
2536 
2537     ps_proc->s_src_buf_props.as_component_bufs[0].pv_data =
2538         ((UWORD8 *) ps_proc->s_src_buf_props.as_component_bufs[0].pv_data) + (i4_mb_x * MB_SIZE) +
2539         ps_proc->s_src_buf_props.as_component_bufs[0].i4_data_stride * (i4_mb_y * MB_SIZE);
2540     ps_proc->s_src_buf_props.as_component_bufs[1].pv_data =
2541         ((UWORD8 *) ps_proc->s_src_pic_buf_props.as_component_bufs[1].pv_data) +
2542         (i4_mb_x * MB_SIZE) +
2543         ps_proc->s_src_buf_props.as_component_bufs[1].i4_data_stride * (i4_mb_y * BLK8x8SIZE);
2544 
2545     ps_proc->s_rec_buf_props.as_component_bufs[0].pv_data =
2546         ((UWORD8 *) ps_proc->s_rec_buf_props.as_component_bufs[0].pv_data) + (i4_mb_x * MB_SIZE) +
2547         ps_proc->s_rec_buf_props.as_component_bufs[0].i4_data_stride * (i4_mb_y * MB_SIZE);
2548     ps_proc->s_rec_buf_props.as_component_bufs[1].pv_data =
2549         ((UWORD8 *) ps_proc->s_rec_buf_props.as_component_bufs[1].pv_data) + (i4_mb_x * MB_SIZE) +
2550         ps_proc->s_rec_buf_props.as_component_bufs[1].i4_data_stride * (i4_mb_y * BLK8x8SIZE);
2551 
2552     ps_proc->as_ref_buf_props[0].as_component_bufs[0].pv_data =
2553         ((UWORD8 *) ps_proc->as_ref_buf_props[0].as_component_bufs[0].pv_data) +
2554         (i4_mb_x * MB_SIZE) +
2555         ps_proc->as_ref_buf_props[0].as_component_bufs[0].i4_data_stride * (i4_mb_y * MB_SIZE);
2556     ps_proc->as_ref_buf_props[0].as_component_bufs[1].pv_data =
2557         ((UWORD8 *) ps_proc->as_ref_buf_props[0].as_component_bufs[1].pv_data) +
2558         (i4_mb_x * MB_SIZE) +
2559         ps_proc->as_ref_buf_props[0].as_component_bufs[1].i4_data_stride * (i4_mb_y * BLK8x8SIZE);
2560 
2561     ps_proc->as_ref_buf_props[1].as_component_bufs[0].pv_data =
2562         ((UWORD8 *) ps_proc->as_ref_buf_props[1].as_component_bufs[0].pv_data) +
2563         (i4_mb_x * MB_SIZE) +
2564         ps_proc->as_ref_buf_props[1].as_component_bufs[0].i4_data_stride * (i4_mb_y * MB_SIZE);
2565     ps_proc->as_ref_buf_props[1].as_component_bufs[1].pv_data =
2566         ((UWORD8 *) ps_proc->as_ref_buf_props[1].as_component_bufs[1].pv_data) +
2567         (i4_mb_x * MB_SIZE) +
2568         ps_proc->as_ref_buf_props[1].as_component_bufs[1].i4_data_stride * (i4_mb_y * BLK8x8SIZE);
2569 
2570     ps_proc->pv_mb_coeff_data =
2571         ((UWORD8 *) ps_proc->pv_pic_mb_coeff_data) + i4_mb_y * ps_codec->u4_size_coeff_data;
2572 
2573     ps_proc->pv_mb_header_data =
2574         ((UWORD8 *) ps_proc->pv_pic_mb_header_data) + i4_mb_y * ps_codec->u4_size_header_data;
2575 
2576     ps_proc->i4_cur_slice_idx = ps_proc->pu1_slice_idx[i4_mb_y * ps_proc->i4_wd_mbs + i4_mb_x];
2577 
2578     ps_proc->ps_mb_info =
2579         ps_cur_mv_buf->ps_svc_layer_data[ps_proc->u1_spatial_layer_id].ps_mb_info +
2580         i4_mb_y * ps_proc->i4_wd_mbs;
2581 
2582     ps_proc->ps_col_mb =
2583         ps_proc->aps_mv_buf[1]->ps_svc_layer_data[ps_proc->u1_spatial_layer_id].ps_mb_info +
2584         i4_mb_y * ps_proc->i4_wd_mbs;
2585 
2586     {
2587         ps_proc->s_nbr_info.ps_top_row_mb_info =
2588             ps_proc->s_nbr_info_base.ps_layer_nbr_info[ps_proc->u1_spatial_layer_id]
2589                 .ps_top_row_mb_info +
2590             (i4_mb_x + (i4_mb_y - 1) * ps_proc->i4_wd_mbs);
2591 
2592         ps_proc->s_nbr_info.ps_top_mb_intra_modes =
2593             ps_proc->s_nbr_info_base.ps_layer_nbr_info[ps_proc->u1_spatial_layer_id]
2594                 .ps_top_mb_intra_modes +
2595             (i4_mb_x + (i4_mb_y - 1) * ps_proc->i4_wd_mbs);
2596     }
2597 
2598     ps_proc->pu4_mb_pu_cnt =
2599         ps_cur_mv_buf->ps_svc_layer_data[ps_proc->u1_spatial_layer_id].pu4_num_pus_in_mb +
2600         (i4_mb_y * ps_proc->i4_wd_mbs);
2601 
2602     ps_proc->ps_mb_info->u2_mb_type = I16x16;
2603 
2604     ps_proc->u4_lambda = gu1_qp0[ps_qp_params->u1_mb_qp];
2605 
2606     ps_proc->i4_mb_distortion = SHRT_MAX;
2607 
2608     if(i4_mb_x == 0)
2609     {
2610         ps_proc->s_nbr_info.ps_left_mb_info[0].i4_mb_distortion = 0;
2611     }
2612 
2613     ps_proc->i4_mb_cost = INT_MAX;
2614 
2615     ps_deblk->i4_mb_x = ps_proc->i4_mb_x;
2616     /* deblk lags the current mb proc by 1 row */
2617     /* NOTE: Intra prediction has to happen with non deblocked samples used as
2618      * reference */
2619     /* Hence to deblk MB 0 of row 0, you have wait till MB 0 of row 1 is encoded.
2620      */
2621     /* For simplicity, we chose to lag deblking by 1 Row wrt to proc */
2622     ps_deblk->i4_mb_y = ps_proc->i4_mb_y - 1;
2623 
2624     ps_deblk->s_rec_pic_buf_props = ps_proc->s_rec_pic_buf_props;
2625 
2626     ps_bs->i4_mb_x = ps_proc->i4_mb_x;
2627     ps_bs->i4_mb_y = ps_proc->i4_mb_y;
2628 
2629     ps_n_mb_ctxt->i4_mb_x = 0;
2630     ps_n_mb_ctxt->i4_mb_y = ps_deblk->i4_mb_y;
2631     ps_n_mb_ctxt->i4_n_mbs = ps_proc->i4_nmb_ntrpy;
2632 
2633     return IH264E_SUCCESS;
2634 }
2635 
2636 /**
2637 *******************************************************************************
2638 *
2639 * @brief
2640 *  Returns size of buffers for storing SVC ILP data
2641 *
2642 * @param[in] u1_num_spatial_layers
2643 *  Num Spatial Layers
2644 *
2645 * @param[in] d_spatial_res_ratio
2646 *  Resolution Ratio b/w spatial layers
2647 *
2648 * @param[in] u4_wd
2649 *  Input Width
2650 *
2651 * @param[in] u4_ht
2652 *  Input Height
2653 *
2654 * @returns  Size of buffers
2655 *
2656 *******************************************************************************
2657 */
isvce_get_svc_ilp_buf_size(UWORD8 u1_num_spatial_layers,DOUBLE d_spatial_res_ratio,UWORD32 u4_wd,UWORD32 u4_ht)2658 UWORD32 isvce_get_svc_ilp_buf_size(UWORD8 u1_num_spatial_layers, DOUBLE d_spatial_res_ratio,
2659                                    UWORD32 u4_wd, UWORD32 u4_ht)
2660 {
2661     WORD32 i;
2662 
2663     UWORD32 u4_size = 0;
2664 
2665     if(u1_num_spatial_layers > 1)
2666     {
2667         /* ps_intra_recon_bufs */
2668         u4_size += u1_num_spatial_layers * sizeof(yuv_buf_props_t);
2669 
2670         /* ps_residual_bufs */
2671         u4_size += u1_num_spatial_layers * sizeof(yuv_buf_props_t);
2672 
2673         /* aps_layer_resampler_props[Y] */
2674         u4_size += u1_num_spatial_layers * sizeof(layer_resampler_props_t);
2675 
2676         /* aps_layer_resampler_props[UV] */
2677         u4_size += u1_num_spatial_layers * sizeof(layer_resampler_props_t);
2678 
2679         for(i = u1_num_spatial_layers - 1; i >= 0; i--)
2680         {
2681             WORD32 i4_layer_luma_wd =
2682                 ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
2683             WORD32 i4_layer_luma_ht =
2684                 ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
2685             WORD32 i4_layer_luma_samples =
2686                 (ALIGN16(i4_layer_luma_wd) + PAD_WD) * (i4_layer_luma_ht + PAD_HT);
2687             WORD32 i4_layer_uv_wd = i4_layer_luma_wd;
2688             WORD32 i4_layer_uv_ht = i4_layer_luma_ht / 2.0 + 0.99;
2689             WORD32 i4_layer_uv_samples =
2690                 (ALIGN16(i4_layer_uv_wd) + PAD_WD) * (i4_layer_uv_ht + PAD_HT);
2691 
2692             /* ps_intra_recon_bufs */
2693             u4_size += (i4_layer_luma_samples + i4_layer_uv_samples) * sizeof(UWORD8);
2694 
2695             /* ps_residual_bufs */
2696             u4_size += (i4_layer_luma_samples + i4_layer_uv_samples) * sizeof(WORD16);
2697         }
2698     }
2699     else
2700     {
2701         WORD32 i4_layer_luma_wd = u4_wd;
2702         WORD32 i4_layer_luma_ht = u4_ht;
2703         WORD32 i4_layer_luma_samples =
2704             (ALIGN16(i4_layer_luma_wd) + PAD_WD) * (i4_layer_luma_ht + PAD_HT);
2705         WORD32 i4_layer_uv_wd = i4_layer_luma_wd;
2706         WORD32 i4_layer_uv_ht = i4_layer_luma_ht / 2.0 + 0.99;
2707         WORD32 i4_layer_uv_samples = (ALIGN16(i4_layer_uv_wd) + PAD_WD) * (i4_layer_uv_ht + PAD_HT);
2708 
2709         /* ps_residual_bufs */
2710         u4_size += sizeof(yuv_buf_props_t);
2711 
2712         /* ps_residual_bufs */
2713         u4_size += (i4_layer_luma_samples + i4_layer_uv_samples) * sizeof(WORD16);
2714     }
2715 
2716     return u4_size;
2717 }
2718 
isvce_layer_resampler_props_init(layer_resampler_props_t * ps_layer_props,DOUBLE d_spatial_res_ratio,UWORD32 u4_wd,UWORD32 u4_ht,UWORD8 u1_level_idc,UWORD8 u1_is_chroma)2719 static void isvce_layer_resampler_props_init(layer_resampler_props_t *ps_layer_props,
2720                                              DOUBLE d_spatial_res_ratio, UWORD32 u4_wd,
2721                                              UWORD32 u4_ht, UWORD8 u1_level_idc,
2722                                              UWORD8 u1_is_chroma)
2723 {
2724     const UWORD8 u1_ref_layer_field_pic_flag = 0;
2725     const UWORD8 u1_field_pic_flag = 0;
2726     const UWORD8 u1_frame_mbs_only_flag = 1;
2727     const UWORD8 u1_ref_layer_frame_mbs_only_flag = 1;
2728     const UWORD8 u1_bot_field_flag = 0;
2729     const WORD32 i4_scaled_ref_layer_left_offset = 0;
2730     const WORD32 i4_scaled_ref_layer_top_offset = 0;
2731     const WORD32 i4_ref_layer_chroma_phase_x_plus1 = 1;
2732     const WORD32 i4_ref_layer_chroma_phase_y_plus1 = 1;
2733     const WORD32 i4_chroma_phase_x_plus1 = 1;
2734     const WORD32 i4_chroma_phase_y_plus1 = 1;
2735     const WORD32 i4_sub_wd_chroma = 2;
2736     const WORD32 i4_sub_ht_chroma = 2;
2737     UWORD32 u4_ref_wd = (u4_wd / d_spatial_res_ratio);
2738     UWORD32 u4_ref_ht = (u4_ht / d_spatial_res_ratio) * (1 + u1_ref_layer_field_pic_flag);
2739     UWORD32 u4_scaled_wd = u4_wd;
2740     UWORD32 u4_scaled_ht = u4_ht * (1 + u1_field_pic_flag);
2741 
2742     u4_ref_wd = u4_ref_wd >> u1_is_chroma;
2743     u4_ref_ht = u4_ref_ht >> u1_is_chroma;
2744     u4_scaled_wd = u4_scaled_wd >> u1_is_chroma;
2745     u4_scaled_ht = u4_scaled_ht >> u1_is_chroma;
2746 
2747     if(u1_is_chroma)
2748     {
2749         ps_layer_props->i4_refphase_x = i4_ref_layer_chroma_phase_x_plus1 - 1;
2750         ps_layer_props->i4_refphase_y = i4_ref_layer_chroma_phase_y_plus1 - 1;
2751         ps_layer_props->i4_phase_x = i4_chroma_phase_x_plus1 - 1;
2752         ps_layer_props->i4_phase_y = i4_chroma_phase_y_plus1 - 1;
2753         ps_layer_props->u4_sub_wd = i4_sub_wd_chroma;
2754         ps_layer_props->u4_sub_ht = i4_sub_ht_chroma;
2755         ps_layer_props->u4_mb_wd = MB_SIZE >> 1;
2756         ps_layer_props->u4_mb_ht = MB_SIZE >> 1;
2757     }
2758     else
2759     {
2760         ps_layer_props->i4_refphase_x = 0;
2761         ps_layer_props->i4_refphase_y = 0;
2762         ps_layer_props->i4_phase_x = 0;
2763         ps_layer_props->i4_phase_y = 0;
2764         ps_layer_props->u4_sub_wd = 1;
2765         ps_layer_props->u4_sub_ht = 1;
2766         ps_layer_props->u4_mb_wd = MB_SIZE;
2767         ps_layer_props->u4_mb_ht = MB_SIZE;
2768     }
2769 
2770     if(u1_level_idc <= 30)
2771     {
2772         ps_layer_props->u4_shift_x = 16;
2773         ps_layer_props->u4_shift_y = 16;
2774     }
2775     else
2776     {
2777         ps_layer_props->u4_shift_x = 31 - isvcd_get_ceil_log2(u4_ref_wd);
2778         ps_layer_props->u4_shift_y = 31 - isvcd_get_ceil_log2(u4_ref_ht);
2779     }
2780 
2781     if((0 == u1_frame_mbs_only_flag) || (0 == u1_ref_layer_frame_mbs_only_flag))
2782     {
2783         ps_layer_props->i4_phase_y = ps_layer_props->i4_phase_y + 4 * u1_bot_field_flag;
2784 
2785         if(1 == u1_ref_layer_frame_mbs_only_flag)
2786         {
2787             ps_layer_props->i4_refphase_y = (2 * ps_layer_props->i4_refphase_y) + 2;
2788         }
2789         else
2790         {
2791             ps_layer_props->i4_refphase_y = ps_layer_props->i4_refphase_y + (4 * u1_bot_field_flag);
2792         }
2793     }
2794 
2795     ps_layer_props->u4_scale_x =
2796         ((u4_ref_wd << ps_layer_props->u4_shift_x) + (u4_scaled_wd >> 1)) / (u4_scaled_wd);
2797     ps_layer_props->u4_scale_y =
2798         ((u4_ref_ht << ps_layer_props->u4_shift_y) + (u4_scaled_ht >> 1)) / (u4_scaled_ht);
2799 
2800     ps_layer_props->i4_offset_x = i4_scaled_ref_layer_left_offset / ps_layer_props->u4_sub_wd;
2801     ps_layer_props->i4_add_x =
2802         (((u4_ref_wd * (2 + ps_layer_props->i4_phase_x)) << (ps_layer_props->u4_shift_x - 2)) +
2803          (u4_scaled_wd >> 1)) /
2804             u4_scaled_wd +
2805         (1 << (ps_layer_props->u4_shift_x - 5));
2806     ps_layer_props->i4_delta_x = 4 * (2 + ps_layer_props->i4_refphase_x);
2807 
2808     if((1 == u1_frame_mbs_only_flag) && (1 == u1_ref_layer_frame_mbs_only_flag))
2809     {
2810         ps_layer_props->i4_offset_y = i4_scaled_ref_layer_top_offset / ps_layer_props->u4_sub_ht;
2811         ps_layer_props->i4_add_y =
2812             (((u4_ref_ht * (2 + ps_layer_props->i4_phase_y)) << (ps_layer_props->u4_shift_y - 2)) +
2813              (u4_scaled_ht >> 1)) /
2814                 u4_scaled_ht +
2815             (1 << (ps_layer_props->u4_shift_y - 5));
2816         ps_layer_props->i4_delta_y = 4 * (2 + ps_layer_props->i4_refphase_y);
2817     }
2818     else
2819     {
2820         ps_layer_props->i4_offset_y =
2821             i4_scaled_ref_layer_top_offset / (2 * ps_layer_props->u4_sub_ht);
2822         ps_layer_props->i4_add_y =
2823             (((u4_ref_ht * (2 + ps_layer_props->i4_phase_y)) << (ps_layer_props->u4_shift_y - 3)) +
2824              (u4_scaled_ht >> 1)) /
2825                 u4_scaled_ht +
2826             (1 << (ps_layer_props->u4_shift_y - 5));
2827         ps_layer_props->i4_delta_y = 2 * (2 + ps_layer_props->i4_refphase_y);
2828     }
2829 }
2830 
2831 /**
2832 *******************************************************************************
2833 *
2834 * @brief
2835 *  Function to initialize svc ilp buffers
2836 *
2837 * @param[in] ps_codec
2838 *  Pointer to codec context
2839 *
2840 * @param[in] ps_mem_rec
2841 *  Pointer to memory allocated for input buffers
2842 *
2843 *******************************************************************************
2844 */
isvce_svc_ilp_buf_init(isvce_codec_t * ps_codec,iv_mem_rec_t * ps_mem_rec)2845 void isvce_svc_ilp_buf_init(isvce_codec_t *ps_codec, iv_mem_rec_t *ps_mem_rec)
2846 {
2847     UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
2848     DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio;
2849     UWORD32 u4_wd = ps_codec->s_cfg.u4_wd;
2850     UWORD32 u4_ht = ps_codec->s_cfg.u4_ht;
2851     UWORD8 *pu1_buf = ps_mem_rec->pv_base;
2852     WORD64 i8_alloc_mem_size =
2853         isvce_get_svc_ilp_buf_size(u1_num_spatial_layers, d_spatial_res_ratio, u4_wd, u4_ht);
2854 
2855     if(u1_num_spatial_layers > 1)
2856     {
2857         WORD32 i, j;
2858 
2859         ps_codec->s_svc_ilp_data.ps_intra_recon_bufs = (yuv_buf_props_t *) pu1_buf;
2860         pu1_buf += u1_num_spatial_layers * sizeof(ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[0]);
2861         i8_alloc_mem_size -=
2862             u1_num_spatial_layers * sizeof(ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[0]);
2863 
2864         ps_codec->s_svc_ilp_data.ps_residual_bufs = (yuv_buf_props_t *) pu1_buf;
2865         pu1_buf += u1_num_spatial_layers * sizeof(ps_codec->s_svc_ilp_data.ps_residual_bufs[0]);
2866         i8_alloc_mem_size -=
2867             u1_num_spatial_layers * sizeof(ps_codec->s_svc_ilp_data.ps_residual_bufs[0]);
2868 
2869         for(i = 0; i < NUM_SP_COMPONENTS; i++)
2870         {
2871             ps_codec->s_svc_ilp_data.aps_layer_resampler_props[i] =
2872                 (layer_resampler_props_t *) pu1_buf;
2873             pu1_buf += u1_num_spatial_layers *
2874                        sizeof(ps_codec->s_svc_ilp_data.aps_layer_resampler_props[i][0]);
2875             i8_alloc_mem_size -= u1_num_spatial_layers *
2876                                  sizeof(ps_codec->s_svc_ilp_data.aps_layer_resampler_props[i][0]);
2877         }
2878 
2879         ASSERT(i8_alloc_mem_size >= 0);
2880 
2881         for(i = u1_num_spatial_layers - 1; i >= 0; i--)
2882         {
2883             WORD32 i4_stride;
2884 
2885             WORD32 i4_layer_luma_wd =
2886                 ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
2887             WORD32 i4_layer_luma_ht =
2888                 ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
2889             WORD32 i4_layer_luma_samples =
2890                 (ALIGN16(i4_layer_luma_wd) + PAD_WD) * (i4_layer_luma_ht + PAD_HT);
2891             WORD32 i4_layer_uv_wd = i4_layer_luma_wd;
2892             WORD32 i4_layer_uv_ht = i4_layer_luma_ht / 2.0 + 0.99;
2893             WORD32 i4_layer_uv_samples =
2894                 (ALIGN16(i4_layer_uv_wd) + PAD_WD) * (i4_layer_uv_ht + PAD_HT);
2895 
2896             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].u4_width = i4_layer_luma_wd;
2897             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].u4_height = i4_layer_luma_ht;
2898             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].e_color_format = IV_YUV_420SP_UV;
2899             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].u1_bit_depth = 8;
2900 
2901             i4_stride = ALIGN16(i4_layer_luma_wd) + PAD_WD;
2902             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].as_component_bufs[Y].pv_data =
2903                 pu1_buf + PAD_LEFT + PAD_TOP * i4_stride;
2904             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].as_component_bufs[Y].i4_data_stride =
2905                 ALIGN16(i4_layer_luma_wd) + PAD_WD;
2906             pu1_buf += i4_layer_luma_samples * sizeof(UWORD8);
2907             i8_alloc_mem_size -= i4_layer_luma_samples * sizeof(UWORD8);
2908 
2909             i4_stride = ALIGN16(i4_layer_uv_wd) + PAD_WD;
2910             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].as_component_bufs[UV].pv_data =
2911                 pu1_buf + PAD_LEFT + PAD_TOP * i4_stride;
2912             ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[i].as_component_bufs[UV].i4_data_stride =
2913                 ALIGN16(i4_layer_uv_wd) + PAD_WD;
2914             pu1_buf += i4_layer_uv_samples * sizeof(UWORD8);
2915             i8_alloc_mem_size -= i4_layer_uv_samples * sizeof(UWORD8);
2916 
2917             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].u4_width = i4_layer_luma_wd;
2918             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].u4_height = i4_layer_luma_ht;
2919             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].e_color_format = IV_YUV_420SP_UV;
2920             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].u1_bit_depth = 10;
2921 
2922             i4_stride = ALIGN16(i4_layer_luma_wd) + PAD_WD;
2923             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].as_component_bufs[Y].pv_data =
2924                 pu1_buf + (PAD_LEFT + PAD_TOP * i4_stride) * (sizeof(WORD16) / sizeof(pu1_buf[0]));
2925             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].as_component_bufs[Y].i4_data_stride =
2926                 i4_stride;
2927             pu1_buf += i4_layer_luma_samples * sizeof(WORD16);
2928             i8_alloc_mem_size -= i4_layer_luma_samples * sizeof(WORD16);
2929 
2930             i4_stride = ALIGN16(i4_layer_uv_wd) + PAD_WD;
2931             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].as_component_bufs[UV].pv_data =
2932                 pu1_buf + (PAD_LEFT + PAD_TOP * i4_stride) * (sizeof(WORD16) / sizeof(pu1_buf[0]));
2933             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].as_component_bufs[UV].i4_data_stride =
2934                 i4_stride;
2935             pu1_buf += i4_layer_uv_samples * sizeof(WORD16);
2936             i8_alloc_mem_size -= i4_layer_uv_samples * sizeof(WORD16);
2937 
2938             ps_codec->s_svc_ilp_data.ps_residual_bufs[i].as_component_bufs[V].pv_data = NULL;
2939 
2940             ASSERT(i8_alloc_mem_size >= 0);
2941 
2942             if(i >= 1)
2943             {
2944                 for(j = 0; j < NUM_SP_COMPONENTS; j++)
2945                 {
2946                     isvce_layer_resampler_props_init(
2947                         &ps_codec->s_svc_ilp_data.aps_layer_resampler_props[j][i],
2948                         d_spatial_res_ratio, i4_layer_luma_wd, i4_layer_luma_ht,
2949                         ps_codec->s_cfg.u4_max_level, ((COMPONENT_TYPE) j) == UV);
2950                 }
2951             }
2952         }
2953     }
2954     else
2955     {
2956         WORD32 i4_stride;
2957 
2958         WORD32 i4_layer_luma_wd = u4_wd;
2959         WORD32 i4_layer_luma_ht = u4_ht;
2960         WORD32 i4_layer_luma_samples =
2961             (ALIGN16(i4_layer_luma_wd) + PAD_WD) * (i4_layer_luma_ht + PAD_HT);
2962         WORD32 i4_layer_uv_wd = i4_layer_luma_wd;
2963         WORD32 i4_layer_uv_ht = i4_layer_luma_ht / 2.0 + 0.99;
2964         WORD32 i4_layer_uv_samples = (ALIGN16(i4_layer_uv_wd) + PAD_WD) * (i4_layer_uv_ht + PAD_HT);
2965 
2966         ps_codec->s_svc_ilp_data.ps_residual_bufs = (yuv_buf_props_t *) pu1_buf;
2967         pu1_buf += sizeof(ps_codec->s_svc_ilp_data.ps_residual_bufs[0]);
2968         i8_alloc_mem_size -= sizeof(ps_codec->s_svc_ilp_data.ps_residual_bufs[0]);
2969 
2970         ASSERT(i8_alloc_mem_size >= 0);
2971 
2972         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].u4_width = i4_layer_luma_wd;
2973         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].u4_height = i4_layer_luma_ht;
2974         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].e_color_format = IV_YUV_420SP_UV;
2975         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].u1_bit_depth = 10;
2976 
2977         i4_stride = ALIGN16(i4_layer_luma_wd) + PAD_WD;
2978         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].as_component_bufs[Y].pv_data =
2979             pu1_buf + (PAD_LEFT + PAD_TOP * i4_stride) * (sizeof(WORD16) / sizeof(pu1_buf[0]));
2980         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].as_component_bufs[Y].i4_data_stride =
2981             i4_stride;
2982         pu1_buf += i4_layer_luma_samples * sizeof(WORD16);
2983         i8_alloc_mem_size -= i4_layer_luma_samples * sizeof(WORD16);
2984 
2985         i4_stride = ALIGN16(i4_layer_uv_wd) + PAD_WD;
2986         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].as_component_bufs[UV].pv_data =
2987             pu1_buf + (PAD_LEFT + PAD_TOP * i4_stride) * (sizeof(WORD16) / sizeof(pu1_buf[0]));
2988         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].as_component_bufs[UV].i4_data_stride =
2989             i4_stride;
2990         pu1_buf += i4_layer_uv_samples * sizeof(WORD16);
2991         i8_alloc_mem_size -= i4_layer_uv_samples * sizeof(WORD16);
2992 
2993         ps_codec->s_svc_ilp_data.ps_residual_bufs[0].as_component_bufs[V].pv_data = NULL;
2994 
2995         ASSERT(i8_alloc_mem_size >= 0);
2996     }
2997 }
2998 
isvce_get_residual_csbf(mem_fxns_t * ps_mem_fxns,buffer_container_t * ps_comp_buf)2999 static FORCEINLINE UWORD32 isvce_get_residual_csbf(mem_fxns_t *ps_mem_fxns,
3000                                                    buffer_container_t *ps_comp_buf)
3001 {
3002     WORD32 i;
3003 
3004     UWORD32 u4_csbf = 0;
3005 
3006     for(i = 0; i < MAX_TU_IN_MB; i++)
3007     {
3008         UWORD8 u1_zscan_idx = gau1_raster_to_zscan_map[i];
3009         UWORD8 u1_offset_x = (i % MAX_TU_IN_MB_ROW) * MIN_TU_SIZE;
3010         UWORD8 u1_offset_y = (i / MAX_TU_IN_MB_ROW) * MIN_TU_SIZE;
3011         WORD16 *pi2_res = ((WORD16 *) ps_comp_buf->pv_data) + u1_offset_x +
3012                           u1_offset_y * ps_comp_buf->i4_data_stride;
3013         UWORD8 u1_cbf = ps_mem_fxns->pf_nonzero_checker(
3014             (UWORD8 *) pi2_res, ps_comp_buf->i4_data_stride * (sizeof(WORD16) / sizeof(UWORD8)),
3015             MIN_TU_SIZE * (sizeof(WORD16) / sizeof(UWORD8)), MIN_TU_SIZE);
3016 
3017         u4_csbf |= (u1_cbf << u1_zscan_idx);
3018     }
3019 
3020     return u4_csbf;
3021 }
3022 
3023 /**
3024 *******************************************************************************
3025 *
3026 * @brief
3027 *  Function to update svc ilp buffers after every MB
3028 *
3029 * @param[in] ps_proc
3030 *  Pointer to process context
3031 *
3032 *******************************************************************************
3033 */
isvce_svc_ilp_buf_update(isvce_process_ctxt_t * ps_proc)3034 void isvce_svc_ilp_buf_update(isvce_process_ctxt_t *ps_proc)
3035 {
3036     isvce_codec_t *ps_codec = ps_proc->ps_codec;
3037     svc_params_t *ps_svc_params = &ps_codec->s_cfg.s_svc_params;
3038 
3039     UWORD8 u1_spatial_layer_id = ps_proc->u1_spatial_layer_id;
3040 
3041     if(ps_svc_params->u1_num_spatial_layers > 1)
3042     {
3043         buffer_container_t s_src;
3044         buffer_container_t s_dst;
3045 
3046         WORD32 i;
3047 
3048         svc_ilp_data_t *ps_svc_ilp_data = &ps_codec->s_svc_ilp_data;
3049         isa_dependent_fxns_t *ps_isa_dependent_fxns = &ps_codec->s_isa_dependent_fxns;
3050         mem_fxns_t *ps_mem_fxns = &ps_isa_dependent_fxns->s_mem_fxns;
3051         yuv_buf_props_t *ps_residual_buf =
3052             &ps_codec->s_svc_ilp_data.ps_residual_bufs[u1_spatial_layer_id];
3053 
3054         WORD32 i4_mb_x = ps_proc->i4_mb_x;
3055         WORD32 i4_mb_y = ps_proc->i4_mb_y;
3056 
3057         ASSERT(ps_proc->s_rec_buf_props.e_color_format == IV_YUV_420SP_UV);
3058 
3059         if(u1_spatial_layer_id < (ps_svc_params->u1_num_spatial_layers - 1))
3060         {
3061             if(ps_proc->ps_mb_info->u1_is_intra)
3062             {
3063                 for(i = 0; i < NUM_SP_COMPONENTS; i++)
3064                 {
3065                     UWORD8 u1_is_chroma = (Y != ((COMPONENT_TYPE) i));
3066 
3067                     s_src = ps_proc->s_rec_buf_props.as_component_bufs[i];
3068 
3069                     s_dst.i4_data_stride = ps_svc_ilp_data->ps_intra_recon_bufs[u1_spatial_layer_id]
3070                                                .as_component_bufs[i]
3071                                                .i4_data_stride;
3072                     s_dst.pv_data =
3073                         ((UWORD8 *) ps_svc_ilp_data->ps_intra_recon_bufs[u1_spatial_layer_id]
3074                              .as_component_bufs[i]
3075                              .pv_data) +
3076                         i4_mb_x * MB_SIZE +
3077                         i4_mb_y * (MB_SIZE >> u1_is_chroma) * s_dst.i4_data_stride;
3078 
3079                     ps_mem_fxns->pf_copy_2d((UWORD8 *) s_dst.pv_data, s_dst.i4_data_stride,
3080                                             (UWORD8 *) s_src.pv_data, s_src.i4_data_stride, MB_SIZE,
3081                                             (MB_SIZE >> u1_is_chroma));
3082                 }
3083             }
3084             else
3085             {
3086                 for(i = 0; i < NUM_SP_COMPONENTS; i++)
3087                 {
3088                     UWORD8 u1_is_chroma = (Y != ((COMPONENT_TYPE) i));
3089 
3090                     s_dst.i4_data_stride = ps_svc_ilp_data->ps_intra_recon_bufs[u1_spatial_layer_id]
3091                                                .as_component_bufs[i]
3092                                                .i4_data_stride;
3093                     s_dst.pv_data =
3094                         ((UWORD8 *) ps_svc_ilp_data->ps_intra_recon_bufs[u1_spatial_layer_id]
3095                              .as_component_bufs[i]
3096                              .pv_data) +
3097                         i4_mb_x * MB_SIZE +
3098                         i4_mb_y * (MB_SIZE >> u1_is_chroma) * s_dst.i4_data_stride;
3099 
3100                     ps_mem_fxns->pf_memset_2d((UWORD8 *) s_dst.pv_data, s_dst.i4_data_stride, 0,
3101                                               MB_SIZE, (MB_SIZE >> u1_is_chroma));
3102                 }
3103             }
3104         }
3105 
3106         if(ENABLE_RESIDUAL_PREDICTION && (ps_proc->i4_slice_type != ISLICE) &&
3107            (u1_spatial_layer_id < (ps_svc_params->u1_num_spatial_layers - 1)))
3108         {
3109             if(ps_proc->ps_mb_info->u1_is_intra || (ps_proc->ps_mb_info->u2_mb_type == PSKIP) ||
3110                (ps_proc->ps_mb_info->u2_mb_type == BSKIP))
3111             {
3112                 for(i = 0; i < NUM_SP_COMPONENTS; i++)
3113                 {
3114                     buffer_container_t *ps_comp_buf;
3115 
3116                     WORD16 *pi2_res;
3117 
3118                     UWORD8 u1_is_chroma = (Y != ((COMPONENT_TYPE) i));
3119 
3120                     ps_comp_buf = &ps_residual_buf->as_component_bufs[u1_is_chroma ? UV : Y];
3121                     pi2_res =
3122                         ((WORD16 *) ps_comp_buf->pv_data) + ps_proc->i4_mb_x * MB_SIZE +
3123                         ps_proc->i4_mb_y * (MB_SIZE >> u1_is_chroma) * ps_comp_buf->i4_data_stride;
3124 
3125                     ps_mem_fxns->pf_memset_2d(
3126                         (UWORD8 *) pi2_res,
3127                         ps_comp_buf->i4_data_stride * (sizeof(WORD16) / sizeof(UWORD8)), 0,
3128                         MB_SIZE * (sizeof(WORD16) / sizeof(UWORD8)), MB_SIZE >> u1_is_chroma);
3129                 }
3130             }
3131         }
3132 
3133         if(ENABLE_RESIDUAL_PREDICTION && (u1_spatial_layer_id > 0) &&
3134            !(ps_proc->ps_mb_info->u1_is_intra || (ps_proc->ps_mb_info->u2_mb_type == PSKIP) ||
3135              (ps_proc->ps_mb_info->u2_mb_type == BSKIP)))
3136         {
3137             s_src = ps_residual_buf->as_component_bufs[Y];
3138             s_src.pv_data = ((WORD16 *) s_src.pv_data) + ps_proc->i4_mb_x * MB_SIZE +
3139                             ps_proc->i4_mb_y * MB_SIZE * s_src.i4_data_stride;
3140 
3141             ps_proc->ps_mb_info->u4_res_csbp = isvce_get_residual_csbf(ps_mem_fxns, &s_src);
3142         }
3143         else
3144         {
3145             ps_proc->ps_mb_info->u4_res_csbp = 0;
3146         }
3147     }
3148     else
3149     {
3150         ps_proc->ps_mb_info->u4_res_csbp = 0;
3151     }
3152 }
3153 
3154 /*
3155  * Padding has a one MB row dependency on deblock  which
3156  * in turn has a one MB row dependency on encode
3157  */
isvce_pad_frame(isvce_process_ctxt_t * ps_proc,yuv_buf_props_t * ps_pad_buf)3158 static IH264E_ERROR_T isvce_pad_frame(isvce_process_ctxt_t *ps_proc, yuv_buf_props_t *ps_pad_buf)
3159 {
3160     /* codec context */
3161     isvce_codec_t *ps_codec = ps_proc->ps_codec;
3162 
3163     WORD32 i4_element_size = (ps_pad_buf->u1_bit_depth > 8) ? 2 : 1;
3164 
3165     /* src buffers luma */
3166     WORD32 i4_luma_stride = ps_pad_buf->as_component_bufs[0].i4_data_stride * i4_element_size;
3167     UWORD8 *pu1_curr_pic_luma = (UWORD8 *) (ps_pad_buf->as_component_bufs[0].pv_data);
3168 
3169     /* src buffers chroma */
3170     WORD32 i4_chroma_stride = ps_pad_buf->as_component_bufs[1].i4_data_stride * i4_element_size;
3171     UWORD8 *pu1_curr_pic_chroma = (UWORD8 *) (ps_pad_buf->as_component_bufs[1].pv_data);
3172 
3173     WORD32 i4_bottom_offset_luma = ps_pad_buf->u4_height * i4_luma_stride;
3174     WORD32 i4_bottom_offset_chroma = (ps_pad_buf->u4_height >> 1) * i4_chroma_stride;
3175 
3176     /* Pad left */
3177     ps_codec->pf_pad_left_luma(pu1_curr_pic_luma, i4_luma_stride, ps_pad_buf->u4_height,
3178                                PAD_LEFT * i4_element_size);
3179     ps_codec->pf_pad_left_chroma(pu1_curr_pic_chroma, i4_chroma_stride, ps_pad_buf->u4_height >> 1,
3180                                  PAD_LEFT * i4_element_size);
3181 
3182     /* Pad right */
3183     ps_codec->pf_pad_right_luma(pu1_curr_pic_luma + ps_pad_buf->u4_width * i4_element_size,
3184                                 i4_luma_stride, ps_pad_buf->u4_height, PAD_RIGHT * i4_element_size);
3185     ps_codec->pf_pad_right_chroma(pu1_curr_pic_chroma + ps_pad_buf->u4_width * i4_element_size,
3186                                   i4_chroma_stride, ps_pad_buf->u4_height >> 1,
3187                                   PAD_RIGHT * i4_element_size);
3188 
3189     /* Pad top */
3190     ps_codec->pf_pad_top(pu1_curr_pic_luma - (PAD_LEFT * i4_element_size), i4_luma_stride,
3191                          (ps_pad_buf->u4_width + PAD_WD) * i4_element_size, PAD_TOP);
3192     ps_codec->pf_pad_top(pu1_curr_pic_chroma - (PAD_LEFT * i4_element_size), i4_chroma_stride,
3193                          (ps_pad_buf->u4_width + PAD_WD) * i4_element_size, PAD_TOP >> 1);
3194 
3195     /* Pad bottom */
3196     ps_codec->pf_pad_bottom(
3197         pu1_curr_pic_luma + i4_bottom_offset_luma - (PAD_LEFT * i4_element_size), i4_luma_stride,
3198         (ps_pad_buf->u4_width + PAD_WD) * i4_element_size, PAD_BOT);
3199     ps_codec->pf_pad_bottom(
3200         pu1_curr_pic_chroma + i4_bottom_offset_chroma - (PAD_LEFT * i4_element_size),
3201         i4_chroma_stride, (ps_pad_buf->u4_width + PAD_WD) * i4_element_size, PAD_BOT >> 1);
3202 
3203     return IH264E_SUCCESS;
3204 }
3205 
isvce_svc_pad_frame(isvce_process_ctxt_t * ps_proc)3206 void isvce_svc_pad_frame(isvce_process_ctxt_t *ps_proc)
3207 {
3208     isvce_codec_t *ps_codec = ps_proc->ps_codec;
3209 
3210     isvce_pad_frame(ps_proc, &(ps_proc->s_rec_pic_buf_props));
3211 
3212     if(ps_proc->s_svc_params.u1_num_spatial_layers > 1)
3213     {
3214         isvce_pad_frame(
3215             ps_proc, &(ps_codec->s_svc_ilp_data.ps_intra_recon_bufs[ps_proc->u1_spatial_layer_id]));
3216         isvce_pad_frame(ps_proc,
3217                         &(ps_codec->s_svc_ilp_data.ps_residual_bufs[ps_proc->u1_spatial_layer_id]));
3218     }
3219 }
3220 
3221 /**
3222 *******************************************************************************
3223 *
3224 * @brief
3225 *  Initialize AIR mb frame Map
3226 *
3227 * @par Description:
3228 *  Initialize AIR mb frame map
3229 *  MB frame map indicates which frame an Mb should be coded as intra according
3230 *to AIR
3231 *
3232 * @param[in] ps_codec
3233 *  Pointer to codec context
3234 *
3235 * @returns  error_status
3236 *
3237 * @remarks
3238 *
3239 *
3240 *******************************************************************************
3241 */
isvce_init_air_map(isvce_codec_t * ps_codec)3242 IH264E_ERROR_T isvce_init_air_map(isvce_codec_t *ps_codec)
3243 {
3244     /* intra refresh map */
3245     UWORD16 *pu2_intr_rfrsh_map = ps_codec->pu2_intr_rfrsh_map;
3246 
3247     /* air mode */
3248     IVE_AIR_MODE_T air_mode = ps_codec->s_cfg.e_air_mode;
3249 
3250     /* refresh period */
3251     UWORD32 air_period = ps_codec->s_cfg.u4_air_refresh_period;
3252 
3253     /* mb cnt */
3254     UWORD32 u4_mb_cnt = ps_codec->s_cfg.i4_wd_mbs * ps_codec->s_cfg.i4_ht_mbs;
3255 
3256     /* temp var */
3257     UWORD32 curr_mb, seed_rand = 1;
3258 
3259     switch(air_mode)
3260     {
3261         case IVE_AIR_MODE_CYCLIC:
3262 
3263             for(curr_mb = 0; curr_mb < u4_mb_cnt; curr_mb++)
3264             {
3265                 pu2_intr_rfrsh_map[curr_mb] = curr_mb % air_period;
3266             }
3267             break;
3268 
3269         case IVE_AIR_MODE_RANDOM:
3270 
3271             for(curr_mb = 0; curr_mb < u4_mb_cnt; curr_mb++)
3272             {
3273                 seed_rand = (seed_rand * 32719 + 3) % 32749;
3274                 pu2_intr_rfrsh_map[curr_mb] = seed_rand % air_period;
3275             }
3276             break;
3277 
3278         default:
3279 
3280             break;
3281     }
3282 
3283     return IH264E_SUCCESS;
3284 }
3285 
3286 /**
3287 ******************************************************************************
3288 *
3289 * @brief
3290 *  derivation process for macroblock availability
3291 *
3292 * @par   Description
3293 *  Calculates the availability of the left, top, topright and topleft macroblocks.
3294 *
3295 * @param[in] ps_proc_ctxt
3296 *  pointer to proc context (handle)
3297 *
3298 * @remarks Based on section 6.4.5 in H264 spec
3299 *
3300 * @return  none
3301 *
3302 ******************************************************************************
3303 */
isvce_derive_nghbr_avbl_of_mbs(isvce_process_ctxt_t * ps_proc)3304 void isvce_derive_nghbr_avbl_of_mbs(isvce_process_ctxt_t *ps_proc)
3305 {
3306     UWORD8 *pu1_slice_idx_curr = ps_proc->pu1_slice_idx;
3307     UWORD8 *pu1_slice_idx_b;
3308     UWORD8 *pu1_slice_idx_a;
3309     UWORD8 *pu1_slice_idx_c;
3310     UWORD8 *pu1_slice_idx_d;
3311     block_neighbors_t *ps_ngbr_avbl;
3312     WORD32 i4_mb_x, i4_mb_y;
3313     WORD32 i4_wd_mbs;
3314 
3315     i4_mb_x = ps_proc->i4_mb_x;
3316     i4_mb_y = ps_proc->i4_mb_y;
3317 
3318     i4_wd_mbs = ps_proc->i4_wd_mbs;
3319 
3320     pu1_slice_idx_curr += (i4_mb_y * i4_wd_mbs) + i4_mb_x;
3321     pu1_slice_idx_a = pu1_slice_idx_curr - 1;
3322     pu1_slice_idx_b = pu1_slice_idx_curr - i4_wd_mbs;
3323     pu1_slice_idx_c = pu1_slice_idx_b + 1;
3324     pu1_slice_idx_d = pu1_slice_idx_b - 1;
3325     ps_ngbr_avbl = ps_proc->ps_ngbr_avbl;
3326 
3327     /**********************************************************************/
3328     /* The macroblock is marked as available, unless one of the following */
3329     /* conditions is true in which case the macroblock shall be marked as */
3330     /* not available.                                                     */
3331     /* 1. mbAddr < 0                                                      */
3332     /* 2  mbAddr > CurrMbAddr                                             */
3333     /* 3. the macroblock with address mbAddr belongs to a different slice */
3334     /* than the macroblock with address CurrMbAddr                        */
3335     /**********************************************************************/
3336 
3337     /* left macroblock availability */
3338     if(i4_mb_x == 0)
3339     { /* macroblocks along first column */
3340         ps_ngbr_avbl->u1_mb_a = 0;
3341     }
3342     else
3343     { /* macroblocks belong to same slice? */
3344         if(*pu1_slice_idx_a != *pu1_slice_idx_curr)
3345             ps_ngbr_avbl->u1_mb_a = 0;
3346         else
3347             ps_ngbr_avbl->u1_mb_a = 1;
3348     }
3349 
3350     /* top macroblock availability */
3351     if(i4_mb_y == 0)
3352     { /* macroblocks along first row */
3353         ps_ngbr_avbl->u1_mb_b = 0;
3354     }
3355     else
3356     { /* macroblocks belong to same slice? */
3357         if(*pu1_slice_idx_b != *pu1_slice_idx_curr)
3358             ps_ngbr_avbl->u1_mb_b = 0;
3359         else
3360             ps_ngbr_avbl->u1_mb_b = 1;
3361     }
3362 
3363     /* top right macroblock availability */
3364     if(i4_mb_x == i4_wd_mbs - 1 || i4_mb_y == 0)
3365     { /* macroblocks along last column */
3366         ps_ngbr_avbl->u1_mb_c = 0;
3367     }
3368     else
3369     { /* macroblocks belong to same slice? */
3370         if(*pu1_slice_idx_c != *pu1_slice_idx_curr)
3371             ps_ngbr_avbl->u1_mb_c = 0;
3372         else
3373             ps_ngbr_avbl->u1_mb_c = 1;
3374     }
3375 
3376     /* top left macroblock availability */
3377     if(i4_mb_x == 0 || i4_mb_y == 0)
3378     { /* macroblocks along first column */
3379         ps_ngbr_avbl->u1_mb_d = 0;
3380     }
3381     else
3382     { /* macroblocks belong to same slice? */
3383         if(*pu1_slice_idx_d != *pu1_slice_idx_curr)
3384             ps_ngbr_avbl->u1_mb_d = 0;
3385         else
3386             ps_ngbr_avbl->u1_mb_d = 1;
3387     }
3388 }
3389 
3390 /**
3391 *******************************************************************************
3392 *
3393 * @brief
3394 *  Codec level initializations
3395 *
3396 * @par Description:
3397 *  Initializes the codec with parameters that needs to be set before encoding
3398 *  first frame
3399 *
3400 * @param[in] ps_codec
3401 *  Pointer to codec context
3402 *
3403 * @param[in] ps_inp_buf
3404 *  Pointer to input buffer context
3405 *
3406 * @returns  error_status
3407 *
3408 * @remarks
3409 *
3410 *
3411 *******************************************************************************
3412 */
isvce_codec_init(isvce_codec_t * ps_codec)3413 IH264E_ERROR_T isvce_codec_init(isvce_codec_t *ps_codec)
3414 {
3415     isa_dependent_fxns_t *ps_isa_dependent_fxns = &ps_codec->s_isa_dependent_fxns;
3416     enc_loop_fxns_t *ps_enc_loop_fxns = &ps_isa_dependent_fxns->s_enc_loop_fxns;
3417     WORD8 i;
3418 
3419     /********************************************************************
3420      *                     INITIALIZE CODEC CONTEXT                     *
3421      ********************************************************************/
3422     /* encoder presets */
3423     if(ps_codec->s_cfg.u4_enc_speed_preset != IVE_CONFIG)
3424     {
3425         if(ps_codec->s_cfg.u4_enc_speed_preset == IVE_SLOWEST)
3426         { /* high quality */
3427             /* enable diamond search */
3428             ps_codec->s_cfg.u4_me_speed_preset = DMND_SRCH;
3429             ps_codec->s_cfg.u4_enable_fast_sad = 0;
3430 
3431             /* disable intra 4x4 */
3432             ps_codec->s_cfg.u4_enable_intra_4x4 = 1;
3433             if(!FORCE_FAST_INTRA4X4)
3434             {
3435                 ps_enc_loop_fxns->apf_luma_energy_compaction[1] =
3436                     isvce_code_luma_intra_macroblock_4x4_rdopt_on;
3437             }
3438 
3439             /* sub pel off */
3440             ps_codec->s_cfg.u4_enable_hpel = 1;
3441 
3442             /* disabled intra inter gating in Inter slices */
3443             ps_codec->u4_inter_gate = 0;
3444         }
3445         else if(ps_codec->s_cfg.u4_enc_speed_preset == IVE_NORMAL)
3446         { /* normal */
3447             /* enable diamond search */
3448             ps_codec->s_cfg.u4_me_speed_preset = DMND_SRCH;
3449             ps_codec->s_cfg.u4_enable_fast_sad = 0;
3450 
3451             /* disable intra 4x4 */
3452             ps_codec->s_cfg.u4_enable_intra_4x4 = 1;
3453 
3454             /* sub pel off */
3455             ps_codec->s_cfg.u4_enable_hpel = 1;
3456 
3457             /* disabled intra inter gating in Inter slices */
3458             ps_codec->u4_inter_gate = 0;
3459         }
3460         else if(ps_codec->s_cfg.u4_enc_speed_preset == IVE_FAST)
3461         { /* normal */
3462             /* enable diamond search */
3463             ps_codec->s_cfg.u4_me_speed_preset = DMND_SRCH;
3464             ps_codec->s_cfg.u4_enable_fast_sad = 0;
3465 
3466             /* disable intra 4x4 */
3467             ps_codec->s_cfg.u4_enable_intra_4x4 = 0;
3468 
3469             /* sub pel off */
3470             ps_codec->s_cfg.u4_enable_hpel = 1;
3471 
3472             /* disabled intra inter gating in Inter slices */
3473             ps_codec->u4_inter_gate = 1;
3474         }
3475         else if(ps_codec->s_cfg.u4_enc_speed_preset == IVE_HIGH_SPEED)
3476         { /* fast */
3477             /* enable diamond search */
3478             ps_codec->s_cfg.u4_me_speed_preset = DMND_SRCH;
3479             ps_codec->s_cfg.u4_enable_fast_sad = 0;
3480 
3481             /* disable intra 4x4 */
3482             ps_codec->s_cfg.u4_enable_intra_4x4 = 0;
3483 
3484             /* sub pel off */
3485             ps_codec->s_cfg.u4_enable_hpel = 0;
3486 
3487             /* disabled intra inter gating in Inter slices */
3488             ps_codec->u4_inter_gate = 0;
3489         }
3490         else if(ps_codec->s_cfg.u4_enc_speed_preset == IVE_FASTEST)
3491         { /* fastest */
3492             /* enable diamond search */
3493             ps_codec->s_cfg.u4_me_speed_preset = DMND_SRCH;
3494 
3495             /* disable intra 4x4 */
3496             ps_codec->s_cfg.u4_enable_intra_4x4 = 0;
3497 
3498             /* sub pel off */
3499             ps_codec->s_cfg.u4_enable_hpel = 0;
3500 
3501             /* disabled intra inter gating in Inter slices */
3502             ps_codec->u4_inter_gate = 1;
3503         }
3504     }
3505 
3506     /*****************************************************************
3507      * Initialize AIR inside codec
3508      *****************************************************************/
3509     if(IVE_AIR_MODE_NONE != ps_codec->s_cfg.e_air_mode)
3510     {
3511         isvce_init_air_map(ps_codec);
3512 
3513         ps_codec->i4_air_pic_cnt = -1;
3514     }
3515 
3516     /****************************************************/
3517     /*           INITIALIZE RATE CONTROL                */
3518     /****************************************************/
3519     {
3520         for(i = 0; i < MAX_NUM_SPATIAL_LAYERS; i++)
3521         {
3522             UWORD8 au1_init_qp[MAX_PIC_TYPE];
3523             UWORD8 au1_min_max_qp[2 * MAX_PIC_TYPE];
3524             UWORD8 au1_min_max_avc_qp[2 * MAX_PIC_TYPE];
3525 
3526             /* update rc lib with modified qp */
3527             au1_init_qp[0] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp[i]];
3528             au1_init_qp[1] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp[i]];
3529             au1_init_qp[2] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp[i]];
3530 
3531             au1_min_max_qp[2 * I_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp_min[i]];
3532             au1_min_max_qp[2 * I_PIC + 1] =
3533                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp_max[i]];
3534 
3535             au1_min_max_qp[2 * P_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp_min[i]];
3536             au1_min_max_qp[2 * P_PIC + 1] =
3537                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp_max[i]];
3538 
3539             au1_min_max_qp[2 * B_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp_min[i]];
3540             au1_min_max_qp[2 * B_PIC + 1] =
3541                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp_max[i]];
3542 
3543             /* get rc mode */
3544             switch(ps_codec->s_cfg.e_rc_mode)
3545             {
3546                 case IVE_RC_STORAGE:
3547                     ps_codec->s_rate_control.e_rc_type = VBR_STORAGE;
3548                     break;
3549                 case IVE_RC_CBR_NON_LOW_DELAY:
3550                     ps_codec->s_rate_control.e_rc_type = CBR_NLDRC;
3551                     break;
3552                 case IVE_RC_CBR_LOW_DELAY:
3553                     ps_codec->s_rate_control.e_rc_type = CBR_LDRC;
3554                     break;
3555                 case IVE_RC_NONE:
3556                     ps_codec->s_rate_control.e_rc_type = CONST_QP;
3557                     break;
3558                 default:
3559                     break;
3560             }
3561 
3562             ps_codec->u1_enable_init_qp = DEFAULT_INIT_QP;
3563 
3564             /* init rate control */
3565             isvce_rc_init(
3566                 ps_codec->s_rate_control.apps_rate_control_api[i],
3567                 ps_codec->s_rate_control.pps_frame_time, ps_codec->s_rate_control.pps_time_stamp,
3568                 ps_codec->s_rate_control.pps_pd_frm_rate, ps_codec->s_cfg.u4_max_framerate,
3569                 ps_codec->s_cfg.u4_src_frame_rate, ps_codec->s_cfg.u4_tgt_frame_rate,
3570                 ps_codec->s_rate_control.e_rc_type, ps_codec->s_cfg.au4_target_bitrate[i],
3571                 ps_codec->s_cfg.au4_max_bitrate[i], ps_codec->s_cfg.au4_vbv_buffer_delay[i],
3572                 ps_codec->s_cfg.u4_i_frm_interval, ps_codec->s_cfg.u4_num_bframes + 1, au1_init_qp,
3573                 ps_codec->s_cfg.u4_num_bframes + 2, au1_min_max_qp,
3574                 MAX(ps_codec->s_cfg.u4_max_level,
3575                     (UWORD32) ih264e_get_min_level(ps_codec->s_cfg.u4_max_wd,
3576                                                    ps_codec->s_cfg.u4_max_ht)));
3577 
3578             au1_min_max_avc_qp[2 * I_PIC] = ps_codec->s_cfg.au4_i_qp_min[i];
3579             au1_min_max_avc_qp[2 * I_PIC + 1] = ps_codec->s_cfg.au4_i_qp_max[i];
3580 
3581             au1_min_max_avc_qp[2 * P_PIC] = ps_codec->s_cfg.au4_p_qp_min[i];
3582             au1_min_max_avc_qp[2 * P_PIC + 1] = ps_codec->s_cfg.au4_p_qp_max[i];
3583 
3584             au1_min_max_avc_qp[2 * B_PIC] = ps_codec->s_cfg.au4_b_qp_min[i];
3585             au1_min_max_avc_qp[2 * B_PIC + 1] = ps_codec->s_cfg.au4_b_qp_max[i];
3586 
3587             irc_change_qp_constraints(ps_codec->s_rate_control.apps_rate_control_api[i],
3588                                       au1_min_max_qp, au1_min_max_avc_qp);
3589         }
3590     }
3591 
3592     /* recon stride */
3593     ps_codec->i4_rec_strd = ALIGN16(ps_codec->s_cfg.u4_max_wd) + PAD_WD;
3594 
3595     /* max ref and reorder cnt */
3596     ps_codec->i4_ref_buf_cnt = ps_codec->s_cfg.u4_max_ref_cnt + ps_codec->s_cfg.u4_max_reorder_cnt;
3597     ps_codec->i4_ref_buf_cnt += MAX_CTXT_SETS;
3598     ps_codec->i4_ref_buf_cnt += ps_codec->s_cfg.s_svc_params.u1_num_temporal_layers;
3599 
3600     DEBUG_HISTOGRAM_INIT();
3601 
3602     /* Init dependecy vars */
3603     ps_codec->i4_last_inp_buff_received = 0;
3604 
3605     /* At codec start no IDR is pending */
3606     ps_codec->i4_pending_idr_flag = 0;
3607 
3608     for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers - 1; i++)
3609     {
3610         ps_codec->au4_constrained_intra_pred[i] = 1;
3611     }
3612 
3613     ps_codec->au4_constrained_intra_pred[ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers - 1] =
3614         0;
3615 
3616     return IH264E_SUCCESS;
3617 }
3618 
3619 /**
3620 *******************************************************************************
3621 *
3622 * @brief update encoder configuration parameters
3623 *
3624 * @par Description:
3625 *  updates encoder configuration parameters from the given config set.
3626 *  Initialize/reinitialize codec parameters according to new configurations.
3627 *
3628 * @param[in] ps_codec
3629 *  Pointer to codec context
3630 *
3631 * @param[in] ps_cfg
3632 *  Pointer to config param set
3633 *
3634 * @remarks none
3635 *
3636 *******************************************************************************
3637 */
isvce_codec_update_config(isvce_codec_t * ps_codec,isvce_cfg_params_t * ps_cfg)3638 IH264E_ERROR_T isvce_codec_update_config(isvce_codec_t *ps_codec, isvce_cfg_params_t *ps_cfg)
3639 {
3640     /* config params */
3641     isvce_cfg_params_t *ps_curr_cfg = &ps_codec->s_cfg;
3642 
3643     /* error status */
3644     IH264E_ERROR_T err = IH264E_SUCCESS;
3645 
3646     /* temp var */
3647     UWORD32 u4_init_rc = 0;
3648 
3649     WORD8 i;
3650 
3651     /***********************/
3652     /* UPDATE CODEC CONFIG */
3653     /***********************/
3654     if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_DIMENSIONS)
3655     {
3656         UWORD32 wd_aln = ALIGN16(ps_cfg->u4_wd);
3657         UWORD32 ht_aln = ALIGN16(ps_cfg->u4_ht);
3658 
3659         if(ps_curr_cfg->u4_wd != wd_aln || ps_curr_cfg->u4_ht != ht_aln ||
3660            ps_curr_cfg->u4_disp_wd != ps_cfg->u4_disp_wd ||
3661            ps_curr_cfg->u4_disp_ht != ps_cfg->u4_disp_ht)
3662         {
3663             ps_curr_cfg->u4_wd = wd_aln;
3664             ps_curr_cfg->u4_ht = ht_aln;
3665 
3666             ps_curr_cfg->u4_disp_wd = ps_cfg->u4_disp_wd;
3667             ps_curr_cfg->u4_disp_ht = ps_cfg->u4_disp_ht;
3668 
3669             ps_curr_cfg->i4_wd_mbs = ps_curr_cfg->u4_wd >> 4;
3670             ps_curr_cfg->i4_ht_mbs = ps_curr_cfg->u4_ht >> 4;
3671 
3672             ps_codec->i4_rec_strd = ALIGN16(ps_cfg->u4_wd) + PAD_WD;
3673 
3674             /* If number of MBs in a frame changes the air map also changes.
3675              * Hence recompute air map also reset air pic cnt */
3676             if(ps_codec->s_cfg.e_air_mode != IVE_AIR_MODE_NONE)
3677             {
3678                 /* re-init the air map */
3679                 isvce_init_air_map(ps_codec);
3680 
3681                 /* reset air counter */
3682                 ps_codec->i4_air_pic_cnt = -1;
3683             }
3684 
3685             /* initialize mv bank buffer manager */
3686             err = isvce_svc_au_data_mgr_add_bufs(ps_codec);
3687             if(err != IH264E_SUCCESS) return err;
3688 
3689             /* initialize ref bank buffer manager */
3690             err = isvce_svc_au_buf_mgr_add_bufs(ps_codec);
3691             if(err != IH264E_SUCCESS) return err;
3692 
3693             /* since dimension changed, start new sequence by forcing IDR */
3694             ps_codec->force_curr_frame_type = IV_IDR_FRAME;
3695 
3696             /* in case dimension changes, we need to reinitialize RC as the
3697              * old model shall not fit further */
3698             u4_init_rc = 1;
3699 
3700             /* when the dimension changes, the header needs to be regenerated */
3701             ps_codec->i4_gen_header = 1;
3702         }
3703     }
3704     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_FRAMERATE)
3705     {
3706         /* temp var */
3707         UWORD32 u4_src_ticks, u4_tgt_ticks;
3708 
3709         u4_src_ticks = ih264e_frame_time_get_src_ticks(ps_codec->s_rate_control.pps_frame_time);
3710 
3711         u4_tgt_ticks = ih264e_frame_time_get_tgt_ticks(ps_codec->s_rate_control.pps_frame_time);
3712 
3713         /* Change frame rate */
3714         if(ps_codec->s_cfg.u4_src_frame_rate != ps_cfg->u4_src_frame_rate * 1000)
3715         {
3716             ps_codec->s_cfg.u4_src_frame_rate = ps_cfg->u4_src_frame_rate * 1000;
3717 
3718             ih264e_frame_time_update_src_frame_rate(ps_codec->s_rate_control.pps_frame_time,
3719                                                     ps_codec->s_cfg.u4_src_frame_rate);
3720 
3721             ih264_time_stamp_update_frame_rate(ps_codec->s_rate_control.pps_time_stamp,
3722                                                ps_codec->s_cfg.u4_src_frame_rate);
3723 
3724             for(i = 0; i < ps_cfg->s_svc_params.u1_num_spatial_layers; i++)
3725             {
3726                 irc_change_frame_rate(ps_codec->s_rate_control.apps_rate_control_api[i],
3727                                       ps_codec->s_cfg.u4_src_frame_rate, u4_src_ticks,
3728                                       u4_tgt_ticks);
3729             }
3730         }
3731 
3732         if(ps_codec->s_cfg.u4_tgt_frame_rate != ps_cfg->u4_tgt_frame_rate * 1000)
3733         {
3734             ps_codec->s_cfg.u4_tgt_frame_rate = ps_cfg->u4_tgt_frame_rate * 1000;
3735 
3736             ih264e_frame_time_update_tgt_frame_rate(ps_codec->s_rate_control.pps_frame_time,
3737                                                     ps_codec->s_cfg.u4_tgt_frame_rate);
3738 
3739             for(i = 0; i < ps_cfg->s_svc_params.u1_num_spatial_layers; i++)
3740             {
3741                 irc_change_frame_rate(ps_codec->s_rate_control.apps_rate_control_api[i],
3742                                       ps_codec->s_cfg.u4_src_frame_rate, u4_src_ticks,
3743                                       u4_tgt_ticks);
3744 
3745                 irc_change_frm_rate_for_bit_alloc(ps_codec->s_rate_control.apps_rate_control_api[i],
3746                                                   ps_codec->s_cfg.u4_tgt_frame_rate);
3747             }
3748         }
3749     }
3750     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_BITRATE)
3751     {
3752         for(i = 0; i < MAX_NUM_SPATIAL_LAYERS; i++)
3753         {
3754             if(ps_curr_cfg->au4_target_bitrate[i] != ps_cfg->au4_target_bitrate[i])
3755             {
3756                 if(IVE_RC_NONE != ps_curr_cfg->e_rc_mode)
3757                     irc_change_avg_bit_rate(ps_codec->s_rate_control.apps_rate_control_api[i],
3758                                             ps_cfg->au4_target_bitrate[i]);
3759 
3760                 ps_curr_cfg->au4_target_bitrate[i] = ps_cfg->au4_target_bitrate[i];
3761             }
3762         }
3763     }
3764     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_FRAMETYPE)
3765     {
3766         switch(ps_cfg->e_frame_type)
3767         {
3768             case IV_I_FRAME:
3769                 ps_codec->force_curr_frame_type = IV_I_FRAME;
3770                 break;
3771 
3772             case IV_IDR_FRAME:
3773                 ps_codec->force_curr_frame_type = IV_IDR_FRAME;
3774                 break;
3775 
3776             case IV_P_FRAME:
3777             default:
3778                 break;
3779         }
3780     }
3781     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_ME_PARAMS)
3782     {
3783         if(ps_curr_cfg->u4_enc_speed_preset == IVE_CONFIG)
3784         {
3785             ps_codec->s_cfg.u4_enable_hpel = ps_cfg->u4_enable_hpel;
3786             ps_codec->s_cfg.u4_enable_fast_sad = ps_cfg->u4_enable_fast_sad;
3787             ps_codec->s_cfg.u4_me_speed_preset = ps_cfg->u4_me_speed_preset;
3788             ps_codec->s_cfg.u4_enable_qpel = ps_cfg->u4_enable_qpel;
3789         }
3790         else if(ps_curr_cfg->u4_enc_speed_preset == IVE_FASTEST)
3791         {
3792             ps_codec->s_cfg.u4_enable_fast_sad = ps_cfg->u4_enable_fast_sad;
3793         }
3794         ps_codec->s_cfg.u4_srch_rng_x = ps_cfg->u4_srch_rng_x;
3795         ps_codec->s_cfg.u4_srch_rng_y = ps_cfg->u4_srch_rng_y;
3796 
3797         if(ps_codec->s_cfg.u4_enable_alt_ref != ps_cfg->u4_enable_alt_ref)
3798         {
3799             ps_codec->s_cfg.u4_enable_alt_ref = ps_cfg->u4_enable_alt_ref;
3800             ps_codec->u4_is_curr_frm_ref = 1;
3801         }
3802     }
3803     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_IPE_PARAMS)
3804     {
3805         ps_curr_cfg->u4_enc_speed_preset = ps_cfg->u4_enc_speed_preset;
3806 
3807         if(ps_curr_cfg->u4_enc_speed_preset == IVE_SLOWEST)
3808         {
3809             isa_dependent_fxns_t *ps_isa_dependent_fxns = &ps_codec->s_isa_dependent_fxns;
3810             enc_loop_fxns_t *ps_enc_loop_fxns = &ps_isa_dependent_fxns->s_enc_loop_fxns;
3811 
3812             /* enable diamond search */
3813             ps_curr_cfg->u4_me_speed_preset = DMND_SRCH;
3814             ps_curr_cfg->u4_enable_fast_sad = 0;
3815 
3816             /* disable intra 4x4 */
3817             ps_curr_cfg->u4_enable_intra_4x4 = 1;
3818             ps_enc_loop_fxns->apf_luma_energy_compaction[1] =
3819                 isvce_code_luma_intra_macroblock_4x4_rdopt_on;
3820 
3821             /* sub pel off */
3822             ps_curr_cfg->u4_enable_hpel = 1;
3823 
3824             /* disabled intra inter gating in Inter slices */
3825             ps_codec->u4_inter_gate = 0;
3826         }
3827         else if(ps_curr_cfg->u4_enc_speed_preset == IVE_NORMAL)
3828         { /* normal */
3829             /* enable diamond search */
3830             ps_curr_cfg->u4_me_speed_preset = DMND_SRCH;
3831             ps_curr_cfg->u4_enable_fast_sad = 0;
3832 
3833             /* disable intra 4x4 */
3834             ps_curr_cfg->u4_enable_intra_4x4 = 1;
3835 
3836             /* sub pel off */
3837             ps_curr_cfg->u4_enable_hpel = 1;
3838 
3839             /* disabled intra inter gating in Inter slices */
3840             ps_codec->u4_inter_gate = 0;
3841         }
3842         else if(ps_curr_cfg->u4_enc_speed_preset == IVE_FAST)
3843         { /* normal */
3844             /* enable diamond search */
3845             ps_curr_cfg->u4_me_speed_preset = DMND_SRCH;
3846             ps_curr_cfg->u4_enable_fast_sad = 0;
3847 
3848             /* disable intra 4x4 */
3849             ps_curr_cfg->u4_enable_intra_4x4 = 0;
3850 
3851             /* sub pel off */
3852             ps_curr_cfg->u4_enable_hpel = 1;
3853 
3854             /* disabled intra inter gating in Inter slices */
3855             ps_codec->u4_inter_gate = 1;
3856         }
3857         else if(ps_curr_cfg->u4_enc_speed_preset == IVE_HIGH_SPEED)
3858         { /* fast */
3859             /* enable diamond search */
3860             ps_curr_cfg->u4_me_speed_preset = DMND_SRCH;
3861             ps_curr_cfg->u4_enable_fast_sad = 0;
3862 
3863             /* disable intra 4x4 */
3864             ps_curr_cfg->u4_enable_intra_4x4 = 0;
3865 
3866             /* sub pel off */
3867             ps_curr_cfg->u4_enable_hpel = 0;
3868 
3869             /* disabled intra inter gating in Inter slices */
3870             ps_codec->u4_inter_gate = 0;
3871         }
3872         else if(ps_curr_cfg->u4_enc_speed_preset == IVE_FASTEST)
3873         { /* fastest */
3874             /* enable diamond search */
3875             ps_curr_cfg->u4_me_speed_preset = DMND_SRCH;
3876             // u4_num_layers = 4;
3877 
3878             /* disable intra 4x4 */
3879             ps_curr_cfg->u4_enable_intra_4x4 = 0;
3880 
3881             /* sub pel off */
3882             ps_curr_cfg->u4_enable_hpel = 0;
3883 
3884             /* disabled intra inter gating in Inter slices */
3885             ps_codec->u4_inter_gate = 1;
3886         }
3887         else if(ps_curr_cfg->u4_enc_speed_preset == IVE_CONFIG)
3888         {
3889             ps_curr_cfg->u4_enable_intra_4x4 = ps_cfg->u4_enable_intra_4x4;
3890         }
3891     }
3892     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_GOP_PARAMS)
3893     {
3894         if(ps_curr_cfg->u4_i_frm_interval != ps_cfg->u4_i_frm_interval)
3895         {
3896             ps_curr_cfg->u4_i_frm_interval = ps_cfg->u4_i_frm_interval;
3897 
3898             /* reset air counter */
3899             ps_codec->i4_air_pic_cnt = -1;
3900 
3901             /* re-init air map */
3902             isvce_init_air_map(ps_codec);
3903 
3904             /*Effect intra frame interval change*/
3905             for(i = 0; i < ps_cfg->s_svc_params.u1_num_spatial_layers; i++)
3906             {
3907                 irc_change_intra_frm_int_call(ps_codec->s_rate_control.apps_rate_control_api[i],
3908                                               ps_curr_cfg->u4_i_frm_interval);
3909             }
3910         }
3911 
3912         ps_curr_cfg->u4_idr_frm_interval = ps_cfg->u4_idr_frm_interval;
3913     }
3914     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_DEBLOCK_PARAMS)
3915     {
3916         ps_curr_cfg->u4_disable_deblock_level = ps_cfg->u4_disable_deblock_level;
3917     }
3918     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_QP)
3919     {
3920         for(i = 0; i < ps_cfg->s_svc_params.u1_num_spatial_layers; i++)
3921         {
3922             UWORD8 au1_init_qp[MAX_PIC_TYPE];
3923             UWORD8 au1_min_max_qp[2 * MAX_PIC_TYPE];
3924             UWORD8 au1_min_max_avc_qp[2 * MAX_PIC_TYPE];
3925 
3926             ps_codec->s_cfg.au4_i_qp_max[i] = ps_cfg->au4_i_qp_max[i];
3927             ps_codec->s_cfg.au4_i_qp_min[i] = ps_cfg->au4_i_qp_min[i];
3928             ps_codec->s_cfg.au4_i_qp[i] = ps_cfg->au4_i_qp[i];
3929 
3930             ps_codec->s_cfg.au4_p_qp_max[i] = ps_cfg->au4_p_qp_max[i];
3931             ps_codec->s_cfg.au4_p_qp_min[i] = ps_cfg->au4_p_qp_min[i];
3932             ps_codec->s_cfg.au4_p_qp[i] = ps_cfg->au4_p_qp[i];
3933 
3934             ps_codec->s_cfg.au4_b_qp_max[i] = ps_cfg->au4_b_qp_max[i];
3935             ps_codec->s_cfg.au4_b_qp_min[i] = ps_cfg->au4_b_qp_min[i];
3936             ps_codec->s_cfg.au4_b_qp[i] = ps_cfg->au4_b_qp[i];
3937 
3938             /* update rc lib with modified qp */
3939             au1_init_qp[0] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp[i]];
3940             au1_init_qp[1] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp[i]];
3941             au1_init_qp[2] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp[i]];
3942 
3943             irc_change_init_qp(ps_codec->s_rate_control.apps_rate_control_api[i], au1_init_qp);
3944 
3945             au1_min_max_qp[2 * I_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp_min[i]];
3946             au1_min_max_qp[2 * I_PIC + 1] =
3947                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp_max[i]];
3948 
3949             au1_min_max_qp[2 * P_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp_min[i]];
3950             au1_min_max_qp[2 * P_PIC + 1] =
3951                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp_max[i]];
3952 
3953             au1_min_max_qp[2 * B_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp_min[i]];
3954             au1_min_max_qp[2 * B_PIC + 1] =
3955                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp_max[i]];
3956 
3957             au1_min_max_avc_qp[2 * I_PIC] = ps_codec->s_cfg.au4_i_qp_min[i];
3958             au1_min_max_avc_qp[2 * I_PIC + 1] = ps_codec->s_cfg.au4_i_qp_max[i];
3959 
3960             au1_min_max_avc_qp[2 * P_PIC] = ps_codec->s_cfg.au4_p_qp_min[i];
3961             au1_min_max_avc_qp[2 * P_PIC + 1] = ps_codec->s_cfg.au4_p_qp_max[i];
3962 
3963             au1_min_max_avc_qp[2 * B_PIC] = ps_codec->s_cfg.au4_b_qp_min[i];
3964             au1_min_max_avc_qp[2 * B_PIC + 1] = ps_codec->s_cfg.au4_b_qp_max[i];
3965 
3966             irc_change_qp_constraints(ps_codec->s_rate_control.apps_rate_control_api[i],
3967                                       au1_min_max_qp, au1_min_max_avc_qp);
3968         }
3969     }
3970     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_ENC_MODE)
3971     {
3972         ps_codec->s_cfg.e_enc_mode = ps_cfg->e_enc_mode;
3973 
3974         if(ps_codec->s_cfg.e_enc_mode == IVE_ENC_MODE_HEADER)
3975         {
3976             ps_codec->i4_header_mode = 1;
3977             ps_codec->s_cfg.e_enc_mode = IVE_ENC_MODE_PICTURE;
3978         }
3979         else
3980         {
3981             ps_codec->i4_header_mode = 0;
3982         }
3983     }
3984     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_VBV_PARAMS &&
3985             IVE_RC_NONE != ps_codec->s_cfg.e_rc_mode)
3986     {
3987         for(i = 0; i < ps_cfg->s_svc_params.u1_num_spatial_layers; i++)
3988         {
3989             ps_codec->s_cfg.au4_vbv_buffer_delay[i] = ps_cfg->au4_vbv_buffer_delay[i];
3990         }
3991         // irc_change_buffer_delay(ps_codec->s_rate_control.pps_rate_control_api,
3992         // ps_codec->s_cfg.u4_vbv_buffer_delay);
3993 
3994         // TODO: remove this when the support for changing buffer dynamically
3995         // is yet to be added.
3996         u4_init_rc = 1;
3997     }
3998     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_AIR_PARAMS)
3999     {
4000         if(ps_curr_cfg->e_air_mode != ps_cfg->e_air_mode ||
4001            ps_curr_cfg->u4_air_refresh_period != ps_cfg->u4_air_refresh_period)
4002         {
4003             ps_curr_cfg->e_air_mode = ps_cfg->e_air_mode;
4004             ps_curr_cfg->u4_air_refresh_period = ps_cfg->u4_air_refresh_period;
4005 
4006             isvce_init_air_map(ps_codec);
4007 
4008             /* reset air counter */
4009             ps_codec->i4_air_pic_cnt = -1;
4010         }
4011     }
4012     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_PROFILE_PARAMS)
4013     {
4014         ps_codec->s_cfg.e_profile = ps_cfg->e_profile;
4015         ps_codec->s_cfg.u4_entropy_coding_mode = ps_cfg->u4_entropy_coding_mode;
4016     }
4017     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_NUM_CORES)
4018     {
4019         ps_codec->s_cfg.u4_num_cores = ps_cfg->u4_num_cores;
4020     }
4021     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_VUI_PARAMS)
4022     {
4023         ps_codec->s_cfg.s_vui = ps_cfg->s_vui;
4024     }
4025 
4026     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_SEI_MDCV_PARAMS)
4027     {
4028         ps_codec->s_cfg.s_sei.u1_sei_mdcv_params_present_flag =
4029             ps_cfg->s_sei.u1_sei_mdcv_params_present_flag;
4030         ps_codec->s_cfg.s_sei.s_sei_mdcv_params = ps_cfg->s_sei.s_sei_mdcv_params;
4031     }
4032     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_SEI_CLL_PARAMS)
4033     {
4034         ps_codec->s_cfg.s_sei.u1_sei_cll_params_present_flag =
4035             ps_cfg->s_sei.u1_sei_cll_params_present_flag;
4036         ps_codec->s_cfg.s_sei.s_sei_cll_params = ps_cfg->s_sei.s_sei_cll_params;
4037     }
4038     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_SEI_AVE_PARAMS)
4039     {
4040         ps_codec->s_cfg.s_sei.u1_sei_ave_params_present_flag =
4041             ps_cfg->s_sei.u1_sei_ave_params_present_flag;
4042         ps_codec->s_cfg.s_sei.s_sei_ave_params = ps_cfg->s_sei.s_sei_ave_params;
4043     }
4044     else if(ps_cfg->e_cmd == ISVCE_CMD_CTL_SET_SEI_CCV_PARAMS)
4045     {
4046         ps_codec->s_cfg.s_sei.u1_sei_ccv_params_present_flag =
4047             ps_cfg->s_sei.u1_sei_ccv_params_present_flag;
4048         ps_codec->s_cfg.s_sei.s_sei_ccv_params = ps_cfg->s_sei.s_sei_ccv_params;
4049     }
4050 
4051     /* reset RC model */
4052     if(u4_init_rc)
4053     {
4054         for(i = 0; i < ps_cfg->s_svc_params.u1_num_spatial_layers; i++)
4055         {
4056             /* init qp */
4057             UWORD8 au1_init_qp[MAX_PIC_TYPE];
4058 
4059             /* min max qp */
4060             UWORD8 au1_min_max_qp[2 * MAX_PIC_TYPE];
4061 
4062             /* init i,p,b qp */
4063             au1_init_qp[0] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp[i]];
4064             au1_init_qp[1] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp[i]];
4065             au1_init_qp[2] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp[i]];
4066 
4067             /* init min max qp */
4068             au1_min_max_qp[2 * I_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp_min[i]];
4069             au1_min_max_qp[2 * I_PIC + 1] =
4070                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_i_qp_max[i]];
4071 
4072             au1_min_max_qp[2 * P_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp_min[i]];
4073             au1_min_max_qp[2 * P_PIC + 1] =
4074                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_p_qp_max[i]];
4075 
4076             au1_min_max_qp[2 * B_PIC] = gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp_min[i]];
4077             au1_min_max_qp[2 * B_PIC + 1] =
4078                 gau1_h264_to_mpeg2_qmap[ps_codec->s_cfg.au4_b_qp_max[i]];
4079 
4080             /* get rc mode */
4081             switch(ps_codec->s_cfg.e_rc_mode)
4082             {
4083                 case IVE_RC_STORAGE:
4084                     ps_codec->s_rate_control.e_rc_type = VBR_STORAGE;
4085                     break;
4086 
4087                 case IVE_RC_CBR_NON_LOW_DELAY:
4088                     ps_codec->s_rate_control.e_rc_type = CBR_NLDRC;
4089                     break;
4090 
4091                 case IVE_RC_CBR_LOW_DELAY:
4092                     ps_codec->s_rate_control.e_rc_type = CBR_LDRC;
4093                     break;
4094 
4095                 case IVE_RC_NONE:
4096                     ps_codec->s_rate_control.e_rc_type = CONST_QP;
4097                     break;
4098 
4099                 default:
4100                     break;
4101             }
4102 
4103             /* init rate control */
4104             for(i = 0; i < MAX_NUM_SPATIAL_LAYERS; i++)
4105             {
4106                 isvce_rc_init(
4107                     ps_codec->s_rate_control.apps_rate_control_api[i],
4108                     ps_codec->s_rate_control.pps_frame_time,
4109                     ps_codec->s_rate_control.pps_time_stamp,
4110                     ps_codec->s_rate_control.pps_pd_frm_rate, ps_codec->s_cfg.u4_max_framerate,
4111                     ps_codec->s_cfg.u4_src_frame_rate, ps_codec->s_cfg.u4_tgt_frame_rate,
4112                     ps_codec->s_rate_control.e_rc_type, ps_codec->s_cfg.au4_target_bitrate[i],
4113                     ps_codec->s_cfg.au4_max_bitrate[i], ps_codec->s_cfg.au4_vbv_buffer_delay[i],
4114                     ps_codec->s_cfg.u4_i_frm_interval, ps_codec->s_cfg.u4_num_bframes + 1,
4115                     au1_init_qp, ps_codec->s_cfg.u4_num_bframes + 2, au1_min_max_qp,
4116                     ps_codec->s_cfg.u4_max_level);
4117             }
4118         }
4119     }
4120 
4121     return err;
4122 }
4123 
isvce_change_rc_init_qp(void * pv_rate_control_api,UWORD8 u1_qp)4124 static FORCEINLINE void isvce_change_rc_init_qp(void *pv_rate_control_api, UWORD8 u1_qp)
4125 {
4126     UWORD8 au1_pic_qps[MAX_PIC_TYPE];
4127     WORD32 i;
4128 
4129     for(i = 0; i < MAX_PIC_TYPE; i++)
4130     {
4131         au1_pic_qps[i] = gau1_h264_to_mpeg2_qmap[CLIP3(MIN_H264_QP, MAX_H264_QP, u1_qp + i)];
4132     }
4133 
4134     irc_change_init_qp(pv_rate_control_api, au1_pic_qps);
4135 }
4136 
4137 /**
4138  *******************************************************************************
4139  *
4140  * @brief
4141  *  Queues the current buffer, gets back a another buffer for encoding with
4142  *corrent picture type
4143  *
4144  * @par Description:
4145  *      This function performs 3 distinct but related functions.
4146  *      1) Maintains an input queue [Note the the term queue donot imply a
4147  *         first-in first-out logic here] that queues input and dequeues them so
4148  *         that input frames can be encoded at any predetermined encoding order
4149  *      2) Uses RC library to decide which frame must be encoded in current pass
4150  *         and which picture type it must be encoded to.
4151  *      3) Uses RC library to decide the QP at which current frame has to be
4152  *         encoded
4153  *      4) Determines if the current picture must be encoded or not based on
4154  *         PRE-ENC skip
4155  *
4156  *     Input queue is used for storing input buffers till they are used for
4157  *     encoding. This queue is maintained at ps_codec->as_inp_list. Whenever a
4158  *     valid input comes, it is added to the end of queue. This same input is
4159  *     added to RC queue using the identifier as ps_codec->i4_pic_cnt. Hence any
4160  *     pic from RC can be located in the input queue easily.
4161  *
4162  *     The dequeue operation does not start till we have
4163  *ps_codec->s_cfg.u4_max_num_bframes frames in the queue. THis is done in order
4164  *to ensure that once output starts we will have a constant stream of output
4165  *with no gaps.
4166  *
4167  *     THe output frame order is governed by RC library. When ever we dequeue a
4168  *     buffer from RC library, it ensures that we will get them in encoding
4169  *order With the output of RC library, we can use the picture id to dequeue the
4170  *     corresponding buffer from input queue and encode it.
4171  *
4172  *     Condition at the end of stream.
4173  *     -------------------------------
4174  *      At the last valid buffer from the app, we will get ps_ive_ip->u4_is_last
4175  *      to be set. This will the given to lib when appropriate input buffer is
4176  *      given to encoding.
4177  *
4178  *      Since we have to output is not in sync with input, we will have frames
4179  *to encode even after we recive the last vaild input buffer. Hence we have to
4180  *      make sure that we donot queue any new buffers once we get the flag [It
4181  *may mess up GOP ?]. This is acheived by setting
4182  *ps_codec->i4_last_inp_buff_received to act as a permenent marker for last
4183  *frame recived [This may not be needed, because in our current app, all buffers
4184  *after the last are marked as last. But can we rely on that?] . Hence after
4185  *this flgag is set no new buffers are queued.
4186  *
4187  * @param[in] ps_codec
4188  *   Pointer to codec descriptor
4189  *
4190  * @param[in] ps_ive_ip
4191  *   Current input buffer to the encoder
4192  *
4193  * @param[out] ps_inp
4194  *   Buffer to be encoded in the current pass
4195  *
4196  * @returns
4197  *   Flag indicating if we have a pre-enc skip or not
4198  *
4199  * @remarks
4200  * TODO (bpic)
4201  *  The check for null ans is last is redudent.
4202  *  Need to see if we can remove it
4203  *
4204  *******************************************************************************
4205  */
isvce_input_queue_update(isvce_codec_t * ps_codec,ive_video_encode_ip_t * ps_ive_ip,isvce_inp_buf_t * ps_enc_buff,WORD8 i1_layer_id)4206 WORD32 isvce_input_queue_update(isvce_codec_t *ps_codec, ive_video_encode_ip_t *ps_ive_ip,
4207                                 isvce_inp_buf_t *ps_enc_buff, WORD8 i1_layer_id)
4208 {
4209     isvce_inp_buf_t *ps_inp_buf;
4210     picture_type_e e_pictype;
4211     WORD32 i4_skip;
4212     UWORD32 ctxt_sel, u4_pic_id, u4_pic_disp_id;
4213     UWORD8 u1_frame_qp = MAX_H264_QP;
4214     UWORD32 max_frame_bits = 0x7FFFFFFF;
4215 
4216     WORD32 i;
4217 
4218     /*  Mark that the last input frame has been received */
4219     if(ps_ive_ip->u4_is_last == 1)
4220     {
4221         ps_codec->i4_last_inp_buff_received = 1;
4222     }
4223 
4224     if(ps_ive_ip->s_inp_buf.apv_bufs[0] == NULL && !ps_codec->i4_last_inp_buff_received)
4225     {
4226         ps_enc_buff->s_inp_props.s_raw_buf.apv_bufs[0] = NULL;
4227         ps_enc_buff->s_inp_props.u4_is_last = ps_ive_ip->u4_is_last;
4228         return 0;
4229     }
4230 
4231     /***************************************************************************
4232      * Check for pre enc skip
4233      *   When src and target frame rates donot match, we skip some frames to
4234      *   maintain the relation ship between them
4235      **************************************************************************/
4236     {
4237         WORD32 skip_src;
4238 
4239         skip_src = isvce_update_rc_framerates(
4240             ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id],
4241             ps_codec->s_rate_control.pps_pd_frm_rate, ps_codec->s_rate_control.pps_time_stamp,
4242             ps_codec->s_rate_control.pps_frame_time);
4243 
4244         if(skip_src)
4245         {
4246             ps_enc_buff->s_inp_props.u4_is_last = ps_ive_ip->u4_is_last;
4247             return 1;
4248         }
4249     }
4250 
4251     /***************************************************************************
4252      *Queue the input to the queue
4253      **************************************************************************/
4254     ps_inp_buf = &(ps_codec->as_inp_list[ps_codec->i4_pic_cnt % SVC_MAX_NUM_INP_FRAMES]);
4255 
4256     /* copy input info. to internal structure */
4257     ps_inp_buf->s_inp_props.s_raw_buf = ps_ive_ip->s_inp_buf;
4258     ps_inp_buf->s_inp_props.u4_timestamp_low = ps_ive_ip->u4_timestamp_low;
4259     ps_inp_buf->s_inp_props.u4_timestamp_high = ps_ive_ip->u4_timestamp_high;
4260     ps_inp_buf->s_inp_props.u4_is_last = ps_ive_ip->u4_is_last;
4261     ps_inp_buf->s_inp_props.pv_mb_info = ps_ive_ip->pv_mb_info;
4262     ps_inp_buf->s_inp_props.u4_mb_info_type = ps_ive_ip->u4_mb_info_type;
4263     ps_inp_buf->s_inp_props.pv_pic_info = ps_ive_ip->pv_pic_info;
4264     ps_inp_buf->s_inp_props.u4_pic_info_type = ps_ive_ip->u4_pic_info_type;
4265 
4266     ps_inp_buf->s_inp_props.u1_sei_ccv_params_present_flag =
4267         ps_codec->s_cfg.s_sei.u1_sei_ccv_params_present_flag;
4268     ps_inp_buf->s_inp_props.s_sei_ccv = ps_codec->s_cfg.s_sei.s_sei_ccv_params;
4269 
4270     if(ps_inp_buf->s_inp_props.s_raw_buf.apv_bufs[0])
4271         isvce_svc_inp_buf_populate(ps_codec, ps_inp_buf);
4272 
4273     /***************************************************************************
4274      * Now we should add the picture to RC stack here
4275      **************************************************************************/
4276     /*
4277      * If an I frame has been requested, ask  RC to force it
4278      * For IDR requests, we have to ask RC to force I and set IDR by our selves
4279      * since RC Donot know about IDR. For forcing an IDR at dequeue stage we
4280      * should record that an IDR has been requested some where. Hence we will
4281      * store it in the u4_idr_inp_list at a position same as that of input frame
4282      */
4283     {
4284         WORD32 i4_force_idr, i4_force_i;
4285 
4286         i4_force_idr = (ps_codec->force_curr_frame_type == IV_IDR_FRAME);
4287         i4_force_idr |= !(ps_codec->i4_pic_cnt % ps_codec->s_cfg.u4_idr_frm_interval);
4288 
4289         i4_force_i = (ps_codec->force_curr_frame_type == IV_I_FRAME);
4290 
4291         ps_codec->i4_pending_idr_flag |= i4_force_idr;
4292 
4293         if((ps_codec->i4_pic_cnt > 0) && (i4_force_idr || i4_force_i))
4294         {
4295             irc_force_I_frame(ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id]);
4296         }
4297 
4298         if(i1_layer_id == (ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers - 1))
4299         {
4300             ps_codec->force_curr_frame_type = IV_NA_FRAME;
4301         }
4302     }
4303 
4304     irc_add_picture_to_stack(ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id],
4305                              ps_codec->i4_pic_cnt);
4306 
4307     /* Delay */
4308     if(ps_codec->i4_encode_api_call_cnt < (WORD32) (ps_codec->s_cfg.u4_num_bframes))
4309     {
4310         ps_enc_buff->s_inp_props.s_raw_buf.apv_bufs[0] = NULL;
4311         ps_enc_buff->s_inp_props.u4_is_last = 0;
4312         return 0;
4313     }
4314 
4315     /***************************************************************************
4316      * Get a new pic to encode
4317      **************************************************************************/
4318     /* Query the picture_type */
4319     e_pictype =
4320         isvce_rc_get_picture_details(ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id],
4321                                      (WORD32 *) (&u4_pic_id), (WORD32 *) (&u4_pic_disp_id));
4322 
4323     switch(e_pictype)
4324     {
4325         case I_PIC:
4326             ps_codec->pic_type = PIC_I;
4327             break;
4328         case P_PIC:
4329             ps_codec->pic_type = PIC_P;
4330             break;
4331         case B_PIC:
4332             ps_codec->pic_type = PIC_B;
4333             break;
4334         default:
4335             ps_codec->pic_type = PIC_NA;
4336             ps_enc_buff->s_inp_props.s_raw_buf.apv_bufs[0] = NULL;
4337             return 0;
4338     }
4339 
4340     /* Set IDR if it has been requested */
4341     if(ps_codec->pic_type == PIC_I)
4342     {
4343         ps_codec->pic_type = ps_codec->i4_pending_idr_flag ? PIC_IDR : ps_codec->pic_type;
4344         ps_codec->i4_pending_idr_flag = 0;
4345     }
4346 
4347     if(ps_codec->s_rate_control.e_rc_type != CONST_QP && ps_codec->u1_enable_init_qp &&
4348        (u4_pic_id == 0 ||
4349         irc_is_scenecut(ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id])))
4350     {
4351         DOUBLE d_bpp;
4352 
4353         svc_rc_utils_ctxt_t *ps_svc_rc_utils = &ps_codec->s_rate_control.s_rc_utils;
4354 
4355         UWORD32 u4_src_fps = ps_codec->s_cfg.u4_src_frame_rate / 1000;
4356         UWORD32 u4_wd = ps_inp_buf->as_layer_yuv_buf_props[i1_layer_id].u4_width;
4357         UWORD32 u4_ht = ps_inp_buf->as_layer_yuv_buf_props[i1_layer_id].u4_height;
4358         DOUBLE d_gpp =
4359             isvce_compute_gpp(ps_svc_rc_utils, &ps_inp_buf->as_layer_yuv_buf_props[i1_layer_id]);
4360 
4361         d_bpp = ((DOUBLE) irc_get_vbv_buf_size(
4362                      ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id]) /
4363                  10.) /
4364                 ((DOUBLE) (u4_src_fps * u4_wd * u4_ht));
4365 
4366         u1_frame_qp = (UWORD8) irc_get_frame_level_init_qp(
4367             ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id],
4368             ps_codec->s_rate_control.e_rc_type, e_pictype, d_bpp, d_gpp);
4369 
4370         isvce_change_rc_init_qp(ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id],
4371                                 u1_frame_qp);
4372 
4373         ps_codec->au4_frame_qp[i1_layer_id] = u1_frame_qp;
4374     }
4375     else
4376     {
4377         /* Get current frame Qp */
4378         u1_frame_qp = (UWORD8) irc_get_frame_level_qp(
4379             ps_codec->s_rate_control.apps_rate_control_api[i1_layer_id], e_pictype, max_frame_bits);
4380         ps_codec->au4_frame_qp[i1_layer_id] = gau1_mpeg2_to_h264_qmap[u1_frame_qp];
4381     }
4382 
4383     /*
4384      * copy the pic id to poc because the display order is assumed to be same
4385      * as input order
4386      */
4387     ps_codec->i4_poc = u4_pic_id;
4388 
4389     /***************************************************************************
4390      * Now retrieve the correct picture from the queue
4391      **************************************************************************/
4392 
4393     /* Mark the skip flag   */
4394     i4_skip = 0;
4395     ctxt_sel = ps_codec->i4_encode_api_call_cnt % MAX_CTXT_SETS;
4396     ps_codec->s_rate_control.pre_encode_skip[ctxt_sel] = i4_skip;
4397 
4398     /* Get a buffer to encode */
4399     ps_inp_buf = &(ps_codec->as_inp_list[u4_pic_id % SVC_MAX_NUM_INP_FRAMES]);
4400 
4401     /* copy dequeued input to output */
4402     ps_enc_buff[0] = ps_inp_buf[0];
4403 
4404     /* Special case for encoding trailing B frames
4405      *
4406      * In encoding streams with B frames it may happen that we have a B frame
4407      * at the end without a P/I frame after it. Hence when we are dequeing from
4408      * the RC, it will return the P frame [next in display order but before in
4409      * encoding order] first. Since the dequeue happens for an invalid frame we
4410      * will get a frame with null buff and set u4_is_last. Hence lib with return
4411      * last frame flag at this point and will stop encoding.
4412      *
4413      * Since for the last B frame, we does not have the forward ref frame
4414      * it makes sense to force it into P.
4415      *
4416      * To solve this, in case the current frame is P and if the last frame flag
4417      * is set, we need to see if there is and pending B frames. If there are any,
4418      * we should just encode that picture as the current P frame and set
4419      * that B frame as the last frame. Hence the encoder will terminate naturally
4420      * once that B-frame is encoded after all the in between frames.
4421      *
4422      * Since we cannot touch RC stack directly, the option of actually swapping
4423      * frames in RC is ruled out. We have to modify the as_inp_list to simulate
4424      * such a behavior by RC. We can do that by
4425      *  1) Search through as_inp_list to locate the largest u4_timestamp_low less
4426      *     than current u4_timestamp_low. This will give us the last B frame
4427      * before the current P frame. Note that this will handle pre encode skip too
4428      * since queue happens after pre enc skip. 2) Swap the position in
4429      * as_inp_list. Hence now the last B frame is encoded as P frame. And the new
4430      * last B frame will have u4_is_last set so that encoder will end naturally
4431      * once we reached that B frame or any subsequent frame. Also the current GOP
4432      * will have 1 less B frame Since we are swapping, the poc will also be
4433      * in-order. 3) In case we have an IPP stream, the result of our search will
4434      * be an I/P frame which is already encoded. Thus swap and encode will result
4435      *     in encoding of duplicate frames. Hence to avoid this we will only
4436      *     have this work around in case of u4_num_bframes > 0.
4437      *
4438      *     In case we have forced an I/IDR frame In between this P frame and
4439      *     the last B frame -> This cannot happen as the current P frame is
4440      *     supposed to have u4_is_last set. Thus forcing an I/ IDR after this
4441      *     is illogical.
4442      *
4443      *     In cae if we have forced an I such that the frame just before last
4444      * frame in is I/P -> This case will never arise. Since we have a closed GOP
4445      * now, once we force an I, the gop gets reset, hence there will be a B
4446      * between I/P and I/P.
4447      */
4448     if(ps_enc_buff->s_inp_props.u4_is_last && (ps_codec->pic_type == PIC_P) &&
4449        ps_codec->s_cfg.u4_num_bframes)
4450     {
4451         WORD32 cntr;
4452         WORD32 lst_bframe = -1;
4453         UWORD32 u4_timestamp_low = 0;
4454         UWORD32 u4_timestamp_high = 0;
4455         isvce_inp_buf_t *ps_swap_buff, *ps_inp_list;
4456 
4457         ps_inp_list = &ps_codec->as_inp_list[0];
4458 
4459         /* Now search the inp list for highest timestamp */
4460         for(cntr = 0; cntr < SVC_MAX_NUM_INP_FRAMES; cntr++)
4461         {
4462             if(ps_inp_list[cntr].s_inp_props.s_raw_buf.apv_bufs[0] != NULL)
4463             {
4464                 if((ps_inp_list[cntr].s_inp_props.u4_timestamp_high > u4_timestamp_high) ||
4465                    (ps_inp_list[cntr].s_inp_props.u4_timestamp_high == u4_timestamp_high &&
4466                     ps_inp_list[cntr].s_inp_props.u4_timestamp_low > u4_timestamp_low))
4467                 {
4468                     u4_timestamp_low = ps_inp_list[cntr].s_inp_props.u4_timestamp_low;
4469                     u4_timestamp_high = ps_inp_list[cntr].s_inp_props.u4_timestamp_high;
4470                     lst_bframe = cntr;
4471                 }
4472             }
4473         }
4474 
4475         if(lst_bframe != -1)
4476         {
4477             ps_swap_buff = &(ps_codec->as_inp_list[lst_bframe]);
4478 
4479             /* copy the last B buffer to output */
4480             *ps_enc_buff = *ps_swap_buff;
4481 
4482             /* Store the current buf into the queue in place of last B buf */
4483             *ps_swap_buff = *ps_inp_buf;
4484         }
4485     }
4486 
4487     if(ps_enc_buff->s_inp_props.u4_is_last)
4488     {
4489         ps_codec->pic_type = PIC_NA;
4490     }
4491 
4492     /* The buffer in the queue is set to NULL to specify that encoding is done for
4493      * that frame */
4494     for(i = 0; i < 3; i++)
4495     {
4496         ps_inp_buf->s_inp_props.s_raw_buf.apv_bufs[i] = NULL;
4497     }
4498 
4499     /* Return the buffer status */
4500     return (0);
4501 }
4502 
4503 /**
4504 ******************************************************************************
4505 *
4506 * @brief
4507 *  This function joins all the spawned threads after successful completion of
4508 *  their tasks
4509 *
4510 * @par   Description
4511 *
4512 * @param[in] ps_codec
4513 *  pointer to codec context
4514 *
4515 * @returns  none
4516 *
4517 ******************************************************************************
4518 */
isvce_join_threads(isvce_codec_t * ps_codec)4519 void isvce_join_threads(isvce_codec_t *ps_codec)
4520 {
4521     WORD32 i = 0;
4522     WORD32 ret = 0;
4523 
4524     /* join spawned threads */
4525     while(i < ps_codec->i4_proc_thread_cnt)
4526     {
4527         if(ps_codec->ai4_process_thread_created[i])
4528         {
4529             ret = ithread_join(ps_codec->apv_proc_thread_handle[i], NULL);
4530 
4531             if(ret != 0)
4532             {
4533                 ASSERT(0);
4534             }
4535 
4536             ps_codec->ai4_process_thread_created[i] = 0;
4537             i++;
4538         }
4539     }
4540 
4541     ps_codec->i4_proc_thread_cnt = 0;
4542 }
4543 
isvce_get_min_outbuf_size(UWORD32 u4_wd,UWORD32 u4_ht,UWORD8 u1_num_spatial_layers)4544 UWORD32 isvce_get_min_outbuf_size(UWORD32 u4_wd, UWORD32 u4_ht, UWORD8 u1_num_spatial_layers)
4545 {
4546     return MAX((u4_wd * u4_ht * 3), MIN_STREAM_SIZE) * u1_num_spatial_layers;
4547 }