Home | History | Annotate | Download | only in encoder
      1 /******************************************************************************
      2  *
      3  * Copyright (C) 2015 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_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 *  - ih264e_join_threads()
     35 *  - ih264e_wait_for_thread()
     36 *  - ih264e_encode()
     37 *
     38 ******************************************************************************
     39 */
     40 
     41 /*****************************************************************************/
     42 /* File Includes                                                             */
     43 /*****************************************************************************/
     44 
     45 /* System Include files */
     46 #include <stdio.h>
     47 #include <stddef.h>
     48 #include <stdlib.h>
     49 #include <string.h>
     50 #include <assert.h>
     51 #include <limits.h>
     52 /* User Include files */
     53 #include "ih264e_config.h"
     54 #include "ih264_typedefs.h"
     55 #include "iv2.h"
     56 #include "ive2.h"
     57 #include "ih264e.h"
     58 #include "ithread.h"
     59 #include "ih264_defs.h"
     60 #include "ih264_macros.h"
     61 #include "ih264_debug.h"
     62 #include "ih264_structs.h"
     63 #include "ih264_platform_macros.h"
     64 #include "ih264_error.h"
     65 #include "ime_distortion_metrics.h"
     66 #include "ime_defs.h"
     67 #include "ime_structs.h"
     68 #include "ih264_trans_quant_itrans_iquant.h"
     69 #include "ih264_inter_pred_filters.h"
     70 #include "ih264_mem_fns.h"
     71 #include "ih264_padding.h"
     72 #include "ih264_intra_pred_filters.h"
     73 #include "ih264_deblk_edge_filters.h"
     74 #include "ih264_cabac_tables.h"
     75 #include "ih264_list.h"
     76 #include "ih264e_error.h"
     77 #include "ih264e_defs.h"
     78 #include "ih264e_bitstream.h"
     79 #include "irc_mem_req_and_acq.h"
     80 #include "irc_cntrl_param.h"
     81 #include "irc_frame_info_collector.h"
     82 #include "ih264e_rate_control.h"
     83 #include "ih264e_time_stamp.h"
     84 #include "ih264e_cabac_structs.h"
     85 #include "ih264e_structs.h"
     86 #include "ih264e_master.h"
     87 #include "ih264e_process.h"
     88 #include "ih264_buf_mgr.h"
     89 #include "ih264_dpb_mgr.h"
     90 #include "ih264e_utils.h"
     91 #include "ih264e_fmt_conv.h"
     92 #include "ih264e_statistics.h"
     93 #include "ih264e_trace.h"
     94 #include "ih264e_debug.h"
     95 #ifdef LOGO_EN
     96 #include "ih264e_ittiam_logo.h"
     97 #endif
     98 
     99 /*****************************************************************************/
    100 /* Function Definitions                                                      */
    101 /*****************************************************************************/
    102 
    103 /**
    104 ******************************************************************************
    105 *
    106 * @brief
    107 *  This function joins all the spawned threads after successful completion of
    108 *  their tasks
    109 *
    110 * @par   Description
    111 *
    112 * @param[in] ps_codec
    113 *  pointer to codec context
    114 *
    115 * @returns  none
    116 *
    117 ******************************************************************************
    118 */
    119 void ih264e_join_threads(codec_t *ps_codec)
    120 {
    121     /* temp var */
    122    WORD32 i = 0;
    123    WORD32 ret = 0;
    124 
    125    /* join spawned threads */
    126    while (i < ps_codec->i4_proc_thread_cnt)
    127    {
    128        if (ps_codec->ai4_process_thread_created[i])
    129        {
    130            ret = ithread_join(ps_codec->apv_proc_thread_handle[i], NULL);
    131            if (ret != 0)
    132            {
    133                printf("pthread Join Failed");
    134                assert(0);
    135            }
    136            ps_codec->ai4_process_thread_created[i] = 0;
    137            i++;
    138        }
    139    }
    140 
    141    ps_codec->i4_proc_thread_cnt = 0;
    142 }
    143 
    144 /**
    145 ******************************************************************************
    146 *
    147 * @brief This function puts the current thread to sleep for a duration
    148 *  of sleep_us
    149 *
    150 * @par Description
    151 *  ithread_yield() method causes the calling thread to yield execution to another
    152 *  thread that is ready to run on the current processor. The operating system
    153 *  selects the thread to yield to. ithread_usleep blocks the current thread for
    154 *  the specified number of milliseconds. In other words, yield just says,
    155 *  end my timeslice prematurely, look around for other threads to run. If there
    156 *  is nothing better than me, continue. Sleep says I don't want to run for x
    157 *  milliseconds. Even if no other thread wants to run, don't make me run.
    158 *
    159 * @param[in] sleep_us
    160 *  thread sleep duration
    161 *
    162 * @returns error_status
    163 *
    164 ******************************************************************************
    165 */
    166 IH264E_ERROR_T ih264e_wait_for_thread(UWORD32 sleep_us)
    167 {
    168     /* yield thread */
    169     ithread_yield();
    170 
    171     /* put thread to sleep */
    172     ithread_usleep(sleep_us);
    173 
    174     return IH264E_SUCCESS;
    175 }
    176 
    177 /**
    178 ******************************************************************************
    179 *
    180 * @brief
    181 *  Encodes in synchronous api mode
    182 *
    183 * @par Description
    184 *  This routine processes input yuv, encodes it and outputs bitstream and recon
    185 *
    186 * @param[in] ps_codec_obj
    187 *  Pointer to codec object at API level
    188 *
    189 * @param[in] pv_api_ip
    190 *  Pointer to input argument structure
    191 *
    192 * @param[out] pv_api_op
    193 *  Pointer to output argument structure
    194 *
    195 * @returns  Status
    196 *
    197 ******************************************************************************
    198 */
    199 WORD32 ih264e_encode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op)
    200 {
    201     /* error status */
    202     IH264E_ERROR_T error_status = IH264E_SUCCESS;
    203 
    204     /* codec ctxt */
    205     codec_t *ps_codec = (codec_t *)ps_codec_obj->pv_codec_handle;
    206 
    207     /* input frame to encode */
    208     ih264e_video_encode_ip_t *ps_video_encode_ip = pv_api_ip;
    209 
    210     /* output buffer to write stream */
    211     ih264e_video_encode_op_t *ps_video_encode_op = pv_api_op;
    212 
    213     /* i/o structures */
    214     inp_buf_t s_inp_buf;
    215     out_buf_t s_out_buf;
    216 
    217     /* temp var */
    218     WORD32 ctxt_sel = 0, i, i4_rc_pre_enc_skip;
    219 
    220     /********************************************************************/
    221     /*                            BEGIN INIT                            */
    222     /********************************************************************/
    223     /* reset output structure */
    224     ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
    225     ps_video_encode_op->s_ive_op.output_present  = 0;
    226     ps_video_encode_op->s_ive_op.dump_recon = 0;
    227     ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
    228 
    229     /* Check for output memory allocation size */
    230     if (ps_video_encode_ip->s_ive_ip.s_out_buf.u4_bufsize < MIN_STREAM_SIZE)
    231     {
    232         error_status |= IH264E_INSUFFICIENT_OUTPUT_BUFFER;
    233         SET_ERROR_ON_RETURN(error_status,
    234                             IVE_UNSUPPORTEDPARAM,
    235                             ps_video_encode_op->s_ive_op.u4_error_code,
    236                             IV_FAIL);
    237     }
    238 
    239     /* copy output info. to internal structure */
    240     s_out_buf.s_bits_buf = ps_video_encode_ip->s_ive_ip.s_out_buf;
    241     s_out_buf.u4_is_last = 0;
    242     s_out_buf.u4_timestamp_low = ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
    243     s_out_buf.u4_timestamp_high = ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
    244 
    245     /* api call cnt */
    246     ps_codec->i4_encode_api_call_cnt += 1;
    247 
    248     /* codec context selector */
    249     ctxt_sel = ps_codec->i4_encode_api_call_cnt % MAX_CTXT_SETS;
    250 
    251     /* reset status flags */
    252     ps_codec->ai4_pic_cnt[ctxt_sel] = -1;
    253     ps_codec->s_rate_control.post_encode_skip[ctxt_sel] = 0;
    254     ps_codec->s_rate_control.pre_encode_skip[ctxt_sel] = 0;
    255 
    256     /* pass output buffer to codec */
    257     ps_codec->as_out_buf[ctxt_sel] = s_out_buf;
    258 
    259     /* initialize codec ctxt with default params for the first encode api call */
    260     if (ps_codec->i4_encode_api_call_cnt == 0)
    261     {
    262         ih264e_codec_init(ps_codec);
    263     }
    264 
    265     /* parse configuration params */
    266     for (i = 0; i < MAX_ACTIVE_CONFIG_PARAMS; i++)
    267     {
    268         cfg_params_t *ps_cfg = &ps_codec->as_cfg[i];
    269 
    270         if (1 == ps_cfg->u4_is_valid)
    271         {
    272             if ( ((ps_cfg->u4_timestamp_high == ps_video_encode_ip->s_ive_ip.u4_timestamp_high) &&
    273                             (ps_cfg->u4_timestamp_low == ps_video_encode_ip->s_ive_ip.u4_timestamp_low)) ||
    274                             ((WORD32)ps_cfg->u4_timestamp_high == -1) ||
    275                             ((WORD32)ps_cfg->u4_timestamp_low == -1) )
    276             {
    277                 error_status |= ih264e_codec_update_config(ps_codec, ps_cfg);
    278                 SET_ERROR_ON_RETURN(error_status,
    279                                     IVE_UNSUPPORTEDPARAM,
    280                                     ps_video_encode_op->s_ive_op.u4_error_code,
    281                                     IV_FAIL);
    282 
    283                 ps_cfg->u4_is_valid = 0;
    284             }
    285         }
    286     }
    287 
    288     /******************************************************************
    289      * INSERT LOGO
    290      *****************************************************************/
    291 #ifdef LOGO_EN
    292     if (s_inp_buf.s_raw_buf.apv_bufs[0] != NULL &&
    293                     ps_codec->i4_header_mode != 1)
    294     {
    295         ih264e_insert_logo(s_inp_buf.s_raw_buf.apv_bufs[0],
    296                            s_inp_buf.s_raw_buf.apv_bufs[1],
    297                            s_inp_buf.s_raw_buf.apv_bufs[2],
    298                            s_inp_buf.s_raw_buf.au4_strd[0],
    299                            0,
    300                            0,
    301                            ps_codec->s_cfg.e_inp_color_fmt,
    302                            ps_codec->s_cfg.u4_disp_wd,
    303                            ps_codec->s_cfg.u4_disp_ht);
    304     }
    305 #endif /*LOGO_EN*/
    306 
    307     /* In case of alt ref and B pics we will have non reference frame in stream */
    308     if (ps_codec->s_cfg.u4_enable_alt_ref || ps_codec->s_cfg.u4_num_bframes)
    309     {
    310         ps_codec->i4_non_ref_frames_in_stream = 1;
    311     }
    312 
    313     if (ps_codec->i4_encode_api_call_cnt == 0)
    314     {
    315         /********************************************************************/
    316         /*   number of mv/ref bank buffers used by the codec,               */
    317         /*      1 to handle curr frame                                      */
    318         /*      1 to store information of ref frame                         */
    319         /*      1 more additional because of the codec employs 2 ctxt sets  */
    320         /*        to assist asynchronous API                                */
    321         /********************************************************************/
    322 
    323         /* initialize mv bank buffer manager */
    324         error_status |= ih264e_mv_buf_mgr_add_bufs(ps_codec);
    325         SET_ERROR_ON_RETURN(error_status,
    326                             IVE_FATALERROR,
    327                             ps_video_encode_op->s_ive_op.u4_error_code,
    328                             IV_FAIL);
    329 
    330         /* initialize ref bank buffer manager */
    331         error_status |= ih264e_pic_buf_mgr_add_bufs(ps_codec);
    332         SET_ERROR_ON_RETURN(error_status,
    333                             IVE_FATALERROR,
    334                             ps_video_encode_op->s_ive_op.u4_error_code,
    335                             IV_FAIL);
    336 
    337         /* for the first frame, generate header when not requested explicitly */
    338         if (ps_codec->i4_header_mode == 0 &&
    339                         ps_codec->u4_header_generated == 0)
    340         {
    341             ps_codec->i4_gen_header = 1;
    342         }
    343     }
    344 
    345     /* generate header and return when encoder is operated in header mode */
    346     if (ps_codec->i4_header_mode == 1)
    347     {
    348         /* whenever the header is generated, this implies a start of sequence
    349          * and a sequence needs to be started with IDR
    350          */
    351         ps_codec->force_curr_frame_type = IV_IDR_FRAME;
    352 
    353         /* generate header */
    354         error_status |= ih264e_generate_sps_pps(ps_codec);
    355 
    356         /* api call cnt */
    357         ps_codec->i4_encode_api_call_cnt --;
    358 
    359         /* header mode tag is not sticky */
    360         ps_codec->i4_header_mode = 0;
    361         ps_codec->i4_gen_header = 0;
    362 
    363         /* send the input to app */
    364         ps_video_encode_op->s_ive_op.s_inp_buf = ps_video_encode_ip->s_ive_ip.s_inp_buf;
    365         ps_video_encode_op->s_ive_op.u4_timestamp_low = ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
    366         ps_video_encode_op->s_ive_op.u4_timestamp_high = ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
    367 
    368         ps_video_encode_op->s_ive_op.u4_is_last = ps_video_encode_ip->s_ive_ip.u4_is_last;
    369 
    370         /* send the output to app */
    371         ps_video_encode_op->s_ive_op.output_present  = 1;
    372         ps_video_encode_op->s_ive_op.dump_recon = 0;
    373         ps_video_encode_op->s_ive_op.s_out_buf = ps_codec->as_out_buf[ctxt_sel].s_bits_buf;
    374 
    375         /* error status */
    376         SET_ERROR_ON_RETURN(error_status,
    377                             IVE_FATALERROR,
    378                             ps_video_encode_op->s_ive_op.u4_error_code,
    379                             IV_FAIL);
    380 
    381         /* indicates that header has been generated previously */
    382         ps_codec->u4_header_generated = 1;
    383 
    384         return IV_SUCCESS;
    385     }
    386 
    387     /* curr pic cnt */
    388      ps_codec->i4_pic_cnt += 1;
    389 
    390     i4_rc_pre_enc_skip = 0;
    391     i4_rc_pre_enc_skip = ih264e_input_queue_update(
    392                     ps_codec, &ps_video_encode_ip->s_ive_ip, &s_inp_buf);
    393 
    394     s_out_buf.u4_is_last = s_inp_buf.u4_is_last;
    395     ps_video_encode_op->s_ive_op.u4_is_last = s_inp_buf.u4_is_last;
    396 
    397     /* Only encode if the current frame is not pre-encode skip */
    398     if (!i4_rc_pre_enc_skip && s_inp_buf.s_raw_buf.apv_bufs[0])
    399     {
    400         /* proc ctxt base idx */
    401         WORD32 proc_ctxt_select = ctxt_sel * MAX_PROCESS_THREADS;
    402 
    403         /* proc ctxt */
    404         process_ctxt_t *ps_proc = &ps_codec->as_process[proc_ctxt_select];
    405 
    406         WORD32 ret = 0;
    407 
    408         /* number of addl. threads to be created */
    409         WORD32 num_thread_cnt = ps_codec->s_cfg.u4_num_cores - 1;
    410 
    411         /* array giving pic cnt that is being processed in curr context set */
    412         ps_codec->ai4_pic_cnt[ctxt_sel] = ps_codec->i4_pic_cnt;
    413 
    414         /* initialize all relevant process ctxts */
    415         error_status |= ih264e_pic_init(ps_codec, &s_inp_buf);
    416         SET_ERROR_ON_RETURN(error_status,
    417                             IVE_FATALERROR,
    418                             ps_video_encode_op->s_ive_op.u4_error_code,
    419                             IV_FAIL);
    420 
    421         for (i = 0; i < num_thread_cnt; i++)
    422         {
    423             ret = ithread_create(ps_codec->apv_proc_thread_handle[i],
    424                                  NULL,
    425                                  (void *)ih264e_process_thread,
    426                                  &ps_codec->as_process[i + 1]);
    427             if (ret != 0)
    428             {
    429                 printf("pthread Create Failed");
    430                 assert(0);
    431             }
    432 
    433             ps_codec->ai4_process_thread_created[i] = 1;
    434 
    435             ps_codec->i4_proc_thread_cnt++;
    436         }
    437 
    438 
    439         /* launch job */
    440         ih264e_process_thread(ps_proc);
    441 
    442         /* Join threads at the end of encoding a frame */
    443         ih264e_join_threads(ps_codec);
    444 
    445         ih264_list_reset(ps_codec->pv_proc_jobq);
    446 
    447         ih264_list_reset(ps_codec->pv_entropy_jobq);
    448     }
    449 
    450 
    451    /****************************************************************************
    452    * RECON
    453    *    Since we have forward dependent frames, we cannot return recon in encoding
    454    *    order. It must be in poc order, or input pic order. To achieve this we
    455    *    introduce a delay of 1 to the recon wrt encode. Now since we have that
    456    *    delay, at any point minimum of pic_cnt in our ref buffer will be the
    457    *    correct frame. For ex let our GOP be IBBP [1 2 3 4] . The encode order
    458    *    will be [1 4 2 3] .Now since we have a delay of 1, when we are done with
    459    *    encoding 4, the min in the list will be 1. After encoding 2, it will be
    460    *    2, 3 after 3 and 4 after 4. Hence we can return in sequence. Note
    461    *    that the 1 delay is critical. Hence if we have post enc skip, we must
    462    *    skip here too. Note that since post enc skip already frees the recon
    463    *    buffer we need not do any thing here
    464    *
    465    *    We need to return a recon when ever we consume an input buffer. This
    466    *    comsumption include a pre or post enc skip. Thus dump recon is set for
    467    *    all cases except when
    468    *    1) We are waiting -> ps_codec->i4_frame_num > 1
    469    *    2) When the input buffer is null [ ie we are not consuming any inp]
    470    *        An exception need to be made for the case when we have the last buffer
    471    *        since we need to flush out the on remainig recon.
    472    ****************************************************************************/
    473 
    474     ps_video_encode_op->s_ive_op.dump_recon = 0;
    475 
    476     if (ps_codec->s_cfg.u4_enable_recon && (ps_codec->i4_frame_num > 1 || s_inp_buf.u4_is_last)
    477                     && (s_inp_buf.s_raw_buf.apv_bufs[0] || s_inp_buf.u4_is_last))
    478     {
    479         /* error status */
    480         IH264_ERROR_T ret = IH264_SUCCESS;
    481         pic_buf_t *ps_pic_buf = NULL;
    482         WORD32 i4_buf_status, i4_curr_poc = 32768;
    483 
    484         /* In case of skips we return recon, but indicate that buffer is zero size */
    485         if (ps_codec->s_rate_control.post_encode_skip[ctxt_sel]
    486                         || i4_rc_pre_enc_skip)
    487         {
    488 
    489             ps_video_encode_op->s_ive_op.dump_recon = 1;
    490             ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[0] = 0;
    491             ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[1] = 0;
    492 
    493         }
    494         else
    495         {
    496             for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
    497             {
    498                 if (ps_codec->as_ref_set[i].i4_pic_cnt == -1)
    499                     continue;
    500 
    501                 i4_buf_status = ih264_buf_mgr_get_status(
    502                                 ps_codec->pv_ref_buf_mgr,
    503                                 ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
    504 
    505                 if ((i4_buf_status & BUF_MGR_IO)
    506                                 && (ps_codec->as_ref_set[i].i4_poc < i4_curr_poc))
    507                 {
    508                     ps_pic_buf = ps_codec->as_ref_set[i].ps_pic_buf;
    509                     i4_curr_poc = ps_codec->as_ref_set[i].i4_poc;
    510                 }
    511             }
    512 
    513             ps_video_encode_op->s_ive_op.s_recon_buf =
    514                             ps_video_encode_ip->s_ive_ip.s_recon_buf;
    515 
    516             /*
    517              * If we get a valid buffer. output and free recon.
    518              *
    519              * we may get an invalid buffer if num_b_frames is 0. This is because
    520              * We assume that there will be a ref frame in ref list after encoding
    521              * the last frame. With B frames this is correct since its forward ref
    522              * pic will be in the ref list. But if num_b_frames is 0, we will not
    523              * have a forward ref pic
    524              */
    525 
    526             if (ps_pic_buf)
    527             {
    528                 /* copy/convert the recon buffer and return */
    529                 ih264e_fmt_conv(ps_codec,
    530                                 ps_pic_buf,
    531                                 ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[0],
    532                                 ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[1],
    533                                 ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[2],
    534                                 ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[0],
    535                                 ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[1],
    536                                 0, ps_codec->s_cfg.u4_disp_ht);
    537 
    538                 ps_video_encode_op->s_ive_op.dump_recon = 1;
    539 
    540                 ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr,
    541                                             ps_pic_buf->i4_buf_id, BUF_MGR_IO);
    542 
    543                 if (IH264_SUCCESS != ret)
    544                 {
    545                     SET_ERROR_ON_RETURN(
    546                                     (IH264E_ERROR_T)ret, IVE_FATALERROR,
    547                                     ps_video_encode_op->s_ive_op.u4_error_code,
    548                                     IV_FAIL);
    549                 }
    550             }
    551         }
    552     }
    553 
    554 
    555     /***************************************************************************
    556      * Free reference buffers:
    557      * In case of a post enc skip, we have to ensure that those pics will not
    558      * be used as reference anymore. In all other cases we will not even mark
    559      * the ref buffers
    560      ***************************************************************************/
    561     if (ps_codec->s_rate_control.post_encode_skip[ctxt_sel])
    562     {
    563         /* pic info */
    564         pic_buf_t *ps_cur_pic;
    565 
    566         /* mv info */
    567         mv_buf_t *ps_cur_mv_buf;
    568 
    569         /* error status */
    570         IH264_ERROR_T ret = IH264_SUCCESS;
    571 
    572         /* Decrement coded pic count */
    573         ps_codec->i4_poc--;
    574 
    575         /* loop through to get the min pic cnt among the list of pics stored in ref list */
    576         /* since the skipped frame may not be on reference list, we may not have an MV bank
    577          * hence free only if we have allocated */
    578         for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
    579         {
    580             if (ps_codec->i4_pic_cnt == ps_codec->as_ref_set[i].i4_pic_cnt)
    581             {
    582 
    583                 ps_cur_pic = ps_codec->as_ref_set[i].ps_pic_buf;
    584 
    585                 ps_cur_mv_buf = ps_codec->as_ref_set[i].ps_mv_buf;
    586 
    587                 /* release this frame from reference list and recon list */
    588                 ret = ih264_buf_mgr_release(ps_codec->pv_mv_buf_mgr, ps_cur_mv_buf->i4_buf_id , BUF_MGR_REF);
    589                 ret |= ih264_buf_mgr_release(ps_codec->pv_mv_buf_mgr, ps_cur_mv_buf->i4_buf_id , BUF_MGR_IO);
    590                 SET_ERROR_ON_RETURN((IH264E_ERROR_T)ret,
    591                                     IVE_FATALERROR,
    592                                     ps_video_encode_op->s_ive_op.u4_error_code,
    593                                     IV_FAIL);
    594 
    595                 ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id , BUF_MGR_REF);
    596                 ret |= ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id , BUF_MGR_IO);
    597                 SET_ERROR_ON_RETURN((IH264E_ERROR_T)ret,
    598                                     IVE_FATALERROR,
    599                                     ps_video_encode_op->s_ive_op.u4_error_code,
    600                                     IV_FAIL);
    601                 break;
    602             }
    603         }
    604     }
    605 
    606     /*
    607      * Since recon is not in sync with output, ie there can be frame to be
    608      * given back as recon even after last output. Hence we need to mark that
    609      * the output is not the last.
    610      * Hence search through reflist and mark appropriately
    611      */
    612     if (ps_codec->s_cfg.u4_enable_recon)
    613     {
    614         WORD32 i4_buf_status = 0;
    615 
    616         for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
    617         {
    618             if (ps_codec->as_ref_set[i].i4_pic_cnt == -1)
    619                 continue;
    620 
    621             i4_buf_status |= ih264_buf_mgr_get_status(
    622                             ps_codec->pv_ref_buf_mgr,
    623                             ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
    624         }
    625 
    626         if (i4_buf_status & BUF_MGR_IO)
    627         {
    628             s_out_buf.u4_is_last = 0;
    629             ps_video_encode_op->s_ive_op.u4_is_last = 0;
    630         }
    631     }
    632 
    633 
    634     /**************************************************************************
    635      * Signaling to APP
    636      *  1) If we valid a valid output mark it so
    637      *  2) Set the codec output ps_video_encode_op
    638      *  3) Set the error status
    639      *  4) Set the return Pic type
    640      *      Note that we already has marked recon properly
    641      *  5)Send the consumed input back to app so that it can free it if possible
    642      *
    643      *  We will have to return the output and input buffers unconditionally
    644      *  so that app can release them
    645      **************************************************************************/
    646     if (!i4_rc_pre_enc_skip
    647                     && !ps_codec->s_rate_control.post_encode_skip[ctxt_sel]
    648                     && s_inp_buf.s_raw_buf.apv_bufs[0])
    649     {
    650 
    651         /* receive output back from codec */
    652         s_out_buf = ps_codec->as_out_buf[ctxt_sel];
    653 
    654         /* send the output to app */
    655         ps_video_encode_op->s_ive_op.output_present  = 1;
    656         ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
    657 
    658         /* Set the time stamps of the encodec input */
    659         ps_video_encode_op->s_ive_op.u4_timestamp_low = s_inp_buf.u4_timestamp_low;
    660         ps_video_encode_op->s_ive_op.u4_timestamp_high = s_inp_buf.u4_timestamp_high;
    661 
    662 
    663         switch (ps_codec->pic_type)
    664         {
    665             case PIC_IDR:
    666                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type =IV_IDR_FRAME;
    667                 break;
    668 
    669             case PIC_I:
    670                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_I_FRAME;
    671                 break;
    672 
    673             case PIC_P:
    674                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_P_FRAME;
    675                 break;
    676 
    677             case PIC_B:
    678                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_B_FRAME;
    679                 break;
    680 
    681             default:
    682                 ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
    683                 break;
    684         }
    685 
    686         for (i = 0; i < (WORD32)ps_codec->s_cfg.u4_num_cores; i++)
    687         {
    688             error_status |= ps_codec->as_process[ctxt_sel + i].i4_error_code;
    689         }
    690         SET_ERROR_ON_RETURN(error_status,
    691                             IVE_FATALERROR,
    692                             ps_video_encode_op->s_ive_op.u4_error_code,
    693                             IV_FAIL);
    694     }
    695     else
    696     {
    697         /* proc ctxt base idx */
    698         WORD32 proc_ctxt_select = ctxt_sel * MAX_PROCESS_THREADS;
    699 
    700         /* proc ctxt */
    701         process_ctxt_t *ps_proc = &ps_codec->as_process[proc_ctxt_select];
    702 
    703         /* receive output back from codec */
    704         s_out_buf = ps_codec->as_out_buf[ctxt_sel];
    705 
    706         ps_video_encode_op->s_ive_op.output_present = 0;
    707         ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
    708 
    709         /* Set the time stamps of the encodec input */
    710         ps_video_encode_op->s_ive_op.u4_timestamp_low = 0;
    711         ps_video_encode_op->s_ive_op.u4_timestamp_high = 0;
    712 
    713         /* receive input back from codec and send it to app */
    714         s_inp_buf = ps_proc->s_inp_buf;
    715         ps_video_encode_op->s_ive_op.s_inp_buf = s_inp_buf.s_raw_buf;
    716 
    717         ps_video_encode_op->s_ive_op.u4_encoded_frame_type =  IV_NA_FRAME;
    718 
    719     }
    720 
    721     /* Send the input to encoder so that it can free it if possible */
    722     ps_video_encode_op->s_ive_op.s_out_buf = s_out_buf.s_bits_buf;
    723     ps_video_encode_op->s_ive_op.s_inp_buf = s_inp_buf.s_raw_buf;
    724 
    725 
    726     if (1 == s_inp_buf.u4_is_last)
    727     {
    728         ps_video_encode_op->s_ive_op.output_present = 0;
    729         ps_video_encode_op->s_ive_op.dump_recon = 0;
    730     }
    731 
    732     return IV_SUCCESS;
    733 }
    734