Coverage Report

Created: 2025-07-11 06:38

/src/libavc/encoder/ih264e_encode.c
Line
Count
Source (jump to first uncovered line)
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
*  Initializes the thread pool for multi-threaded encoding.
117
*
118
* @par Description:
119
*  Creates and initializes the thread pool based on the number of configured
120
*  cores. It spawns worker threads and sets up necessary synchronization
121
*  mechanisms.
122
*
123
* @param[in] ps_codec
124
*  Pointer to the codec context structure.
125
*
126
* @returns  IV_SUCCESS on success, IV_FAIL on failure.
127
*
128
*******************************************************************************
129
*/
130
WORD32 ih264e_thread_pool_init(codec_t *ps_codec)
131
9.44k
{
132
    /* temp var */
133
9.44k
    WORD32 i = 0, ret = 0;
134
135
    /* thread pool */
136
9.44k
    thread_pool_t *ps_pool = &ps_codec->s_thread_pool;
137
138
    /* Return if already initialized */
139
9.44k
    if (ps_pool->i4_init_done == 1) return IV_SUCCESS;
140
141
    /* initializing thread pool initialization done */
142
4.75k
    ps_pool->i4_init_done = 0;
143
144
    /* initializing end of stream */
145
4.75k
    ps_pool->i4_end_of_stream = 0;
146
147
    /* initializing active threads */
148
4.75k
    ps_pool->i4_working_threads = 0;
149
150
    /* Initialize new frame ready flag */
151
4.75k
    ps_pool->i4_has_frame = 0;
152
153
12.0k
    for (i = 1; i < ps_codec->s_cfg.u4_num_cores; i++)
154
7.33k
    {
155
7.33k
        ret = ithread_create(ps_codec->apv_proc_thread_handle[i], NULL, ih264e_thread_worker,
156
7.33k
                             (void *) &ps_codec->as_process[i]);
157
7.33k
        if (ret != 0)
158
0
        {
159
0
            ps_codec->ai4_process_thread_created[i] = 0;
160
0
        }
161
7.33k
        else
162
7.33k
        {
163
7.33k
            ps_codec->ai4_process_thread_created[i] = 1;
164
7.33k
            ps_codec->i4_proc_thread_cnt++;
165
7.33k
        }
166
7.33k
    }
167
168
    /* Thread pool initialized */
169
4.75k
    ps_pool->i4_init_done = 1;
170
4.75k
    return IV_SUCCESS;
171
9.44k
}
172
173
/**
174
*******************************************************************************
175
*
176
* @brief
177
*  Shuts down the thread pool and cleans up resources.
178
*
179
* @par Description:
180
*  Signals worker threads to terminate, joins all active threads, and
181
*  destroys associated synchronization primitives.
182
*
183
* @param[in] ps_codec
184
*  Pointer to the codec context structure.
185
*
186
* @returns  IV_SUCCESS on success, IV_FAIL on failure.
187
*
188
*******************************************************************************
189
*/
190
WORD32 ih264e_thread_pool_shutdown(codec_t *ps_codec)
191
9.39k
{
192
    /* thread pool */
193
9.39k
    thread_pool_t *ps_pool = &ps_codec->s_thread_pool;
194
195
    /* temp var */
196
9.39k
    WORD32 i = 0;
197
9.39k
    WORD32 ret = IV_SUCCESS;
198
199
    /* Wake all threads waiting */
200
9.39k
    ithread_mutex_lock(ps_codec->s_thread_pool.pv_thread_pool_mutex);
201
9.39k
    ps_pool->i4_end_of_stream = 1;
202
9.39k
    ithread_cond_broadcast(ps_codec->s_thread_pool.pv_thread_pool_cond);
203
9.39k
    ithread_mutex_unlock(ps_codec->s_thread_pool.pv_thread_pool_mutex);
204
205
    /* Join threads */
206
23.8k
    for (i = 1; i < ps_codec->s_cfg.u4_num_cores; i++)
207
14.4k
    {
208
14.4k
        if (ps_codec->ai4_process_thread_created[i])
209
7.33k
        {
210
7.33k
            if (ithread_join(ps_codec->apv_proc_thread_handle[i], NULL) != 0)
211
0
            {
212
0
                ret = IV_FAIL;
213
0
            }
214
7.33k
            else
215
7.33k
            {
216
7.33k
                ps_codec->ai4_process_thread_created[i] = 0;
217
7.33k
                ps_codec->i4_proc_thread_cnt--;
218
7.33k
            }
219
7.33k
        }
220
14.4k
    }
221
222
    /* Reset all thread pool state variables */
223
9.39k
    ps_pool->i4_init_done = 0;
224
9.39k
    ps_pool->i4_end_of_stream = 0;
225
9.39k
    ps_pool->i4_working_threads = 0;
226
9.39k
    ps_pool->i4_has_frame = 0;
227
228
9.39k
    return ret;
229
9.39k
}
230
231
/**
232
*******************************************************************************
233
*
234
* @brief
235
*  Worker thread function for processing encoding tasks.
236
*
237
* @par Description:
238
*  Waits for available jobs and processes encoding tasks until signaled to
239
*  terminate.
240
*
241
* @param[in] pv_proc
242
*  Pointer to the process context.
243
*
244
* @returns  IH264_SUCCESS on completion.
245
*
246
*******************************************************************************
247
*/
248
static WORD32 ih264e_thread_worker(void *pv_proc)
249
7.33k
{
250
    /* process ctxt */
251
7.33k
    process_ctxt_t *ps_proc = (process_ctxt_t *)pv_proc;
252
253
    /* process ctxt */
254
7.33k
    codec_t *ps_codec = ps_proc->ps_codec;
255
256
    /* thread pool ctxt */
257
7.33k
    thread_pool_t *ps_pool = &ps_codec->s_thread_pool;
258
259
33.4M
    while (1)
260
33.4M
    {
261
        // Wait until a frame is ready or end of stream
262
33.4M
        ithread_mutex_lock(ps_pool->pv_thread_pool_mutex);
263
33.5M
        while (!ps_pool->i4_has_frame && !ps_pool->i4_end_of_stream)
264
59.3k
        {
265
59.3k
            ithread_cond_wait(ps_pool->pv_thread_pool_cond,
266
59.3k
                              ps_pool->pv_thread_pool_mutex);
267
59.3k
        }
268
269
33.4M
        if (ps_pool->i4_end_of_stream)
270
7.33k
        {
271
7.33k
            ithread_mutex_unlock(ps_pool->pv_thread_pool_mutex);
272
7.33k
            break;
273
7.33k
        }
274
275
        /* incrementing active threads */
276
33.4M
        ps_pool->i4_working_threads++;
277
33.4M
        ithread_mutex_unlock(ps_pool->pv_thread_pool_mutex);
278
279
        /* worker processes available jobs */
280
33.4M
        ih264e_process_thread(pv_proc);
281
282
        /* decreasing active threads */
283
33.4M
        ithread_mutex_lock(ps_pool->pv_thread_pool_mutex);
284
33.4M
        ps_pool->i4_working_threads--;
285
286
        /* Notify main thread if all workers are done */
287
33.4M
        if (ps_pool->i4_working_threads == 0 &&
288
33.4M
            ih264_get_job_count_in_list(ps_codec->pv_proc_jobq) == 0 &&
289
33.4M
            ih264_get_job_count_in_list(ps_codec->pv_entropy_jobq) == 0)
290
26.2k
        {
291
26.2k
            ps_pool->i4_has_frame = 0;
292
26.2k
            ithread_cond_signal(ps_pool->pv_thread_pool_cond);
293
26.2k
        }
294
33.4M
        ithread_mutex_unlock(ps_pool->pv_thread_pool_mutex);
295
33.4M
    }
296
297
7.33k
    return IH264_SUCCESS;
298
7.33k
}
299
300
/**
301
*******************************************************************************
302
*
303
* @brief
304
*  Resets the thread pool state for the next encoding frame.
305
*
306
* @par Description:
307
*  Resets the active thread count and signals worker threads to start
308
*  processing a new frame.
309
*
310
* @param[in] ps_codec
311
*  Pointer to the codec context structure.
312
*
313
* @returns  IH264_SUCCESS on success.
314
*
315
*******************************************************************************
316
*/
317
WORD32 ih264e_thread_pool_activate(codec_t *ps_codec)
318
43.3k
{
319
43.3k
    IH264_ERROR_T ret = IH264_SUCCESS;
320
321
    /* thread pool ctxt */
322
43.3k
    thread_pool_t *ps_pool = &ps_codec->s_thread_pool;
323
324
43.3k
    if (ps_codec->i4_proc_thread_cnt == 0)
325
17.0k
    {
326
17.0k
        return ret;
327
17.0k
    }
328
329
    /* reset working threads and new frame */
330
26.2k
    ithread_mutex_lock(ps_pool->pv_thread_pool_mutex);
331
26.2k
    ps_pool->i4_working_threads = 0;
332
26.2k
    ps_pool->i4_has_frame = 1;
333
26.2k
    ithread_cond_broadcast(ps_pool->pv_thread_pool_cond);
334
26.2k
    ithread_mutex_unlock(ps_pool->pv_thread_pool_mutex);
335
336
26.2k
    return ret;
337
43.3k
}
338
339
/**
340
*******************************************************************************
341
*
342
* @brief
343
*  Synchronizes the thread pool by waiting for all tasks to complete.
344
*
345
* @par Description:
346
*  Ensures that all worker threads complete their processing before
347
*  proceeding to the next frame.
348
*
349
* @param[in] ps_codec
350
*  Pointer to the codec context structure.
351
*
352
* @returns  IH264_SUCCESS on success.
353
*
354
*******************************************************************************
355
*/
356
WORD32 ih264e_thread_pool_sync(codec_t *ps_codec)
357
43.3k
{
358
43.3k
    IH264_ERROR_T ret = IH264_SUCCESS;
359
360
    /* thread pool ctxt */
361
43.3k
    thread_pool_t *ps_pool = &ps_codec->s_thread_pool;
362
363
    /* skip for single thread */
364
43.3k
    if (ps_codec->i4_proc_thread_cnt == 0)
365
17.0k
    {
366
17.0k
        return ret;
367
17.0k
    }
368
369
    // Wait for workers to complete
370
26.2k
    ithread_mutex_lock(ps_pool->pv_thread_pool_mutex);
371
45.0k
    while (ps_pool->i4_has_frame == 1)
372
18.8k
    {
373
18.8k
        ithread_cond_wait(ps_pool->pv_thread_pool_cond,
374
18.8k
                          ps_pool->pv_thread_pool_mutex);
375
18.8k
    }
376
26.2k
    ithread_mutex_unlock(ps_pool->pv_thread_pool_mutex);
377
378
26.2k
    return ret;
379
43.3k
}
380
381
/**
382
******************************************************************************
383
*
384
* @brief
385
*  This function joins all the spawned threads after successful completion of
386
*  their tasks
387
*
388
* @par   Description
389
*
390
* @param[in] ps_codec
391
*  pointer to codec context
392
*
393
* @returns  none
394
*
395
******************************************************************************
396
*/
397
void ih264e_join_threads(codec_t *ps_codec)
398
0
{
399
    /* temp var */
400
0
   WORD32 i = 0;
401
0
   WORD32 ret = 0;
402
403
   /* join spawned threads */
404
0
   while (i < ps_codec->i4_proc_thread_cnt)
405
0
   {
406
0
       if (ps_codec->ai4_process_thread_created[i])
407
0
       {
408
0
           ret = ithread_join(ps_codec->apv_proc_thread_handle[i], NULL);
409
0
           if (ret != 0)
410
0
           {
411
0
               printf("pthread Join Failed");
412
0
               assert(0);
413
0
           }
414
0
           ps_codec->ai4_process_thread_created[i] = 0;
415
0
           i++;
416
0
       }
417
0
   }
418
419
0
   ps_codec->i4_proc_thread_cnt = 0;
420
0
}
421
422
/**
423
******************************************************************************
424
*
425
* @brief This function puts the current thread to sleep for a duration
426
*  of sleep_us
427
*
428
* @par Description
429
*  ithread_yield() method causes the calling thread to yield execution to another
430
*  thread that is ready to run on the current processor. The operating system
431
*  selects the thread to yield to. ithread_usleep blocks the current thread for
432
*  the specified number of milliseconds. In other words, yield just says,
433
*  end my timeslice prematurely, look around for other threads to run. If there
434
*  is nothing better than me, continue. Sleep says I don't want to run for x
435
*  milliseconds. Even if no other thread wants to run, don't make me run.
436
*
437
* @param[in] sleep_us
438
*  thread sleep duration
439
*
440
* @returns error_status
441
*
442
******************************************************************************
443
*/
444
IH264E_ERROR_T ih264e_wait_for_thread(UWORD32 sleep_us)
445
0
{
446
    /* yield thread */
447
0
    ithread_yield();
448
449
    /* put thread to sleep */
450
0
    ithread_usleep(sleep_us);
451
452
0
    return IH264E_SUCCESS;
453
0
}
454
455
/**
456
*******************************************************************************
457
*
458
* @brief
459
*  Used to test validity of input dimensions
460
*
461
* @par Description:
462
*  Dimensions of the input buffer passed to encode call are validated
463
*
464
* @param[in] ps_codec
465
*  Codec context
466
*
467
* @param[in] ps_ip
468
*  Pointer to input structure
469
*
470
* @param[out] ps_op
471
*  Pointer to output structure
472
*
473
* @returns error status
474
*
475
* @remarks none
476
*
477
*******************************************************************************
478
*/
479
static IV_STATUS_T api_check_input_dimensions(codec_t *ps_codec,
480
                                              ih264e_video_encode_ip_t *ps_ip,
481
                                              ih264e_video_encode_op_t *ps_op)
482
45.6k
{
483
45.6k
    UWORD32 u4_wd, u4_ht;
484
45.6k
    cfg_params_t *ps_curr_cfg = &ps_codec->s_cfg;
485
45.6k
    iv_raw_buf_t *ps_inp_buf = &ps_ip->s_ive_ip.s_inp_buf;
486
487
45.6k
    u4_wd = ps_inp_buf->au4_wd[0];
488
45.6k
    u4_ht = ps_inp_buf->au4_ht[0];
489
45.6k
    switch (ps_inp_buf->e_color_fmt)
490
45.6k
    {
491
22.5k
        case IV_YUV_420P:
492
22.5k
            if (((ps_inp_buf->au4_wd[0] / 2) != ps_inp_buf->au4_wd[1]) ||
493
22.5k
                            ((ps_inp_buf->au4_wd[0] / 2) != ps_inp_buf->au4_wd[2]) ||
494
22.5k
                            (ps_inp_buf->au4_wd[1] != ps_inp_buf->au4_wd[2]))
495
0
            {
496
0
                ps_op->s_ive_op.u4_error_code |= 1 << IVE_UNSUPPORTEDPARAM;
497
0
                ps_op->s_ive_op.u4_error_code |= IH264E_WIDTH_NOT_SUPPORTED;
498
0
                return (IV_FAIL);
499
0
            }
500
22.5k
            if (((ps_inp_buf->au4_ht[0] / 2) != ps_inp_buf->au4_ht[1]) ||
501
22.5k
                            ((ps_inp_buf->au4_ht[0] / 2) != ps_inp_buf->au4_ht[2]) ||
502
22.5k
                            (ps_inp_buf->au4_ht[1] != ps_inp_buf->au4_ht[2]))
503
0
            {
504
0
                ps_op->s_ive_op.u4_error_code |= 1 << IVE_UNSUPPORTEDPARAM;
505
0
                ps_op->s_ive_op.u4_error_code |= IH264E_HEIGHT_NOT_SUPPORTED;
506
0
                return (IV_FAIL);
507
0
            }
508
22.5k
            break;
509
22.5k
        case IV_YUV_420SP_UV:
510
21.8k
        case IV_YUV_420SP_VU:
511
21.8k
            if (ps_inp_buf->au4_wd[0] != ps_inp_buf->au4_wd[1])
512
0
            {
513
0
                ps_op->s_ive_op.u4_error_code |= 1 << IVE_UNSUPPORTEDPARAM;
514
0
                ps_op->s_ive_op.u4_error_code |= IH264E_WIDTH_NOT_SUPPORTED;
515
0
                return (IV_FAIL);
516
0
            }
517
21.8k
            if ((ps_inp_buf->au4_ht[0] / 2) != ps_inp_buf->au4_ht[1])
518
0
            {
519
0
                ps_op->s_ive_op.u4_error_code |= 1 << IVE_UNSUPPORTEDPARAM;
520
0
                ps_op->s_ive_op.u4_error_code |= IH264E_HEIGHT_NOT_SUPPORTED;
521
0
                return (IV_FAIL);
522
0
            }
523
21.8k
            break;
524
21.8k
        case IV_YUV_422ILE:
525
1.31k
            u4_wd = ps_inp_buf->au4_wd[0] / 2;
526
1.31k
            break;
527
0
        default:
528
0
            ps_op->s_ive_op.u4_error_code |= 1 << IVE_UNSUPPORTEDPARAM;
529
0
            ps_op->s_ive_op.u4_error_code |= IH264E_INPUT_CHROMA_FORMAT_NOT_SUPPORTED;
530
0
            return (IV_FAIL);
531
45.6k
    }
532
533
45.6k
    if (u4_wd != ps_curr_cfg->u4_disp_wd)
534
60
    {
535
60
        ps_op->s_ive_op.u4_error_code |= 1 << IVE_UNSUPPORTEDPARAM;
536
60
        ps_op->s_ive_op.u4_error_code |= IH264E_WIDTH_NOT_SUPPORTED;
537
60
        return (IV_FAIL);
538
60
    }
539
540
45.6k
    if (u4_ht != ps_curr_cfg->u4_disp_ht)
541
12
    {
542
12
        ps_op->s_ive_op.u4_error_code |= 1 << IVE_UNSUPPORTEDPARAM;
543
12
        ps_op->s_ive_op.u4_error_code |= IH264E_HEIGHT_NOT_SUPPORTED;
544
12
        return (IV_FAIL);
545
12
    }
546
547
45.6k
    return IV_SUCCESS;
548
45.6k
}
549
550
/**
551
******************************************************************************
552
*
553
* @brief
554
*  Encodes in synchronous api mode
555
*
556
* @par Description
557
*  This routine processes input yuv, encodes it and outputs bitstream and recon
558
*
559
* @param[in] ps_codec_obj
560
*  Pointer to codec object at API level
561
*
562
* @param[in] pv_api_ip
563
*  Pointer to input argument structure
564
*
565
* @param[out] pv_api_op
566
*  Pointer to output argument structure
567
*
568
* @returns  Status
569
*
570
******************************************************************************
571
*/
572
WORD32 ih264e_encode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op)
573
70.7k
{
574
    /* error status */
575
70.7k
    IH264E_ERROR_T error_status = IH264E_SUCCESS;
576
577
    /* codec ctxt */
578
70.7k
    codec_t *ps_codec = (codec_t *)ps_codec_obj->pv_codec_handle;
579
580
    /* input frame to encode */
581
70.7k
    ih264e_video_encode_ip_t *ps_video_encode_ip = pv_api_ip;
582
583
    /* output buffer to write stream */
584
70.7k
    ih264e_video_encode_op_t *ps_video_encode_op = pv_api_op;
585
586
    /* i/o structures */
587
70.7k
    inp_buf_t s_inp_buf = {};
588
70.7k
    out_buf_t s_out_buf = {};
589
590
    /* temp var */
591
70.7k
    WORD32 ctxt_sel = 0, i, i4_rc_pre_enc_skip;
592
593
    /********************************************************************/
594
    /*                            BEGIN INIT                            */
595
    /********************************************************************/
596
    /* reset output structure */
597
70.7k
    ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
598
70.7k
    ps_video_encode_op->s_ive_op.output_present  = 0;
599
70.7k
    ps_video_encode_op->s_ive_op.dump_recon = 0;
600
70.7k
    ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
601
    /* By default set the current input buffer as the buffer to be freed */
602
    /* This will later be updated to the actual input that gets encoded */
603
70.7k
    ps_video_encode_op->s_ive_op.s_inp_buf = ps_video_encode_ip->s_ive_ip.s_inp_buf;
604
605
70.7k
    if (ps_codec->i4_error_code & (1 << IVE_FATALERROR))
606
8.23k
    {
607
8.23k
        error_status = ps_codec->i4_error_code & 0xFF;
608
8.23k
        SET_ERROR_ON_RETURN(error_status,
609
8.23k
                            IVE_FATALERROR,
610
8.23k
                            ps_video_encode_op->s_ive_op.u4_error_code,
611
8.23k
                            IV_FAIL);
612
0
    }
613
614
    /* Check for output memory allocation size */
615
62.5k
    if (ps_video_encode_ip->s_ive_ip.s_out_buf.u4_bufsize < MIN_STREAM_SIZE)
616
48.7k
    {
617
48.7k
        error_status = IH264E_INSUFFICIENT_OUTPUT_BUFFER;
618
48.7k
        SET_ERROR_ON_RETURN(error_status,
619
48.7k
                            IVE_UNSUPPORTEDPARAM,
620
48.7k
                            ps_video_encode_op->s_ive_op.u4_error_code,
621
48.7k
                            IV_FAIL);
622
48.7k
    }
623
624
62.5k
    if (ps_codec->i4_init_done != 1)
625
0
    {
626
0
        error_status = IH264E_INIT_NOT_DONE;
627
0
        SET_ERROR_ON_RETURN(error_status,
628
0
                            IVE_FATALERROR,
629
0
                            ps_video_encode_op->s_ive_op.u4_error_code,
630
0
                            IV_FAIL);
631
0
    }
632
633
    /* copy output info. to internal structure */
634
62.5k
    s_out_buf.s_bits_buf = ps_video_encode_ip->s_ive_ip.s_out_buf;
635
62.5k
    s_out_buf.u4_is_last = 0;
636
62.5k
    s_out_buf.u4_timestamp_low = ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
637
62.5k
    s_out_buf.u4_timestamp_high = ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
638
639
    /* api call cnt */
640
62.5k
    ps_codec->i4_encode_api_call_cnt += 1;
641
642
    /* codec context selector */
643
62.5k
    ctxt_sel = ps_codec->i4_encode_api_call_cnt % MAX_CTXT_SETS;
644
645
    /* reset status flags */
646
62.5k
    ps_codec->ai4_pic_cnt[ctxt_sel] = -1;
647
62.5k
    ps_codec->s_rate_control.post_encode_skip[ctxt_sel] = 0;
648
62.5k
    ps_codec->s_rate_control.pre_encode_skip[ctxt_sel] = 0;
649
650
    /* pass output buffer to codec */
651
62.5k
    ps_codec->as_out_buf[ctxt_sel] = s_out_buf;
652
653
    /* initialize codec ctxt with default params for the first encode api call */
654
62.5k
    if (ps_codec->i4_encode_api_call_cnt == 0)
655
9.51k
    {
656
9.51k
        ih264e_codec_init(ps_codec);
657
9.51k
    }
658
659
    /* parse configuration params */
660
2.06M
    for (i = 0; i < MAX_ACTIVE_CONFIG_PARAMS; i++)
661
2.00M
    {
662
2.00M
        cfg_params_t *ps_cfg = &ps_codec->as_cfg[i];
663
664
2.00M
        if (1 == ps_cfg->u4_is_valid)
665
89.2k
        {
666
89.2k
            if ( ((ps_cfg->u4_timestamp_high == ps_video_encode_ip->s_ive_ip.u4_timestamp_high) &&
667
89.2k
                            (ps_cfg->u4_timestamp_low == ps_video_encode_ip->s_ive_ip.u4_timestamp_low)) ||
668
89.2k
                            ((WORD32)ps_cfg->u4_timestamp_high == -1) ||
669
89.2k
                            ((WORD32)ps_cfg->u4_timestamp_low == -1) )
670
89.2k
            {
671
89.2k
                error_status = ih264e_codec_update_config(ps_codec, ps_cfg);
672
89.2k
                SET_ERROR_ON_RETURN(error_status,
673
89.2k
                                    IVE_FATALERROR,
674
89.2k
                                    ps_video_encode_op->s_ive_op.u4_error_code,
675
89.2k
                                    IV_FAIL);
676
677
89.2k
                ps_cfg->u4_is_valid = 0;
678
89.2k
            }
679
89.2k
        }
680
2.00M
    }
681
    /* Force IDR based on SEI params */
682
62.5k
#if SEI_BASED_FORCE_IDR
683
62.5k
    {
684
62.5k
        int i;
685
62.5k
        bool au4_sub_layer_num_units_in_shutter_interval_flag = 0;
686
687
62.5k
        sei_mdcv_params_t *ps_sei_mdcv_params = &ps_codec->s_sei.s_sei_mdcv_params;
688
62.5k
        sei_mdcv_params_t *ps_cfg_sei_mdcv_params =
689
62.5k
                                &ps_codec->s_cfg.s_sei.s_sei_mdcv_params;
690
62.5k
        sei_cll_params_t *ps_sei_cll_params = &ps_codec->s_sei.s_sei_cll_params;
691
62.5k
        sei_cll_params_t *ps_cfg_sei_cll_params =
692
62.5k
                                &ps_codec->s_cfg.s_sei.s_sei_cll_params;
693
62.5k
        sei_ave_params_t *ps_sei_ave_params = &ps_codec->s_sei.s_sei_ave_params;
694
62.5k
        sei_ave_params_t *ps_cfg_sei_ave_params =
695
62.5k
                                &ps_codec->s_cfg.s_sei.s_sei_ave_params;
696
62.5k
        sei_sii_params_t *ps_sei_sii_params = &ps_codec->s_sei.s_sei_sii_params;
697
62.5k
        sei_sii_params_t *ps_cfg_sei_sii_params = &ps_codec->s_cfg.s_sei.s_sei_sii_params;
698
699
62.5k
        if((ps_sei_mdcv_params->au2_display_primaries_x[0]!=
700
62.5k
                                ps_cfg_sei_mdcv_params->au2_display_primaries_x[0]) ||
701
62.5k
            (ps_sei_mdcv_params->au2_display_primaries_x[1] !=
702
60.5k
                                ps_cfg_sei_mdcv_params->au2_display_primaries_x[1]) ||
703
62.5k
            (ps_sei_mdcv_params->au2_display_primaries_x[2] !=
704
60.5k
                                ps_cfg_sei_mdcv_params->au2_display_primaries_x[2]) ||
705
62.5k
            (ps_sei_mdcv_params->au2_display_primaries_y[0] !=
706
60.5k
                                ps_cfg_sei_mdcv_params->au2_display_primaries_y[0]) ||
707
62.5k
            (ps_sei_mdcv_params->au2_display_primaries_y[1] !=
708
60.5k
                                ps_cfg_sei_mdcv_params->au2_display_primaries_y[1]) ||
709
62.5k
            (ps_sei_mdcv_params->au2_display_primaries_y[2] !=
710
60.5k
                                ps_cfg_sei_mdcv_params->au2_display_primaries_y[2]) ||
711
62.5k
            (ps_sei_mdcv_params->u2_white_point_x !=
712
60.5k
                                ps_cfg_sei_mdcv_params->u2_white_point_x) ||
713
62.5k
            (ps_sei_mdcv_params->u2_white_point_y !=
714
60.5k
                                ps_cfg_sei_mdcv_params->u2_white_point_y) ||
715
62.5k
            (ps_sei_mdcv_params->u4_max_display_mastering_luminance !=
716
60.5k
                                ps_cfg_sei_mdcv_params->u4_max_display_mastering_luminance) ||
717
62.5k
            (ps_sei_mdcv_params->u4_min_display_mastering_luminance !=
718
60.5k
                                ps_cfg_sei_mdcv_params->u4_min_display_mastering_luminance))
719
2.01k
        {
720
2.01k
            ps_codec->s_sei.s_sei_mdcv_params = ps_codec->s_cfg.s_sei.s_sei_mdcv_params;
721
2.01k
            ps_codec->s_sei.u1_sei_mdcv_params_present_flag = 1;
722
2.01k
        }
723
60.5k
        else
724
60.5k
        {
725
60.5k
            ps_codec->s_sei.u1_sei_mdcv_params_present_flag = 0;
726
60.5k
        }
727
728
62.5k
        if((ps_sei_cll_params->u2_max_content_light_level !=
729
62.5k
                                ps_cfg_sei_cll_params->u2_max_content_light_level) ||
730
62.5k
                (ps_sei_cll_params->u2_max_pic_average_light_level !=
731
62.5k
                                ps_cfg_sei_cll_params->u2_max_pic_average_light_level))
732
0
        {
733
0
            ps_codec->s_sei.s_sei_cll_params = ps_codec->s_cfg.s_sei.s_sei_cll_params;
734
0
            ps_codec->s_sei.u1_sei_cll_params_present_flag = 1;
735
0
        }
736
62.5k
        else
737
62.5k
        {
738
62.5k
            ps_codec->s_sei.u1_sei_cll_params_present_flag = 0;
739
62.5k
        }
740
741
62.5k
        if((ps_sei_ave_params->u4_ambient_illuminance !=
742
62.5k
                                ps_cfg_sei_ave_params->u4_ambient_illuminance) ||
743
62.5k
                (ps_sei_ave_params->u2_ambient_light_x !=
744
60.7k
                                ps_cfg_sei_ave_params->u2_ambient_light_x) ||
745
62.5k
                (ps_sei_ave_params->u2_ambient_light_y !=
746
60.7k
                                ps_cfg_sei_ave_params->u2_ambient_light_y))
747
1.80k
        {
748
1.80k
            ps_codec->s_sei.s_sei_ave_params = ps_codec->s_cfg.s_sei.s_sei_ave_params;
749
1.80k
            ps_codec->s_sei.u1_sei_ave_params_present_flag = 1;
750
1.80k
        }
751
60.7k
        else
752
60.7k
        {
753
60.7k
            ps_codec->s_sei.u1_sei_ave_params_present_flag = 0;
754
60.7k
        }
755
756
279k
        for(i = 0; i <= ps_cfg_sei_sii_params->u1_sii_max_sub_layers_minus1; i++)
757
216k
        {
758
216k
            au4_sub_layer_num_units_in_shutter_interval_flag =
759
216k
                (au4_sub_layer_num_units_in_shutter_interval_flag ||
760
216k
                 (ps_sei_sii_params->au4_sub_layer_num_units_in_shutter_interval[i] !=
761
204k
                  ps_cfg_sei_sii_params->au4_sub_layer_num_units_in_shutter_interval[i]));
762
216k
        }
763
764
62.5k
        if((ps_sei_sii_params->u4_sii_sub_layer_idx !=
765
62.5k
            ps_cfg_sei_sii_params->u4_sii_sub_layer_idx) ||
766
62.5k
           (ps_sei_sii_params->u1_shutter_interval_info_present_flag !=
767
62.5k
            ps_cfg_sei_sii_params->u1_shutter_interval_info_present_flag) ||
768
62.5k
           (ps_sei_sii_params->u4_sii_time_scale != ps_cfg_sei_sii_params->u4_sii_time_scale) ||
769
62.5k
           (ps_sei_sii_params->u1_fixed_shutter_interval_within_cvs_flag !=
770
60.6k
            ps_cfg_sei_sii_params->u1_fixed_shutter_interval_within_cvs_flag) ||
771
62.5k
           (ps_sei_sii_params->u4_sii_num_units_in_shutter_interval !=
772
60.6k
            ps_cfg_sei_sii_params->u4_sii_num_units_in_shutter_interval) ||
773
62.5k
           (ps_sei_sii_params->u1_sii_max_sub_layers_minus1 !=
774
60.6k
            ps_cfg_sei_sii_params->u1_sii_max_sub_layers_minus1) ||
775
62.5k
           au4_sub_layer_num_units_in_shutter_interval_flag)
776
1.83k
        {
777
1.83k
            ps_codec->s_sei.s_sei_sii_params = ps_codec->s_cfg.s_sei.s_sei_sii_params;
778
1.83k
            ps_codec->s_sei.u1_sei_sii_params_present_flag = 1;
779
1.83k
        }
780
60.6k
        else
781
60.6k
        {
782
60.6k
            ps_codec->s_sei.u1_sei_sii_params_present_flag = 0;
783
60.6k
        }
784
785
62.5k
        if((1 == ps_codec->s_sei.u1_sei_mdcv_params_present_flag) ||
786
62.5k
                (1 == ps_codec->s_sei.u1_sei_cll_params_present_flag) ||
787
62.5k
           (1 == ps_codec->s_sei.u1_sei_ave_params_present_flag) ||
788
62.5k
           (1 == ps_codec->s_sei.u1_sei_sii_params_present_flag))
789
3.25k
        {
790
3.25k
            ps_codec->force_curr_frame_type = IV_IDR_FRAME;
791
3.25k
        }
792
62.5k
    }
793
62.5k
#endif
794
795
62.5k
    if (ps_video_encode_ip->s_ive_ip.s_inp_buf.apv_bufs[0] != NULL &&
796
62.5k
                    ps_codec->i4_header_mode != 1)
797
45.6k
    {
798
45.6k
        if (IV_SUCCESS != api_check_input_dimensions(ps_codec, pv_api_ip, pv_api_op))
799
72
        {
800
72
            error_status = IH264E_FAIL;
801
72
            SET_ERROR_ON_RETURN(error_status,
802
72
                                IVE_FATALERROR,
803
72
                                ps_video_encode_op->s_ive_op.u4_error_code,
804
72
                                IV_FAIL);
805
0
        }
806
        /******************************************************************
807
         * INSERT LOGO
808
         *****************************************************************/
809
#ifdef LOGO_EN
810
        ih264e_insert_logo(ps_video_encode_ip->s_ive_ip.s_inp_buf.apv_bufs[0],
811
                           ps_video_encode_ip->s_ive_ip.s_inp_buf.apv_bufs[1],
812
                           ps_video_encode_ip->s_ive_ip.s_inp_buf.apv_bufs[2],
813
                           ps_video_encode_ip->s_ive_ip.s_inp_buf.au4_strd[0],
814
                           0,
815
                           0,
816
                           ps_codec->s_cfg.e_inp_color_fmt,
817
                           ps_codec->s_cfg.u4_disp_wd,
818
                           ps_codec->s_cfg.u4_disp_ht);
819
#endif /*LOGO_EN*/
820
45.6k
    }
821
822
    /* In case of alt ref and B pics we will have non reference frame in stream */
823
62.4k
    if (ps_codec->s_cfg.u4_enable_alt_ref || ps_codec->s_cfg.u4_num_bframes)
824
43.9k
    {
825
43.9k
        ps_codec->i4_non_ref_frames_in_stream = 1;
826
43.9k
    }
827
828
62.4k
    if (ps_codec->i4_encode_api_call_cnt == 0)
829
9.44k
    {
830
        /********************************************************************/
831
        /*   number of mv/ref bank buffers used by the codec,               */
832
        /*      1 to handle curr frame                                      */
833
        /*      1 to store information of ref frame                         */
834
        /*      1 more additional because of the codec employs 2 ctxt sets  */
835
        /*        to assist asynchronous API                                */
836
        /********************************************************************/
837
838
        /* initialize mv bank buffer manager */
839
9.44k
        error_status = ih264e_mv_buf_mgr_add_bufs(ps_codec);
840
9.44k
        SET_ERROR_ON_RETURN(error_status,
841
9.44k
                            IVE_FATALERROR,
842
9.44k
                            ps_video_encode_op->s_ive_op.u4_error_code,
843
9.44k
                            IV_FAIL);
844
845
        /* initialize ref bank buffer manager */
846
9.44k
        error_status = ih264e_pic_buf_mgr_add_bufs(ps_codec);
847
9.44k
        SET_ERROR_ON_RETURN(error_status,
848
9.44k
                            IVE_FATALERROR,
849
9.44k
                            ps_video_encode_op->s_ive_op.u4_error_code,
850
9.44k
                            IV_FAIL);
851
852
        /* for the first frame, generate header when not requested explicitly */
853
9.44k
        if (ps_codec->i4_header_mode == 0 &&
854
9.44k
                        ps_codec->u4_header_generated == 0)
855
0
        {
856
0
            ps_codec->i4_gen_header = 1;
857
0
        }
858
859
9.44k
        if (ps_codec->s_cfg.u4_keep_threads_active)
860
9.44k
        {
861
9.44k
            ih264e_thread_pool_init(ps_codec);
862
9.44k
        }
863
9.44k
    }
864
865
    /* generate header and return when encoder is operated in header mode */
866
62.4k
    if (ps_codec->i4_header_mode == 1)
867
4.75k
    {
868
        /* whenever the header is generated, this implies a start of sequence
869
         * and a sequence needs to be started with IDR
870
         */
871
4.75k
        ps_codec->force_curr_frame_type = IV_IDR_FRAME;
872
873
        /* generate header */
874
4.75k
        error_status = ih264e_generate_sps_pps(ps_codec);
875
876
        /* send the input to app */
877
4.75k
        ps_video_encode_op->s_ive_op.s_inp_buf = ps_video_encode_ip->s_ive_ip.s_inp_buf;
878
4.75k
        ps_video_encode_op->s_ive_op.u4_timestamp_low = ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
879
4.75k
        ps_video_encode_op->s_ive_op.u4_timestamp_high = ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
880
881
4.75k
        ps_video_encode_op->s_ive_op.u4_is_last = ps_video_encode_ip->s_ive_ip.u4_is_last;
882
883
        /* send the output to app */
884
4.75k
        ps_video_encode_op->s_ive_op.output_present  = 1;
885
4.75k
        ps_video_encode_op->s_ive_op.dump_recon = 0;
886
4.75k
        ps_video_encode_op->s_ive_op.s_out_buf = ps_codec->as_out_buf[ctxt_sel].s_bits_buf;
887
888
        /* error status */
889
4.75k
        SET_ERROR_ON_RETURN(error_status,
890
4.75k
                            IVE_UNSUPPORTEDPARAM,
891
4.75k
                            ps_video_encode_op->s_ive_op.u4_error_code,
892
4.75k
                            IV_FAIL);
893
894
        /* indicates that header has been generated previously */
895
4.75k
        ps_codec->u4_header_generated = 1;
896
897
        /* api call cnt */
898
4.75k
        ps_codec->i4_encode_api_call_cnt --;
899
900
        /* header mode tag is not sticky */
901
4.75k
        ps_codec->i4_header_mode = 0;
902
4.75k
        ps_codec->i4_gen_header = 0;
903
904
4.75k
        return IV_SUCCESS;
905
4.75k
    }
906
907
    /* curr pic cnt */
908
57.6k
    ps_codec->i4_pic_cnt += 1;
909
910
57.6k
    i4_rc_pre_enc_skip = 0;
911
57.6k
    i4_rc_pre_enc_skip = ih264e_input_queue_update(
912
57.6k
                    ps_codec, &ps_video_encode_ip->s_ive_ip, &s_inp_buf);
913
914
57.6k
    s_out_buf.u4_is_last = s_inp_buf.u4_is_last;
915
57.6k
    ps_video_encode_op->s_ive_op.u4_is_last = s_inp_buf.u4_is_last;
916
917
    /* Send the input to application so that it can free it */
918
57.6k
    ps_video_encode_op->s_ive_op.s_inp_buf = s_inp_buf.s_raw_buf;
919
920
    /* Only encode if the current frame is not pre-encode skip */
921
57.6k
    if (!i4_rc_pre_enc_skip && s_inp_buf.s_raw_buf.apv_bufs[0])
922
43.3k
    {
923
        /* proc ctxt base idx */
924
43.3k
        WORD32 proc_ctxt_select = ctxt_sel * MAX_PROCESS_THREADS;
925
926
        /* proc ctxt */
927
43.3k
        process_ctxt_t *ps_proc = &ps_codec->as_process[proc_ctxt_select];
928
929
43.3k
        WORD32 ret = 0;
930
931
        /* number of addl. threads to be created */
932
43.3k
        WORD32 num_thread_cnt = ps_codec->s_cfg.u4_num_cores - 1;
933
934
        /* array giving pic cnt that is being processed in curr context set */
935
43.3k
        ps_codec->ai4_pic_cnt[ctxt_sel] = ps_codec->i4_pic_cnt;
936
937
        /* initialize all relevant process ctxts */
938
43.3k
        error_status = ih264e_pic_init(ps_codec, &s_inp_buf);
939
43.3k
        SET_ERROR_ON_RETURN(error_status,
940
43.3k
                            IVE_FATALERROR,
941
43.3k
                            ps_video_encode_op->s_ive_op.u4_error_code,
942
43.3k
                            IV_FAIL);
943
944
43.3k
        if (ps_codec->s_cfg.u4_keep_threads_active)
945
43.3k
        {
946
            /* reset thread pool and prepare for new frame */
947
43.3k
            ih264e_thread_pool_activate(ps_codec);
948
949
            /* main thread */
950
43.3k
            ih264e_process_thread(&ps_codec->as_process[0]);
951
952
            /* sync all threads */
953
43.3k
            ih264e_thread_pool_sync(ps_codec);
954
43.3k
        }
955
0
        else
956
0
        {
957
0
            for (i = 0; i < num_thread_cnt; i++)
958
0
            {
959
0
                ret = ithread_create(ps_codec->apv_proc_thread_handle[i],
960
0
                                     NULL,
961
0
                                     (void *)ih264e_process_thread,
962
0
                                     &ps_codec->as_process[i + 1]);
963
0
                if (ret != 0)
964
0
                {
965
0
                    printf("pthread Create Failed");
966
0
                    assert(0);
967
0
                }
968
969
0
                ps_codec->ai4_process_thread_created[i] = 1;
970
971
0
                ps_codec->i4_proc_thread_cnt++;
972
0
            }
973
974
            /* launch job */
975
0
            ih264e_process_thread(ps_proc);
976
977
            /* Join threads at the end of encoding a frame */
978
0
            ih264e_join_threads(ps_codec);
979
0
        }
980
981
43.3k
        ih264_list_reset(ps_codec->pv_proc_jobq);
982
983
43.3k
        ih264_list_reset(ps_codec->pv_entropy_jobq);
984
985
43.3k
        error_status = ih264e_update_rc_post_enc(ps_codec, ctxt_sel, (ps_codec->i4_poc == 0));
986
43.3k
        SET_ERROR_ON_RETURN(error_status,
987
43.3k
                            ((error_status == IH264E_BITSTREAM_BUFFER_OVERFLOW) ?
988
43.3k
                                            IVE_UNSUPPORTEDPARAM : IVE_FATALERROR),
989
43.3k
                            ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
990
991
43.3k
        if (ps_codec->s_cfg.u4_enable_quality_metrics & QUALITY_MASK_PSNR)
992
0
        {
993
0
            ih264e_compute_quality_stats(ps_proc);
994
0
        }
995
996
43.3k
    }
997
998
   /****************************************************************************
999
   * RECON
1000
   *    Since we have forward dependent frames, we cannot return recon in encoding
1001
   *    order. It must be in poc order, or input pic order. To achieve this we
1002
   *    introduce a delay of 1 to the recon wrt encode. Now since we have that
1003
   *    delay, at any point minimum of pic_cnt in our ref buffer will be the
1004
   *    correct frame. For ex let our GOP be IBBP [1 2 3 4] . The encode order
1005
   *    will be [1 4 2 3] .Now since we have a delay of 1, when we are done with
1006
   *    encoding 4, the min in the list will be 1. After encoding 2, it will be
1007
   *    2, 3 after 3 and 4 after 4. Hence we can return in sequence. Note
1008
   *    that the 1 delay is critical. Hence if we have post enc skip, we must
1009
   *    skip here too. Note that since post enc skip already frees the recon
1010
   *    buffer we need not do any thing here
1011
   *
1012
   *    We need to return a recon when ever we consume an input buffer. This
1013
   *    comsumption include a pre or post enc skip. Thus dump recon is set for
1014
   *    all cases except when
1015
   *    1) We are waiting -> ps_codec->i4_pic_cnt > ps_codec->s_cfg.u4_num_bframe
1016
   *        An exception need to be made for the case when we have the last buffer
1017
   *        since we need to flush out the on remainig recon.
1018
   ****************************************************************************/
1019
1020
57.6k
    ps_video_encode_op->s_ive_op.dump_recon = 0;
1021
1022
57.6k
    if (ps_codec->s_cfg.u4_enable_recon
1023
57.6k
                    && (ps_codec->i4_pic_cnt > (WORD32)ps_codec->s_cfg.u4_num_bframes ||
1024
0
                        s_inp_buf.u4_is_last))
1025
0
    {
1026
        /* error status */
1027
0
        IH264_ERROR_T ret = IH264_SUCCESS;
1028
0
        pic_buf_t *ps_pic_buf = NULL;
1029
0
        WORD32 i4_buf_status, i4_curr_poc = 32768;
1030
0
        WORD8 buf_idx = -1;
1031
1032
        /* In case of skips we return recon, but indicate that buffer is zero size */
1033
0
        if (ps_codec->s_rate_control.post_encode_skip[ctxt_sel]
1034
0
                        || i4_rc_pre_enc_skip)
1035
0
        {
1036
1037
0
            ps_video_encode_op->s_ive_op.dump_recon = 1;
1038
0
            ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[0] = 0;
1039
0
            ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[1] = 0;
1040
1041
0
        }
1042
0
        else
1043
0
        {
1044
0
            for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
1045
0
            {
1046
0
                if (ps_codec->as_ref_set[i].i4_pic_cnt == -1)
1047
0
                    continue;
1048
1049
0
                i4_buf_status = ih264_buf_mgr_get_status(
1050
0
                                ps_codec->pv_ref_buf_mgr,
1051
0
                                ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
1052
1053
0
                if ((i4_buf_status & BUF_MGR_IO)
1054
0
                                && (ps_codec->as_ref_set[i].i4_poc < i4_curr_poc))
1055
0
                {
1056
0
                    ps_pic_buf = ps_codec->as_ref_set[i].ps_pic_buf;
1057
0
                    i4_curr_poc = ps_codec->as_ref_set[i].i4_poc;
1058
0
                    buf_idx = i;
1059
0
                }
1060
0
            }
1061
0
            if ((ps_codec->s_cfg.u4_enable_quality_metrics & QUALITY_MASK_PSNR)
1062
0
                                && buf_idx >= 0)
1063
0
            {
1064
0
                UWORD8 comp;
1065
0
                for(comp = 0; comp < 3; comp++)
1066
0
                {
1067
0
                    DEBUG("PSNR[%d]: %f\n", comp,
1068
0
                        ps_codec->as_ref_set[buf_idx].s_pic_quality_stats.total_psnr[comp]);
1069
0
                }
1070
0
            }
1071
1072
0
            ps_video_encode_op->s_ive_op.s_recon_buf =
1073
0
                            ps_video_encode_ip->s_ive_ip.s_recon_buf;
1074
1075
            /*
1076
             * If we get a valid buffer. output and free recon.
1077
             *
1078
             * we may get an invalid buffer if num_b_frames is 0. This is because
1079
             * We assume that there will be a ref frame in ref list after encoding
1080
             * the last frame. With B frames this is correct since its forward ref
1081
             * pic will be in the ref list. But if num_b_frames is 0, we will not
1082
             * have a forward ref pic
1083
             */
1084
1085
0
            if (ps_pic_buf)
1086
0
            {
1087
                /* copy/convert the recon buffer and return */
1088
0
                ih264e_fmt_conv(ps_codec,
1089
0
                                ps_pic_buf,
1090
0
                                ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[0],
1091
0
                                ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[1],
1092
0
                                ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[2],
1093
0
                                ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[0],
1094
0
                                ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[1],
1095
0
                                0, ps_codec->s_cfg.u4_disp_ht);
1096
1097
0
                ps_video_encode_op->s_ive_op.dump_recon = 1;
1098
1099
0
                ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr,
1100
0
                                            ps_pic_buf->i4_buf_id, BUF_MGR_IO);
1101
1102
0
                if (IH264_SUCCESS != ret)
1103
0
                {
1104
0
                    SET_ERROR_ON_RETURN(
1105
0
                                    (IH264E_ERROR_T)ret, IVE_FATALERROR,
1106
0
                                    ps_video_encode_op->s_ive_op.u4_error_code,
1107
0
                                    IV_FAIL);
1108
0
                }
1109
0
            }
1110
0
        }
1111
0
    }
1112
1113
    /***************************************************************************
1114
     * Free reference buffers:
1115
     * In case of a post enc skip, we have to ensure that those pics will not
1116
     * be used as reference anymore. In all other cases we will not even mark
1117
     * the ref buffers
1118
     ***************************************************************************/
1119
57.6k
    if (ps_codec->s_rate_control.post_encode_skip[ctxt_sel])
1120
0
    {
1121
        /* pic info */
1122
0
        pic_buf_t *ps_cur_pic;
1123
1124
        /* mv info */
1125
0
        mv_buf_t *ps_cur_mv_buf;
1126
1127
        /* error status */
1128
0
        IH264_ERROR_T ret = IH264_SUCCESS;
1129
1130
        /* Decrement coded pic count */
1131
0
        ps_codec->i4_poc--;
1132
1133
        /* loop through to get the min pic cnt among the list of pics stored in ref list */
1134
        /* since the skipped frame may not be on reference list, we may not have an MV bank
1135
         * hence free only if we have allocated */
1136
0
        for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
1137
0
        {
1138
0
            if (ps_codec->i4_pic_cnt == ps_codec->as_ref_set[i].i4_pic_cnt)
1139
0
            {
1140
1141
0
                ps_cur_pic = ps_codec->as_ref_set[i].ps_pic_buf;
1142
1143
0
                ps_cur_mv_buf = ps_codec->as_ref_set[i].ps_mv_buf;
1144
1145
                /* release this frame from reference list and recon list */
1146
0
                ret = ih264_buf_mgr_release(ps_codec->pv_mv_buf_mgr, ps_cur_mv_buf->i4_buf_id , BUF_MGR_REF);
1147
0
                ret |= ih264_buf_mgr_release(ps_codec->pv_mv_buf_mgr, ps_cur_mv_buf->i4_buf_id , BUF_MGR_IO);
1148
0
                SET_ERROR_ON_RETURN((IH264E_ERROR_T)ret,
1149
0
                                    IVE_FATALERROR,
1150
0
                                    ps_video_encode_op->s_ive_op.u4_error_code,
1151
0
                                    IV_FAIL);
1152
1153
0
                ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id , BUF_MGR_REF);
1154
0
                ret |= ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id , BUF_MGR_IO);
1155
0
                SET_ERROR_ON_RETURN((IH264E_ERROR_T)ret,
1156
0
                                    IVE_FATALERROR,
1157
0
                                    ps_video_encode_op->s_ive_op.u4_error_code,
1158
0
                                    IV_FAIL);
1159
0
                break;
1160
0
            }
1161
0
        }
1162
0
    }
1163
1164
    /*
1165
     * Since recon is not in sync with output, ie there can be frame to be
1166
     * given back as recon even after last output. Hence we need to mark that
1167
     * the output is not the last.
1168
     * Hence search through reflist and mark appropriately
1169
     */
1170
57.6k
    if (ps_codec->s_cfg.u4_enable_recon)
1171
0
    {
1172
0
        WORD32 i4_buf_status = 0;
1173
1174
0
        for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
1175
0
        {
1176
0
            if (ps_codec->as_ref_set[i].i4_pic_cnt == -1)
1177
0
                continue;
1178
1179
0
            i4_buf_status |= ih264_buf_mgr_get_status(
1180
0
                            ps_codec->pv_ref_buf_mgr,
1181
0
                            ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
1182
0
        }
1183
1184
0
        if (i4_buf_status & BUF_MGR_IO)
1185
0
        {
1186
0
            s_out_buf.u4_is_last = 0;
1187
0
            ps_video_encode_op->s_ive_op.u4_is_last = 0;
1188
0
        }
1189
0
    }
1190
1191
    /**************************************************************************
1192
     * Signaling to APP
1193
     *  1) If we valid a valid output mark it so
1194
     *  2) Set the codec output ps_video_encode_op
1195
     *  3) Set the error status
1196
     *  4) Set the return Pic type
1197
     *      Note that we already has marked recon properly
1198
     *  5)Send the consumed input back to app so that it can free it if possible
1199
     *
1200
     *  We will have to return the output and input buffers unconditionally
1201
     *  so that app can release them
1202
     **************************************************************************/
1203
57.6k
    if (!i4_rc_pre_enc_skip
1204
57.6k
                    && !ps_codec->s_rate_control.post_encode_skip[ctxt_sel]
1205
57.6k
                    && s_inp_buf.s_raw_buf.apv_bufs[0])
1206
43.3k
    {
1207
1208
        /* receive output back from codec */
1209
43.3k
        s_out_buf = ps_codec->as_out_buf[ctxt_sel];
1210
1211
        /* send the output to app */
1212
43.3k
        ps_video_encode_op->s_ive_op.output_present  = 1;
1213
43.3k
        ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
1214
1215
        /* Set the time stamps of the encodec input */
1216
43.3k
        ps_video_encode_op->s_ive_op.u4_timestamp_low = s_inp_buf.u4_timestamp_low;
1217
43.3k
        ps_video_encode_op->s_ive_op.u4_timestamp_high = s_inp_buf.u4_timestamp_high;
1218
1219
43.3k
        switch (ps_codec->pic_type)
1220
43.3k
        {
1221
9.58k
            case PIC_IDR:
1222
9.58k
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type =IV_IDR_FRAME;
1223
9.58k
                break;
1224
1225
2.04k
            case PIC_I:
1226
2.04k
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_I_FRAME;
1227
2.04k
                break;
1228
1229
16.4k
            case PIC_P:
1230
16.4k
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_P_FRAME;
1231
16.4k
                break;
1232
1233
15.2k
            case PIC_B:
1234
15.2k
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_B_FRAME;
1235
15.2k
                break;
1236
1237
0
            default:
1238
0
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
1239
0
                break;
1240
43.3k
        }
1241
1242
144k
        for (i = 0; i < (WORD32)ps_codec->s_cfg.u4_num_cores; i++)
1243
100k
        {
1244
100k
            error_status |= ps_codec->as_process[ctxt_sel + i].i4_error_code;
1245
100k
        }
1246
43.3k
        SET_ERROR_ON_RETURN(error_status,
1247
43.3k
                            ((error_status == IH264E_BITSTREAM_BUFFER_OVERFLOW) ?
1248
43.3k
                                            IVE_UNSUPPORTEDPARAM : IVE_FATALERROR),
1249
43.3k
                            ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
1250
43.3k
    }
1251
14.3k
    else
1252
14.3k
    {
1253
        /* receive output back from codec */
1254
14.3k
        s_out_buf = ps_codec->as_out_buf[ctxt_sel];
1255
1256
14.3k
        ps_video_encode_op->s_ive_op.output_present = 0;
1257
14.3k
        ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
1258
1259
        /* Set the time stamps of the encodec input */
1260
14.3k
        ps_video_encode_op->s_ive_op.u4_timestamp_low = 0;
1261
14.3k
        ps_video_encode_op->s_ive_op.u4_timestamp_high = 0;
1262
1263
14.3k
        ps_video_encode_op->s_ive_op.u4_encoded_frame_type =  IV_NA_FRAME;
1264
1265
14.3k
    }
1266
1267
57.6k
    ps_video_encode_op->s_ive_op.s_out_buf = s_out_buf.s_bits_buf;
1268
1269
57.6k
    if (ps_codec->s_cfg.u4_keep_threads_active && ps_video_encode_op->s_ive_op.u4_is_last)
1270
4.63k
    {
1271
4.63k
        ih264e_thread_pool_shutdown(ps_codec);
1272
4.63k
    }
1273
1274
57.6k
    return IV_SUCCESS;
1275
57.6k
}