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