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