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*/
119void 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*/
166IH264E_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*/
199WORD32 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