/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 | } |