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