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