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