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