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 }