Coverage Report

Created: 2025-07-12 06:37

/src/libavc/encoder/svc/isvce_encode.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Copyright (C) 2022 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
*  isvce_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
*  - isvce_join_threads()
35
*  - isvce_wait_for_thread()
36
*  - isvce_encode()
37
*
38
******************************************************************************
39
*/
40
#include <stdio.h>
41
#include <stddef.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <limits.h>
45
#include <assert.h>
46
#include <math.h>
47
#include <stdbool.h>
48
49
#include "ih264_typedefs.h"
50
/* Dependencies of ih264_buf_mgr.h */
51
/* Dependencies of ih264_list.h */
52
#include "ih264_error.h"
53
/* Dependencies of ih264_common_tables.h */
54
#include "ih264_defs.h"
55
#include "ih264_structs.h"
56
#include "ih264_buf_mgr.h"
57
#include "ih264_common_tables.h"
58
#include "ih264_list.h"
59
#include "ih264_platform_macros.h"
60
#include "ih264_trans_data.h"
61
#include "ih264_size_defs.h"
62
/* Dependencies of ih264e_cabac_structs.h */
63
#include "ih264_cabac_tables.h"
64
/* Dependencies of ime_structs.h */
65
#include "ime_defs.h"
66
#include "ime_distortion_metrics.h"
67
/* Dependencies of ih264e_structs.h */
68
#include "iv2.h"
69
#include "ive2.h"
70
#include "ih264_defs.h"
71
#include "ih264_deblk_edge_filters.h"
72
#include "ih264_inter_pred_filters.h"
73
#include "ih264_structs.h"
74
#include "ih264_trans_quant_itrans_iquant.h"
75
/* Dependencies of ih264e_bitstream.h */
76
#include "ih264e_error.h"
77
#include "ih264e_bitstream.h"
78
#include "ih264e_cabac_structs.h"
79
#include "irc_cntrl_param.h"
80
#include "irc_frame_info_collector.h"
81
#include "ime_statistics.h"
82
#include "ime_structs.h"
83
/* Dependencies of 'ih264e_utils.h' */
84
#include "ih264e_defs.h"
85
#include "ih264e_structs.h"
86
#include "ih264e_utils.h"
87
#include "ime.h"
88
#include "isvce.h"
89
#include "isvce_cabac.h"
90
#include "isvce_deblk.h"
91
#include "isvce_defs.h"
92
#include "isvce_downscaler.h"
93
#include "isvce_encode_header.h"
94
#include "isvce_fmt_conv.h"
95
#include "isvce_ibl_eval.h"
96
#include "isvce_ilp_mv.h"
97
#include "isvce_intra_modes_eval.h"
98
#include "isvce_me.h"
99
#include "isvce_process.h"
100
#include "isvce_rate_control.h"
101
#include "isvce_residual_pred.h"
102
#include "isvce_sub_pic_rc.h"
103
#include "isvce_utils.h"
104
105
#define SEI_BASED_FORCE_IDR 1
106
107
/*****************************************************************************/
108
/* Function Definitions                                                      */
109
/*****************************************************************************/
110
111
/**
112
******************************************************************************
113
*
114
* @brief
115
*  Encodes in synchronous api mode
116
*
117
* @par Description
118
*  This routine processes input yuv, encodes it and outputs bitstream and recon
119
*
120
* @param[in] ps_codec_obj
121
*  Pointer to codec object at API level
122
*
123
* @param[in] pv_api_ip
124
*  Pointer to input argument structure
125
*
126
* @param[out] pv_api_op
127
*  Pointer to output argument structure
128
*
129
* @returns  Status
130
*
131
******************************************************************************
132
*/
133
WORD32 isvce_encode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op)
134
45.7k
{
135
    /* error status */
136
45.7k
    IH264E_ERROR_T error_status = IH264E_SUCCESS;
137
138
    /* codec ctxt */
139
45.7k
    isvce_codec_t *ps_codec = (isvce_codec_t *) ps_codec_obj->pv_codec_handle;
140
141
    /* input frame to encode */
142
45.7k
    isvce_video_encode_ip_t *ps_video_encode_ip = pv_api_ip;
143
144
    /* output buffer to write stream */
145
45.7k
    isvce_video_encode_op_t *ps_video_encode_op = pv_api_op;
146
147
    /* i/o structures */
148
45.7k
    isvce_inp_buf_t s_inp_buf;
149
45.7k
    isvce_out_buf_t s_out_buf;
150
151
45.7k
    WORD32 ctxt_sel = 0, i4_rc_pre_enc_skip;
152
45.7k
    WORD32 i, j;
153
154
45.7k
    ASSERT(MAX_CTXT_SETS == 1);
155
156
    /********************************************************************/
157
    /*                            BEGIN INIT                            */
158
    /********************************************************************/
159
    /* reset output structure */
160
45.7k
    ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
161
45.7k
    ps_video_encode_op->s_ive_op.output_present = 0;
162
45.7k
    ps_video_encode_op->s_ive_op.dump_recon = 0;
163
45.7k
    ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
164
165
    /* Check for output memory allocation size */
166
45.7k
    {
167
45.7k
        UWORD32 u4_min_bufsize =
168
45.7k
            isvce_get_min_outbuf_size(ps_codec->s_cfg.u4_wd, ps_codec->s_cfg.u4_ht,
169
45.7k
                                      ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers);
170
45.7k
        UWORD32 u4_bufsize_per_layer = ps_video_encode_ip->s_ive_ip.s_out_buf.u4_bufsize /
171
45.7k
                                       ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
172
173
45.7k
        if(ps_video_encode_ip->s_ive_ip.s_out_buf.u4_bufsize < u4_min_bufsize)
174
36.0k
        {
175
36.0k
            error_status = IH264E_INSUFFICIENT_OUTPUT_BUFFER;
176
177
36.0k
            SET_ERROR_ON_RETURN(error_status, IVE_UNSUPPORTEDPARAM,
178
36.0k
                                ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
179
36.0k
        }
180
181
144k
        for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
182
98.3k
        {
183
98.3k
            s_out_buf.as_bits_buf[i] = ps_video_encode_ip->s_ive_ip.s_out_buf;
184
185
98.3k
            s_out_buf.as_bits_buf[i].u4_bufsize = u4_bufsize_per_layer;
186
98.3k
            s_out_buf.as_bits_buf[i].pv_buf =
187
98.3k
                ((UWORD8 *) ps_video_encode_ip->s_ive_ip.s_out_buf.pv_buf) +
188
98.3k
                u4_bufsize_per_layer * i;
189
98.3k
        }
190
45.7k
    }
191
192
0
    s_out_buf.u4_is_last = 0;
193
45.7k
    s_out_buf.u4_timestamp_low = ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
194
45.7k
    s_out_buf.u4_timestamp_high = ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
195
196
    /* api call cnt */
197
45.7k
    ps_codec->i4_encode_api_call_cnt += 1;
198
199
    /* codec context selector */
200
45.7k
    ctxt_sel = ps_codec->i4_encode_api_call_cnt % MAX_CTXT_SETS;
201
202
    /* reset status flags */
203
45.7k
    ps_codec->ai4_pic_cnt[ctxt_sel] = -1;
204
45.7k
    ps_codec->s_rate_control.post_encode_skip[ctxt_sel] = 0;
205
45.7k
    ps_codec->s_rate_control.pre_encode_skip[ctxt_sel] = 0;
206
207
    /* pass output buffer to codec */
208
45.7k
    ps_codec->as_out_buf[ctxt_sel] = s_out_buf;
209
210
    /* initialize codec ctxt with default params for the first encode api call */
211
45.7k
    if(ps_codec->i4_encode_api_call_cnt == 0)
212
10.2k
    {
213
10.2k
        error_status = isvce_codec_init(ps_codec);
214
215
10.2k
        SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
216
10.2k
                            ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
217
10.2k
    }
218
219
45.6k
    error_status =
220
45.6k
        isvce_svc_frame_params_validate(ps_codec->s_rate_control.apps_rate_control_api,
221
45.6k
                                        ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers);
222
45.6k
    SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR, ps_video_encode_op->s_ive_op.u4_error_code,
223
45.6k
                        IV_FAIL);
224
225
    /* parse configuration params */
226
1.44M
    for(i = 0; i < MAX_ACTIVE_CONFIG_PARAMS; i++)
227
1.39M
    {
228
1.39M
        isvce_cfg_params_t *ps_cfg = &ps_codec->as_cfg[i];
229
230
1.39M
        if(1 == ps_cfg->u4_is_valid)
231
89.1k
        {
232
89.1k
            if(((ps_cfg->u4_timestamp_high == ps_video_encode_ip->s_ive_ip.u4_timestamp_high) &&
233
89.1k
                (ps_cfg->u4_timestamp_low == ps_video_encode_ip->s_ive_ip.u4_timestamp_low)) ||
234
89.1k
               ((WORD32) ps_cfg->u4_timestamp_high == -1) ||
235
89.1k
               ((WORD32) ps_cfg->u4_timestamp_low == -1))
236
89.1k
            {
237
89.1k
                error_status = isvce_codec_update_config(ps_codec, ps_cfg);
238
89.1k
                SET_ERROR_ON_RETURN(error_status, IVE_UNSUPPORTEDPARAM,
239
89.1k
                                    ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
240
241
89.1k
                ps_cfg->u4_is_valid = 0;
242
89.1k
            }
243
89.1k
        }
244
1.39M
    }
245
    /* Force IDR based on SEI params */
246
43.6k
#if SEI_BASED_FORCE_IDR
247
43.6k
    {
248
43.6k
        sei_mdcv_params_t *ps_sei_mdcv_params = &ps_codec->s_sei.s_sei_mdcv_params;
249
43.6k
        sei_mdcv_params_t *ps_cfg_sei_mdcv_params = &ps_codec->s_cfg.s_sei.s_sei_mdcv_params;
250
43.6k
        sei_cll_params_t *ps_sei_cll_params = &ps_codec->s_sei.s_sei_cll_params;
251
43.6k
        sei_cll_params_t *ps_cfg_sei_cll_params = &ps_codec->s_cfg.s_sei.s_sei_cll_params;
252
43.6k
        sei_ave_params_t *ps_sei_ave_params = &ps_codec->s_sei.s_sei_ave_params;
253
43.6k
        sei_ave_params_t *ps_cfg_sei_ave_params = &ps_codec->s_cfg.s_sei.s_sei_ave_params;
254
255
43.6k
        if((ps_sei_mdcv_params->au2_display_primaries_x[0] !=
256
43.6k
            ps_cfg_sei_mdcv_params->au2_display_primaries_x[0]) ||
257
43.6k
           (ps_sei_mdcv_params->au2_display_primaries_x[1] !=
258
41.3k
            ps_cfg_sei_mdcv_params->au2_display_primaries_x[1]) ||
259
43.6k
           (ps_sei_mdcv_params->au2_display_primaries_x[2] !=
260
41.3k
            ps_cfg_sei_mdcv_params->au2_display_primaries_x[2]) ||
261
43.6k
           (ps_sei_mdcv_params->au2_display_primaries_y[0] !=
262
41.3k
            ps_cfg_sei_mdcv_params->au2_display_primaries_y[0]) ||
263
43.6k
           (ps_sei_mdcv_params->au2_display_primaries_y[1] !=
264
41.3k
            ps_cfg_sei_mdcv_params->au2_display_primaries_y[1]) ||
265
43.6k
           (ps_sei_mdcv_params->au2_display_primaries_y[2] !=
266
41.3k
            ps_cfg_sei_mdcv_params->au2_display_primaries_y[2]) ||
267
43.6k
           (ps_sei_mdcv_params->u2_white_point_x != ps_cfg_sei_mdcv_params->u2_white_point_x) ||
268
43.6k
           (ps_sei_mdcv_params->u2_white_point_y != ps_cfg_sei_mdcv_params->u2_white_point_y) ||
269
43.6k
           (ps_sei_mdcv_params->u4_max_display_mastering_luminance !=
270
41.3k
            ps_cfg_sei_mdcv_params->u4_max_display_mastering_luminance) ||
271
43.6k
           (ps_sei_mdcv_params->u4_min_display_mastering_luminance !=
272
41.3k
            ps_cfg_sei_mdcv_params->u4_min_display_mastering_luminance))
273
2.27k
        {
274
2.27k
            ps_codec->s_sei.s_sei_mdcv_params = ps_codec->s_cfg.s_sei.s_sei_mdcv_params;
275
2.27k
            ps_codec->s_sei.u1_sei_mdcv_params_present_flag = 1;
276
2.27k
        }
277
41.3k
        else
278
41.3k
        {
279
41.3k
            ps_codec->s_sei.u1_sei_mdcv_params_present_flag = 0;
280
41.3k
        }
281
282
43.6k
        if((ps_sei_cll_params->u2_max_content_light_level !=
283
43.6k
            ps_cfg_sei_cll_params->u2_max_content_light_level) ||
284
43.6k
           (ps_sei_cll_params->u2_max_pic_average_light_level !=
285
43.6k
            ps_cfg_sei_cll_params->u2_max_pic_average_light_level))
286
0
        {
287
0
            ps_codec->s_sei.s_sei_cll_params = ps_codec->s_cfg.s_sei.s_sei_cll_params;
288
0
            ps_codec->s_sei.u1_sei_cll_params_present_flag = 1;
289
0
        }
290
43.6k
        else
291
43.6k
        {
292
43.6k
            ps_codec->s_sei.u1_sei_cll_params_present_flag = 0;
293
43.6k
        }
294
295
43.6k
        if((ps_sei_ave_params->u4_ambient_illuminance !=
296
43.6k
            ps_cfg_sei_ave_params->u4_ambient_illuminance) ||
297
43.6k
           (ps_sei_ave_params->u2_ambient_light_x != ps_cfg_sei_ave_params->u2_ambient_light_x) ||
298
43.6k
           (ps_sei_ave_params->u2_ambient_light_y != ps_cfg_sei_ave_params->u2_ambient_light_y))
299
2.32k
        {
300
2.32k
            ps_codec->s_sei.s_sei_ave_params = ps_codec->s_cfg.s_sei.s_sei_ave_params;
301
2.32k
            ps_codec->s_sei.u1_sei_ave_params_present_flag = 1;
302
2.32k
        }
303
41.3k
        else
304
41.3k
        {
305
41.3k
            ps_codec->s_sei.u1_sei_ave_params_present_flag = 0;
306
41.3k
        }
307
308
43.6k
        if((1 == ps_codec->s_sei.u1_sei_mdcv_params_present_flag) ||
309
43.6k
           (1 == ps_codec->s_sei.u1_sei_cll_params_present_flag) ||
310
43.6k
           (1 == ps_codec->s_sei.u1_sei_ave_params_present_flag))
311
3.30k
        {
312
3.30k
            ps_codec->force_curr_frame_type = IV_IDR_FRAME;
313
3.30k
        }
314
43.6k
    }
315
43.6k
#endif
316
317
    /* In case of alt ref and B pics we will have non reference frame in stream */
318
43.6k
    if(ps_codec->s_cfg.u4_enable_alt_ref || ps_codec->s_cfg.u4_num_bframes)
319
0
    {
320
0
        ps_codec->i4_non_ref_frames_in_stream = 1;
321
0
    }
322
323
43.6k
    if(ps_codec->i4_encode_api_call_cnt == 0)
324
10.1k
    {
325
        /********************************************************************/
326
        /*   number of mv/ref bank buffers used by the codec,               */
327
        /*      1 to handle curr frame                                      */
328
        /*      1 to store information of ref frame                         */
329
        /*      1 more additional because of the codec employs 2 ctxt sets  */
330
        /*        to assist asynchronous API                                */
331
        /********************************************************************/
332
333
        /* initialize mv bank buffer manager */
334
10.1k
        error_status = isvce_svc_au_data_mgr_add_bufs(ps_codec);
335
336
10.1k
        SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
337
10.1k
                            ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
338
339
        /* initialize ref bank buffer manager */
340
10.1k
        error_status = isvce_svc_au_buf_mgr_add_bufs(ps_codec);
341
342
10.1k
        SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
343
10.1k
                            ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
344
345
        /* for the first frame, generate header when not requested explicitly */
346
10.1k
        if(ps_codec->i4_header_mode == 0 && ps_codec->u4_header_generated == 0)
347
0
        {
348
0
            ps_codec->i4_gen_header = 1;
349
0
        }
350
10.1k
    }
351
352
    /* generate header and return when encoder is operated in header mode */
353
43.6k
    if(ps_codec->i4_header_mode == 1)
354
5.14k
    {
355
        /* whenever the header is generated, this implies a start of sequence
356
         * and a sequence needs to be started with IDR
357
         */
358
5.14k
        ps_codec->force_curr_frame_type = IV_IDR_FRAME;
359
360
5.14k
        s_inp_buf.s_svc_params = ps_codec->s_cfg.s_svc_params;
361
5.14k
        s_inp_buf.s_inp_props.s_raw_buf = ps_video_encode_ip->s_ive_ip.s_inp_buf;
362
5.14k
        s_inp_buf.s_inp_props.s_raw_buf.au4_wd[Y] = ps_codec->s_cfg.u4_wd;
363
5.14k
        s_inp_buf.s_inp_props.s_raw_buf.au4_ht[Y] = ps_codec->s_cfg.u4_ht;
364
365
5.14k
        isvce_init_svc_dimension(&s_inp_buf);
366
367
        /* generate header */
368
5.14k
        error_status = isvce_generate_sps_pps(ps_codec, &s_inp_buf);
369
370
        /* send the input to app */
371
5.14k
        ps_video_encode_op->s_ive_op.s_inp_buf = ps_video_encode_ip->s_ive_ip.s_inp_buf;
372
5.14k
        ps_video_encode_op->s_ive_op.u4_timestamp_low =
373
5.14k
            ps_video_encode_ip->s_ive_ip.u4_timestamp_low;
374
5.14k
        ps_video_encode_op->s_ive_op.u4_timestamp_high =
375
5.14k
            ps_video_encode_ip->s_ive_ip.u4_timestamp_high;
376
377
5.14k
        ps_video_encode_op->s_ive_op.u4_is_last = ps_video_encode_ip->s_ive_ip.u4_is_last;
378
379
        /* send the output to app */
380
5.14k
        ps_video_encode_op->s_ive_op.output_present = 1;
381
5.14k
        ps_video_encode_op->s_ive_op.dump_recon = 0;
382
5.14k
        ps_video_encode_op->s_ive_op.s_out_buf = ps_codec->as_out_buf[ctxt_sel].as_bits_buf[0];
383
384
11.8k
        for(i = 1; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
385
6.72k
        {
386
6.72k
            memmove(((UWORD8 *) ps_video_encode_op->s_ive_op.s_out_buf.pv_buf +
387
6.72k
                     ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes),
388
6.72k
                    ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].pv_buf,
389
6.72k
                    ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes);
390
391
6.72k
            ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes +=
392
6.72k
                ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes;
393
6.72k
        }
394
395
        /* error status */
396
5.14k
        SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
397
5.14k
                            ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
398
399
        /* indicates that header has been generated previously */
400
5.14k
        ps_codec->u4_header_generated = 1;
401
402
        /* api call cnt */
403
5.14k
        ps_codec->i4_encode_api_call_cnt--;
404
405
        /* header mode tag is not sticky */
406
5.14k
        ps_codec->i4_header_mode = 0;
407
5.14k
        ps_codec->i4_gen_header = 0;
408
409
5.14k
        return IV_SUCCESS;
410
5.14k
    }
411
412
    /* curr pic cnt */
413
38.5k
    ps_codec->i4_pic_cnt += 1;
414
415
38.5k
    i4_rc_pre_enc_skip = 0;
416
121k
    for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
417
82.8k
    {
418
82.8k
        i4_rc_pre_enc_skip =
419
82.8k
            isvce_input_queue_update(ps_codec, &ps_video_encode_ip->s_ive_ip, &s_inp_buf, i);
420
82.8k
    }
421
422
38.5k
    s_out_buf.u4_is_last = s_inp_buf.s_inp_props.u4_is_last;
423
38.5k
    ps_video_encode_op->s_ive_op.u4_is_last = s_inp_buf.s_inp_props.u4_is_last;
424
425
    /* Only encode if the current frame is not pre-encode skip */
426
38.5k
    if(!i4_rc_pre_enc_skip && s_inp_buf.s_inp_props.s_raw_buf.apv_bufs[0])
427
31.5k
    {
428
31.5k
        isvce_process_ctxt_t *ps_proc = &ps_codec->as_process[ctxt_sel * MAX_PROCESS_THREADS];
429
430
31.5k
        WORD32 num_thread_cnt = ps_codec->s_cfg.u4_num_cores - 1;
431
432
31.5k
        ps_codec->ai4_pic_cnt[ctxt_sel] = ps_codec->i4_pic_cnt;
433
434
31.5k
        error_status = isvce_svc_au_init(ps_codec, &s_inp_buf);
435
436
31.5k
        SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
437
31.5k
                            ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
438
439
30.1k
        isvce_nalu_info_au_init(ps_codec->as_nalu_descriptors,
440
30.1k
                                ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers);
441
442
#if ENABLE_MODE_STAT_VISUALISER
443
        isvce_msv_get_input_frame(ps_codec->ps_mode_stat_visualiser, &s_inp_buf);
444
#endif
445
446
95.3k
        for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
447
65.1k
        {
448
65.1k
            isvce_svc_layer_pic_init(ps_codec, &s_inp_buf, i);
449
450
152k
            for(j = 0; j < num_thread_cnt; j++)
451
87.5k
            {
452
87.5k
                ithread_create(ps_codec->apv_proc_thread_handle[j], NULL, isvce_process_thread,
453
87.5k
                               &ps_codec->as_process[j + 1]);
454
455
87.5k
                ps_codec->ai4_process_thread_created[j] = 1;
456
457
87.5k
                ps_codec->i4_proc_thread_cnt++;
458
87.5k
            }
459
460
            /* launch job */
461
65.1k
            isvce_process_thread(ps_proc);
462
463
            /* Join threads at the end of encoding a frame */
464
65.1k
            isvce_join_threads(ps_codec);
465
466
65.1k
            ih264_list_reset(ps_codec->pv_proc_jobq);
467
468
65.1k
            ih264_list_reset(ps_codec->pv_entropy_jobq);
469
65.1k
        }
470
471
#if ENABLE_MODE_STAT_VISUALISER
472
        isvce_msv_dump_visualisation(ps_codec->ps_mode_stat_visualiser);
473
#endif
474
475
30.1k
        isvce_sub_pic_rc_dump_data(ps_codec->as_process->ps_sub_pic_rc_ctxt);
476
30.1k
    }
477
478
    /****************************************************************************
479
     * RECON
480
     *    Since we have forward dependent frames, we cannot return recon in
481
     *encoding order. It must be in poc order, or input pic order. To achieve this
482
     *we introduce a delay of 1 to the recon wrt encode. Now since we have that
483
     *    delay, at any point minimum of pic_cnt in our ref buffer will be the
484
     *    correct frame. For ex let our GOP be IBBP [1 2 3 4] . The encode order
485
     *    will be [1 4 2 3] .Now since we have a delay of 1, when we are done with
486
     *    encoding 4, the min in the list will be 1. After encoding 2, it will be
487
     *    2, 3 after 3 and 4 after 4. Hence we can return in sequence. Note
488
     *    that the 1 delay is critical. Hence if we have post enc skip, we must
489
     *    skip here too. Note that since post enc skip already frees the recon
490
     *    buffer we need not do any thing here
491
     *
492
     *    We need to return a recon when ever we consume an input buffer. This
493
     *    comsumption include a pre or post enc skip. Thus dump recon is set for
494
     *    all cases except when
495
     *    1) We are waiting -> ps_codec->i4_pic_cnt >
496
     *ps_codec->s_cfg.u4_num_bframe An exception need to be made for the case when
497
     *we have the last buffer since we need to flush out the on remainig recon.
498
     ****************************************************************************/
499
500
37.0k
    ps_video_encode_op->s_ive_op.dump_recon = 0;
501
502
37.0k
    if(ps_codec->s_cfg.u4_enable_recon &&
503
37.0k
       ((ps_codec->i4_pic_cnt > (WORD32) ps_codec->s_cfg.u4_num_bframes) ||
504
8.38k
        s_inp_buf.s_inp_props.u4_is_last))
505
6.43k
    {
506
        /* error status */
507
6.43k
        IH264_ERROR_T ret = IH264_SUCCESS;
508
509
6.43k
        svc_au_buf_t *ps_pic_buf = NULL;
510
511
6.43k
        WORD32 i4_buf_status, i4_curr_poc = 32768;
512
513
        /* In case of skips we return recon, but indicate that buffer is zero size
514
         */
515
6.43k
        if(ps_codec->s_rate_control.post_encode_skip[ctxt_sel] || i4_rc_pre_enc_skip)
516
78
        {
517
78
            ps_video_encode_op->s_ive_op.dump_recon = 1;
518
78
            ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[0] = 0;
519
78
            ps_video_encode_op->s_ive_op.s_recon_buf.au4_wd[1] = 0;
520
78
        }
521
6.35k
        else
522
6.35k
        {
523
38.5k
            for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
524
32.1k
            {
525
32.1k
                if(ps_codec->as_ref_set[i].i4_pic_cnt == -1) continue;
526
527
16.0k
                i4_buf_status = ih264_buf_mgr_get_status(
528
16.0k
                    ps_codec->pv_ref_buf_mgr, ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
529
530
16.0k
                if((i4_buf_status & BUF_MGR_IO) && (ps_codec->as_ref_set[i].i4_poc < i4_curr_poc))
531
12.9k
                {
532
12.9k
                    ps_pic_buf = ps_codec->as_ref_set[i].ps_pic_buf;
533
12.9k
                    i4_curr_poc = ps_codec->as_ref_set[i].i4_poc;
534
12.9k
                }
535
16.0k
            }
536
537
6.35k
            ps_video_encode_op->s_ive_op.s_recon_buf = ps_video_encode_ip->s_ive_ip.s_recon_buf;
538
539
            /*
540
             * If we get a valid buffer. output and free recon.
541
             *
542
             * we may get an invalid buffer if num_b_frames is 0. This is because
543
             * We assume that there will be a ref frame in ref list after encoding
544
             * the last frame. With B frames this is correct since its forward ref
545
             * pic will be in the ref list. But if num_b_frames is 0, we will not
546
             * have a forward ref pic
547
             */
548
549
6.35k
            if(ps_pic_buf)
550
6.00k
            {
551
6.00k
                if((ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[Y] !=
552
6.00k
                    ps_codec->s_cfg.u4_disp_wd) ||
553
6.00k
                   (ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_ht[Y] !=
554
3.04k
                    ps_codec->s_cfg.u4_disp_ht))
555
3.97k
                {
556
3.97k
                    SET_ERROR_ON_RETURN(IH264E_NO_FREE_RECONBUF, IVE_FATALERROR,
557
3.97k
                                        ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
558
0
                }
559
560
2.02k
                isvce_fmt_conv(ps_codec, ps_pic_buf,
561
2.02k
                               ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[0],
562
2.02k
                               ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[1],
563
2.02k
                               ps_video_encode_ip->s_ive_ip.s_recon_buf.apv_bufs[2],
564
2.02k
                               ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[0],
565
2.02k
                               ps_video_encode_ip->s_ive_ip.s_recon_buf.au4_wd[1], 0,
566
2.02k
                               ps_codec->s_cfg.u4_disp_ht);
567
568
2.02k
                ps_video_encode_op->s_ive_op.dump_recon = 1;
569
570
2.02k
                ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_pic_buf->i4_buf_id,
571
2.02k
                                            BUF_MGR_IO);
572
573
2.02k
                if(IH264_SUCCESS != ret)
574
0
                {
575
0
                    SET_ERROR_ON_RETURN((IH264E_ERROR_T) ret, IVE_FATALERROR,
576
0
                                        ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
577
0
                }
578
2.02k
            }
579
6.35k
        }
580
6.43k
    }
581
582
    /***************************************************************************
583
     * Free reference buffers:
584
     * In case of a post enc skip, we have to ensure that those pics will not
585
     * be used as reference anymore. In all other cases we will not even mark
586
     * the ref buffers
587
     ***************************************************************************/
588
33.1k
    if(ps_codec->s_rate_control.post_encode_skip[ctxt_sel])
589
0
    {
590
        /* pic info */
591
0
        svc_au_buf_t *ps_cur_pic;
592
593
        /* mv info */
594
0
        svc_au_data_t *ps_cur_mv_buf;
595
596
        /* error status */
597
0
        IH264_ERROR_T ret = IH264_SUCCESS;
598
599
        /* Decrement coded pic count */
600
0
        ps_codec->i4_poc--;
601
602
        /* loop through to get the min pic cnt among the list of pics stored in ref
603
         * list */
604
        /* since the skipped frame may not be on reference list, we may not have an
605
         * MV bank hence free only if we have allocated */
606
0
        for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
607
0
        {
608
0
            if(ps_codec->i4_pic_cnt == ps_codec->as_ref_set[i].i4_pic_cnt)
609
0
            {
610
0
                ps_cur_pic = ps_codec->as_ref_set[i].ps_pic_buf;
611
612
0
                ps_cur_mv_buf = ps_codec->as_ref_set[i].ps_svc_au_data;
613
614
                /* release this frame from reference list and recon list */
615
0
                ret = ih264_buf_mgr_release(ps_codec->pv_svc_au_data_store_mgr,
616
0
                                            ps_cur_mv_buf->i4_buf_id, BUF_MGR_REF);
617
0
                ret |= ih264_buf_mgr_release(ps_codec->pv_svc_au_data_store_mgr,
618
0
                                             ps_cur_mv_buf->i4_buf_id, BUF_MGR_IO);
619
0
                SET_ERROR_ON_RETURN((IH264E_ERROR_T) ret, IVE_FATALERROR,
620
0
                                    ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
621
622
0
                ret = ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id,
623
0
                                            BUF_MGR_REF);
624
0
                ret |= ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr, ps_cur_pic->i4_buf_id,
625
0
                                             BUF_MGR_IO);
626
0
                SET_ERROR_ON_RETURN((IH264E_ERROR_T) ret, IVE_FATALERROR,
627
0
                                    ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
628
0
                break;
629
0
            }
630
0
        }
631
0
    }
632
633
    /*
634
     * Since recon is not in sync with output, ie there can be frame to be
635
     * given back as recon even after last output. Hence we need to mark that
636
     * the output is not the last.
637
     * Hence search through reflist and mark appropriately
638
     */
639
33.1k
    if(ps_codec->s_cfg.u4_enable_recon)
640
4.41k
    {
641
4.41k
        WORD32 i4_buf_status = 0;
642
643
26.1k
        for(i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
644
21.7k
        {
645
21.7k
            if(ps_codec->as_ref_set[i].i4_pic_cnt == -1) continue;
646
647
6.97k
            i4_buf_status |= ih264_buf_mgr_get_status(
648
6.97k
                ps_codec->pv_ref_buf_mgr, ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
649
6.97k
        }
650
651
4.41k
        if(i4_buf_status & BUF_MGR_IO)
652
3.16k
        {
653
3.16k
            s_out_buf.u4_is_last = 0;
654
3.16k
            ps_video_encode_op->s_ive_op.u4_is_last = 0;
655
3.16k
        }
656
4.41k
    }
657
658
    /**************************************************************************
659
     * Signaling to APP
660
     *  1) If we valid a valid output mark it so
661
     *  2) Set the codec output ps_video_encode_op
662
     *  3) Set the error status
663
     *  4) Set the return Pic type
664
     *      Note that we already has marked recon properly
665
     *  5)Send the consumed input back to app so that it can free it if possible
666
     *
667
     *  We will have to return the output and input buffers unconditionally
668
     *  so that app can release them
669
     **************************************************************************/
670
33.1k
    if(!i4_rc_pre_enc_skip && !ps_codec->s_rate_control.post_encode_skip[ctxt_sel] &&
671
33.1k
       s_inp_buf.s_inp_props.s_raw_buf.apv_bufs[0])
672
28.4k
    {
673
        /* receive output back from codec */
674
28.4k
        s_out_buf = ps_codec->as_out_buf[ctxt_sel];
675
676
        /* send the output to app */
677
28.4k
        ps_video_encode_op->s_ive_op.output_present = 1;
678
28.4k
        ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
679
680
        /* Set the time stamps of the encodec input */
681
28.4k
        ps_video_encode_op->s_ive_op.u4_timestamp_low = s_inp_buf.s_inp_props.u4_timestamp_low;
682
28.4k
        ps_video_encode_op->s_ive_op.u4_timestamp_high = s_inp_buf.s_inp_props.u4_timestamp_high;
683
684
28.4k
        switch(ps_codec->pic_type)
685
28.4k
        {
686
8.51k
            case PIC_IDR:
687
8.51k
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_IDR_FRAME;
688
8.51k
                break;
689
690
1.56k
            case PIC_I:
691
1.56k
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_I_FRAME;
692
1.56k
                break;
693
694
18.3k
            case PIC_P:
695
18.3k
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_P_FRAME;
696
18.3k
                break;
697
698
0
            case PIC_B:
699
0
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_B_FRAME;
700
0
                break;
701
702
0
            default:
703
0
                ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
704
0
                break;
705
28.4k
        }
706
707
91.6k
        for(i = 0; i < (WORD32) ps_codec->s_cfg.u4_num_cores; i++)
708
64.7k
        {
709
64.7k
            error_status = ps_codec->as_process[ctxt_sel + i].i4_error_code;
710
64.7k
            SET_ERROR_ON_RETURN(error_status, IVE_FATALERROR,
711
64.7k
                                ps_video_encode_op->s_ive_op.u4_error_code, IV_FAIL);
712
63.2k
        }
713
28.4k
    }
714
4.65k
    else
715
4.65k
    {
716
        /* receive output back from codec */
717
4.65k
        s_out_buf = ps_codec->as_out_buf[ctxt_sel];
718
719
4.65k
        ps_video_encode_op->s_ive_op.output_present = 0;
720
4.65k
        ps_video_encode_op->s_ive_op.u4_error_code = IV_SUCCESS;
721
722
        /* Set the time stamps of the encodec input */
723
4.65k
        ps_video_encode_op->s_ive_op.u4_timestamp_low = 0;
724
4.65k
        ps_video_encode_op->s_ive_op.u4_timestamp_high = 0;
725
726
4.65k
        ps_video_encode_op->s_ive_op.s_inp_buf = s_inp_buf.s_inp_props.s_raw_buf;
727
728
4.65k
        ps_video_encode_op->s_ive_op.u4_encoded_frame_type = IV_NA_FRAME;
729
4.65k
    }
730
731
    /* Send the input to encoder so that it can free it if possible */
732
31.5k
    ps_video_encode_op->s_ive_op.s_out_buf = ps_codec->as_out_buf[ctxt_sel].as_bits_buf[0];
733
734
67.8k
    for(i = 1; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
735
36.3k
    {
736
36.3k
        memmove(((UWORD8 *) ps_video_encode_op->s_ive_op.s_out_buf.pv_buf +
737
36.3k
                 ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes),
738
36.3k
                ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].pv_buf,
739
36.3k
                ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes);
740
741
36.3k
        ps_video_encode_op->s_ive_op.s_out_buf.u4_bytes +=
742
36.3k
            ps_codec->as_out_buf[ctxt_sel].as_bits_buf[i].u4_bytes;
743
36.3k
    }
744
745
31.5k
    if(ps_codec->s_cfg.b_nalu_info_export_enable && !i4_rc_pre_enc_skip &&
746
31.5k
       !ps_codec->s_rate_control.post_encode_skip[ctxt_sel] &&
747
31.5k
       s_inp_buf.s_inp_props.s_raw_buf.apv_bufs[0])
748
8.12k
    {
749
8.12k
        ps_video_encode_op->b_is_nalu_info_present = true;
750
751
27.5k
        for(i = 0; i < ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; i++)
752
19.3k
        {
753
19.3k
            isvce_nalu_info_csv_translator(&ps_codec->as_nalu_descriptors[i],
754
19.3k
                                           &ps_video_encode_ip->ps_nalu_info_buf[i]);
755
756
19.3k
            ps_video_encode_op->ps_nalu_info_buf[i] = ps_video_encode_ip->ps_nalu_info_buf[i];
757
19.3k
        }
758
8.12k
    }
759
23.4k
    else
760
23.4k
    {
761
23.4k
        ps_video_encode_op->b_is_nalu_info_present = false;
762
23.4k
    }
763
764
31.5k
    ps_video_encode_op->s_ive_op.s_inp_buf = s_inp_buf.s_inp_props.s_raw_buf;
765
766
31.5k
    return IV_SUCCESS;
767
33.1k
}