xref: /aosp_15_r20/external/libavc/encoder/svc/isvce_encode.c (revision 495ae853bb871d1e5a258cb02c2cc13cde8ddb9a)
1 /******************************************************************************
2  *
3  * Copyright (C) 2022 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 
21 /**
22 ******************************************************************************
23 * @file
24 *  isvce_encode.c
25 *
26 * @brief
27 *  This file contains functions for encoding the input yuv frame in synchronous
28 *  api mode
29 *
30 * @author
31 *  ittiam
32 *
33 * List of Functions
34 *  - isvce_join_threads()
35 *  - isvce_wait_for_thread()
36 *  - isvce_encode()
37 *
38 ******************************************************************************
39 */
40 #include <stdio.h>
41 #include <stddef.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <limits.h>
45 #include <assert.h>
46 #include <math.h>
47 #include <stdbool.h>
48 
49 #include "ih264_typedefs.h"
50 /* Dependencies of ih264_buf_mgr.h */
51 /* Dependencies of ih264_list.h */
52 #include "ih264_error.h"
53 /* Dependencies of ih264_common_tables.h */
54 #include "ih264_defs.h"
55 #include "ih264_structs.h"
56 #include "ih264_buf_mgr.h"
57 #include "ih264_common_tables.h"
58 #include "ih264_list.h"
59 #include "ih264_platform_macros.h"
60 #include "ih264_trans_data.h"
61 #include "ih264_size_defs.h"
62 /* Dependencies of ih264e_cabac_structs.h */
63 #include "ih264_cabac_tables.h"
64 /* Dependencies of ime_structs.h */
65 #include "ime_defs.h"
66 #include "ime_distortion_metrics.h"
67 /* Dependencies of ih264e_structs.h */
68 #include "iv2.h"
69 #include "ive2.h"
70 #include "ih264_defs.h"
71 #include "ih264_deblk_edge_filters.h"
72 #include "ih264_inter_pred_filters.h"
73 #include "ih264_structs.h"
74 #include "ih264_trans_quant_itrans_iquant.h"
75 /* Dependencies of ih264e_bitstream.h */
76 #include "ih264e_error.h"
77 #include "ih264e_bitstream.h"
78 #include "ih264e_cabac_structs.h"
79 #include "irc_cntrl_param.h"
80 #include "irc_frame_info_collector.h"
81 #include "ime_statistics.h"
82 #include "ime_structs.h"
83 /* Dependencies of 'ih264e_utils.h' */
84 #include "ih264e_defs.h"
85 #include "ih264e_structs.h"
86 #include "ih264e_utils.h"
87 #include "ime.h"
88 #include "isvce.h"
89 #include "isvce_cabac.h"
90 #include "isvce_deblk.h"
91 #include "isvce_defs.h"
92 #include "isvce_downscaler.h"
93 #include "isvce_encode_header.h"
94 #include "isvce_fmt_conv.h"
95 #include "isvce_ibl_eval.h"
96 #include "isvce_ilp_mv.h"
97 #include "isvce_intra_modes_eval.h"
98 #include "isvce_me.h"
99 #include "isvce_process.h"
100 #include "isvce_rate_control.h"
101 #include "isvce_residual_pred.h"
102 #include "isvce_sub_pic_rc.h"
103 #include "isvce_utils.h"
104 
105 #define SEI_BASED_FORCE_IDR 1
106 
107 /*****************************************************************************/
108 /* Function Definitions                                                      */
109 /*****************************************************************************/
110 
111 /**
112 ******************************************************************************
113 *
114 * @brief
115 *  Encodes in synchronous api mode
116 *
117 * @par Description
118 *  This routine processes input yuv, encodes it and outputs bitstream and recon
119 *
120 * @param[in] ps_codec_obj
121 *  Pointer to codec object at API level
122 *
123 * @param[in] pv_api_ip
124 *  Pointer to input argument structure
125 *
126 * @param[out] pv_api_op
127 *  Pointer to output argument structure
128 *
129 * @returns  Status
130 *
131 ******************************************************************************
132 */
isvce_encode(iv_obj_t * ps_codec_obj,void * pv_api_ip,void * pv_api_op)133 WORD32 isvce_encode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op)
134 {
135     /* error status */
136     IH264E_ERROR_T error_status = IH264E_SUCCESS;
137 
138     /* codec ctxt */
139     isvce_codec_t *ps_codec = (isvce_codec_t *) ps_codec_obj->pv_codec_handle;
140 
141     /* input frame to encode */
142     isvce_video_encode_ip_t *ps_video_encode_ip = pv_api_ip;
143 
144     /* output buffer to write stream */
145     isvce_video_encode_op_t *ps_video_encode_op = pv_api_op;
146 
147     /* i/o structures */
148     isvce_inp_buf_t s_inp_buf;
149     isvce_out_buf_t s_out_buf;
150 
151     WORD32 ctxt_sel = 0, i4_rc_pre_enc_skip;
152     WORD32 i, j;
153 
154     ASSERT(MAX_CTXT_SETS == 1);
155 
156     /********************************************************************/
157     /*                            BEGIN INIT                            */
158     /********************************************************************/
159     /* reset output structure */
160     ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
161     ps_video_encode_op->s_ive_op.output_present = 0;
162     ps_video_encode_op->s_ive_op.dump_recon = 0;
163     ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
164 
165     /* Check for output memory allocation size */
166     {
167         UWORD32 u4_min_bufsize =
168             isvce_get_min_outbuf_size(ps_codec->s_cfg.u4_wd, ps_codec->s_cfg.u4_ht,
169                                       ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers);
170         UWORD32 u4_bufsize_per_layer = ps_video_encode_ip->s_ive_ip.s_out_buf.u4_bufsize /
171                                        ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
172 
173         if(ps_video_encode_ip->s_ive_ip.s_out_buf.u4_bufsize < u4_min_bufsize)
174         {
175             error_status = IH264E_INSUFFICIENT_OUTPUT_BUFFER;
176 
177             SET_ERROR_ON_RETURN(error_status, IVE_UNSUPPORTEDPARAM,
178                                 ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
179         }
180 
181         for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
182         {
183             s_out_buf.as_bits_buf[i] = ps_video_encode_ip->s_ive_ip.s_out_buf;
184 
185             s_out_buf.as_bits_buf[i].u4_bufsize = u4_bufsize_per_layer;
186             s_out_buf.as_bits_buf[i].pv_buf =
187                 ((UWORD8 *) ps_video_encode_ip->s_ive_ip.s_out_buf.pv_buf) +
188                 u4_bufsize_per_layer * i;
189         }
190     }
191 
192     s_out_buf.u4_is_last = 0;
193     s_out_buf.u4_timestamp_low = ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
194     s_out_buf.u4_timestamp_high = ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
195 
196     /* api call cnt */
197     ps_codec->i4_encode_api_call_cnt += 1;
198 
199     /* codec context selector */
200     ctxt_sel = ps_codec->i4_encode_api_call_cnt % MAX_CTXT_SETS;
201 
202     /* reset status flags */
203     ps_codec->ai4_pic_cnt[ctxt_sel] = -1;
204     ps_codec->s_rate_control.post_encode_skip[ctxt_sel] = 0;
205     ps_codec->s_rate_control.pre_encode_skip[ctxt_sel] = 0;
206 
207     /* pass output buffer to codec */
208     ps_codec->as_out_buf[ctxt_sel] = s_out_buf;
209 
210     /* initialize codec ctxt with default params for the first encode api call */
211     if(ps_codec->i4_encode_api_call_cnt == 0)
212     {
213         error_status = isvce_codec_init(ps_codec);
214 
215         SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
216                             ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
217     }
218 
219     error_status =
220         isvce_svc_frame_params_validate(ps_codec->s_rate_control.apps_rate_control_api,
221                                         ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers);
222     SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR, ps_video_encode_op->s_ive_op.u4_error_code,
223                         IV_FAIL);
224 
225     /* parse configuration params */
226     for(i = 0; i < MAX_ACTIVE_CONFIG_PARAMS; i++)
227     {
228         isvce_cfg_params_t *ps_cfg = &ps_codec->as_cfg[i];
229 
230         if(1 == ps_cfg->u4_is_valid)
231         {
232             if(((ps_cfg->u4_timestamp_high == ps_video_encode_ip->s_ive_ip.u4_timestamp_high) &&
233                 (ps_cfg->u4_timestamp_low == ps_video_encode_ip->s_ive_ip.u4_timestamp_low)) ||
234                ((WORD32) ps_cfg->u4_timestamp_high == -1) ||
235                ((WORD32) ps_cfg->u4_timestamp_low == -1))
236             {
237                 error_status = isvce_codec_update_config(ps_codec, ps_cfg);
238                 SET_ERROR_ON_RETURN(error_status, IVE_UNSUPPORTEDPARAM,
239                                     ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
240 
241                 ps_cfg->u4_is_valid = 0;
242             }
243         }
244     }
245     /* Force IDR based on SEI params */
246 #if SEI_BASED_FORCE_IDR
247     {
248         sei_mdcv_params_t *ps_sei_mdcv_params = &ps_codec->s_sei.s_sei_mdcv_params;
249         sei_mdcv_params_t *ps_cfg_sei_mdcv_params = &ps_codec->s_cfg.s_sei.s_sei_mdcv_params;
250         sei_cll_params_t *ps_sei_cll_params = &ps_codec->s_sei.s_sei_cll_params;
251         sei_cll_params_t *ps_cfg_sei_cll_params = &ps_codec->s_cfg.s_sei.s_sei_cll_params;
252         sei_ave_params_t *ps_sei_ave_params = &ps_codec->s_sei.s_sei_ave_params;
253         sei_ave_params_t *ps_cfg_sei_ave_params = &ps_codec->s_cfg.s_sei.s_sei_ave_params;
254 
255         if((ps_sei_mdcv_params->au2_display_primaries_x[0] !=
256             ps_cfg_sei_mdcv_params->au2_display_primaries_x[0]) ||
257            (ps_sei_mdcv_params->au2_display_primaries_x[1] !=
258             ps_cfg_sei_mdcv_params->au2_display_primaries_x[1]) ||
259            (ps_sei_mdcv_params->au2_display_primaries_x[2] !=
260             ps_cfg_sei_mdcv_params->au2_display_primaries_x[2]) ||
261            (ps_sei_mdcv_params->au2_display_primaries_y[0] !=
262             ps_cfg_sei_mdcv_params->au2_display_primaries_y[0]) ||
263            (ps_sei_mdcv_params->au2_display_primaries_y[1] !=
264             ps_cfg_sei_mdcv_params->au2_display_primaries_y[1]) ||
265            (ps_sei_mdcv_params->au2_display_primaries_y[2] !=
266             ps_cfg_sei_mdcv_params->au2_display_primaries_y[2]) ||
267            (ps_sei_mdcv_params->u2_white_point_x != ps_cfg_sei_mdcv_params->u2_white_point_x) ||
268            (ps_sei_mdcv_params->u2_white_point_y != ps_cfg_sei_mdcv_params->u2_white_point_y) ||
269            (ps_sei_mdcv_params->u4_max_display_mastering_luminance !=
270             ps_cfg_sei_mdcv_params->u4_max_display_mastering_luminance) ||
271            (ps_sei_mdcv_params->u4_min_display_mastering_luminance !=
272             ps_cfg_sei_mdcv_params->u4_min_display_mastering_luminance))
273         {
274             ps_codec->s_sei.s_sei_mdcv_params = ps_codec->s_cfg.s_sei.s_sei_mdcv_params;
275             ps_codec->s_sei.u1_sei_mdcv_params_present_flag = 1;
276         }
277         else
278         {
279             ps_codec->s_sei.u1_sei_mdcv_params_present_flag = 0;
280         }
281 
282         if((ps_sei_cll_params->u2_max_content_light_level !=
283             ps_cfg_sei_cll_params->u2_max_content_light_level) ||
284            (ps_sei_cll_params->u2_max_pic_average_light_level !=
285             ps_cfg_sei_cll_params->u2_max_pic_average_light_level))
286         {
287             ps_codec->s_sei.s_sei_cll_params = ps_codec->s_cfg.s_sei.s_sei_cll_params;
288             ps_codec->s_sei.u1_sei_cll_params_present_flag = 1;
289         }
290         else
291         {
292             ps_codec->s_sei.u1_sei_cll_params_present_flag = 0;
293         }
294 
295         if((ps_sei_ave_params->u4_ambient_illuminance !=
296             ps_cfg_sei_ave_params->u4_ambient_illuminance) ||
297            (ps_sei_ave_params->u2_ambient_light_x != ps_cfg_sei_ave_params->u2_ambient_light_x) ||
298            (ps_sei_ave_params->u2_ambient_light_y != ps_cfg_sei_ave_params->u2_ambient_light_y))
299         {
300             ps_codec->s_sei.s_sei_ave_params = ps_codec->s_cfg.s_sei.s_sei_ave_params;
301             ps_codec->s_sei.u1_sei_ave_params_present_flag = 1;
302         }
303         else
304         {
305             ps_codec->s_sei.u1_sei_ave_params_present_flag = 0;
306         }
307 
308         if((1 == ps_codec->s_sei.u1_sei_mdcv_params_present_flag) ||
309            (1 == ps_codec->s_sei.u1_sei_cll_params_present_flag) ||
310            (1 == ps_codec->s_sei.u1_sei_ave_params_present_flag))
311         {
312             ps_codec->force_curr_frame_type = IV_IDR_FRAME;
313         }
314     }
315 #endif
316 
317     /* In case of alt ref and B pics we will have non reference frame in stream */
318     if(ps_codec->s_cfg.u4_enable_alt_ref || ps_codec->s_cfg.u4_num_bframes)
319     {
320         ps_codec->i4_non_ref_frames_in_stream = 1;
321     }
322 
323     if(ps_codec->i4_encode_api_call_cnt == 0)
324     {
325         /********************************************************************/
326         /*   number of mv/ref bank buffers used by the codec,               */
327         /*      1 to handle curr frame                                      */
328         /*      1 to store information of ref frame                         */
329         /*      1 more additional because of the codec employs 2 ctxt sets  */
330         /*        to assist asynchronous API                                */
331         /********************************************************************/
332 
333         /* initialize mv bank buffer manager */
334         error_status = isvce_svc_au_data_mgr_add_bufs(ps_codec);
335 
336         SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
337                             ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
338 
339         /* initialize ref bank buffer manager */
340         error_status = isvce_svc_au_buf_mgr_add_bufs(ps_codec);
341 
342         SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
343                             ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
344 
345         /* for the first frame, generate header when not requested explicitly */
346         if(ps_codec->i4_header_mode == 0 && ps_codec->u4_header_generated == 0)
347         {
348             ps_codec->i4_gen_header = 1;
349         }
350     }
351 
352     /* generate header and return when encoder is operated in header mode */
353     if(ps_codec->i4_header_mode == 1)
354     {
355         /* whenever the header is generated, this implies a start of sequence
356          * and a sequence needs to be started with IDR
357          */
358         ps_codec->force_curr_frame_type = IV_IDR_FRAME;
359 
360         s_inp_buf.s_svc_params = ps_codec->s_cfg.s_svc_params;
361         s_inp_buf.s_inp_props.s_raw_buf = ps_video_encode_ip->s_ive_ip.s_inp_buf;
362         s_inp_buf.s_inp_props.s_raw_buf.au4_wd[Y] = ps_codec->s_cfg.u4_wd;
363         s_inp_buf.s_inp_props.s_raw_buf.au4_ht[Y] = ps_codec->s_cfg.u4_ht;
364 
365         isvce_init_svc_dimension(&s_inp_buf);
366 
367         /* generate header */
368         error_status = isvce_generate_sps_pps(ps_codec, &s_inp_buf);
369 
370         /* send the input to app */
371         ps_video_encode_op->s_ive_op.s_inp_buf = ps_video_encode_ip->s_ive_ip.s_inp_buf;
372         ps_video_encode_op->s_ive_op.u4_timestamp_low =
373             ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
374         ps_video_encode_op->s_ive_op.u4_timestamp_high =
375             ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
376 
377         ps_video_encode_op->s_ive_op.u4_is_last = ps_video_encode_ip->s_ive_ip.u4_is_last;
378 
379         /* send the output to app */
380         ps_video_encode_op->s_ive_op.output_present = 1;
381         ps_video_encode_op->s_ive_op.dump_recon = 0;
382         ps_video_encode_op->s_ive_op.s_out_buf = ps_codec->as_out_buf[ctxt_sel].as_bits_buf[0];
383 
384         for(i = 1; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
385         {
386             memmove(((UWORD8 *) ps_video_encode_op->s_ive_op.s_out_buf.pv_buf +
387                      ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes),
388                     ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].pv_buf,
389                     ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes);
390 
391             ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes +=
392                 ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes;
393         }
394 
395         /* error status */
396         SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
397                             ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
398 
399         /* indicates that header has been generated previously */
400         ps_codec->u4_header_generated = 1;
401 
402         /* api call cnt */
403         ps_codec->i4_encode_api_call_cnt--;
404 
405         /* header mode tag is not sticky */
406         ps_codec->i4_header_mode = 0;
407         ps_codec->i4_gen_header = 0;
408 
409         return IV_SUCCESS;
410     }
411 
412     /* curr pic cnt */
413     ps_codec->i4_pic_cnt += 1;
414 
415     i4_rc_pre_enc_skip = 0;
416     for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
417     {
418         i4_rc_pre_enc_skip =
419             isvce_input_queue_update(ps_codec, &ps_video_encode_ip->s_ive_ip, &s_inp_buf, i);
420     }
421 
422     s_out_buf.u4_is_last = s_inp_buf.s_inp_props.u4_is_last;
423     ps_video_encode_op->s_ive_op.u4_is_last = s_inp_buf.s_inp_props.u4_is_last;
424 
425     /* Only encode if the current frame is not pre-encode skip */
426     if(!i4_rc_pre_enc_skip && s_inp_buf.s_inp_props.s_raw_buf.apv_bufs[0])
427     {
428         isvce_process_ctxt_t *ps_proc = &ps_codec->as_process[ctxt_sel * MAX_PROCESS_THREADS];
429 
430         WORD32 num_thread_cnt = ps_codec->s_cfg.u4_num_cores - 1;
431 
432         ps_codec->ai4_pic_cnt[ctxt_sel] = ps_codec->i4_pic_cnt;
433 
434         error_status = isvce_svc_au_init(ps_codec, &s_inp_buf);
435 
436         SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
437                             ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
438 
439         isvce_nalu_info_au_init(ps_codec->as_nalu_descriptors,
440                                 ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers);
441 
442 #if ENABLE_MODE_STAT_VISUALISER
443         isvce_msv_get_input_frame(ps_codec->ps_mode_stat_visualiser, &s_inp_buf);
444 #endif
445 
446         for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
447         {
448             isvce_svc_layer_pic_init(ps_codec, &s_inp_buf, i);
449 
450             for(j = 0; j < num_thread_cnt; j++)
451             {
452                 ithread_create(ps_codec->apv_proc_thread_handle[j], NULL, isvce_process_thread,
453                                &ps_codec->as_process[j + 1]);
454 
455                 ps_codec->ai4_process_thread_created[j] = 1;
456 
457                 ps_codec->i4_proc_thread_cnt++;
458             }
459 
460             /* launch job */
461             isvce_process_thread(ps_proc);
462 
463             /* Join threads at the end of encoding a frame */
464             isvce_join_threads(ps_codec);
465 
466             ih264_list_reset(ps_codec->pv_proc_jobq);
467 
468             ih264_list_reset(ps_codec->pv_entropy_jobq);
469         }
470 
471 #if ENABLE_MODE_STAT_VISUALISER
472         isvce_msv_dump_visualisation(ps_codec->ps_mode_stat_visualiser);
473 #endif
474 
475         isvce_sub_pic_rc_dump_data(ps_codec->as_process->ps_sub_pic_rc_ctxt);
476     }
477 
478     /****************************************************************************
479      * RECON
480      *    Since we have forward dependent frames, we cannot return recon in
481      *encoding order. It must be in poc order, or input pic order. To achieve this
482      *we introduce a delay of 1 to the recon wrt encode. Now since we have that
483      *    delay, at any point minimum of pic_cnt in our ref buffer will be the
484      *    correct frame. For ex let our GOP be IBBP [1 2 3 4] . The encode order
485      *    will be [1 4 2 3] .Now since we have a delay of 1, when we are done with
486      *    encoding 4, the min in the list will be 1. After encoding 2, it will be
487      *    2, 3 after 3 and 4 after 4. Hence we can return in sequence. Note
488      *    that the 1 delay is critical. Hence if we have post enc skip, we must
489      *    skip here too. Note that since post enc skip already frees the recon
490      *    buffer we need not do any thing here
491      *
492      *    We need to return a recon when ever we consume an input buffer. This
493      *    comsumption include a pre or post enc skip. Thus dump recon is set for
494      *    all cases except when
495      *    1) We are waiting -> ps_codec->i4_pic_cnt >
496      *ps_codec->s_cfg.u4_num_bframe An exception need to be made for the case when
497      *we have the last buffer since we need to flush out the on remainig recon.
498      ****************************************************************************/
499 
500     ps_video_encode_op->s_ive_op.dump_recon = 0;
501 
502     if(ps_codec->s_cfg.u4_enable_recon &&
503        ((ps_codec->i4_pic_cnt > (WORD32) ps_codec->s_cfg.u4_num_bframes) ||
504         s_inp_buf.s_inp_props.u4_is_last))
505     {
506         /* error status */
507         IH264_ERROR_T ret = IH264_SUCCESS;
508 
509         svc_au_buf_t *ps_pic_buf = NULL;
510 
511         WORD32 i4_buf_status, i4_curr_poc = 32768;
512 
513         /* In case of skips we return recon, but indicate that buffer is zero size
514          */
515         if(ps_codec->s_rate_control.post_encode_skip[ctxt_sel] || i4_rc_pre_enc_skip)
516         {
517             ps_video_encode_op->s_ive_op.dump_recon = 1;
518             ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[0] = 0;
519             ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[1] = 0;
520         }
521         else
522         {
523             for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
524             {
525                 if(ps_codec->as_ref_set[i].i4_pic_cnt == -1) continue;
526 
527                 i4_buf_status = ih264_buf_mgr_get_status(
528                     ps_codec->pv_ref_buf_mgr, ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
529 
530                 if((i4_buf_status & BUF_MGR_IO) && (ps_codec->as_ref_set[i].i4_poc < i4_curr_poc))
531                 {
532                     ps_pic_buf = ps_codec->as_ref_set[i].ps_pic_buf;
533                     i4_curr_poc = ps_codec->as_ref_set[i].i4_poc;
534                 }
535             }
536 
537             ps_video_encode_op->s_ive_op.s_recon_buf = ps_video_encode_ip->s_ive_ip.s_recon_buf;
538 
539             /*
540              * If we get a valid buffer. output and free recon.
541              *
542              * we may get an invalid buffer if num_b_frames is 0. This is because
543              * We assume that there will be a ref frame in ref list after encoding
544              * the last frame. With B frames this is correct since its forward ref
545              * pic will be in the ref list. But if num_b_frames is 0, we will not
546              * have a forward ref pic
547              */
548 
549             if(ps_pic_buf)
550             {
551                 if((ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[Y] !=
552                     ps_codec->s_cfg.u4_disp_wd) ||
553                    (ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_ht[Y] !=
554                     ps_codec->s_cfg.u4_disp_ht))
555                 {
556                     SET_ERROR_ON_RETURN(IH264E_NO_FREE_RECONBUF, IVE_FATALERROR,
557                                         ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
558                 }
559 
560                 isvce_fmt_conv(ps_codec, ps_pic_buf,
561                                ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[0],
562                                ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[1],
563                                ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[2],
564                                ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[0],
565                                ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[1], 0,
566                                ps_codec->s_cfg.u4_disp_ht);
567 
568                 ps_video_encode_op->s_ive_op.dump_recon = 1;
569 
570                 ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_pic_buf->i4_buf_id,
571                                             BUF_MGR_IO);
572 
573                 if(IH264_SUCCESS != ret)
574                 {
575                     SET_ERROR_ON_RETURN((IH264E_ERROR_T) ret, IVE_FATALERROR,
576                                         ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
577                 }
578             }
579         }
580     }
581 
582     /***************************************************************************
583      * Free reference buffers:
584      * In case of a post enc skip, we have to ensure that those pics will not
585      * be used as reference anymore. In all other cases we will not even mark
586      * the ref buffers
587      ***************************************************************************/
588     if(ps_codec->s_rate_control.post_encode_skip[ctxt_sel])
589     {
590         /* pic info */
591         svc_au_buf_t *ps_cur_pic;
592 
593         /* mv info */
594         svc_au_data_t *ps_cur_mv_buf;
595 
596         /* error status */
597         IH264_ERROR_T ret = IH264_SUCCESS;
598 
599         /* Decrement coded pic count */
600         ps_codec->i4_poc--;
601 
602         /* loop through to get the min pic cnt among the list of pics stored in ref
603          * list */
604         /* since the skipped frame may not be on reference list, we may not have an
605          * MV bank hence free only if we have allocated */
606         for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
607         {
608             if(ps_codec->i4_pic_cnt == ps_codec->as_ref_set[i].i4_pic_cnt)
609             {
610                 ps_cur_pic = ps_codec->as_ref_set[i].ps_pic_buf;
611 
612                 ps_cur_mv_buf = ps_codec->as_ref_set[i].ps_svc_au_data;
613 
614                 /* release this frame from reference list and recon list */
615                 ret = ih264_buf_mgr_release(ps_codec->pv_svc_au_data_store_mgr,
616                                             ps_cur_mv_buf->i4_buf_id, BUF_MGR_REF);
617                 ret |= ih264_buf_mgr_release(ps_codec->pv_svc_au_data_store_mgr,
618                                              ps_cur_mv_buf->i4_buf_id, BUF_MGR_IO);
619                 SET_ERROR_ON_RETURN((IH264E_ERROR_T) ret, IVE_FATALERROR,
620                                     ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
621 
622                 ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id,
623                                             BUF_MGR_REF);
624                 ret |= ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id,
625                                              BUF_MGR_IO);
626                 SET_ERROR_ON_RETURN((IH264E_ERROR_T) ret, IVE_FATALERROR,
627                                     ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
628                 break;
629             }
630         }
631     }
632 
633     /*
634      * Since recon is not in sync with output, ie there can be frame to be
635      * given back as recon even after last output. Hence we need to mark that
636      * the output is not the last.
637      * Hence search through reflist and mark appropriately
638      */
639     if(ps_codec->s_cfg.u4_enable_recon)
640     {
641         WORD32 i4_buf_status = 0;
642 
643         for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
644         {
645             if(ps_codec->as_ref_set[i].i4_pic_cnt == -1) continue;
646 
647             i4_buf_status |= ih264_buf_mgr_get_status(
648                 ps_codec->pv_ref_buf_mgr, ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
649         }
650 
651         if(i4_buf_status & BUF_MGR_IO)
652         {
653             s_out_buf.u4_is_last = 0;
654             ps_video_encode_op->s_ive_op.u4_is_last = 0;
655         }
656     }
657 
658     /**************************************************************************
659      * Signaling to APP
660      *  1) If we valid a valid output mark it so
661      *  2) Set the codec output ps_video_encode_op
662      *  3) Set the error status
663      *  4) Set the return Pic type
664      *      Note that we already has marked recon properly
665      *  5)Send the consumed input back to app so that it can free it if possible
666      *
667      *  We will have to return the output and input buffers unconditionally
668      *  so that app can release them
669      **************************************************************************/
670     if(!i4_rc_pre_enc_skip && !ps_codec->s_rate_control.post_encode_skip[ctxt_sel] &&
671        s_inp_buf.s_inp_props.s_raw_buf.apv_bufs[0])
672     {
673         /* receive output back from codec */
674         s_out_buf = ps_codec->as_out_buf[ctxt_sel];
675 
676         /* send the output to app */
677         ps_video_encode_op->s_ive_op.output_present = 1;
678         ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
679 
680         /* Set the time stamps of the encodec input */
681         ps_video_encode_op->s_ive_op.u4_timestamp_low = s_inp_buf.s_inp_props.u4_timestamp_low;
682         ps_video_encode_op->s_ive_op.u4_timestamp_high = s_inp_buf.s_inp_props.u4_timestamp_high;
683 
684         switch(ps_codec->pic_type)
685         {
686             case PIC_IDR:
687                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_IDR_FRAME;
688                 break;
689 
690             case PIC_I:
691                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_I_FRAME;
692                 break;
693 
694             case PIC_P:
695                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_P_FRAME;
696                 break;
697 
698             case PIC_B:
699                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_B_FRAME;
700                 break;
701 
702             default:
703                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
704                 break;
705         }
706 
707         for(i = 0; i < (WORD32) ps_codec->s_cfg.u4_num_cores; i++)
708         {
709             error_status = ps_codec->as_process[ctxt_sel + i].i4_error_code;
710             SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
711                                 ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
712         }
713     }
714     else
715     {
716         /* receive output back from codec */
717         s_out_buf = ps_codec->as_out_buf[ctxt_sel];
718 
719         ps_video_encode_op->s_ive_op.output_present = 0;
720         ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
721 
722         /* Set the time stamps of the encodec input */
723         ps_video_encode_op->s_ive_op.u4_timestamp_low = 0;
724         ps_video_encode_op->s_ive_op.u4_timestamp_high = 0;
725 
726         ps_video_encode_op->s_ive_op.s_inp_buf = s_inp_buf.s_inp_props.s_raw_buf;
727 
728         ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
729     }
730 
731     /* Send the input to encoder so that it can free it if possible */
732     ps_video_encode_op->s_ive_op.s_out_buf = ps_codec->as_out_buf[ctxt_sel].as_bits_buf[0];
733 
734     for(i = 1; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
735     {
736         memmove(((UWORD8 *) ps_video_encode_op->s_ive_op.s_out_buf.pv_buf +
737                  ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes),
738                 ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].pv_buf,
739                 ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes);
740 
741         ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes +=
742             ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes;
743     }
744 
745     if(ps_codec->s_cfg.b_nalu_info_export_enable && !i4_rc_pre_enc_skip &&
746        !ps_codec->s_rate_control.post_encode_skip[ctxt_sel] &&
747        s_inp_buf.s_inp_props.s_raw_buf.apv_bufs[0])
748     {
749         ps_video_encode_op->b_is_nalu_info_present = true;
750 
751         for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
752         {
753             isvce_nalu_info_csv_translator(&ps_codec->as_nalu_descriptors[i],
754                                            &ps_video_encode_ip->ps_nalu_info_buf[i]);
755 
756             ps_video_encode_op->ps_nalu_info_buf[i] = ps_video_encode_ip->ps_nalu_info_buf[i];
757         }
758     }
759     else
760     {
761         ps_video_encode_op->b_is_nalu_info_present = false;
762     }
763 
764     ps_video_encode_op->s_ive_op.s_inp_buf = s_inp_buf.s_inp_props.s_raw_buf;
765 
766     return IV_SUCCESS;
767 }
768