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 */
ih264e_join_threads(codec_t * ps_codec)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 */
ih264e_wait_for_thread(UWORD32 sleep_us)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 */
ih264e_encode(iv_obj_t * ps_codec_obj,void * pv_api_ip,void * pv_api_op)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