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