/work/svt-av1/Source/Lib/Globals/enc_settings.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright(c) 2022 Intel Corporation |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 3-Clause Clear License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at https://www.aomedia.org/license. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license. |
10 | | */ |
11 | | // SUMMARY |
12 | | // Contains the encoder settings API functions |
13 | | |
14 | | /************************************** |
15 | | * Includes |
16 | | **************************************/ |
17 | | #include <stdbool.h> |
18 | | #include <stdlib.h> |
19 | | #include <stdio.h> |
20 | | #include <stdint.h> |
21 | | #include "EbVersion.h" |
22 | | #include "definitions.h" |
23 | | #include "EbSvtAv1Enc.h" |
24 | | #include "EbSvtAv1Metadata.h" |
25 | | #include "enc_settings.h" |
26 | | #include "entropy_coding.h" |
27 | | |
28 | | #include "svt_log.h" |
29 | | #include "utility.h" |
30 | | |
31 | | #ifdef _WIN32 |
32 | | #include <windows.h> |
33 | | #else |
34 | | #include <errno.h> |
35 | | #include <pthread.h> |
36 | | #include <unistd.h> |
37 | | #endif |
38 | | |
39 | | /****************************************** |
40 | | * Verify Settings |
41 | | ******************************************/ |
42 | 430 | EbErrorType svt_av1_verify_settings(SequenceControlSet* scs) { |
43 | 430 | EbErrorType return_error = EB_ErrorNone; |
44 | 430 | EbSvtAv1EncConfiguration* config = &scs->static_config; |
45 | 430 | if (config->enc_mode > MAX_ENC_PRESET || config->enc_mode < MIN_ENC_PRESET) { |
46 | 0 | SVT_ERROR("EncoderMode must be in the range of [%d-%d]\n", MIN_ENC_PRESET, MAX_ENC_PRESET); |
47 | 0 | return_error = EB_ErrorBadParameter; |
48 | 0 | } |
49 | 430 | if (scs->max_input_luma_width < 1) { |
50 | 0 | SVT_ERROR("Source Width must be at least 1\n"); |
51 | 0 | return_error = EB_ErrorBadParameter; |
52 | 0 | } |
53 | 430 | if (scs->max_input_luma_height < 1) { |
54 | 0 | SVT_ERROR("Source Height must be at least 1\n"); |
55 | 0 | return_error = EB_ErrorBadParameter; |
56 | 0 | } |
57 | 430 | if (config->pred_structure > RANDOM_ACCESS) { |
58 | 0 | SVT_ERROR("Pred Structure must be [%d (ALL_INTRA), %d (LOW_DELAY), or %d (RANDOM_ACCESS)]\n", |
59 | 0 | ALL_INTRA, |
60 | 0 | LOW_DELAY, |
61 | 0 | RANDOM_ACCESS); |
62 | 0 | return_error = EB_ErrorBadParameter; |
63 | 0 | } |
64 | 430 | if (config->pred_structure == LOW_DELAY && config->pass > 0) { |
65 | 0 | SVT_ERROR("Multi-passes is not support with Low Delay mode \n"); |
66 | 0 | return_error = EB_ErrorBadParameter; |
67 | 0 | } |
68 | 430 | if (config->maximum_buffer_size_ms < 20 || config->maximum_buffer_size_ms > 10000) { |
69 | 0 | SVT_ERROR("The maximum buffer size must be between [20, 10000]\n"); |
70 | 0 | return_error = EB_ErrorBadParameter; |
71 | 0 | } |
72 | | |
73 | 430 | if (config->starting_buffer_level_ms < 20 || config->starting_buffer_level_ms > 10000) { |
74 | 0 | SVT_ERROR("The initial buffer size must be between [20, 10000] \n"); |
75 | 0 | return_error = EB_ErrorBadParameter; |
76 | 430 | } else if (config->starting_buffer_level_ms >= config->maximum_buffer_size_ms) { |
77 | 0 | SVT_WARN( |
78 | 0 | "The initial buffer size must be less than maximum buffer size. Defaulting optimal " |
79 | 0 | "buffer size to maximum buffer size - 1 (%u)\n", |
80 | 0 | config->maximum_buffer_size_ms - 1); |
81 | 0 | config->starting_buffer_level_ms = (config->maximum_buffer_size_ms - 1); |
82 | 0 | } |
83 | | |
84 | 430 | if (config->optimal_buffer_level_ms < 20 || config->optimal_buffer_level_ms > 10000) { |
85 | 0 | SVT_ERROR("The optimal buffer size must be between [20, 10000]\n"); |
86 | 0 | return_error = EB_ErrorBadParameter; |
87 | 430 | } else if (config->optimal_buffer_level_ms >= config->maximum_buffer_size_ms) { |
88 | 0 | SVT_WARN( |
89 | 0 | "The optimal buffer size must be less than maximum buffer size. Defaulting optimal " |
90 | 0 | "buffer size to maximum buffer size - 1 (%u)\n", |
91 | 0 | config->maximum_buffer_size_ms - 1); |
92 | 0 | config->optimal_buffer_level_ms = (config->maximum_buffer_size_ms - 1); |
93 | 0 | } |
94 | | |
95 | 430 | if (config->over_shoot_pct > 100) { |
96 | 0 | SVT_ERROR("The overshoot percentage must be between [0, 100] \n"); |
97 | 0 | return_error = EB_ErrorBadParameter; |
98 | 0 | } |
99 | | |
100 | 430 | if (config->mbr_over_shoot_pct > 100) { |
101 | 0 | SVT_ERROR("The max bitrate overshoot percentage must be between [0, 100] \n"); |
102 | 0 | return_error = EB_ErrorBadParameter; |
103 | 0 | } |
104 | | |
105 | 430 | if (config->under_shoot_pct > 100) { |
106 | 0 | SVT_ERROR("The undershoot percentage must be between [0, 100] \n"); |
107 | 0 | return_error = EB_ErrorBadParameter; |
108 | 0 | } |
109 | | |
110 | 430 | if (config->target_bit_rate > 100000000) { |
111 | 0 | SVT_ERROR("The target bit rate must be between [0, 100000] kbps \n"); |
112 | 0 | return_error = EB_ErrorBadParameter; |
113 | 0 | } |
114 | 430 | if (config->max_bit_rate > 100000000) { |
115 | 0 | SVT_ERROR("The maximum bit rate must be between [0, 100000] kbps \n"); |
116 | 0 | return_error = EB_ErrorBadParameter; |
117 | 0 | } |
118 | 430 | if (config->vbr_max_section_pct > 10000) { |
119 | 0 | SVT_ERROR("The max section percentage must be between [0, 10000] \n"); |
120 | 0 | return_error = EB_ErrorBadParameter; |
121 | 0 | } |
122 | | |
123 | 430 | if (config->vbr_min_section_pct > 100) { |
124 | 0 | SVT_ERROR("he min section percentage must be between [0, 100] \n"); |
125 | 0 | return_error = EB_ErrorBadParameter; |
126 | 0 | } |
127 | 430 | if (config->gop_constraint_rc && |
128 | 0 | ((config->rate_control_mode != SVT_AV1_RC_MODE_VBR) || config->intra_period_length < 119)) { |
129 | 0 | SVT_ERROR( |
130 | 0 | "Gop constraint rc is only supported with VBR mode when Gop size is " |
131 | 0 | "greater than 119 \n"); |
132 | 0 | return_error = EB_ErrorBadParameter; |
133 | 0 | } |
134 | 430 | if (config->gop_constraint_rc) { |
135 | 0 | SVT_WARN( |
136 | 0 | "The GoP constraint RC mode is a work-in-progress project, and is only " |
137 | 0 | "available for demos, experimentation, and further development uses and should not be " |
138 | 0 | "used for benchmarking until fully implemented.\n"); |
139 | 0 | } |
140 | | |
141 | 430 | if (config->force_key_frames && |
142 | 0 | (config->rate_control_mode == SVT_AV1_RC_MODE_CBR || config->pred_structure == LOW_DELAY)) { |
143 | 0 | SVT_WARN( |
144 | 0 | "Force key frames is now supported for lowdelay but the force_key_frames flag" |
145 | 0 | " does not need to be set be on. Please follow the app samples shown by the FTR_KF_ON_FLY_SAMPLE" |
146 | 0 | " macro on how to use it. force_key_frames will now be set to 0 \n"); |
147 | 0 | config->force_key_frames = 0; |
148 | 0 | } |
149 | 430 | if (config->force_key_frames && config->rate_control_mode == SVT_AV1_RC_MODE_VBR) { |
150 | 0 | SVT_ERROR("Force key frames is not supported for VBR mode \n"); |
151 | 0 | return_error = EB_ErrorBadParameter; |
152 | 0 | } |
153 | 430 | if (config->rate_control_mode != SVT_AV1_RC_MODE_CQP_OR_CRF && (config->max_bit_rate != 0)) { |
154 | 0 | SVT_ERROR("Max Bitrate only supported with CRF mode\n"); |
155 | 0 | return_error = EB_ErrorBadParameter; |
156 | 0 | } |
157 | 430 | if (config->rate_control_mode == SVT_AV1_RC_MODE_CBR && config->pred_structure != LOW_DELAY) { |
158 | 0 | SVT_ERROR("CBR Rate control is currently not supported for RANDOM_ACCESS/ALL_INTRA, use VBR mode\n"); |
159 | 0 | return_error = EB_ErrorBadParameter; |
160 | 0 | } |
161 | | // Ref-frame management validation: ABI cap + LD-CBR-only when enabled. |
162 | 430 | if (config->max_managed_refs > 4) { |
163 | 0 | SVT_ERROR("max_managed_refs must be in [0, 4] (got %u)\n", (unsigned)config->max_managed_refs); |
164 | 0 | return_error = EB_ErrorBadParameter; |
165 | 0 | } |
166 | 430 | if (config->max_managed_refs > 0 && config->pred_structure != LOW_DELAY) { |
167 | 0 | SVT_ERROR("max_managed_refs > 0 requires pred_structure == LOW_DELAY\n"); |
168 | 0 | return_error = EB_ErrorBadParameter; |
169 | 0 | } |
170 | 430 | if (config->max_managed_refs > 0 && config->rate_control_mode != SVT_AV1_RC_MODE_CBR) { |
171 | | // Only LD-CBR is implemented; LD-CRF's shifted lay1_offset would |
172 | | // collide with the STORE-safe slot pool. See pd_process.c. |
173 | 0 | SVT_ERROR("max_managed_refs > 0 requires rate_control_mode == CBR (got %u)\n", |
174 | 0 | (unsigned)config->rate_control_mode); |
175 | 0 | return_error = EB_ErrorBadParameter; |
176 | 0 | } |
177 | 430 | if (config->rate_control_mode == SVT_AV1_RC_MODE_VBR && config->pred_structure == LOW_DELAY) { |
178 | 0 | SVT_ERROR("VBR Rate control is currently not supported for LOW_DELAY, use CBR mode\n"); |
179 | 0 | return_error = EB_ErrorBadParameter; |
180 | 0 | } |
181 | 430 | if (config->rate_control_mode == SVT_AV1_RC_MODE_CQP_OR_CRF && config->target_bit_rate != DEFAULT_TBR) { |
182 | 0 | SVT_ERROR("Target Bitrate only supported when --rc is 1/2 (VBR/CBR). Current --rc: %d\n", |
183 | 0 | config->rate_control_mode); |
184 | 0 | return_error = EB_ErrorBadParameter; |
185 | 0 | } |
186 | | |
187 | 430 | if (scs->max_input_luma_width > 16384) { |
188 | 0 | SVT_ERROR("Source Width must be less than or equal to 16384\n"); |
189 | 0 | return_error = EB_ErrorBadParameter; |
190 | 0 | } |
191 | | |
192 | 430 | if (scs->max_input_luma_height > 8704) { |
193 | 0 | SVT_ERROR("Source Height must be less than or equal to 8704)\n"); |
194 | 0 | return_error = EB_ErrorBadParameter; |
195 | 0 | } |
196 | | |
197 | 430 | if (scs->seq_header.max_frame_width < 1) { |
198 | 0 | SVT_ERROR("Forced Max Width must be at least 1\n"); |
199 | 0 | return_error = EB_ErrorBadParameter; |
200 | 0 | } |
201 | 430 | if (scs->seq_header.max_frame_height < 1) { |
202 | 0 | SVT_ERROR("Forced Max Height must be at least 1\n"); |
203 | 0 | return_error = EB_ErrorBadParameter; |
204 | 0 | } |
205 | 430 | if (scs->seq_header.max_frame_width > 16384) { |
206 | 0 | SVT_ERROR("Forced Max Width must be less than or equal to 16384\n"); |
207 | 0 | return_error = EB_ErrorBadParameter; |
208 | 0 | } |
209 | 430 | if (scs->seq_header.max_frame_height > 8704) { |
210 | 0 | SVT_ERROR("Forced Max Height must be less than or equal to 8704)\n"); |
211 | 0 | return_error = EB_ErrorBadParameter; |
212 | 0 | } |
213 | | |
214 | | // This is not an AV1 spec limitation, but an implementation limitation in the encoder |
215 | | // This check will stay in place until restoration filtering can handle these dimensions |
216 | 430 | if ((scs->max_input_luma_width >= 1 && scs->max_input_luma_width < 64) || |
217 | 430 | (scs->max_input_luma_height >= 1 && scs->max_input_luma_height < 64)) { |
218 | 0 | if (config->aq_mode != 0) { |
219 | 0 | SVT_WARN("AQ mode %i is unsupported with source dimensions (%i / %i), setting AQ mode to 0\n", |
220 | 0 | config->aq_mode, |
221 | 0 | scs->max_input_luma_width, |
222 | 0 | scs->max_input_luma_height); |
223 | 0 | config->aq_mode = 0; |
224 | 0 | } |
225 | 0 | if (config->enable_restoration_filtering != 0) { |
226 | 0 | SVT_WARN( |
227 | 0 | "Restoration Filtering is unsupported with source dimensions (%i / %i), disabling " |
228 | 0 | "Restoration Filtering\n", |
229 | 0 | scs->max_input_luma_width, |
230 | 0 | scs->max_input_luma_height); |
231 | 0 | config->enable_restoration_filtering = 0; |
232 | 0 | } |
233 | 0 | } |
234 | | |
235 | 430 | if ((scs->max_input_luma_width > scs->seq_header.max_frame_width) || |
236 | 430 | (scs->max_input_luma_height > scs->seq_header.max_frame_height)) { |
237 | 0 | SVT_ERROR( |
238 | 0 | "Source Width/Height must be less than or equal to Forced Max " |
239 | 0 | "Width/Height\n"); |
240 | 0 | return_error = EB_ErrorBadParameter; |
241 | 0 | } |
242 | | |
243 | 430 | if (config->level != 0) { |
244 | 0 | BitstreamLevel bl; |
245 | 0 | bl.major = config->level / 10; |
246 | 0 | bl.minor = config->level % 10; |
247 | | // Defined AV1 levels only have major versions 2-9 and minor versions 0-3 |
248 | 0 | if (bl.minor > LEVEL_MINOR_MAX || bl.major < LEVEL_MAJOR_MIN || bl.major > LEVEL_MAJOR_MAX) { |
249 | 0 | SVT_ERROR("Invalid or undefined level specified: %d.%d. See AV1 spec Annex A for defined levels.\n", |
250 | 0 | bl.major, |
251 | 0 | bl.minor); |
252 | 0 | return_error = EB_ErrorBadParameter; |
253 | 0 | } else { |
254 | | // Some levels in the allowable range are undefined by the spec. |
255 | 0 | const uint8_t seq_level_idx = major_minor_to_seq_level_idx(bl); |
256 | 0 | if (!is_valid_seq_level_idx(seq_level_idx)) { |
257 | 0 | SVT_ERROR("Invalid or undefined level specified: %d.%d. See AV1 spec Annex A for defined levels.\n", |
258 | 0 | bl.major, |
259 | 0 | bl.minor); |
260 | 0 | return_error = EB_ErrorBadParameter; |
261 | 0 | } |
262 | 0 | } |
263 | 0 | } |
264 | | |
265 | 430 | if (config->qp > MAX_QP_VALUE) { |
266 | 0 | SVT_ERROR("%s must be [0 - %d]\n", config->aq_mode ? "CRF" : "QP", MAX_QP_VALUE); |
267 | 0 | return_error = EB_ErrorBadParameter; |
268 | 0 | } |
269 | | |
270 | 430 | if ((config->qp == MAX_QP_VALUE && config->extended_crf_qindex_offset > (7 * 4))) { |
271 | 0 | SVT_ERROR("%s must be [0 - %d]\n", "CRF", 70); |
272 | 0 | return_error = EB_ErrorBadParameter; |
273 | 0 | } |
274 | | |
275 | 430 | if (config->hierarchical_levels > 5) { |
276 | 0 | #if OPT_USE_HL0_FLAT |
277 | 0 | SVT_ERROR("Hierarchical Levels supported: [0-5]\n"); |
278 | | #else |
279 | | SVT_ERROR("Hierarchical Levels supported [0-5]\n"); |
280 | | #endif |
281 | 0 | return_error = EB_ErrorBadParameter; |
282 | 0 | } |
283 | 430 | if ((config->intra_period_length < -2 || config->intra_period_length > 2 * ((1 << 30) - 1)) && |
284 | 0 | config->rate_control_mode == SVT_AV1_RC_MODE_CQP_OR_CRF) { |
285 | 0 | SVT_ERROR("The intra period must be [-2, 2^31-2]\n"); |
286 | 0 | return_error = EB_ErrorBadParameter; |
287 | 0 | } |
288 | 430 | if ((config->intra_period_length < 0) && config->rate_control_mode == SVT_AV1_RC_MODE_VBR) { |
289 | 0 | SVT_ERROR("The intra period must be > 0 for RateControlMode %d\n", config->rate_control_mode); |
290 | 0 | return_error = EB_ErrorBadParameter; |
291 | 0 | } |
292 | | |
293 | 430 | if (config->intra_refresh_type > 2 || config->intra_refresh_type < 1) { |
294 | 0 | SVT_ERROR("Invalid intra Refresh Type [1-2]\n"); |
295 | 0 | return_error = EB_ErrorBadParameter; |
296 | 0 | } |
297 | | |
298 | 430 | if (config->enable_dlf_flag > 2) { |
299 | 0 | SVT_ERROR("Invalid LoopFilterEnable. LoopFilterEnable must be [0 - 2]\n"); |
300 | 0 | return_error = EB_ErrorBadParameter; |
301 | 0 | } |
302 | | |
303 | 430 | if (config->rate_control_mode > SVT_AV1_RC_MODE_CBR && |
304 | 0 | (config->pass == ENC_FIRST_PASS || config->rc_stats_buffer.buf)) { |
305 | 0 | SVT_ERROR("Only rate control mode 0~2 are supported for 2-pass \n"); |
306 | 0 | return_error = EB_ErrorBadParameter; |
307 | 0 | } |
308 | | // Stats file is checked by the app in handle_stats_file, but must be re-checked here since ffmpeg calls |
309 | | // the library but not the app |
310 | 430 | if (config->rate_control_mode == SVT_AV1_RC_MODE_VBR && config->pass == ENC_SECOND_PASS) { |
311 | 0 | if (!config->rc_stats_buffer.buf) { |
312 | 0 | SVT_ERROR("RC stats buffer not available \n"); |
313 | 0 | return_error = EB_ErrorBadParameter; |
314 | 0 | } else if (config->rc_stats_buffer.sz == 0) { |
315 | 0 | SVT_ERROR("RC stats buffer size is 0 \n"); |
316 | 0 | return_error = EB_ErrorBadParameter; |
317 | 0 | } |
318 | 0 | } |
319 | 430 | if (config->profile > 2) { |
320 | 0 | SVT_ERROR("The maximum allowed profile value is 2 \n"); |
321 | 0 | return_error = EB_ErrorBadParameter; |
322 | 0 | } |
323 | | |
324 | | // Check if the current input video is conformant with the Level constraint |
325 | 430 | if (scs->frame_rate > 240) { |
326 | 0 | SVT_ERROR("The maximum allowed frame rate is 240 fps\n"); |
327 | 0 | return_error = EB_ErrorBadParameter; |
328 | 0 | } |
329 | | // Check that the frame_rate is non-zero |
330 | 430 | if (!scs->frame_rate) { |
331 | 0 | SVT_ERROR("The frame rate should be greater than 0 fps \n"); |
332 | 0 | return_error = EB_ErrorBadParameter; |
333 | 0 | } |
334 | 430 | if (scs->static_config.frame_rate_numerator == 0 || scs->static_config.frame_rate_denominator == 0) { |
335 | 0 | SVT_ERROR("The frame_rate_numerator and frame_rate_denominator must be greater than 0\n"); |
336 | 0 | return_error = EB_ErrorBadParameter; |
337 | 0 | } |
338 | 430 | if (config->recode_loop > 4) { |
339 | 0 | SVT_ERROR("The recode_loop must be [0 - 4] \n"); |
340 | 0 | return_error = EB_ErrorBadParameter; |
341 | 0 | } |
342 | 430 | if (config->rate_control_mode > SVT_AV1_RC_MODE_CBR) { |
343 | 0 | SVT_ERROR("The rate control mode must be [0 - 2] \n"); |
344 | 0 | return_error = EB_ErrorBadParameter; |
345 | 0 | } |
346 | 430 | if (config->look_ahead_distance > MAX_LAD && config->look_ahead_distance != (uint32_t)~0) { |
347 | 0 | SVT_ERROR("The lookahead distance must be [0 - %d] \n", MAX_LAD); |
348 | |
|
349 | 0 | return_error = EB_ErrorBadParameter; |
350 | 0 | } |
351 | 430 | if ((unsigned)config->tile_rows > 6 || (unsigned)config->tile_columns > 6) { |
352 | 0 | SVT_ERROR("Log2Tile rows/cols must be [0 - 6] \n"); |
353 | 0 | return_error = EB_ErrorBadParameter; |
354 | 0 | } |
355 | 430 | if ((1u << config->tile_rows) * (1u << config->tile_columns) > 128 || config->tile_columns > 4) { |
356 | 0 | SVT_ERROR("MaxTiles is 128 and MaxTileCols is 16 (Annex A.3) \n"); |
357 | 0 | return_error = EB_ErrorBadParameter; |
358 | 0 | } |
359 | 430 | if (config->max_qp_allowed > MAX_QP_VALUE) { |
360 | 0 | SVT_ERROR("MaxQpAllowed must be [0 - %d]\n", MAX_QP_VALUE); |
361 | 0 | return_error = EB_ErrorBadParameter; |
362 | 430 | } else if (config->min_qp_allowed > MAX_QP_VALUE) { |
363 | 0 | SVT_ERROR("MinQpAllowed must be [0 - %d]\n", MAX_QP_VALUE); |
364 | 0 | return_error = EB_ErrorBadParameter; |
365 | 430 | } else if (config->min_qp_allowed > config->max_qp_allowed) { |
366 | 0 | SVT_ERROR("MinQpAllowed must be smaller than or equal to MaxQpAllowed\n"); |
367 | 0 | return_error = EB_ErrorBadParameter; |
368 | 0 | } |
369 | 430 | if (config->use_fixed_qindex_offsets > 2) { |
370 | 0 | SVT_ERROR("The use_fixed_qindex_offsets must be [0 - 2] \n"); |
371 | 0 | return_error = EB_ErrorBadParameter; |
372 | 0 | } |
373 | | |
374 | 430 | if (config->key_frame_qindex_offset < -64 || config->key_frame_qindex_offset > 63) { |
375 | 0 | SVT_ERROR("Invalid key_frame_qindex_offset. key_frame_qindex_offset must be [-64 - 63]\n"); |
376 | 0 | return_error = EB_ErrorBadParameter; |
377 | 0 | } |
378 | | |
379 | 1.72k | for (uint8_t i = 0; i < config->hierarchical_levels + 1; ++i) { |
380 | 1.29k | if (config->qindex_offsets[i] < -64 || config->qindex_offsets[i] > 63) { |
381 | 0 | SVT_ERROR("Invalid qindex_offsets. qindex_offsets must be [-64 - 63]\n"); |
382 | 0 | return_error = EB_ErrorBadParameter; |
383 | 0 | } |
384 | 1.29k | } |
385 | 430 | if (config->key_frame_chroma_qindex_offset < -64 || config->key_frame_chroma_qindex_offset > 63) { |
386 | 0 | SVT_ERROR( |
387 | 0 | "Invalid key_frame_chroma_qindex_offset. key_frame_chroma_qindex_offset " |
388 | 0 | "must be [-64 - 63]\n"); |
389 | 0 | return_error = EB_ErrorBadParameter; |
390 | 0 | } |
391 | 430 | if (config->luma_y_dc_qindex_offset < -64 || config->luma_y_dc_qindex_offset > 63) { |
392 | 0 | SVT_ERROR( |
393 | 0 | "Invalid luma_y_dc_qindex_offset. luma_y_dc_qindex_offset " |
394 | 0 | "must be [-64 - 63]\n"); |
395 | 0 | return_error = EB_ErrorBadParameter; |
396 | 0 | } |
397 | 430 | if (config->chroma_u_dc_qindex_offset < -64 || config->chroma_u_dc_qindex_offset > 63) { |
398 | 0 | SVT_ERROR( |
399 | 0 | "Invalid chroma_u_dc_qindex_offset. chroma_u_dc_qindex_offset " |
400 | 0 | "must be [-64 - 63]\n"); |
401 | 0 | return_error = EB_ErrorBadParameter; |
402 | 0 | } |
403 | 430 | if (config->chroma_u_ac_qindex_offset < -64 || config->chroma_u_ac_qindex_offset > 63) { |
404 | 0 | SVT_ERROR( |
405 | 0 | "Invalid chroma_u_ac_qindex_offset. chroma_u_ac_qindex_offset " |
406 | 0 | "must be [-64 - 63]\n"); |
407 | 0 | return_error = EB_ErrorBadParameter; |
408 | 0 | } |
409 | 430 | if (config->chroma_v_dc_qindex_offset < -64 || config->chroma_v_dc_qindex_offset > 63) { |
410 | 0 | SVT_ERROR( |
411 | 0 | "Invalid chroma_v_dc_qindex_offset. chroma_v_dc_qindex_offset " |
412 | 0 | "must be [-64 - 63]\n"); |
413 | 0 | return_error = EB_ErrorBadParameter; |
414 | 0 | } |
415 | 430 | if (config->chroma_v_ac_qindex_offset < -64 || config->chroma_v_ac_qindex_offset > 63) { |
416 | 0 | SVT_ERROR( |
417 | 0 | "Invalid chroma_v_ac_qindex_offset. chroma_v_ac_qindex_offset " |
418 | 0 | "must be [-64 - 63]\n"); |
419 | 0 | return_error = EB_ErrorBadParameter; |
420 | 0 | } |
421 | | |
422 | 1.72k | for (uint8_t i = 0; i < config->hierarchical_levels + 1; ++i) { |
423 | 1.29k | if (config->chroma_qindex_offsets[i] < -64 || config->chroma_qindex_offsets[i] > 63) { |
424 | 0 | SVT_ERROR("Invalid chroma_qindex_offsets. chroma_qindex_offsets must be [-64 - 63]\n"); |
425 | 0 | return_error = EB_ErrorBadParameter; |
426 | 0 | } |
427 | 1.29k | } |
428 | 430 | if (config->startup_qp_offset < -63 || config->startup_qp_offset > 63) { |
429 | 0 | SVT_ERROR("Invalid startup_qp_offset. startup_qp_offset must be [-63 - 63]\n"); |
430 | 0 | return_error = EB_ErrorBadParameter; |
431 | 0 | } |
432 | 430 | if (config->stat_report == 1) { |
433 | 0 | SVT_WARN("Enabling StatReport can decrease encoding speed\n"); |
434 | 0 | } |
435 | | |
436 | 430 | if (config->stat_report > 1) { |
437 | 0 | SVT_ERROR("Invalid StatReport. StatReport must be [0 - 1]\n"); |
438 | 0 | return_error = EB_ErrorBadParameter; |
439 | 0 | } |
440 | 430 | if (config->screen_content_mode > 3) { |
441 | 0 | SVT_ERROR("Invalid screen_content_mode. screen_content_mode must be [0 - 3]\n"); |
442 | 0 | return_error = EB_ErrorBadParameter; |
443 | 0 | } |
444 | | |
445 | 430 | if (scs->static_config.aq_mode > 2) { |
446 | 0 | SVT_ERROR("Invalid adaptive quantization (AQ) mode. AQ mode must be [0-2]\n"); |
447 | 0 | return_error = EB_ErrorBadParameter; |
448 | 0 | } |
449 | | |
450 | 430 | if ((config->encoder_bit_depth != 8) && (config->encoder_bit_depth != 10)) { |
451 | 0 | SVT_ERROR("Encoder Bit Depth shall be only 8 or 10 \n"); |
452 | 0 | return_error = EB_ErrorBadParameter; |
453 | 0 | } |
454 | | // Check if the EncoderBitDepth is conformant with the Profile constraint |
455 | 430 | if ((config->profile == 0 || config->profile == 1) && config->encoder_bit_depth > 10) { |
456 | 0 | SVT_ERROR("The encoder bit depth shall be equal to 8 or 10 for Main/High Profile\n"); |
457 | 0 | return_error = EB_ErrorBadParameter; |
458 | 0 | } |
459 | | |
460 | 430 | if (config->encoder_color_format != EB_YUV420) { |
461 | 0 | SVT_ERROR("Only support 420 now \n"); |
462 | 0 | return_error = EB_ErrorBadParameter; |
463 | 0 | } |
464 | | |
465 | 430 | if (config->profile == 0 && config->encoder_color_format > EB_YUV420) { |
466 | 0 | SVT_ERROR("Non 420 color format requires profile 1 or 2\n"); |
467 | 0 | return_error = EB_ErrorBadParameter; |
468 | 0 | } |
469 | | |
470 | 430 | if (config->profile == 1 && config->encoder_color_format != EB_YUV444) { |
471 | 0 | SVT_ERROR("Profile 1 requires 4:4:4 color format\n"); |
472 | 0 | return_error = EB_ErrorBadParameter; |
473 | 0 | } |
474 | | |
475 | 430 | if (config->profile == 2 && config->encoder_bit_depth <= 10 && config->encoder_color_format != EB_YUV422) { |
476 | 0 | SVT_ERROR("Profile 2 bit-depth < 10 requires 4:2:2 color format\n"); |
477 | 0 | return_error = EB_ErrorBadParameter; |
478 | 0 | } |
479 | | |
480 | 430 | if (config->use_cpu_flags & EB_CPU_FLAGS_INVALID) { |
481 | | #ifdef ARCH_AARCH64 |
482 | | SVT_ERROR( |
483 | | "param '--asm' have invalid value.\n" |
484 | | "Value should be [0 - 6] or [c, neon, crc32, neon_dotprod, neon_i8mm, sve, sve2, max]\n"); |
485 | | #else |
486 | 0 | SVT_ERROR( |
487 | 0 | "param '--asm' have invalid value.\n" |
488 | 0 | "Value should be [0 - 11] or [c, mmx, sse, sse2, sse3, ssse3, sse4_1, sse4_2, avx, " |
489 | 0 | "avx2, avx512, avx512icl, max]\n"); |
490 | 0 | #endif |
491 | 0 | return_error = EB_ErrorBadParameter; |
492 | 0 | } |
493 | | |
494 | | // HBD mode decision |
495 | 430 | if (scs->enable_hbd_mode_decision < (int8_t)(-1) || scs->enable_hbd_mode_decision > 2) { |
496 | 0 | SVT_ERROR("Invalid HBD mode decision flag [-1 - 2], your input: %d\n", scs->enable_hbd_mode_decision); |
497 | 0 | return_error = EB_ErrorBadParameter; |
498 | 0 | } |
499 | | |
500 | | // CDEF |
501 | 430 | if (config->cdef_level > 4 || config->cdef_level < -1) { |
502 | 0 | SVT_ERROR("Invalid CDEF level [0 - 4, -1 for auto], your input: %d\n", config->cdef_level); |
503 | 0 | return_error = EB_ErrorBadParameter; |
504 | 0 | } |
505 | | |
506 | | // Restoration Filtering |
507 | 430 | if (config->enable_restoration_filtering != 0 && config->enable_restoration_filtering != 1 && |
508 | 430 | config->enable_restoration_filtering != -1) { |
509 | 0 | SVT_ERROR("Invalid restoration flag [0 - 1, -1 for auto], your input: %d\n", |
510 | 0 | config->enable_restoration_filtering); |
511 | 0 | return_error = EB_ErrorBadParameter; |
512 | 0 | } |
513 | | |
514 | 430 | if (config->enable_mfmv != 0 && config->enable_mfmv != 1 && config->enable_mfmv != -1) { |
515 | 0 | SVT_ERROR( |
516 | 0 | "Invalid motion field motion vector flag [0/1 or -1 for auto], your " |
517 | 0 | "input: %d\n", |
518 | 0 | config->enable_mfmv); |
519 | 0 | return_error = EB_ErrorBadParameter; |
520 | 0 | } |
521 | 430 | if (config->fast_decode > 2) { |
522 | 0 | SVT_ERROR( |
523 | 0 | "Invalid fast decode flag [0 - 2, 0 for no decoder-targeted optimization], your " |
524 | 0 | "input: %d\n", |
525 | 0 | config->fast_decode); |
526 | 0 | return_error = EB_ErrorBadParameter; |
527 | 0 | } |
528 | 430 | #if FTR_TUNE_VMAF |
529 | 430 | if (config->tune > TUNE_VMAF) { |
530 | 0 | SVT_ERROR( |
531 | 0 | "Invalid tune flag [0 - 5, 0 for VQ, 1 for PSNR, 2 for SSIM, 3 for IQ, 4 for MS_SSIM, and 5 for VMAF], " |
532 | 0 | "your input: " |
533 | 0 | "%d\n", |
534 | 0 | config->tune); |
535 | 0 | return_error = EB_ErrorBadParameter; |
536 | 0 | } |
537 | | // RC: SSIM, IQ, MS_SSIM, VMAF -> CRF only (VBR, CBR not supported) |
538 | 430 | if (config->tune == TUNE_SSIM || config->tune == TUNE_IQ || config->tune == TUNE_MS_SSIM || |
539 | 430 | config->tune == TUNE_VMAF) { |
540 | 0 | if (config->rate_control_mode != 0) { |
541 | 0 | SVT_ERROR("Tune %s only supports CRF rate control mode\n", |
542 | 0 | config->tune == TUNE_SSIM ? "SSIM" |
543 | 0 | : config->tune == TUNE_IQ ? "IQ" |
544 | 0 | : config->tune == TUNE_VMAF ? "VMAF" |
545 | 0 | : "MS_SSIM"); |
546 | 0 | return_error = EB_ErrorBadParameter; |
547 | 0 | } |
548 | 0 | } |
549 | | |
550 | | // pred_struct: SSIM, MS_SSIM -> ALL_INTRA and RA only (LOW_DELAY not supported) |
551 | 430 | if (config->tune == TUNE_SSIM || config->tune == TUNE_MS_SSIM) { |
552 | 0 | if (config->pred_structure == LOW_DELAY) { |
553 | 0 | SVT_ERROR("Tune %s only supports all-intra and random access prediction structures\n", |
554 | 0 | config->tune == TUNE_SSIM ? "SSIM" : "MS_SSIM"); |
555 | 0 | return_error = EB_ErrorBadParameter; |
556 | 0 | } |
557 | 0 | } |
558 | | |
559 | | // pred_struct: VMAF -> RA only (ALL_INTRA and LOW_DELAY not supported) |
560 | 430 | if (config->tune == TUNE_VMAF && (config->pred_structure == ALL_INTRA || config->pred_structure == LOW_DELAY)) { |
561 | 0 | SVT_ERROR("Tune VMAF only supports random access prediction structure\n"); |
562 | 0 | return_error = EB_ErrorBadParameter; |
563 | 0 | } |
564 | | |
565 | | // pred_struct: IQ -> ALL_INTRA and LOW_DELAY only (RA not supported); LOW_DELAY is experimental |
566 | 430 | if (config->tune == TUNE_IQ && config->pred_structure == RANDOM_ACCESS) { |
567 | 0 | SVT_ERROR("Tune IQ only supports all-intra and low delay (experimental) prediction structures\n"); |
568 | 0 | return_error = EB_ErrorBadParameter; |
569 | 0 | } |
570 | 430 | if (config->tune == TUNE_IQ && config->pred_structure == LOW_DELAY) { |
571 | 0 | SVT_WARN("Tune IQ with low delay prediction structure is experimental\n"); |
572 | 0 | } |
573 | | #else |
574 | | if (config->tune > TUNE_MS_SSIM) { |
575 | | SVT_ERROR( |
576 | | "Invalid tune flag [0 - 4, 0 for VQ, 1 for PSNR, 2 for SSIM, 3 for IQ, and 4 for MS_SSIM], your input: " |
577 | | "%d\n", |
578 | | config->tune); |
579 | | return_error = EB_ErrorBadParameter; |
580 | | } |
581 | | if (config->tune == TUNE_SSIM || config->tune == TUNE_IQ || config->tune == TUNE_MS_SSIM) { |
582 | | if (config->rate_control_mode != 0 || config->pred_structure == LOW_DELAY) { |
583 | | SVT_ERROR("tune %s only supports CRF rate control mode currently\n", |
584 | | config->tune == TUNE_SSIM ? "SSIM" |
585 | | : config->tune == TUNE_IQ ? "IQ" |
586 | | : "MS_SSIM"); |
587 | | return_error = EB_ErrorBadParameter; |
588 | | } |
589 | | } |
590 | | #endif |
591 | | |
592 | 430 | if (config->superres_mode > SUPERRES_AUTO) { |
593 | 0 | SVT_ERROR("invalid superres-mode %d, should be in the range [%d - %d]\n", |
594 | 0 | config->superres_mode, |
595 | 0 | SUPERRES_NONE, |
596 | 0 | SUPERRES_AUTO); |
597 | 0 | return_error = EB_ErrorBadParameter; |
598 | 0 | } |
599 | 430 | if (config->superres_mode > 0 && ((config->rc_stats_buffer.sz || config->pass == ENC_FIRST_PASS))) { |
600 | 0 | SVT_ERROR("superres is not supported for 2-pass\n"); |
601 | 0 | return_error = EB_ErrorBadParameter; |
602 | 0 | } |
603 | | |
604 | 430 | if (config->superres_qthres > MAX_QP_VALUE) { |
605 | 0 | SVT_ERROR("Invalid superres-qthres %d, should be in the range [%d - %d]\n", |
606 | 0 | config->superres_qthres, |
607 | 0 | MIN_QP_VALUE, |
608 | 0 | MAX_QP_VALUE); |
609 | 0 | return_error = EB_ErrorBadParameter; |
610 | 0 | } |
611 | | |
612 | 430 | if (config->superres_kf_qthres > MAX_QP_VALUE) { |
613 | 0 | SVT_ERROR("Invalid superres-kf-qthres %d, should be in the range [%d - %d]\n", |
614 | 0 | config->superres_kf_qthres, |
615 | 0 | MIN_QP_VALUE, |
616 | 0 | MAX_QP_VALUE); |
617 | 0 | return_error = EB_ErrorBadParameter; |
618 | 0 | } |
619 | | |
620 | 430 | if (config->superres_kf_denom < MIN_SUPERRES_DENOM || config->superres_kf_denom > MAX_SUPERRES_DENOM) { |
621 | 0 | SVT_ERROR("Invalid superres-kf-denom %d, should be in the range [%d - %d]\n", |
622 | 0 | config->superres_kf_denom, |
623 | 0 | MIN_SUPERRES_DENOM, |
624 | 0 | MAX_SUPERRES_DENOM); |
625 | 0 | return_error = EB_ErrorBadParameter; |
626 | 0 | } |
627 | | |
628 | 430 | if (config->superres_denom < MIN_SUPERRES_DENOM || config->superres_denom > MAX_SUPERRES_DENOM) { |
629 | 0 | SVT_ERROR("Invalid superres-denom %d, should be in the range [%d - %d]\n", |
630 | 0 | config->superres_denom, |
631 | 0 | MIN_SUPERRES_DENOM, |
632 | 0 | MAX_SUPERRES_DENOM); |
633 | 0 | return_error = EB_ErrorBadParameter; |
634 | 0 | } |
635 | | |
636 | 430 | if (config->resize_mode > RESIZE_RANDOM_ACCESS) { |
637 | 0 | SVT_ERROR("Invalid resize-mode %d, should be in the range [%d - %d]\n", |
638 | 0 | config->resize_mode, |
639 | 0 | RESIZE_NONE, |
640 | 0 | RESIZE_RANDOM_ACCESS); |
641 | 0 | return_error = EB_ErrorBadParameter; |
642 | 0 | } |
643 | | |
644 | 430 | if (config->resize_kf_denom < MIN_RESIZE_DENOM || config->resize_kf_denom > MAX_RESIZE_DENOM) { |
645 | 0 | SVT_ERROR("Invalid resize-kf-denom %d, should be in the range [%d - %d]\n", |
646 | 0 | config->resize_kf_denom, |
647 | 0 | MIN_RESIZE_DENOM, |
648 | 0 | MAX_RESIZE_DENOM); |
649 | 0 | return_error = EB_ErrorBadParameter; |
650 | 0 | } |
651 | | |
652 | 430 | if (config->resize_denom < MIN_RESIZE_DENOM || config->resize_denom > MAX_RESIZE_DENOM) { |
653 | 0 | SVT_ERROR("Invalid resize-denom %d, should be in the range [%d - %d]\n", |
654 | 0 | config->resize_denom, |
655 | 0 | MIN_RESIZE_DENOM, |
656 | 0 | MAX_RESIZE_DENOM); |
657 | 0 | return_error = EB_ErrorBadParameter; |
658 | 0 | } |
659 | | |
660 | 430 | if (config->matrix_coefficients == 0 && config->encoder_color_format != EB_YUV444) { |
661 | 0 | SVT_ERROR( |
662 | 0 | "Identity matrix (matrix_coefficient = 0) may be used only with 4:4:4 " |
663 | 0 | "color format.\n"); |
664 | 0 | return_error = EB_ErrorBadParameter; |
665 | 0 | } |
666 | | #if !OPT_USE_HL0_FLAT |
667 | | if (config->hierarchical_levels < 2 || config->hierarchical_levels > 5) { |
668 | | SVT_ERROR("Only hierarchical levels 2-5 is currently supported.\n"); |
669 | | return_error = EB_ErrorBadParameter; |
670 | | } |
671 | | #endif |
672 | | |
673 | 430 | if (config->rate_control_mode == SVT_AV1_RC_MODE_VBR && config->intra_period_length == -1) { |
674 | 0 | SVT_ERROR( |
675 | 0 | "keyint = -1 is not supported for modes other than CRF rate control " |
676 | 0 | "encoding modes.\n"); |
677 | 0 | return_error = EB_ErrorBadParameter; |
678 | 0 | } |
679 | | // Block the use of M4 or lower for resolutions higher than 4K, unless allintra coding is used (due to memory constraints) |
680 | 430 | if (!scs->allintra && (uint64_t)(scs->max_input_luma_width * scs->max_input_luma_height) > INPUT_SIZE_4K_TH && |
681 | 0 | config->enc_mode <= ENC_M4) { |
682 | 0 | SVT_ERROR("8k+ resolution support is limited to M5 and faster presets.\n"); |
683 | 0 | return_error = EB_ErrorBadParameter; |
684 | 0 | } |
685 | 430 | if (config->pass > 0 && scs->static_config.enable_overlays) { |
686 | 0 | SVT_ERROR( |
687 | 0 | "The overlay frames feature is currently not supported with multi-pass " |
688 | 0 | "encoding\n"); |
689 | 0 | return_error = EB_ErrorBadParameter; |
690 | 0 | } |
691 | 430 | int pass = config->pass; |
692 | | |
693 | 430 | if (pass < 0 || pass > 2) { |
694 | 0 | SVT_ERROR("%d pass encode is not supported. --pass has a range of [0-2]\n", pass); |
695 | 0 | return_error = EB_ErrorBadParameter; |
696 | 0 | } |
697 | | |
698 | 430 | if (config->intra_refresh_type != 2 && pass > 0) { |
699 | 0 | SVT_ERROR("Multi-pass encode only supports closed-gop configurations.\n"); |
700 | 0 | return_error = EB_ErrorBadParameter; |
701 | 0 | } |
702 | 430 | if (config->pass > 1 && config->rate_control_mode == SVT_AV1_RC_MODE_CQP_OR_CRF) { |
703 | 0 | SVT_ERROR("CRF does not support multi-pass. Use single pass.\n"); |
704 | 0 | return_error = EB_ErrorBadParameter; |
705 | 0 | } |
706 | | |
707 | 430 | if (config->aq_mode == 0 && config->rate_control_mode) { |
708 | 0 | SVT_ERROR("Adaptive quantization can not be turned OFF when RC ON\n"); |
709 | 0 | return_error = EB_ErrorBadParameter; |
710 | 0 | } |
711 | | |
712 | 430 | if (config->sframe_dist < 0) { |
713 | 0 | SVT_ERROR("Switch frame interval must be >= 0\n"); |
714 | 0 | return_error = EB_ErrorBadParameter; |
715 | 0 | } |
716 | 430 | if (config->sframe_dist > 0 && config->hierarchical_levels == 0) { |
717 | 0 | SVT_ERROR("Switch frame feature does not support flat IPPP\n"); |
718 | 0 | return_error = EB_ErrorBadParameter; |
719 | 0 | } |
720 | 430 | if (config->sframe_dist > 0 && |
721 | 0 | (config->sframe_mode < SFRAME_STRICT_BASE || config->sframe_mode > SFRAME_DEC_POSI_BASE)) { |
722 | 0 | SVT_ERROR("Invalid switch frame mode %d, should be in the range [%d - %d]\n", |
723 | 0 | config->sframe_mode, |
724 | 0 | SFRAME_STRICT_BASE, |
725 | 0 | SFRAME_DEC_POSI_BASE); |
726 | 0 | return_error = EB_ErrorBadParameter; |
727 | 0 | } |
728 | 430 | if (config->sframe_posi.sframe_posis && !IS_SFRAME_FLEXIBLE_INSERT(config->sframe_mode)) { |
729 | 0 | SVT_ERROR("S-Frame positions are only supported in S-Frame Flexible ARF mode\n"); |
730 | 0 | return_error = EB_ErrorBadParameter; |
731 | 0 | } |
732 | 430 | if (config->sframe_posi.sframe_qp_num && config->rate_control_mode != SVT_AV1_RC_MODE_CQP_OR_CRF) { |
733 | 0 | SVT_ERROR("S-Frame QP feature only supports CRF/CQP rate control mode\n"); |
734 | 0 | return_error = EB_ErrorBadParameter; |
735 | 0 | } |
736 | 430 | if ((config->sframe_posi.sframe_qps && config->sframe_posi.sframe_qp_offsets) || |
737 | 430 | (config->sframe_qp > 0 && config->sframe_qp_offset != 0)) { |
738 | 0 | SVT_ERROR("S-Frame QP feature cannot support QP value and QP offset at same time\n"); |
739 | 0 | return_error = EB_ErrorBadParameter; |
740 | 0 | } |
741 | | |
742 | | /* Warnings about the use of features that are incomplete */ |
743 | 430 | if (config->aq_mode == 1) { |
744 | 0 | SVT_WARN( |
745 | 0 | "The adaptive quantization mode using segmentation is at a support level " |
746 | 0 | "only to be available for demos, experimentation, and further development uses and " |
747 | 0 | "should not be used for benchmarking until fully implemented.\n"); |
748 | 0 | } |
749 | | |
750 | | // color description |
751 | 430 | if (config->color_primaries == 0 || config->color_primaries == 3 || |
752 | 430 | (config->color_primaries >= 13 && config->color_primaries <= 21) || config->color_primaries > 22) { |
753 | 0 | SVT_WARN("Value %u for color_primaries is reserved and not recommended for usage.\n", config->color_primaries); |
754 | 0 | } |
755 | 430 | if (config->transfer_characteristics == 0 || config->transfer_characteristics == 3 || |
756 | 430 | config->transfer_characteristics > 18) { |
757 | 0 | SVT_WARN("Value %u for transfer_characteristics is reserved and not recommended for usage.\n", |
758 | 0 | config->transfer_characteristics); |
759 | 0 | } |
760 | | |
761 | 430 | if (config->matrix_coefficients == 3 || config->matrix_coefficients > 14) { |
762 | 0 | SVT_WARN("Value %u for matrix_coefficients is reserved and not recommended for usage.\n", |
763 | 0 | config->matrix_coefficients); |
764 | 0 | } |
765 | | |
766 | 430 | if (config->chroma_sample_position < EB_CSP_UNKNOWN || config->chroma_sample_position > EB_CSP_COLOCATED) { |
767 | 0 | if (config->chroma_sample_position != EB_CSP_RESERVED) { |
768 | 0 | SVT_ERROR("Chroma sample position %d is unknown.\n", config->chroma_sample_position); |
769 | 0 | return_error = EB_ErrorBadParameter; |
770 | 0 | } else { |
771 | 0 | SVT_WARN( |
772 | 0 | "Value %d for chroma_sample_position is reserved " |
773 | 0 | "and not recommended for usage.\n", |
774 | 0 | config->chroma_sample_position); |
775 | 0 | } |
776 | 0 | } |
777 | | |
778 | 430 | if (config->film_grain_denoise_strength > 0 && config->enc_mode > 6) { |
779 | 0 | SVT_WARN( |
780 | 0 | "It is recommended to not use Film Grain for presets greater than 6 as it " |
781 | 0 | "produces a significant compute overhead. This combination should only be used for " |
782 | 0 | "debug purposes.\n"); |
783 | 0 | } |
784 | | |
785 | 430 | if (config->film_grain_denoise_strength > 50) { |
786 | 0 | SVT_ERROR( |
787 | 0 | "Film grain denoise strength is only supported for values between " |
788 | 0 | "[0,50]\n"); |
789 | 0 | return_error = EB_ErrorBadParameter; |
790 | 0 | } |
791 | | |
792 | 430 | if (config->film_grain_denoise_apply != 0 && config->film_grain_denoise_apply != 1) { |
793 | 0 | SVT_ERROR("The film grain denoise apply signal can only have a value of 0 or 1\n"); |
794 | 0 | return_error = EB_ErrorBadParameter; |
795 | 0 | } |
796 | | |
797 | | // Limit 8K & 16K support |
798 | 430 | if ((uint64_t)(scs->max_input_luma_width * scs->max_input_luma_height) > INPUT_SIZE_4K_TH) { |
799 | 0 | SVT_WARN( |
800 | 0 | "8K and higher resolution support is currently a work-in-progress " |
801 | 0 | "project, and is only available for demos, experimentation, and further development " |
802 | 0 | "uses and should not be used for benchmarking until fully implemented.\n"); |
803 | 0 | } |
804 | | |
805 | 430 | if (config->pred_structure == LOW_DELAY) { |
806 | 0 | if (config->tune == TUNE_VQ) { |
807 | 0 | SVT_WARN("Tune 0 is not applicable for low-delay, tune will be forced to 1.\n"); |
808 | 0 | config->tune = TUNE_PSNR; |
809 | 0 | } |
810 | |
|
811 | 0 | if (config->superres_mode != 0) { |
812 | 0 | SVT_ERROR("Superres is not supported for low-delay.\n"); |
813 | 0 | return_error = EB_ErrorBadParameter; |
814 | 0 | } |
815 | |
|
816 | 0 | if (config->enable_overlays) { |
817 | 0 | SVT_ERROR("Overlay is not supported for low-delay.\n"); |
818 | 0 | return_error = EB_ErrorBadParameter; |
819 | 0 | } |
820 | 0 | } |
821 | | |
822 | 430 | if (!config->rtc && config->enc_mode >= ENC_M10) { |
823 | 0 | SVT_WARN("Non-RTC M10+ are meant for automation tooling usage. Visual artifacts may occur otherwise.\n"); |
824 | 0 | } |
825 | | |
826 | 430 | if (scs->static_config.scene_change_detection) { |
827 | 0 | scs->static_config.scene_change_detection = 0; |
828 | 0 | SVT_WARN( |
829 | 0 | "SVT-AV1 has an integrated mode decision mechanism to handle scene changes and will " |
830 | 0 | "not insert a key frame at scene changes\n"); |
831 | 0 | } |
832 | 430 | if ((config->tile_columns > 0 || config->tile_rows > 0)) { |
833 | 430 | SVT_WARN( |
834 | 430 | "If you are using tiles with the intent of increasing the decoder speed, please also " |
835 | 430 | "consider using --fast-decode 1 or 2, especially if the intended decoder is running with " |
836 | 430 | "limited multi-threading capabilities.\n"); |
837 | 430 | } |
838 | 430 | if (config->tune == TUNE_VQ && config->fast_decode > 0) { |
839 | 0 | SVT_WARN( |
840 | 0 | "--fast-decode has been developed and optimized with --tune 1. " |
841 | 0 | "Please use it with caution when encoding with --tune 0. You can also consider using " |
842 | 0 | "--tile-columns 1 if you are targeting a high quality encode and a multi-core " |
843 | 0 | "high-performance decoder HW\n"); |
844 | 0 | } |
845 | 430 | if (config->enable_qm && config->min_qm_level > config->max_qm_level) { |
846 | 0 | SVT_ERROR("Min quant matrix level must not greater than max quant matrix level\n"); |
847 | 0 | return_error = EB_ErrorBadParameter; |
848 | 0 | } |
849 | 430 | if (config->enable_qm && config->min_chroma_qm_level > config->max_chroma_qm_level) { |
850 | 0 | SVT_ERROR("Min chroma quant matrix level must not greater than max chroma quant matrix level\n"); |
851 | 0 | return_error = EB_ErrorBadParameter; |
852 | 0 | } |
853 | 430 | if (config->startup_mg_size != 0 && config->startup_mg_size != 2 && config->startup_mg_size != 3 && |
854 | 0 | config->startup_mg_size != 4) { |
855 | 0 | SVT_ERROR("Startup MG size supported [0, 2, 3, 4]\n"); |
856 | 0 | return_error = EB_ErrorBadParameter; |
857 | 0 | } |
858 | 430 | if (config->startup_mg_size > config->hierarchical_levels) { |
859 | 0 | SVT_ERROR("Startup MG size must less than or equal to hierarchical levels\n"); |
860 | 0 | return_error = EB_ErrorBadParameter; |
861 | 0 | } |
862 | 430 | if (config->startup_mg_size != 0 && config->rate_control_mode != SVT_AV1_RC_MODE_CQP_OR_CRF) { |
863 | 0 | SVT_ERROR("Startup MG size feature only supports CRF/CQP rate control mode\n"); |
864 | 0 | return_error = EB_ErrorBadParameter; |
865 | 0 | } |
866 | 430 | if (config->startup_qp_offset != 0 && config->rate_control_mode != 0) { |
867 | 0 | SVT_ERROR("Startup QP offset only supports CRF/CQP rate control mode\n"); |
868 | 0 | return_error = EB_ErrorBadParameter; |
869 | 0 | } |
870 | | |
871 | 430 | if (config->variance_boost_strength < 1 || config->variance_boost_strength > 4) { |
872 | 0 | SVT_ERROR("Variance Boost strength must be between 1 and 4\n"); |
873 | 0 | return_error = EB_ErrorBadParameter; |
874 | 0 | } |
875 | | |
876 | 430 | if (config->variance_octile < 1 || config->variance_octile > 8) { |
877 | 0 | SVT_ERROR("Variance Boost octile must be between 1 and 8\n"); |
878 | 0 | return_error = EB_ErrorBadParameter; |
879 | 0 | } |
880 | | |
881 | 430 | if (config->tf_strength > 4) { |
882 | 0 | SVT_ERROR("Temporal filtering strength must be between 0 and 4\n"); |
883 | 0 | return_error = EB_ErrorBadParameter; |
884 | 0 | } |
885 | | |
886 | 430 | if (config->variance_boost_curve > 2) { |
887 | 0 | SVT_ERROR("Variance Boost curve must be between 0 and 2\n"); |
888 | 0 | return_error = EB_ErrorBadParameter; |
889 | 0 | } |
890 | | |
891 | 430 | if (config->luminance_qp_bias > 100) { |
892 | 0 | SVT_ERROR("Luminance-based QP bias value must be between 0 and 100\n"); |
893 | 0 | return_error = EB_ErrorBadParameter; |
894 | 0 | } |
895 | | |
896 | 430 | if (config->sharpness > 7 || config->sharpness < -7) { |
897 | 0 | SVT_ERROR("Sharpness level must be between -7 and 7\n"); |
898 | 0 | return_error = EB_ErrorBadParameter; |
899 | 0 | } |
900 | | |
901 | 430 | if (config->qp_scale_compress_strength > 3) { |
902 | 0 | SVT_ERROR("QP scale compress strength must be between 0 and 3\n"); |
903 | 0 | return_error = EB_ErrorBadParameter; |
904 | 0 | } |
905 | | |
906 | 430 | if (config->max_tx_size != 32 && config->max_tx_size != 64) { |
907 | 0 | SVT_ERROR("Supported Max TX size values are 32 and 64\n"); |
908 | 0 | return_error = EB_ErrorBadParameter; |
909 | 0 | } |
910 | | |
911 | 430 | if (config->ac_bias > 8.0 || config->ac_bias < 0.0) { |
912 | 0 | SVT_ERROR("AC bias strength must be between 0.0 and 8.0\n"); |
913 | 0 | return_error = EB_ErrorBadParameter; |
914 | 0 | } |
915 | | |
916 | | //User configurable High Bit Depth Mode Decision Setting |
917 | 430 | if (config->hbd_mds < -1 || config->hbd_mds > 2) { |
918 | 0 | SVT_ERROR("hbd-mds must be -1 (preset default), 0, 1, or 2\n"); |
919 | 0 | return_error = EB_ErrorBadParameter; |
920 | 0 | } |
921 | | |
922 | 430 | if (config->encoder_bit_depth == 8 && (config->hbd_mds == 1 || config->hbd_mds == 2)) { |
923 | 0 | SVT_WARN("Please use 10-bit encoding if you want to take advantage of hbd-mds 1 and 2.\n"); |
924 | 0 | SVT_ERROR("Full high bit depth and hybrid 8/10 mode decision are not supported when encoder bit depth is 8\n"); |
925 | 0 | return_error = EB_ErrorBadParameter; |
926 | 0 | } |
927 | | |
928 | 430 | return return_error; |
929 | 430 | } |
930 | | |
931 | | /********************************** |
932 | | Set Default Library Params |
933 | | **********************************/ |
934 | 430 | EbErrorType svt_av1_set_default_params(EbSvtAv1EncConfiguration* config_ptr) { |
935 | 430 | EbErrorType return_error = EB_ErrorNone; |
936 | | |
937 | 430 | if (!config_ptr) { |
938 | 0 | SVT_ERROR("The EbSvtAv1EncConfiguration structure is empty!\n"); |
939 | 0 | return EB_ErrorBadParameter; |
940 | 0 | } |
941 | 430 | config_ptr->frame_rate_numerator = 60000; |
942 | 430 | config_ptr->frame_rate_denominator = 1000; |
943 | 430 | config_ptr->encoder_bit_depth = 8; |
944 | 430 | config_ptr->source_width = 0; |
945 | 430 | config_ptr->source_height = 0; |
946 | 430 | config_ptr->forced_max_frame_width = 0; |
947 | 430 | config_ptr->forced_max_frame_height = 0; |
948 | 430 | config_ptr->stat_report = 0; |
949 | 430 | config_ptr->tile_rows = DEFAULT; |
950 | 430 | config_ptr->tile_columns = DEFAULT; |
951 | 430 | config_ptr->qp = DEFAULT_QP; |
952 | 430 | config_ptr->use_qp_file = false; |
953 | 430 | config_ptr->use_fixed_qindex_offsets = 0; |
954 | 430 | memset(config_ptr->qindex_offsets, 0, sizeof(config_ptr->qindex_offsets)); |
955 | 430 | config_ptr->key_frame_chroma_qindex_offset = 0; |
956 | 430 | config_ptr->key_frame_qindex_offset = 0; |
957 | 430 | memset(config_ptr->chroma_qindex_offsets, 0, sizeof(config_ptr->chroma_qindex_offsets)); |
958 | 430 | config_ptr->luma_y_dc_qindex_offset = 0; |
959 | 430 | config_ptr->chroma_u_dc_qindex_offset = 0; |
960 | 430 | config_ptr->chroma_u_ac_qindex_offset = 0; |
961 | 430 | config_ptr->chroma_v_dc_qindex_offset = 0; |
962 | 430 | config_ptr->chroma_v_ac_qindex_offset = 0; |
963 | | |
964 | 3.44k | for (int i = 0; i < SVT_AV1_FRAME_UPDATE_TYPES; i++) { |
965 | 3.01k | config_ptr->lambda_scale_factors[i] = 128; |
966 | 3.01k | } |
967 | | |
968 | 430 | config_ptr->scene_change_detection = 0; |
969 | 430 | config_ptr->rate_control_mode = SVT_AV1_RC_MODE_CQP_OR_CRF; |
970 | 430 | config_ptr->look_ahead_distance = (uint32_t)~0; |
971 | 430 | config_ptr->target_bit_rate = DEFAULT_TBR; |
972 | 430 | config_ptr->max_bit_rate = 0; |
973 | 430 | config_ptr->max_qp_allowed = 63; |
974 | 430 | config_ptr->min_qp_allowed = MIN_QP_AUTO; |
975 | 430 | config_ptr->aq_mode = 2; |
976 | 430 | config_ptr->enc_mode = ENC_M8; |
977 | 430 | config_ptr->intra_period_length = -2; |
978 | 430 | config_ptr->multiply_keyint = false; |
979 | 430 | config_ptr->intra_refresh_type = 2; |
980 | 430 | config_ptr->hierarchical_levels = HIERARCHICAL_LEVELS_AUTO; |
981 | 430 | config_ptr->pred_structure = RANDOM_ACCESS; |
982 | 430 | config_ptr->enable_dlf_flag = 1; |
983 | 430 | config_ptr->cdef_level = DEFAULT; |
984 | 430 | config_ptr->enable_restoration_filtering = DEFAULT; |
985 | 430 | config_ptr->enable_mfmv = DEFAULT; |
986 | 430 | config_ptr->enable_dg = 1; |
987 | 430 | config_ptr->fast_decode = 0; |
988 | 430 | config_ptr->encoder_color_format = EB_YUV420; |
989 | 430 | config_ptr->rtc = 0; |
990 | | // Rate control options |
991 | | // Set the default value toward more flexible rate allocation |
992 | 430 | config_ptr->vbr_min_section_pct = 0; |
993 | 430 | config_ptr->vbr_max_section_pct = 2000; |
994 | 430 | config_ptr->under_shoot_pct = (uint32_t)DEFAULT; |
995 | 430 | config_ptr->over_shoot_pct = (uint32_t)DEFAULT; |
996 | 430 | config_ptr->mbr_over_shoot_pct = 50; |
997 | 430 | config_ptr->max_intra_bitrate_pct = 300; |
998 | 430 | config_ptr->max_inter_bitrate_pct = 0; |
999 | 430 | config_ptr->gop_constraint_rc = 0; |
1000 | 430 | config_ptr->maximum_buffer_size_ms = 1000; // default settings for CBR |
1001 | 430 | config_ptr->starting_buffer_level_ms = 600; // default settings for CBR |
1002 | 430 | config_ptr->optimal_buffer_level_ms = 600; // default settings for CBR |
1003 | 430 | config_ptr->recode_loop = ALLOW_RECODE_DEFAULT; |
1004 | 430 | config_ptr->screen_content_mode = 2; |
1005 | 430 | config_ptr->enable_intrabc = true; |
1006 | | |
1007 | | // Annex A parameters |
1008 | 430 | config_ptr->profile = 0; |
1009 | 430 | config_ptr->tier = 0; |
1010 | 430 | config_ptr->level = 0; |
1011 | | |
1012 | | // Film grain denoising |
1013 | 430 | config_ptr->film_grain_denoise_strength = 0; |
1014 | 430 | config_ptr->film_grain_denoise_apply = 0; |
1015 | | |
1016 | | // CPU Flags |
1017 | 430 | config_ptr->use_cpu_flags = EB_CPU_FLAGS_ALL; |
1018 | | |
1019 | | // Channel info |
1020 | 430 | config_ptr->level_of_parallelism = 0; |
1021 | | |
1022 | | // Debug info |
1023 | 430 | config_ptr->recon_enabled = 0; |
1024 | | |
1025 | | // Alt-Ref default values |
1026 | 430 | config_ptr->enable_tf = 1; |
1027 | 430 | config_ptr->enable_tf_key = 1; |
1028 | 430 | config_ptr->enable_overlays = false; |
1029 | 430 | config_ptr->tune = 1; |
1030 | | // Super-resolution default values |
1031 | 430 | config_ptr->superres_mode = SUPERRES_NONE; |
1032 | 430 | config_ptr->superres_denom = SCALE_NUMERATOR; |
1033 | 430 | config_ptr->superres_kf_denom = SCALE_NUMERATOR; |
1034 | 430 | config_ptr->superres_qthres = 43; // random threshold, change |
1035 | 430 | config_ptr->superres_kf_qthres = 43; // random threshold, change |
1036 | | |
1037 | | // Reference Scaling default values |
1038 | 430 | config_ptr->resize_mode = RESIZE_NONE; |
1039 | 430 | config_ptr->resize_denom = SCALE_NUMERATOR; |
1040 | 430 | config_ptr->resize_kf_denom = SCALE_NUMERATOR; |
1041 | | |
1042 | | // Color description default values |
1043 | 430 | config_ptr->color_primaries = 2; |
1044 | 430 | config_ptr->transfer_characteristics = 2; |
1045 | 430 | config_ptr->matrix_coefficients = 2; |
1046 | 430 | config_ptr->color_range = EB_CR_STUDIO_RANGE; |
1047 | 430 | config_ptr->chroma_sample_position = EB_CSP_UNKNOWN; |
1048 | 430 | config_ptr->pass = 0; |
1049 | 430 | memset(&config_ptr->mastering_display, 0, sizeof(config_ptr->mastering_display)); |
1050 | 430 | memset(&config_ptr->content_light_level, 0, sizeof(config_ptr->content_light_level)); |
1051 | | |
1052 | | // Switch frame default values |
1053 | 430 | config_ptr->sframe_dist = 0; |
1054 | 430 | config_ptr->sframe_mode = SFRAME_NEAREST_BASE; |
1055 | 430 | config_ptr->force_key_frames = 0; |
1056 | | |
1057 | | // Quant Matrices (QM) |
1058 | 430 | config_ptr->enable_qm = 0; |
1059 | 430 | config_ptr->min_qm_level = 8; |
1060 | 430 | config_ptr->max_qm_level = 15; |
1061 | 430 | config_ptr->min_chroma_qm_level = 8; |
1062 | 430 | config_ptr->max_chroma_qm_level = 15; |
1063 | | |
1064 | 430 | config_ptr->startup_mg_size = 0; |
1065 | 430 | config_ptr->startup_qp_offset = 0; |
1066 | 430 | config_ptr->frame_scale_evts.evt_num = 0; |
1067 | 430 | config_ptr->frame_scale_evts.resize_denoms = NULL; |
1068 | 430 | config_ptr->frame_scale_evts.resize_kf_denoms = NULL; |
1069 | 430 | config_ptr->frame_scale_evts.start_frame_nums = NULL; |
1070 | 430 | config_ptr->enable_roi_map = false; |
1071 | 430 | config_ptr->fgs_table = NULL; |
1072 | 430 | config_ptr->enable_variance_boost = false; |
1073 | 430 | config_ptr->variance_boost_strength = 2; |
1074 | 430 | config_ptr->variance_octile = 5; |
1075 | 430 | config_ptr->tf_strength = 3; |
1076 | 430 | config_ptr->variance_boost_curve = 0; |
1077 | 430 | config_ptr->luminance_qp_bias = 0; |
1078 | 430 | config_ptr->sharpness = 0; |
1079 | 430 | config_ptr->lossless = false; |
1080 | 430 | config_ptr->avif = false; |
1081 | 430 | config_ptr->qp_scale_compress_strength = 0; |
1082 | 430 | config_ptr->sframe_posi.sframe_num = 0; |
1083 | 430 | config_ptr->sframe_posi.sframe_posis = NULL; |
1084 | 430 | config_ptr->sframe_posi.sframe_qp_num = 0; |
1085 | 430 | config_ptr->sframe_posi.sframe_qps = NULL; |
1086 | 430 | config_ptr->sframe_posi.sframe_qp_offsets = NULL; |
1087 | 430 | config_ptr->sframe_qp = 0; |
1088 | 430 | config_ptr->sframe_qp_offset = 0; |
1089 | 430 | config_ptr->adaptive_film_grain = true; |
1090 | 430 | config_ptr->max_tx_size = 64; |
1091 | 430 | config_ptr->extended_crf_qindex_offset = 0; |
1092 | 430 | config_ptr->ac_bias = 0.0; |
1093 | 430 | config_ptr->hbd_mds = DEFAULT; |
1094 | | |
1095 | | // Ref-frame management disabled by default → legacy bit-exact behavior |
1096 | | // and no extra ref-buffer memory allocated. |
1097 | 430 | config_ptr->max_managed_refs = 0; |
1098 | | |
1099 | 430 | return return_error; |
1100 | 430 | } |
1101 | | |
1102 | 430 | static const char* tier_to_str(unsigned in) { |
1103 | 430 | if (!in) { |
1104 | 430 | return "(auto)"; |
1105 | 430 | } |
1106 | 0 | static char ret[11]; |
1107 | 0 | snprintf(ret, 11, "%u", in); |
1108 | 0 | return ret; |
1109 | 430 | } |
1110 | | |
1111 | 430 | static const char* level_to_str(unsigned in) { |
1112 | 430 | if (!in) { |
1113 | 430 | return "(auto)"; |
1114 | 430 | } |
1115 | 0 | static char ret[313]; |
1116 | 0 | snprintf(ret, 313, "%.1f", in / 10.0); |
1117 | 0 | return ret; |
1118 | 430 | } |
1119 | | |
1120 | 248 | static double get_extended_crf(EbSvtAv1EncConfiguration* config_ptr) { |
1121 | 248 | return (double)config_ptr->qp + (double)config_ptr->extended_crf_qindex_offset / 4; |
1122 | 248 | } |
1123 | | |
1124 | | //#define DEBUG_BUFFERS |
1125 | 430 | void svt_av1_print_lib_params(SequenceControlSet* scs) { |
1126 | 430 | EbSvtAv1EncConfiguration* config = &scs->static_config; |
1127 | | |
1128 | 430 | SVT_INFO("-------------------------------------------\n"); |
1129 | 430 | if (config->pass == ENC_FIRST_PASS) { |
1130 | 0 | SVT_INFO("SVT [config]: preset \t\t\t\t\t\t\t: Pass 1\n"); |
1131 | 430 | } else { |
1132 | 430 | SVT_INFO("SVT [config]: %s\ttier %s\tlevel %s\n", |
1133 | 430 | config->profile == MAIN_PROFILE ? "main profile" |
1134 | 430 | : config->profile == HIGH_PROFILE ? "high profile" |
1135 | 430 | : config->profile == PROFESSIONAL_PROFILE ? "professional profile" |
1136 | 430 | : "Unknown profile", |
1137 | 430 | tier_to_str(config->tier), |
1138 | 430 | level_to_str(config->level)); |
1139 | 430 | SVT_INFO( |
1140 | 430 | "SVT [config]: width / height / fps numerator / fps denominator \t\t: %d / %d / %d / " |
1141 | 430 | "%d\n", |
1142 | 430 | config->source_width, |
1143 | 430 | config->source_height, |
1144 | 430 | config->frame_rate_numerator, |
1145 | 430 | config->frame_rate_denominator); |
1146 | 430 | SVT_INFO( |
1147 | 430 | "SVT [config]: bit-depth / color format \t\t\t\t\t: %d / " |
1148 | 430 | "%s\n", |
1149 | 430 | config->encoder_bit_depth, |
1150 | 430 | config->encoder_color_format == EB_YUV400 ? "YUV400" |
1151 | 430 | : config->encoder_color_format == EB_YUV420 ? "YUV420" |
1152 | 430 | : config->encoder_color_format == EB_YUV422 ? "YUV422" |
1153 | 430 | : config->encoder_color_format == EB_YUV444 ? "YUV444" |
1154 | 430 | : "Unknown color format"); |
1155 | | |
1156 | 430 | #if FTR_TUNE_VMAF |
1157 | 430 | SVT_INFO("SVT [config]: preset / tune / pred struct \t\t\t\t\t: %d / %s / %s\n", |
1158 | 430 | config->enc_mode, |
1159 | 430 | config->tune == TUNE_VQ ? "VQ" |
1160 | 430 | : config->tune == TUNE_PSNR ? "PSNR" |
1161 | 430 | : config->tune == TUNE_SSIM ? "SSIM" |
1162 | 430 | : config->tune == TUNE_MS_SSIM ? "MS_SSIM" |
1163 | 430 | : config->tune == TUNE_VMAF ? "VMAF" |
1164 | 430 | : "IQ", |
1165 | 430 | config->pred_structure == LOW_DELAY ? "low delay" |
1166 | 430 | : config->pred_structure == RANDOM_ACCESS ? "random access" |
1167 | 430 | : config->pred_structure == ALL_INTRA ? "all intra" |
1168 | 430 | : "Unknown pred structure"); |
1169 | | #else |
1170 | | SVT_INFO("SVT [config]: preset / tune / pred struct \t\t\t\t\t: %d / %s / %s\n", |
1171 | | config->enc_mode, |
1172 | | config->tune == TUNE_VQ ? "VQ" |
1173 | | : config->tune == TUNE_PSNR ? "PSNR" |
1174 | | : config->tune == TUNE_SSIM ? "SSIM" |
1175 | | : config->tune == TUNE_MS_SSIM ? "MS_SSIM" |
1176 | | : "IQ", |
1177 | | config->pred_structure == LOW_DELAY ? "low delay" |
1178 | | : config->pred_structure == RANDOM_ACCESS ? "random access" |
1179 | | : config->pred_structure == ALL_INTRA ? "all intra" |
1180 | | : "Unknown pred structure"); |
1181 | | #endif |
1182 | 430 | SVT_INFO( |
1183 | 430 | "SVT [config]: gop size / mini-gop size / key-frame type \t\t\t: " |
1184 | 430 | "%d / %d / %s\n", |
1185 | 430 | config->intra_period_length + 1, |
1186 | 430 | (1 << config->hierarchical_levels), |
1187 | 430 | config->intra_refresh_type == SVT_AV1_FWDKF_REFRESH ? "FWD key frame" |
1188 | 430 | : config->intra_refresh_type == SVT_AV1_KF_REFRESH ? "key frame" |
1189 | 430 | : "Unknown key frame type"); |
1190 | 430 | if (config->lossless) { |
1191 | 182 | SVT_INFO("SVT [config]: BRC mode\t\t\t\t\t\t\t: Lossless Coding \n"); |
1192 | 248 | } else { |
1193 | 248 | switch (config->rate_control_mode) { |
1194 | 248 | case SVT_AV1_RC_MODE_CQP_OR_CRF: |
1195 | 248 | if (config->max_bit_rate) { |
1196 | 0 | SVT_INFO( |
1197 | 0 | "SVT [config]: BRC mode / %s / max bitrate (kbps)\t\t\t: %s / %.2f / " |
1198 | 0 | "%d\n", |
1199 | 0 | scs->tpl || scs->static_config.enable_variance_boost ? "rate factor" : "CQP Assignment", |
1200 | 0 | scs->tpl || scs->static_config.enable_variance_boost ? "capped CRF" : "CQP", |
1201 | 0 | get_extended_crf(config), |
1202 | 0 | (int)config->max_bit_rate / 1000); |
1203 | 248 | } else { |
1204 | 248 | SVT_INFO("SVT [config]: BRC mode / %s \t\t\t\t\t: %s / %.2f \n", |
1205 | 248 | scs->tpl || scs->static_config.enable_variance_boost ? "rate factor" : "CQP Assignment", |
1206 | 248 | scs->tpl || scs->static_config.enable_variance_boost ? "CRF" : "CQP", |
1207 | 248 | get_extended_crf(config)); |
1208 | 248 | } |
1209 | 248 | break; |
1210 | 0 | case SVT_AV1_RC_MODE_VBR: |
1211 | 0 | SVT_INFO("SVT [config]: BRC mode / target bitrate (kbps)\t\t\t\t: VBR / %d \n", |
1212 | 0 | (int)config->target_bit_rate / 1000); |
1213 | 0 | break; |
1214 | 0 | case SVT_AV1_RC_MODE_CBR: |
1215 | 0 | SVT_INFO( |
1216 | 0 | "SVT [config]: BRC mode / target bitrate (kbps)\t\t\t\t: CBR " |
1217 | 0 | "/ %d\n", |
1218 | 0 | (int)config->target_bit_rate / 1000); |
1219 | 0 | break; |
1220 | 248 | } |
1221 | 248 | } |
1222 | 430 | if (config->rate_control_mode != SVT_AV1_RC_MODE_CBR) { |
1223 | 430 | if (!config->enable_variance_boost) { |
1224 | 430 | SVT_INFO("SVT [config]: AQ mode / Variance Boost \t\t\t\t\t: %d / %d\n", |
1225 | 430 | config->aq_mode, |
1226 | 430 | config->enable_variance_boost); |
1227 | 430 | } else { |
1228 | 0 | SVT_INFO("SVT [config]: AQ mode / Variance Boost strength / octile / curve \t\t: %d / %d / %d / %d\n", |
1229 | 0 | config->aq_mode, |
1230 | 0 | config->variance_boost_strength, |
1231 | 0 | config->variance_octile, |
1232 | 0 | config->variance_boost_curve); |
1233 | 0 | } |
1234 | 430 | } |
1235 | | |
1236 | 430 | if (config->film_grain_denoise_strength != 0) { |
1237 | 0 | if (config->adaptive_film_grain) { |
1238 | 0 | SVT_INFO( |
1239 | 0 | "SVT [config]: film grain synth / denoising / level / adaptive blocksize \t: %d / %d / %d / True\n", |
1240 | 0 | 1, |
1241 | 0 | config->film_grain_denoise_apply, |
1242 | 0 | config->film_grain_denoise_strength); |
1243 | 0 | } else { |
1244 | 0 | SVT_INFO( |
1245 | 0 | "SVT [config]: film grain synth / denoising / level / adaptive blocksize \t: %d / %d / %d / " |
1246 | 0 | "False\n", |
1247 | 0 | 1, |
1248 | 0 | config->film_grain_denoise_apply, |
1249 | 0 | config->film_grain_denoise_strength); |
1250 | 0 | } |
1251 | 0 | } |
1252 | 430 | SVT_INFO("SVT [config]: sharpness / luminance-based QP bias \t\t\t\t: %d / %d\n", |
1253 | 430 | config->sharpness, |
1254 | 430 | config->luminance_qp_bias); |
1255 | | |
1256 | 430 | switch (config->enable_tf) { |
1257 | 0 | case 1: |
1258 | 0 | if (config->tf_strength != 3) { |
1259 | 0 | SVT_INFO("SVT [config]: temporal filtering strength \t\t\t\t\t: %d\n", config->tf_strength); |
1260 | 0 | } |
1261 | 0 | break; |
1262 | 0 | case 2: |
1263 | 0 | SVT_INFO("SVT [config]: temporal filtering strength \t\t\t\t\t: auto\n"); |
1264 | 0 | break; |
1265 | 430 | default: |
1266 | 430 | break; |
1267 | 430 | } |
1268 | | |
1269 | 430 | SVT_INFO("SVT [config]: QP scale compress strength \t\t\t\t\t: %d\n", config->qp_scale_compress_strength); |
1270 | | |
1271 | 430 | if (config->ac_bias) { |
1272 | 0 | SVT_INFO("SVT [config]: AC Bias Strength \t\t\t\t\t\t: %.2f\n", config->ac_bias); |
1273 | 0 | } |
1274 | | |
1275 | 430 | if (config->hbd_mds) { |
1276 | 430 | SVT_INFO("SVT [config]: High Bit Depth Mode Decision setting \t\t\t\t\t: %d\n", config->hbd_mds); |
1277 | 430 | } |
1278 | 430 | } |
1279 | | #if DEBUG_BUFFERS |
1280 | | SVT_INFO("SVT [config]: INPUT / OUTPUT \t\t\t\t\t\t\t: %d / %d\n", |
1281 | | scs->input_buffer_fifo_init_count, |
1282 | | scs->output_stream_buffer_fifo_init_count); |
1283 | | SVT_INFO("SVT [config]: CPCS / PAREF / REF / ME\t\t\t\t\t\t: %d / %d / %d / %d\n", |
1284 | | scs->picture_control_set_pool_init_count_child, |
1285 | | scs->pa_reference_picture_buffer_init_count, |
1286 | | scs->reference_picture_buffer_init_count, |
1287 | | scs->me_pool_init_count); |
1288 | | SVT_INFO("SVT [config]: ME_SEG_W / ME_SEG_H \t\t\t: %u / %u\n", |
1289 | | scs->me_segment_col_count_array, |
1290 | | scs->me_segment_row_count_array); |
1291 | | SVT_INFO("SVT [config]: ENC_DEC_SEG_W / ENC_DEC_SEG_H \t\t\t: %u / %u\n", |
1292 | | scs->enc_dec_segment_col_count_array, |
1293 | | scs->enc_dec_segment_row_count_array); |
1294 | | SVT_INFO( |
1295 | | "SVT [config]: PA_P / ME_P / SBO_P / MDC_P / ED_P / EC_P \t\t\t: %d / %d / %d / %d / %d / " |
1296 | | "%d\n", |
1297 | | scs->picture_analysis_process_init_count, |
1298 | | scs->motion_estimation_process_init_count, |
1299 | | scs->source_based_operations_process_init_count, |
1300 | | scs->mode_decision_configuration_process_init_count, |
1301 | | scs->enc_dec_process_init_count, |
1302 | | scs->entropy_coding_process_init_count); |
1303 | | SVT_INFO("SVT [config]: DLF_P / CDEF_P / REST_P \t\t\t\t\t\t: %d / %d / %d\n", |
1304 | | scs->dlf_process_init_count, |
1305 | | scs->cdef_process_init_count, |
1306 | | scs->rest_process_init_count); |
1307 | | #endif |
1308 | 430 | SVT_INFO("-------------------------------------------\n"); |
1309 | | |
1310 | 430 | fflush(stdout); |
1311 | 430 | } |
1312 | | |
1313 | | /********************************** |
1314 | | * Parse Single Parameter |
1315 | | **********************************/ |
1316 | | |
1317 | 0 | static EbErrorType str_to_int64(const char* nptr, int64_t* out, char** nextptr) { |
1318 | 0 | char* endptr; |
1319 | 0 | int64_t val; |
1320 | |
|
1321 | 0 | val = strtoll(nptr, &endptr, 0); |
1322 | |
|
1323 | 0 | if (endptr == nptr || (!nextptr && *endptr)) { |
1324 | 0 | return EB_ErrorBadParameter; |
1325 | 0 | } |
1326 | | |
1327 | 0 | *out = val; |
1328 | 0 | if (nextptr) { |
1329 | 0 | *nextptr = endptr; |
1330 | 0 | } |
1331 | 0 | return EB_ErrorNone; |
1332 | 0 | } |
1333 | | |
1334 | 0 | static EbErrorType str_to_int(const char* nptr, int32_t* out, char** nextptr) { |
1335 | 0 | char* endptr; |
1336 | 0 | int32_t val; |
1337 | |
|
1338 | 0 | val = strtol(nptr, &endptr, 0); |
1339 | |
|
1340 | 0 | if (endptr == nptr || (!nextptr && *endptr)) { |
1341 | 0 | return EB_ErrorBadParameter; |
1342 | 0 | } |
1343 | | |
1344 | 0 | *out = val; |
1345 | 0 | if (nextptr) { |
1346 | 0 | *nextptr = endptr; |
1347 | 0 | } |
1348 | 0 | return EB_ErrorNone; |
1349 | 0 | } |
1350 | | |
1351 | 0 | static EbErrorType str_to_uint64(const char* nptr, uint64_t* out, char** nextptr) { |
1352 | 0 | char* endptr; |
1353 | 0 | uint64_t val; |
1354 | |
|
1355 | 0 | if (strtoll(nptr, NULL, 0) < 0) { |
1356 | 0 | return EB_ErrorBadParameter; |
1357 | 0 | } |
1358 | | |
1359 | 0 | val = strtoull(nptr, &endptr, 0); |
1360 | |
|
1361 | 0 | if (endptr == nptr || (!nextptr && *endptr)) { |
1362 | 0 | return EB_ErrorBadParameter; |
1363 | 0 | } |
1364 | | |
1365 | 0 | *out = val; |
1366 | 0 | if (nextptr) { |
1367 | 0 | *nextptr = endptr; |
1368 | 0 | } |
1369 | 0 | return EB_ErrorNone; |
1370 | 0 | } |
1371 | | |
1372 | 0 | static EbErrorType str_to_uint(const char* nptr, uint32_t* out, char** nextptr) { |
1373 | 0 | char* endptr; |
1374 | 0 | uint32_t val; |
1375 | |
|
1376 | 0 | if (strtol(nptr, NULL, 0) < 0) { |
1377 | 0 | return EB_ErrorBadParameter; |
1378 | 0 | } |
1379 | | |
1380 | 0 | val = strtoul(nptr, &endptr, 0); |
1381 | |
|
1382 | 0 | if (endptr == nptr || (!nextptr && *endptr)) { |
1383 | 0 | return EB_ErrorBadParameter; |
1384 | 0 | } |
1385 | | |
1386 | 0 | *out = val; |
1387 | 0 | if (nextptr) { |
1388 | 0 | *nextptr = endptr; |
1389 | 0 | } |
1390 | 0 | return EB_ErrorNone; |
1391 | 0 | } |
1392 | | |
1393 | 0 | static EbErrorType str_to_int8(const char* nptr, int8_t* out, char** nextptr) { |
1394 | 0 | char* endptr; |
1395 | 0 | int32_t val; |
1396 | |
|
1397 | 0 | val = strtol(nptr, &endptr, 0); |
1398 | |
|
1399 | 0 | if (endptr == nptr || (!nextptr && *endptr)) { |
1400 | 0 | return EB_ErrorBadParameter; |
1401 | 0 | } |
1402 | | |
1403 | | // check for the range |
1404 | 0 | if (val < INT8_MIN || val > INT8_MAX) { |
1405 | 0 | return EB_ErrorBadParameter; |
1406 | 0 | } |
1407 | | |
1408 | 0 | *out = (int8_t)val; |
1409 | 0 | if (nextptr) { |
1410 | 0 | *nextptr = endptr; |
1411 | 0 | } |
1412 | 0 | return EB_ErrorNone; |
1413 | 0 | } |
1414 | | |
1415 | 0 | static EbErrorType str_to_uint8(const char* nptr, uint8_t* out, char** nextptr) { |
1416 | 0 | char* endptr; |
1417 | 0 | uint32_t val; |
1418 | |
|
1419 | 0 | if (strtol(nptr, NULL, 0) < 0) { |
1420 | 0 | return EB_ErrorBadParameter; |
1421 | 0 | } |
1422 | | |
1423 | 0 | val = strtoul(nptr, &endptr, 0); |
1424 | |
|
1425 | 0 | if (endptr == nptr || (!nextptr && *endptr)) { |
1426 | 0 | return EB_ErrorBadParameter; |
1427 | 0 | } |
1428 | | |
1429 | | // check for the range |
1430 | 0 | if (val > UINT8_MAX) { |
1431 | 0 | return EB_ErrorBadParameter; |
1432 | 0 | } |
1433 | | |
1434 | 0 | *out = (uint8_t)val; |
1435 | 0 | if (nextptr) { |
1436 | 0 | *nextptr = endptr; |
1437 | 0 | } |
1438 | 0 | return EB_ErrorNone; |
1439 | 0 | } |
1440 | | |
1441 | 0 | #define str_to_int32 str_to_int |
1442 | 0 | #define str_to_uint32 str_to_uint |
1443 | | |
1444 | 0 | static EbErrorType str_to_double(const char* nptr, double* out, char** nextptr) { |
1445 | 0 | char* endptr; |
1446 | 0 | double val; |
1447 | |
|
1448 | 0 | val = strtod(nptr, &endptr); |
1449 | |
|
1450 | 0 | if (endptr == nptr || (!nextptr && *endptr)) { |
1451 | 0 | return EB_ErrorBadParameter; |
1452 | 0 | } |
1453 | | |
1454 | 0 | *out = val; |
1455 | 0 | if (nextptr) { |
1456 | 0 | *nextptr = endptr; |
1457 | 0 | } |
1458 | 0 | return EB_ErrorNone; |
1459 | 0 | } |
1460 | | |
1461 | | //assume the input list of values are in the format of "[v1,v2,v3,...]" |
1462 | | #define PARSE_LIST(list_type) \ |
1463 | 0 | static EbErrorType parse_list_##list_type(const char* nptr, list_type##_t* list, size_t n) { \ |
1464 | 0 | const char* ptr = nptr; \ |
1465 | 0 | char* endptr; \ |
1466 | 0 | size_t i = 0; \ |
1467 | 0 | memset(list, 0, n * sizeof(*list)); \ |
1468 | 0 | while (*ptr) { \ |
1469 | 0 | if (*ptr == '[' || *ptr == ']') { \ |
1470 | 0 | ptr++; \ |
1471 | 0 | continue; \ |
1472 | 0 | } \ |
1473 | 0 | list_type##_t rawval; \ |
1474 | 0 | EbErrorType err = str_to_##list_type(ptr, &rawval, &endptr); \ |
1475 | 0 | if (err != EB_ErrorNone) \ |
1476 | 0 | return err; \ |
1477 | 0 | if (i >= n) { \ |
1478 | 0 | return EB_ErrorBadParameter; \ |
1479 | 0 | } else if (*endptr == ',' || *endptr == ']') { \ |
1480 | 0 | endptr++; \ |
1481 | 0 | } else if (*endptr) { \ |
1482 | 0 | return EB_ErrorBadParameter; \ |
1483 | 0 | } \ |
1484 | 0 | list[i++] = rawval; \ |
1485 | 0 | ptr = endptr; \ |
1486 | 0 | } \ |
1487 | 0 | return EB_ErrorNone; \ |
1488 | 0 | } Unexecuted instantiation: enc_settings.c:parse_list_int32 Unexecuted instantiation: enc_settings.c:parse_list_uint64 Unexecuted instantiation: enc_settings.c:parse_list_uint32 Unexecuted instantiation: enc_settings.c:parse_list_uint8 Unexecuted instantiation: enc_settings.c:parse_list_int8 |
1489 | | PARSE_LIST(int8) |
1490 | | PARSE_LIST(uint8) |
1491 | | PARSE_LIST(int32) |
1492 | | PARSE_LIST(uint32) |
1493 | | PARSE_LIST(uint64) |
1494 | | |
1495 | 0 | static uint32_t count_params(const char* nptr) { |
1496 | 0 | const char* ptr = nptr; |
1497 | 0 | char* endptr; |
1498 | 0 | uint32_t i = 0; |
1499 | 0 | while (*ptr) { |
1500 | 0 | if (*ptr == '[' || *ptr == ']') { |
1501 | 0 | ptr++; |
1502 | 0 | continue; |
1503 | 0 | } |
1504 | | |
1505 | 0 | strtoll(ptr, &endptr, 10); |
1506 | 0 | if (*endptr == ',' || *endptr == ']') { |
1507 | 0 | endptr++; |
1508 | 0 | } else if (*endptr) { |
1509 | 0 | return i; |
1510 | 0 | } |
1511 | 0 | i++; |
1512 | 0 | ptr = endptr; |
1513 | 0 | } |
1514 | 0 | return i; |
1515 | 0 | } |
1516 | | |
1517 | | #ifdef _MSC_VER |
1518 | | #define strcasecmp _stricmp |
1519 | | #endif |
1520 | 0 | static EbErrorType str_to_bool(const char* nptr, bool* out) { |
1521 | 0 | bool val; |
1522 | 0 | if (!strcmp(nptr, "1") || !strcasecmp(nptr, "true") || !strcasecmp(nptr, "yes")) { |
1523 | 0 | val = true; |
1524 | 0 | } else if (!strcmp(nptr, "0") || !strcasecmp(nptr, "false") || !strcasecmp(nptr, "no")) { |
1525 | 0 | val = false; |
1526 | 0 | } else { |
1527 | 0 | return EB_ErrorBadParameter; |
1528 | 0 | } |
1529 | | |
1530 | 0 | *out = val; |
1531 | 0 | return EB_ErrorNone; |
1532 | 0 | } |
1533 | | |
1534 | 0 | static EbErrorType str_to_crf(const char* nptr, EbSvtAv1EncConfiguration* config_struct) { |
1535 | 0 | double crf; |
1536 | 0 | EbErrorType return_error; |
1537 | |
|
1538 | 0 | return_error = str_to_double(nptr, &crf, NULL); |
1539 | |
|
1540 | 0 | if (return_error == EB_ErrorBadParameter) { |
1541 | 0 | return return_error; |
1542 | 0 | } |
1543 | 0 | if (crf < 0) { |
1544 | 0 | return EB_ErrorBadParameter; |
1545 | 0 | } |
1546 | | |
1547 | 0 | uint32_t extended_q_index = (uint32_t)(crf * 4); |
1548 | 0 | uint32_t qp = AOMMIN(MAX_QP_VALUE, (uint32_t)crf); |
1549 | 0 | uint32_t extended_crf_qindex_offset = extended_q_index - qp * 4; |
1550 | |
|
1551 | 0 | config_struct->qp = qp; |
1552 | 0 | config_struct->rate_control_mode = SVT_AV1_RC_MODE_CQP_OR_CRF; |
1553 | 0 | config_struct->aq_mode = 2; |
1554 | 0 | config_struct->extended_crf_qindex_offset = extended_crf_qindex_offset; |
1555 | |
|
1556 | 0 | return EB_ErrorNone; |
1557 | 0 | } |
1558 | | |
1559 | 0 | static EbErrorType str_to_cqp(const char* nptr, EbSvtAv1EncConfiguration* config_struct) { |
1560 | 0 | double cqp; |
1561 | 0 | EbErrorType return_error; |
1562 | |
|
1563 | 0 | return_error = str_to_double(nptr, &cqp, NULL); |
1564 | |
|
1565 | 0 | if (return_error == EB_ErrorBadParameter) { |
1566 | 0 | return return_error; |
1567 | 0 | } |
1568 | 0 | if (cqp < 0) { |
1569 | 0 | return EB_ErrorBadParameter; |
1570 | 0 | } |
1571 | | |
1572 | 0 | uint32_t extended_q_index = (uint32_t)(cqp * 4); |
1573 | 0 | uint32_t qp = AOMMIN(MAX_QP_VALUE, (uint32_t)cqp); |
1574 | 0 | uint32_t extended_crf_qindex_offset = extended_q_index - qp * 4; |
1575 | |
|
1576 | 0 | config_struct->qp = qp; |
1577 | 0 | config_struct->rate_control_mode = SVT_AV1_RC_MODE_CQP_OR_CRF; |
1578 | 0 | config_struct->aq_mode = 0; |
1579 | 0 | config_struct->extended_crf_qindex_offset = extended_crf_qindex_offset; |
1580 | |
|
1581 | 0 | return EB_ErrorNone; |
1582 | 0 | } |
1583 | | |
1584 | 0 | static EbErrorType str_to_keyint(const char* nptr, int32_t* out, bool* multi) { |
1585 | 0 | char* suff; |
1586 | 0 | const long keyint = strtol(nptr, &suff, 0); |
1587 | |
|
1588 | 0 | if (keyint > INT32_MAX || keyint < -2) { |
1589 | 0 | return EB_ErrorBadParameter; |
1590 | 0 | } |
1591 | | |
1592 | 0 | switch (*suff) { |
1593 | 0 | case 's': |
1594 | | // signal we need to multiply keyint * frame_rate |
1595 | 0 | *multi = true; |
1596 | 0 | *out = keyint; |
1597 | 0 | break; |
1598 | 0 | case '\0': |
1599 | 0 | *multi = false; |
1600 | 0 | *out = keyint < 0 ? keyint : keyint - 1; |
1601 | 0 | break; |
1602 | 0 | default: |
1603 | | // else leave as untouched, we have an invalid keyint |
1604 | 0 | SVT_ERROR("Invalid keyint value: %s\n", nptr); |
1605 | 0 | return EB_ErrorBadParameter; |
1606 | 0 | } |
1607 | | |
1608 | 0 | return EB_ErrorNone; |
1609 | 0 | } |
1610 | | |
1611 | 0 | static EbErrorType str_to_bitrate(const char* nptr, uint32_t* out) { |
1612 | 0 | char* suff; |
1613 | 0 | const double bitrate = strtod(nptr, &suff); |
1614 | |
|
1615 | 0 | if (bitrate < 0 || bitrate > UINT32_MAX) { |
1616 | 0 | SVT_ERROR("Invalid bitrate value: %s\n", nptr); |
1617 | 0 | return EB_ErrorBadParameter; |
1618 | 0 | } |
1619 | | |
1620 | 0 | switch (*suff) { |
1621 | 0 | case 'b': |
1622 | 0 | case 'B': |
1623 | 0 | *out = (uint32_t)bitrate; |
1624 | 0 | break; |
1625 | 0 | case '\0': |
1626 | 0 | case 'k': |
1627 | 0 | case 'K': |
1628 | 0 | *out = (uint32_t)(1000 * bitrate); |
1629 | 0 | break; |
1630 | 0 | case 'm': |
1631 | 0 | case 'M': |
1632 | 0 | *out = (uint32_t)(1000000 * bitrate); |
1633 | 0 | break; |
1634 | 0 | default: |
1635 | 0 | return EB_ErrorBadParameter; |
1636 | 0 | } |
1637 | 0 | if (*out > 100000000) { |
1638 | 0 | *out = 100000000; |
1639 | 0 | SVT_WARN("Bitrate value: %s has been set to 100000000\n", nptr); |
1640 | 0 | } |
1641 | 0 | return EB_ErrorNone; |
1642 | 0 | } |
1643 | | |
1644 | 0 | static EbErrorType str_to_profile(const char* nptr, EbAv1SeqProfile* out) { |
1645 | 0 | const struct { |
1646 | 0 | const char* name; |
1647 | 0 | EbAv1SeqProfile profile; |
1648 | 0 | } profiles[] = { |
1649 | 0 | {"main", MAIN_PROFILE}, |
1650 | 0 | {"high", HIGH_PROFILE}, |
1651 | 0 | {"professional", PROFESSIONAL_PROFILE}, |
1652 | 0 | }; |
1653 | |
|
1654 | 0 | const size_t profiles_size = sizeof(profiles) / sizeof(profiles[0]); |
1655 | |
|
1656 | 0 | for (size_t i = 0; i < profiles_size; i++) { |
1657 | 0 | if (!strcmp(nptr, profiles[i].name)) { |
1658 | 0 | *out = profiles[i].profile; |
1659 | 0 | return EB_ErrorNone; |
1660 | 0 | } |
1661 | 0 | } |
1662 | | |
1663 | 0 | return EB_ErrorBadParameter; |
1664 | 0 | } |
1665 | | |
1666 | 0 | static EbErrorType str_to_color_fmt(const char* nptr, EbColorFormat* out) { |
1667 | 0 | const struct { |
1668 | 0 | const char* name; |
1669 | 0 | EbColorFormat fmt; |
1670 | 0 | } color_formats[] = { |
1671 | 0 | {"mono", EB_YUV400}, |
1672 | 0 | {"400", EB_YUV400}, |
1673 | 0 | {"420", EB_YUV420}, |
1674 | 0 | {"422", EB_YUV422}, |
1675 | 0 | {"444", EB_YUV444}, |
1676 | 0 | }; |
1677 | |
|
1678 | 0 | const size_t color_format_size = sizeof(color_formats) / sizeof(color_formats[0]); |
1679 | |
|
1680 | 0 | for (size_t i = 0; i < color_format_size; i++) { |
1681 | 0 | if (!strcmp(nptr, color_formats[i].name)) { |
1682 | 0 | *out = color_formats[i].fmt; |
1683 | 0 | return EB_ErrorNone; |
1684 | 0 | } |
1685 | 0 | } |
1686 | | |
1687 | 0 | return EB_ErrorBadParameter; |
1688 | 0 | } |
1689 | | |
1690 | 0 | static EbErrorType str_to_intra_rt(const char* nptr, SvtAv1IntraRefreshType* out) { |
1691 | 0 | const struct { |
1692 | 0 | const char* name; |
1693 | 0 | SvtAv1IntraRefreshType type; |
1694 | 0 | } refresh_types[] = { |
1695 | 0 | {"cra", SVT_AV1_FWDKF_REFRESH}, |
1696 | 0 | {"fwdkf", SVT_AV1_FWDKF_REFRESH}, |
1697 | 0 | {"idr", SVT_AV1_KF_REFRESH}, |
1698 | 0 | {"kf", SVT_AV1_KF_REFRESH}, |
1699 | 0 | }; |
1700 | |
|
1701 | 0 | const size_t refresh_type_size = sizeof(refresh_types) / sizeof(refresh_types[0]); |
1702 | |
|
1703 | 0 | for (size_t i = 0; i < refresh_type_size; i++) { |
1704 | 0 | if (!strcmp(nptr, refresh_types[i].name)) { |
1705 | 0 | *out = refresh_types[i].type; |
1706 | 0 | return EB_ErrorNone; |
1707 | 0 | } |
1708 | 0 | } |
1709 | | |
1710 | 0 | return EB_ErrorBadParameter; |
1711 | 0 | } |
1712 | | |
1713 | 0 | static EbErrorType str_to_asm(const char* nptr, EbCpuFlags* out) { |
1714 | | // need to handle numbers in here since the numbers to no match the |
1715 | | // internal representation |
1716 | 0 | const struct { |
1717 | 0 | const char* name; |
1718 | 0 | EbCpuFlags flag; |
1719 | 0 | } simds[] = { |
1720 | 0 | {"c", 0}, |
1721 | 0 | {"0", 0}, |
1722 | | #ifdef ARCH_X86_64 |
1723 | | {"mmx", (EB_CPU_FLAGS_MMX << 1) - 1}, |
1724 | | {"1", (EB_CPU_FLAGS_MMX << 1) - 1}, |
1725 | | {"sse", (EB_CPU_FLAGS_SSE << 1) - 1}, |
1726 | | {"2", (EB_CPU_FLAGS_SSE << 1) - 1}, |
1727 | | {"sse2", (EB_CPU_FLAGS_SSE2 << 1) - 1}, |
1728 | | {"3", (EB_CPU_FLAGS_SSE2 << 1) - 1}, |
1729 | | {"sse3", (EB_CPU_FLAGS_SSE3 << 1) - 1}, |
1730 | | {"4", (EB_CPU_FLAGS_SSE3 << 1) - 1}, |
1731 | | {"ssse3", (EB_CPU_FLAGS_SSSE3 << 1) - 1}, |
1732 | | {"5", (EB_CPU_FLAGS_SSSE3 << 1) - 1}, |
1733 | | {"sse4_1", (EB_CPU_FLAGS_SSE4_1 << 1) - 1}, |
1734 | | {"6", (EB_CPU_FLAGS_SSE4_1 << 1) - 1}, |
1735 | | {"sse4_2", (EB_CPU_FLAGS_SSE4_2 << 1) - 1}, |
1736 | | {"7", (EB_CPU_FLAGS_SSE4_2 << 1) - 1}, |
1737 | | {"avx", (EB_CPU_FLAGS_AVX << 1) - 1}, |
1738 | | {"8", (EB_CPU_FLAGS_AVX << 1) - 1}, |
1739 | | {"avx2", (EB_CPU_FLAGS_AVX2 << 1) - 1}, |
1740 | | {"9", (EB_CPU_FLAGS_AVX2 << 1) - 1}, |
1741 | | {"avx512", (EB_CPU_FLAGS_AVX512VL << 1) - 1}, |
1742 | | {"10", (EB_CPU_FLAGS_AVX512VL << 1) - 1}, |
1743 | | {"avx512icl", (EB_CPU_FLAGS_AVX512ICL << 1) - 1}, |
1744 | | {"11", (EB_CPU_FLAGS_AVX512ICL << 1) - 1}, |
1745 | | #elif defined(ARCH_AARCH64) |
1746 | | {"neon", (EB_CPU_FLAGS_NEON << 1) - 1}, |
1747 | | {"1", (EB_CPU_FLAGS_NEON << 1) - 1}, |
1748 | | {"crc32", (EB_CPU_FLAGS_ARM_CRC32 << 1) - 1}, |
1749 | | {"2", (EB_CPU_FLAGS_ARM_CRC32 << 1) - 1}, |
1750 | | {"neon_dotprod", (EB_CPU_FLAGS_NEON_DOTPROD << 1) - 1}, |
1751 | | {"3", (EB_CPU_FLAGS_NEON_DOTPROD << 1) - 1}, |
1752 | | {"neon_i8mm", (EB_CPU_FLAGS_NEON_I8MM << 1) - 1}, |
1753 | | {"4", (EB_CPU_FLAGS_NEON_I8MM << 1) - 1}, |
1754 | | {"sve", (EB_CPU_FLAGS_SVE << 1) - 1}, |
1755 | | {"5", (EB_CPU_FLAGS_SVE << 1) - 1}, |
1756 | | {"sve2", (EB_CPU_FLAGS_SVE2 << 1) - 1}, |
1757 | | {"6", (EB_CPU_FLAGS_SVE2 << 1) - 1}, |
1758 | | #endif |
1759 | 0 | {"max", EB_CPU_FLAGS_ALL}, |
1760 | 0 | {"100", EB_CPU_FLAGS_ALL}, |
1761 | 0 | }; |
1762 | 0 | const size_t simds_size = sizeof(simds) / sizeof(simds[0]); |
1763 | |
|
1764 | 0 | for (size_t i = 0; i < simds_size; i++) { |
1765 | 0 | if (!strcmp(nptr, simds[i].name)) { |
1766 | 0 | *out = simds[i].flag; |
1767 | 0 | return EB_ErrorNone; |
1768 | 0 | } |
1769 | 0 | } |
1770 | | |
1771 | 0 | *out = EB_CPU_FLAGS_INVALID; |
1772 | |
|
1773 | 0 | return EB_ErrorBadParameter; |
1774 | 0 | } |
1775 | | |
1776 | 0 | static EbErrorType str_to_color_primaries(const char* nptr, EbColorPrimaries* out) { |
1777 | 0 | const struct { |
1778 | 0 | const char* name; |
1779 | 0 | EbColorPrimaries primaries; |
1780 | 0 | } color_primaries[] = { |
1781 | 0 | {"bt709", EB_CICP_CP_BT_709}, |
1782 | 0 | {"bt470m", EB_CICP_CP_BT_470_M}, |
1783 | 0 | {"bt470bg", EB_CICP_CP_BT_470_B_G}, |
1784 | 0 | {"bt601", EB_CICP_CP_BT_601}, |
1785 | 0 | {"smpte240", EB_CICP_CP_SMPTE_240}, |
1786 | 0 | {"film", EB_CICP_CP_GENERIC_FILM}, |
1787 | 0 | {"bt2020", EB_CICP_CP_BT_2020}, |
1788 | 0 | {"xyz", EB_CICP_CP_XYZ}, |
1789 | 0 | {"smpte431", EB_CICP_CP_SMPTE_431}, |
1790 | 0 | {"smpte432", EB_CICP_CP_SMPTE_432}, |
1791 | 0 | {"ebu3213", EB_CICP_CP_EBU_3213}, |
1792 | 0 | }; |
1793 | |
|
1794 | 0 | const size_t color_primaries_size = sizeof(color_primaries) / sizeof(color_primaries[0]); |
1795 | |
|
1796 | 0 | for (size_t i = 0; i < color_primaries_size; i++) { |
1797 | 0 | if (!strcmp(nptr, color_primaries[i].name)) { |
1798 | 0 | *out = color_primaries[i].primaries; |
1799 | 0 | return EB_ErrorNone; |
1800 | 0 | } |
1801 | 0 | } |
1802 | | |
1803 | 0 | return EB_ErrorBadParameter; |
1804 | 0 | } |
1805 | | |
1806 | 0 | static EbErrorType str_to_transfer_characteristics(const char* nptr, EbTransferCharacteristics* out) { |
1807 | 0 | const struct { |
1808 | 0 | const char* name; |
1809 | 0 | EbTransferCharacteristics tfc; |
1810 | 0 | } transfer_characteristics[] = { |
1811 | 0 | {"bt709", EB_CICP_TC_BT_709}, |
1812 | 0 | {"bt470m", EB_CICP_TC_BT_470_M}, |
1813 | 0 | {"bt470bg", EB_CICP_TC_BT_470_B_G}, |
1814 | 0 | {"bt601", EB_CICP_TC_BT_601}, |
1815 | 0 | {"smpte240", EB_CICP_TC_SMPTE_240}, |
1816 | 0 | {"linear", EB_CICP_TC_LINEAR}, |
1817 | 0 | {"log100", EB_CICP_TC_LOG_100}, |
1818 | 0 | {"log100-sqrt10", EB_CICP_TC_LOG_100_SQRT10}, |
1819 | 0 | {"iec61966", EB_CICP_TC_IEC_61966}, |
1820 | 0 | {"bt1361", EB_CICP_TC_BT_1361}, |
1821 | 0 | {"srgb", EB_CICP_TC_SRGB}, |
1822 | 0 | {"bt2020-10", EB_CICP_TC_BT_2020_10_BIT}, |
1823 | 0 | {"bt2020-12", EB_CICP_TC_BT_2020_12_BIT}, |
1824 | 0 | {"smpte2084", EB_CICP_TC_SMPTE_2084}, |
1825 | 0 | {"smpte428", EB_CICP_TC_SMPTE_428}, |
1826 | 0 | {"hlg", EB_CICP_TC_HLG}, |
1827 | 0 | }; |
1828 | |
|
1829 | 0 | const size_t transfer_characteristics_size = sizeof(transfer_characteristics) / sizeof(transfer_characteristics[0]); |
1830 | |
|
1831 | 0 | for (size_t i = 0; i < transfer_characteristics_size; i++) { |
1832 | 0 | if (!strcmp(nptr, transfer_characteristics[i].name)) { |
1833 | 0 | *out = transfer_characteristics[i].tfc; |
1834 | 0 | return EB_ErrorNone; |
1835 | 0 | } |
1836 | 0 | } |
1837 | | |
1838 | 0 | return EB_ErrorBadParameter; |
1839 | 0 | } |
1840 | | |
1841 | 0 | static EbErrorType str_to_matrix_coefficients(const char* nptr, EbMatrixCoefficients* out) { |
1842 | 0 | const struct { |
1843 | 0 | const char* name; |
1844 | 0 | EbMatrixCoefficients coeff; |
1845 | 0 | } matrix_coefficients[] = { |
1846 | 0 | {"identity", EB_CICP_MC_IDENTITY}, |
1847 | 0 | {"bt709", EB_CICP_MC_BT_709}, |
1848 | 0 | {"fcc", EB_CICP_MC_FCC}, |
1849 | 0 | {"bt470bg", EB_CICP_MC_BT_470_B_G}, |
1850 | 0 | {"bt601", EB_CICP_MC_BT_601}, |
1851 | 0 | {"smpte240", EB_CICP_MC_SMPTE_240}, |
1852 | 0 | {"ycgco", EB_CICP_MC_SMPTE_YCGCO}, |
1853 | 0 | {"bt2020-ncl", EB_CICP_MC_BT_2020_NCL}, |
1854 | 0 | {"bt2020-cl", EB_CICP_MC_BT_2020_CL}, |
1855 | 0 | {"smpte2085", EB_CICP_MC_SMPTE_2085}, |
1856 | 0 | {"chroma-ncl", EB_CICP_MC_CHROMAT_NCL}, |
1857 | 0 | {"chroma-cl", EB_CICP_MC_CHROMAT_CL}, |
1858 | 0 | {"ictcp", EB_CICP_MC_ICTCP}, |
1859 | 0 | }; |
1860 | |
|
1861 | 0 | const size_t matrix_coefficients_size = sizeof(matrix_coefficients) / sizeof(matrix_coefficients[0]); |
1862 | |
|
1863 | 0 | for (size_t i = 0; i < matrix_coefficients_size; i++) { |
1864 | 0 | if (!strcmp(nptr, matrix_coefficients[i].name)) { |
1865 | 0 | *out = matrix_coefficients[i].coeff; |
1866 | 0 | return EB_ErrorNone; |
1867 | 0 | } |
1868 | 0 | } |
1869 | | |
1870 | 0 | return EB_ErrorBadParameter; |
1871 | 0 | } |
1872 | | |
1873 | 0 | static EbErrorType str_to_color_range(const char* nptr, EbColorRange* out) { |
1874 | 0 | const struct { |
1875 | 0 | const char* name; |
1876 | 0 | EbColorRange range; |
1877 | 0 | } color_range[] = { |
1878 | 0 | {"studio", EB_CR_STUDIO_RANGE}, |
1879 | 0 | {"full", EB_CR_FULL_RANGE}, |
1880 | 0 | }; |
1881 | |
|
1882 | 0 | const size_t color_range_size = sizeof(color_range) / sizeof(color_range[0]); |
1883 | |
|
1884 | 0 | for (size_t i = 0; i < color_range_size; i++) { |
1885 | 0 | if (!strcmp(nptr, color_range[i].name)) { |
1886 | 0 | *out = color_range[i].range; |
1887 | 0 | return EB_ErrorNone; |
1888 | 0 | } |
1889 | 0 | } |
1890 | | |
1891 | 0 | return EB_ErrorBadParameter; |
1892 | 0 | } |
1893 | | |
1894 | 0 | static EbErrorType str_to_chroma_sample_position(const char* nptr, EbChromaSamplePosition* out) { |
1895 | 0 | const struct { |
1896 | 0 | const char* name; |
1897 | 0 | EbChromaSamplePosition pos; |
1898 | 0 | } chroma_sample_positions[] = { |
1899 | 0 | {"unknown", EB_CSP_UNKNOWN}, |
1900 | 0 | {"vertical", EB_CSP_VERTICAL}, |
1901 | 0 | {"left", EB_CSP_VERTICAL}, |
1902 | 0 | {"colocated", EB_CSP_COLOCATED}, |
1903 | 0 | {"topleft", EB_CSP_COLOCATED}, |
1904 | 0 | }; |
1905 | |
|
1906 | 0 | const size_t chroma_sample_positions_size = sizeof(chroma_sample_positions) / sizeof(chroma_sample_positions[0]); |
1907 | |
|
1908 | 0 | for (size_t i = 0; i < chroma_sample_positions_size; i++) { |
1909 | 0 | if (!strcmp(nptr, chroma_sample_positions[i].name)) { |
1910 | 0 | *out = chroma_sample_positions[i].pos; |
1911 | 0 | return EB_ErrorNone; |
1912 | 0 | } |
1913 | 0 | } |
1914 | | |
1915 | 0 | return EB_ErrorBadParameter; |
1916 | 0 | } |
1917 | | |
1918 | 0 | static EbErrorType str_to_sframe_mode(const char* nptr, EbSFrameMode* out) { |
1919 | 0 | const struct { |
1920 | 0 | const char* name; |
1921 | 0 | EbSFrameMode mode; |
1922 | 0 | } sframe_mode[] = { |
1923 | 0 | {"strict", SFRAME_STRICT_BASE}, |
1924 | 0 | {"nearest", SFRAME_NEAREST_BASE}, |
1925 | 0 | {"flexible", SFRAME_FLEXIBLE_BASE}, |
1926 | 0 | {"decposi", SFRAME_DEC_POSI_BASE}, |
1927 | 0 | }; |
1928 | |
|
1929 | 0 | const size_t sframe_mode_size = sizeof(sframe_mode) / sizeof(sframe_mode[0]); |
1930 | |
|
1931 | 0 | for (size_t i = 0; i < sframe_mode_size; i++) { |
1932 | 0 | if (!strcmp(nptr, sframe_mode[i].name)) { |
1933 | 0 | *out = sframe_mode[i].mode; |
1934 | 0 | return EB_ErrorNone; |
1935 | 0 | } |
1936 | 0 | } |
1937 | | |
1938 | 0 | return EB_ErrorBadParameter; |
1939 | 0 | } |
1940 | | |
1941 | 0 | static EbErrorType str_to_rc_mode(const char* nptr, uint8_t* out, uint8_t* aq_mode) { |
1942 | | // separate rc mode enum to distinguish between cqp and crf modes |
1943 | 0 | enum rc_modes { |
1944 | 0 | RC_MODE_ZERO = 0, // unique mode in case user passes a literal 0 |
1945 | 0 | RC_MODE_CQP, |
1946 | 0 | RC_MODE_CRF, |
1947 | 0 | RC_MODE_VBR, |
1948 | 0 | RC_MODE_CBR, |
1949 | 0 | RC_MODE_INVALID, |
1950 | 0 | }; |
1951 | |
|
1952 | 0 | const struct { |
1953 | 0 | const char* name; |
1954 | 0 | uint32_t mode; |
1955 | 0 | } rc_mode[] = { |
1956 | 0 | {"0", RC_MODE_ZERO}, |
1957 | 0 | {"1", RC_MODE_VBR}, |
1958 | 0 | {"2", RC_MODE_CBR}, |
1959 | 0 | {"cqp", RC_MODE_CQP}, |
1960 | 0 | {"crf", RC_MODE_CRF}, |
1961 | 0 | {"vbr", RC_MODE_VBR}, |
1962 | 0 | {"cbr", RC_MODE_CBR}, |
1963 | 0 | }; |
1964 | |
|
1965 | 0 | const size_t rc_mode_size = sizeof(rc_mode) / sizeof(rc_mode[0]); |
1966 | |
|
1967 | 0 | enum rc_modes mode = RC_MODE_INVALID; |
1968 | |
|
1969 | 0 | for (size_t i = 0; i < rc_mode_size; i++) { |
1970 | 0 | if (!strcmp(nptr, rc_mode[i].name)) { |
1971 | 0 | mode = rc_mode[i].mode; |
1972 | 0 | break; |
1973 | 0 | } |
1974 | 0 | } |
1975 | |
|
1976 | 0 | switch (mode) { |
1977 | 0 | case RC_MODE_ZERO: |
1978 | 0 | *out = 0; |
1979 | 0 | break; |
1980 | 0 | case RC_MODE_CQP: |
1981 | 0 | *out = SVT_AV1_RC_MODE_CQP_OR_CRF; |
1982 | 0 | *aq_mode = 0; |
1983 | 0 | break; |
1984 | 0 | case RC_MODE_CRF: |
1985 | 0 | *out = SVT_AV1_RC_MODE_CQP_OR_CRF; |
1986 | 0 | *aq_mode = 2; |
1987 | 0 | break; |
1988 | 0 | case RC_MODE_VBR: |
1989 | 0 | *out = SVT_AV1_RC_MODE_VBR; |
1990 | 0 | break; |
1991 | 0 | case RC_MODE_CBR: |
1992 | 0 | *out = SVT_AV1_RC_MODE_CBR; |
1993 | 0 | break; |
1994 | 0 | default: |
1995 | 0 | SVT_ERROR("Invalid rc mode: %s\n", nptr); |
1996 | 0 | return EB_ErrorBadParameter; |
1997 | 0 | } |
1998 | 0 | return EB_ErrorNone; |
1999 | 0 | } |
2000 | | |
2001 | 0 | static EbErrorType str_to_pred_struct(const char* nptr, PredStructure* pred_structure) { |
2002 | 0 | const struct { |
2003 | 0 | const char* name; |
2004 | 0 | PredStructure mode; |
2005 | 0 | } pred_structs[] = {{"0", ALL_INTRA}, |
2006 | 0 | {"all-intra", ALL_INTRA}, |
2007 | 0 | {"ai", ALL_INTRA}, |
2008 | 0 | {"1", LOW_DELAY}, |
2009 | 0 | {"low-delay", LOW_DELAY}, |
2010 | 0 | {"ld", LOW_DELAY}, |
2011 | 0 | {"2", RANDOM_ACCESS}, |
2012 | 0 | {"random-access", RANDOM_ACCESS}, |
2013 | 0 | {"ra", RANDOM_ACCESS}}; |
2014 | |
|
2015 | 0 | const size_t pred_structs_size = sizeof(pred_structs) / sizeof(pred_structs[0]); |
2016 | |
|
2017 | 0 | for (size_t i = 0; i < pred_structs_size; i++) { |
2018 | 0 | if (!strcmp(nptr, pred_structs[i].name)) { |
2019 | 0 | *pred_structure = pred_structs[i].mode; |
2020 | 0 | return EB_ErrorNone; |
2021 | 0 | } |
2022 | 0 | } |
2023 | | |
2024 | 0 | SVT_ERROR("Invalid pred struct: %s\n", nptr); |
2025 | 0 | return EB_ErrorBadParameter; |
2026 | 0 | } |
2027 | | |
2028 | 0 | static EbErrorType str_to_frm_resz_evts(const char* nptr, SvtAv1FrameScaleEvts* evts) { |
2029 | 0 | const uint32_t param_count = count_params(nptr); |
2030 | 0 | if ((evts->evt_num != 0 && evts->evt_num != param_count) || param_count == 0) { |
2031 | 0 | SVT_ERROR("Error: Size for the list passed to %s doesn't match %u\n", "frame-resz-events", evts->evt_num); |
2032 | 0 | return EB_ErrorBadParameter; |
2033 | 0 | } |
2034 | 0 | if (evts->start_frame_nums) { |
2035 | 0 | EB_FREE(evts->start_frame_nums); |
2036 | 0 | } |
2037 | 0 | EB_MALLOC(evts->start_frame_nums, param_count * sizeof(uint64_t)); |
2038 | 0 | evts->evt_num = param_count; |
2039 | 0 | return parse_list_uint64(nptr, evts->start_frame_nums, param_count); |
2040 | 0 | } |
2041 | | |
2042 | 0 | static EbErrorType str_to_resz_kf_denoms(const char* nptr, SvtAv1FrameScaleEvts* evts) { |
2043 | 0 | const uint32_t param_count = count_params(nptr); |
2044 | 0 | if ((evts->evt_num != 0 && evts->evt_num != param_count) || param_count == 0) { |
2045 | 0 | SVT_ERROR("Error: Size for the list passed to %s doesn't match %u\n", "frame-resz-kf-denoms", evts->evt_num); |
2046 | 0 | return EB_ErrorBadParameter; |
2047 | 0 | } |
2048 | 0 | if (evts->resize_kf_denoms) { |
2049 | 0 | EB_FREE(evts->resize_kf_denoms); |
2050 | 0 | } |
2051 | 0 | EB_MALLOC(evts->resize_kf_denoms, param_count * sizeof(uint32_t)); |
2052 | 0 | evts->evt_num = param_count; |
2053 | 0 | return parse_list_uint32(nptr, evts->resize_kf_denoms, param_count); |
2054 | 0 | } |
2055 | | |
2056 | 0 | static EbErrorType str_to_resz_denoms(const char* nptr, SvtAv1FrameScaleEvts* evts) { |
2057 | 0 | const uint32_t param_count = count_params(nptr); |
2058 | 0 | if ((evts->evt_num != 0 && evts->evt_num != param_count) || param_count == 0) { |
2059 | 0 | SVT_ERROR("Error: Size for the list passed to %s doesn't match %u\n", "frame-resz-denoms", evts->evt_num); |
2060 | 0 | return EB_ErrorBadParameter; |
2061 | 0 | } |
2062 | 0 | if (evts->resize_denoms) { |
2063 | 0 | EB_FREE(evts->resize_denoms); |
2064 | 0 | } |
2065 | 0 | EB_MALLOC(evts->resize_denoms, param_count * sizeof(uint32_t)); |
2066 | 0 | evts->evt_num = param_count; |
2067 | 0 | return parse_list_uint32(nptr, evts->resize_denoms, param_count); |
2068 | 0 | } |
2069 | | |
2070 | 0 | static EbErrorType str_to_sframe_posi(const char* nptr, SvtAv1SFramePositions* posis) { |
2071 | 0 | const uint32_t param_count = count_params(nptr); |
2072 | 0 | if ((posis->sframe_num != 0 && posis->sframe_num != param_count) || param_count == 0) { |
2073 | 0 | SVT_ERROR("Error: Size for the list passed to %s doesn't match %u\n", "sframe-posi", posis->sframe_num); |
2074 | 0 | return EB_ErrorBadParameter; |
2075 | 0 | } |
2076 | 0 | if (posis->sframe_posis) { |
2077 | 0 | EB_FREE(posis->sframe_posis); |
2078 | 0 | } |
2079 | 0 | EB_MALLOC(posis->sframe_posis, param_count * sizeof(uint64_t)); |
2080 | 0 | posis->sframe_num = param_count; |
2081 | 0 | return parse_list_uint64(nptr, posis->sframe_posis, param_count); |
2082 | 0 | } |
2083 | | |
2084 | 0 | static EbErrorType str_to_sframe_qp(const char* nptr, SvtAv1SFramePositions* posis, uint8_t* qp) { |
2085 | 0 | const uint32_t param_count = count_params(nptr); |
2086 | 0 | if ((posis->sframe_num != 0 && posis->sframe_num != param_count && param_count != 1) || param_count == 0) { |
2087 | 0 | SVT_ERROR("Error: Size for the list passed to %s doesn't match %u\n", "sframe-qp", posis->sframe_num); |
2088 | 0 | return EB_ErrorBadParameter; |
2089 | 0 | } |
2090 | 0 | if (posis->sframe_qps) { |
2091 | 0 | EB_FREE(posis->sframe_qps); |
2092 | 0 | } |
2093 | 0 | EB_MALLOC(posis->sframe_qps, param_count * sizeof(uint8_t)); |
2094 | 0 | posis->sframe_qp_num = param_count; |
2095 | 0 | EbErrorType err = parse_list_uint8(nptr, posis->sframe_qps, param_count); |
2096 | | // check if the QP values are valid |
2097 | 0 | for (uint32_t i = 0; i < posis->sframe_qp_num; ++i) { |
2098 | 0 | if (posis->sframe_qps[i] < 1 || posis->sframe_qps[i] > 63) { |
2099 | 0 | SVT_ERROR("Error: Invalid S-Frame QP value. QPs must be [1 - 63]\n"); |
2100 | 0 | EB_FREE(posis->sframe_qps); |
2101 | 0 | posis->sframe_qp_num = 0; |
2102 | 0 | err = EB_ErrorBadParameter; |
2103 | 0 | } |
2104 | 0 | } |
2105 | | // If sframe-qp parameter contains only one value, apply it to all S-frames |
2106 | 0 | if (err == EB_ErrorNone && param_count == 1) { |
2107 | 0 | *qp = posis->sframe_qps[0]; |
2108 | 0 | } |
2109 | 0 | return err; |
2110 | 0 | } |
2111 | | |
2112 | 0 | static EbErrorType str_to_sframe_qp_offset(const char* nptr, SvtAv1SFramePositions* posis, int8_t* qp_offset) { |
2113 | 0 | const uint32_t param_count = count_params(nptr); |
2114 | 0 | if ((posis->sframe_num != 0 && posis->sframe_num != param_count && param_count != 1) || param_count == 0) { |
2115 | 0 | SVT_ERROR("Error: Size for the list passed to %s doesn't match %u\n", "sframe-qp-offset", posis->sframe_num); |
2116 | 0 | return EB_ErrorBadParameter; |
2117 | 0 | } |
2118 | 0 | if (posis->sframe_qp_offsets) { |
2119 | 0 | EB_FREE(posis->sframe_qp_offsets); |
2120 | 0 | } |
2121 | 0 | EB_MALLOC(posis->sframe_qp_offsets, param_count * sizeof(int8_t)); |
2122 | 0 | posis->sframe_qp_num = param_count; |
2123 | 0 | EbErrorType err = parse_list_int8(nptr, posis->sframe_qp_offsets, param_count); |
2124 | | // check if the QP offset values are valid |
2125 | 0 | for (uint32_t i = 0; i < posis->sframe_qp_num; ++i) { |
2126 | 0 | if (posis->sframe_qp_offsets[i] < -63 || posis->sframe_qp_offsets[i] > 63) { |
2127 | 0 | SVT_ERROR("Error: Invalid S-Frame QP offset value. QP offsets must be [-63 - 63]\n"); |
2128 | 0 | EB_FREE(posis->sframe_qp_offsets); |
2129 | 0 | posis->sframe_qp_num = 0; |
2130 | 0 | err = EB_ErrorBadParameter; |
2131 | 0 | } |
2132 | 0 | } |
2133 | | // If sframe-qp-offset parameter contains only one value, apply it to all S-frames |
2134 | 0 | if (err == EB_ErrorNone && param_count == 1) { |
2135 | 0 | *qp_offset = posis->sframe_qp_offsets[0]; |
2136 | 0 | } |
2137 | 0 | return err; |
2138 | 0 | } |
2139 | | |
2140 | | #define COLOR_OPT(par, opt) \ |
2141 | 0 | do { \ |
2142 | 0 | if (!strcmp(name, par)) { \ |
2143 | 0 | return_error = str_to_##opt(value, &config_struct->opt); \ |
2144 | 0 | if (return_error == EB_ErrorNone) \ |
2145 | 0 | return return_error; \ |
2146 | 0 | uint32_t val; \ |
2147 | 0 | return_error = str_to_uint(value, &val, NULL); \ |
2148 | 0 | if (return_error == EB_ErrorNone) \ |
2149 | 0 | config_struct->opt = val; \ |
2150 | 0 | return return_error; \ |
2151 | 0 | } \ |
2152 | 0 | } while (0) |
2153 | | |
2154 | | #define COLOR_METADATA_OPT(par, opt) \ |
2155 | 0 | do { \ |
2156 | 0 | if (!strcmp(name, par)) \ |
2157 | 0 | return svt_aom_parse_##opt(&config_struct->opt, value) ? EB_ErrorNone : EB_ErrorBadParameter; \ |
2158 | 0 | } while (0) |
2159 | | |
2160 | | EB_API EbErrorType svt_av1_enc_parse_parameter(EbSvtAv1EncConfiguration* config_struct, const char* name, |
2161 | 0 | const char* value) { |
2162 | 0 | if (config_struct == NULL || name == NULL || value == NULL) { |
2163 | 0 | return EB_ErrorBadParameter; |
2164 | 0 | } |
2165 | | |
2166 | 0 | EbErrorType return_error = EB_ErrorBadParameter; |
2167 | |
|
2168 | 0 | if (!strcmp(name, "keyint")) { |
2169 | 0 | return str_to_keyint(value, &config_struct->intra_period_length, &config_struct->multiply_keyint); |
2170 | 0 | } |
2171 | | |
2172 | 0 | if (!strcmp(name, "tbr")) { |
2173 | 0 | return str_to_bitrate(value, &config_struct->target_bit_rate); |
2174 | 0 | } |
2175 | | |
2176 | 0 | if (!strcmp(name, "mbr")) { |
2177 | 0 | return str_to_bitrate(value, &config_struct->max_bit_rate); |
2178 | 0 | } |
2179 | | |
2180 | | // options updating more than one field |
2181 | 0 | if (!strcmp(name, "crf")) { |
2182 | 0 | return str_to_crf(value, config_struct); |
2183 | 0 | } |
2184 | | |
2185 | 0 | if (!strcmp(name, "cqp")) { |
2186 | 0 | return str_to_cqp(value, config_struct); |
2187 | 0 | } |
2188 | | |
2189 | 0 | if (!strcmp(name, "rc")) { |
2190 | 0 | return str_to_rc_mode(value, &config_struct->rate_control_mode, &config_struct->aq_mode); |
2191 | 0 | } |
2192 | | |
2193 | | // custom enum fields |
2194 | 0 | if (!strcmp(name, "profile")) { |
2195 | 0 | return str_to_profile(value, &config_struct->profile) == EB_ErrorBadParameter |
2196 | 0 | ? str_to_uint(value, (uint32_t*)&config_struct->profile, NULL) |
2197 | 0 | : EB_ErrorNone; |
2198 | 0 | } |
2199 | | |
2200 | 0 | if (!strcmp(name, "color-format")) { |
2201 | 0 | return str_to_color_fmt(value, &config_struct->encoder_color_format) == EB_ErrorBadParameter |
2202 | 0 | ? str_to_uint(value, (uint32_t*)&config_struct->encoder_color_format, NULL) |
2203 | 0 | : EB_ErrorNone; |
2204 | 0 | } |
2205 | | |
2206 | 0 | if (!strcmp(name, "irefresh-type")) { |
2207 | 0 | return str_to_intra_rt(value, &config_struct->intra_refresh_type) == EB_ErrorBadParameter |
2208 | 0 | ? str_to_uint(value, (uint32_t*)&config_struct->intra_refresh_type, NULL) |
2209 | 0 | : EB_ErrorNone; |
2210 | 0 | } |
2211 | | |
2212 | 0 | if (!strcmp(name, "sframe-mode")) { |
2213 | 0 | return str_to_sframe_mode(value, &config_struct->sframe_mode) == EB_ErrorBadParameter |
2214 | 0 | ? str_to_uint(value, (uint32_t*)&config_struct->sframe_mode, NULL) |
2215 | 0 | : EB_ErrorNone; |
2216 | 0 | } |
2217 | | |
2218 | 0 | if (!strcmp(name, "asm")) { |
2219 | 0 | return str_to_asm(value, &config_struct->use_cpu_flags); |
2220 | 0 | } |
2221 | | |
2222 | 0 | if (!strcmp(name, "pred-struct")) { |
2223 | 0 | return str_to_pred_struct(value, &config_struct->pred_structure); |
2224 | 0 | } |
2225 | | |
2226 | 0 | COLOR_OPT("color-primaries", color_primaries); |
2227 | 0 | COLOR_OPT("transfer-characteristics", transfer_characteristics); |
2228 | 0 | COLOR_OPT("matrix-coefficients", matrix_coefficients); |
2229 | 0 | COLOR_OPT("color-range", color_range); |
2230 | 0 | COLOR_OPT("chroma-sample-position", chroma_sample_position); |
2231 | | |
2232 | | // custom struct fields |
2233 | 0 | COLOR_METADATA_OPT("mastering-display", mastering_display); |
2234 | 0 | COLOR_METADATA_OPT("content-light", content_light_level); |
2235 | | |
2236 | | // arrays |
2237 | 0 | if (!strcmp(name, "qindex-offsets")) { |
2238 | 0 | return parse_list_int32(value, config_struct->qindex_offsets, EB_MAX_TEMPORAL_LAYERS); |
2239 | 0 | } |
2240 | | |
2241 | 0 | if (!strcmp(name, "chroma-qindex-offsets")) { |
2242 | 0 | return parse_list_int32(value, config_struct->chroma_qindex_offsets, EB_MAX_TEMPORAL_LAYERS); |
2243 | 0 | } |
2244 | | |
2245 | 0 | if (!strcmp(name, "lambda-scale-factors")) { |
2246 | 0 | return parse_list_int32(value, config_struct->lambda_scale_factors, SVT_AV1_FRAME_UPDATE_TYPES); |
2247 | 0 | } |
2248 | | |
2249 | 0 | if (!strcmp(name, "frame-resz-events")) { |
2250 | 0 | return str_to_frm_resz_evts(value, &config_struct->frame_scale_evts); |
2251 | 0 | } |
2252 | | |
2253 | 0 | if (!strcmp(name, "frame-resz-kf-denoms")) { |
2254 | 0 | return str_to_resz_kf_denoms(value, &config_struct->frame_scale_evts); |
2255 | 0 | } |
2256 | | |
2257 | 0 | if (!strcmp(name, "frame-resz-denoms")) { |
2258 | 0 | return str_to_resz_denoms(value, &config_struct->frame_scale_evts); |
2259 | 0 | } |
2260 | | |
2261 | 0 | if (!strcmp(name, "sframe-posi")) { |
2262 | 0 | return str_to_sframe_posi(value, &config_struct->sframe_posi); |
2263 | 0 | } |
2264 | | |
2265 | 0 | if (!strcmp(name, "sframe-qp")) { |
2266 | 0 | return str_to_sframe_qp(value, &config_struct->sframe_posi, &config_struct->sframe_qp); |
2267 | 0 | } |
2268 | | |
2269 | 0 | if (!strcmp(name, "sframe-qp-offset")) { |
2270 | 0 | return str_to_sframe_qp_offset(value, &config_struct->sframe_posi, &config_struct->sframe_qp_offset); |
2271 | 0 | } |
2272 | | |
2273 | | // uint32_t fields |
2274 | 0 | const struct { |
2275 | 0 | const char* name; |
2276 | 0 | uint32_t* out; |
2277 | 0 | } uint_opts[] = { |
2278 | 0 | {"w", &config_struct->source_width}, |
2279 | 0 | {"width", &config_struct->source_width}, |
2280 | 0 | {"h", &config_struct->source_height}, |
2281 | 0 | {"height", &config_struct->source_height}, |
2282 | 0 | {"q", &config_struct->qp}, |
2283 | 0 | {"qp", &config_struct->qp}, |
2284 | 0 | {"film-grain", &config_struct->film_grain_denoise_strength}, |
2285 | 0 | {"hierarchical-levels", &config_struct->hierarchical_levels}, |
2286 | 0 | {"tier", &config_struct->tier}, |
2287 | 0 | {"level", &config_struct->level}, |
2288 | 0 | {"lp", &config_struct->level_of_parallelism}, |
2289 | 0 | {"fps-num", &config_struct->frame_rate_numerator}, |
2290 | 0 | {"fps-denom", &config_struct->frame_rate_denominator}, |
2291 | 0 | {"lookahead", &config_struct->look_ahead_distance}, |
2292 | 0 | {"scd", &config_struct->scene_change_detection}, |
2293 | 0 | {"max-qp", &config_struct->max_qp_allowed}, |
2294 | 0 | {"min-qp", &config_struct->min_qp_allowed}, |
2295 | 0 | {"minsection-pct", &config_struct->vbr_min_section_pct}, |
2296 | 0 | {"maxsection-pct", &config_struct->vbr_max_section_pct}, |
2297 | 0 | {"undershoot-pct", &config_struct->under_shoot_pct}, |
2298 | 0 | {"overshoot-pct", &config_struct->over_shoot_pct}, |
2299 | 0 | {"mbr-overshoot-pct", &config_struct->mbr_over_shoot_pct}, |
2300 | 0 | {"max-intra-bitrate-pct", &config_struct->max_intra_bitrate_pct}, |
2301 | 0 | {"max-inter-bitrate-pct", &config_struct->max_inter_bitrate_pct}, |
2302 | 0 | {"recode-loop", &config_struct->recode_loop}, |
2303 | 0 | {"enable-stat-report", &config_struct->stat_report}, |
2304 | 0 | {"scm", &config_struct->screen_content_mode}, |
2305 | 0 | {"input-depth", &config_struct->encoder_bit_depth}, |
2306 | 0 | {"forced-max-frame-width", &config_struct->forced_max_frame_width}, |
2307 | 0 | {"forced-max-frame-height", &config_struct->forced_max_frame_height}, |
2308 | 0 | }; |
2309 | |
|
2310 | 0 | const size_t uint_opts_size = sizeof(uint_opts) / sizeof(uint_opts[0]); |
2311 | |
|
2312 | 0 | for (size_t i = 0; i < uint_opts_size; i++) { |
2313 | 0 | if (!strcmp(name, uint_opts[i].name)) { |
2314 | 0 | return str_to_uint(value, uint_opts[i].out, NULL); |
2315 | 0 | } |
2316 | 0 | } |
2317 | | |
2318 | | // uint8_t fields |
2319 | 0 | const struct { |
2320 | 0 | const char* name; |
2321 | 0 | uint8_t* out; |
2322 | 0 | } uint8_opts[] = { |
2323 | 0 | {"aq-mode", &config_struct->aq_mode}, |
2324 | 0 | {"superres-mode", &config_struct->superres_mode}, |
2325 | 0 | {"superres-qthres", &config_struct->superres_qthres}, |
2326 | 0 | {"superres-kf-qthres", &config_struct->superres_kf_qthres}, |
2327 | 0 | {"superres-denom", &config_struct->superres_denom}, |
2328 | 0 | {"superres-kf-denom", &config_struct->superres_kf_denom}, |
2329 | 0 | {"tune", &config_struct->tune}, |
2330 | 0 | {"film-grain-denoise", &config_struct->film_grain_denoise_apply}, |
2331 | 0 | {"enable-dlf", &config_struct->enable_dlf_flag}, |
2332 | 0 | {"resize-mode", &config_struct->resize_mode}, |
2333 | 0 | {"resize-denom", &config_struct->resize_denom}, |
2334 | 0 | {"resize-kf-denom", &config_struct->resize_kf_denom}, |
2335 | 0 | {"qm-min", &config_struct->min_qm_level}, |
2336 | 0 | {"qm-max", &config_struct->max_qm_level}, |
2337 | 0 | {"chroma-qm-min", &config_struct->min_chroma_qm_level}, |
2338 | 0 | {"chroma-qm-max", &config_struct->max_chroma_qm_level}, |
2339 | 0 | {"use-fixed-qindex-offsets", &config_struct->use_fixed_qindex_offsets}, |
2340 | 0 | {"startup-mg-size", &config_struct->startup_mg_size}, |
2341 | 0 | {"variance-boost-strength", &config_struct->variance_boost_strength}, |
2342 | 0 | {"variance-octile", &config_struct->variance_octile}, |
2343 | 0 | {"variance-boost-curve", &config_struct->variance_boost_curve}, |
2344 | 0 | {"qp-scale-compress-strength", &config_struct->qp_scale_compress_strength}, |
2345 | 0 | {"fast-decode", &config_struct->fast_decode}, |
2346 | 0 | {"luminance-qp-bias", &config_struct->luminance_qp_bias}, |
2347 | 0 | {"enable-tf", &config_struct->enable_tf}, |
2348 | 0 | {"tf-strength", &config_struct->tf_strength}, |
2349 | 0 | {"max-tx-size", &config_struct->max_tx_size}, |
2350 | 0 | }; |
2351 | |
|
2352 | 0 | const size_t uint8_opts_size = sizeof(uint8_opts) / sizeof(uint8_opts[0]); |
2353 | |
|
2354 | 0 | for (size_t i = 0; i < uint8_opts_size; i++) { |
2355 | 0 | if (!strcmp(name, uint8_opts[i].name)) { |
2356 | 0 | uint32_t val; |
2357 | 0 | return_error = str_to_uint(value, &val, NULL); |
2358 | 0 | if (return_error == EB_ErrorNone) { |
2359 | | // add protection if the input param is roll-over |
2360 | 0 | if (val > 255) { |
2361 | 0 | return EB_ErrorBadParameter; |
2362 | 0 | } |
2363 | 0 | *uint8_opts[i].out = val; |
2364 | 0 | } |
2365 | 0 | return return_error; |
2366 | 0 | } |
2367 | 0 | } |
2368 | | |
2369 | | // int64_t fields |
2370 | 0 | const struct { |
2371 | 0 | const char* name; |
2372 | 0 | int64_t* out; |
2373 | 0 | } int64_opts[] = { |
2374 | 0 | {"buf-initial-sz", &config_struct->starting_buffer_level_ms}, |
2375 | 0 | {"buf-optimal-sz", &config_struct->optimal_buffer_level_ms}, |
2376 | 0 | {"buf-sz", &config_struct->maximum_buffer_size_ms}, |
2377 | 0 | }; |
2378 | |
|
2379 | 0 | const size_t int64_opts_size = sizeof(int64_opts) / sizeof(int64_opts[0]); |
2380 | |
|
2381 | 0 | for (size_t i = 0; i < int64_opts_size; i++) { |
2382 | 0 | if (!strcmp(name, int64_opts[i].name)) { |
2383 | 0 | return str_to_int64(value, int64_opts[i].out, NULL); |
2384 | 0 | } |
2385 | 0 | } |
2386 | | |
2387 | | // double fields |
2388 | 0 | const struct { |
2389 | 0 | const char* name; |
2390 | 0 | double* out; |
2391 | 0 | } double_opts[] = { |
2392 | 0 | {"ac-bias", &config_struct->ac_bias}, |
2393 | 0 | }; |
2394 | |
|
2395 | 0 | const size_t double_opts_size = sizeof(double_opts) / sizeof(double_opts[0]); |
2396 | |
|
2397 | 0 | for (size_t i = 0; i < double_opts_size; i++) { |
2398 | 0 | if (!strcmp(name, double_opts[i].name)) { |
2399 | 0 | return str_to_double(value, double_opts[i].out, NULL); |
2400 | 0 | } |
2401 | 0 | } |
2402 | | |
2403 | | // int32_t fields |
2404 | 0 | const struct { |
2405 | 0 | const char* name; |
2406 | 0 | int32_t* out; |
2407 | 0 | } int_opts[] = { |
2408 | 0 | {"key-frame-chroma-qindex-offset", &config_struct->key_frame_chroma_qindex_offset}, |
2409 | 0 | {"key-frame-qindex-offset", &config_struct->key_frame_qindex_offset}, |
2410 | 0 | {"luma-y-dc-qindex-offset", &config_struct->luma_y_dc_qindex_offset}, |
2411 | 0 | {"chroma-u-dc-qindex-offset", &config_struct->chroma_u_dc_qindex_offset}, |
2412 | 0 | {"chroma-u-ac-qindex-offset", &config_struct->chroma_u_ac_qindex_offset}, |
2413 | 0 | {"chroma-v-dc-qindex-offset", &config_struct->chroma_v_dc_qindex_offset}, |
2414 | 0 | {"chroma-v-ac-qindex-offset", &config_struct->chroma_v_ac_qindex_offset}, |
2415 | 0 | {"pass", &config_struct->pass}, |
2416 | 0 | {"enable-cdef", &config_struct->cdef_level}, |
2417 | 0 | {"enable-restoration", &config_struct->enable_restoration_filtering}, |
2418 | 0 | {"enable-mfmv", &config_struct->enable_mfmv}, |
2419 | 0 | {"intra-period", &config_struct->intra_period_length}, |
2420 | 0 | {"tile-rows", &config_struct->tile_rows}, |
2421 | 0 | {"tile-columns", &config_struct->tile_columns}, |
2422 | 0 | {"sframe-dist", &config_struct->sframe_dist}, |
2423 | 0 | {"hbd-mds", &config_struct->hbd_mds}, |
2424 | 0 | }; |
2425 | |
|
2426 | 0 | const size_t int_opts_size = sizeof(int_opts) / sizeof(int_opts[0]); |
2427 | |
|
2428 | 0 | for (size_t i = 0; i < int_opts_size; i++) { |
2429 | 0 | if (!strcmp(name, int_opts[i].name)) { |
2430 | 0 | return str_to_int(value, int_opts[i].out, NULL); |
2431 | 0 | } |
2432 | 0 | } |
2433 | | |
2434 | | // int8_t fields |
2435 | 0 | const struct { |
2436 | 0 | const char* name; |
2437 | 0 | int8_t* out; |
2438 | 0 | } int8_opts[] = { |
2439 | 0 | {"preset", &config_struct->enc_mode}, |
2440 | 0 | {"sharpness", &config_struct->sharpness}, |
2441 | 0 | {"startup-qp-offset", &config_struct->startup_qp_offset}, |
2442 | 0 | }; |
2443 | |
|
2444 | 0 | const size_t int8_opts_size = sizeof(int8_opts) / sizeof(int8_opts[0]); |
2445 | |
|
2446 | 0 | for (size_t i = 0; i < int8_opts_size; i++) { |
2447 | 0 | if (!strcmp(name, int8_opts[i].name)) { |
2448 | 0 | int32_t val; |
2449 | 0 | return_error = str_to_int(value, &val, NULL); |
2450 | 0 | if (return_error == EB_ErrorNone) { |
2451 | | // add protection if the input param is roll-over |
2452 | 0 | if (val > 127 || val < -128) { |
2453 | 0 | return EB_ErrorBadParameter; |
2454 | 0 | } |
2455 | 0 | *int8_opts[i].out = val; |
2456 | 0 | } |
2457 | 0 | return return_error; |
2458 | 0 | } |
2459 | 0 | } |
2460 | | |
2461 | | // bool fields |
2462 | 0 | const struct { |
2463 | 0 | const char* name; |
2464 | 0 | bool* out; |
2465 | 0 | } bool_opts[] = { |
2466 | 0 | {"use-q-file", &config_struct->use_qp_file}, |
2467 | 0 | {"enable-overlays", &config_struct->enable_overlays}, |
2468 | 0 | {"enable-force-key-frames", &config_struct->force_key_frames}, |
2469 | 0 | #if CONFIG_ENABLE_QUANT_MATRIX |
2470 | 0 | {"enable-qm", &config_struct->enable_qm}, |
2471 | 0 | #endif |
2472 | 0 | {"enable-dg", &config_struct->enable_dg}, |
2473 | 0 | {"gop-constraint-rc", &config_struct->gop_constraint_rc}, |
2474 | 0 | {"enable-variance-boost", &config_struct->enable_variance_boost}, |
2475 | 0 | {"lossless", &config_struct->lossless}, |
2476 | 0 | {"avif", &config_struct->avif}, |
2477 | 0 | {"rtc", &config_struct->rtc}, |
2478 | 0 | {"adaptive-film-grain", &config_struct->adaptive_film_grain}, |
2479 | 0 | {"enable-kf-tf", &config_struct->enable_tf_key}, |
2480 | 0 | {"enable-intrabc", &config_struct->enable_intrabc}, |
2481 | 0 | }; |
2482 | 0 | const size_t bool_opts_size = sizeof(bool_opts) / sizeof(bool_opts[0]); |
2483 | |
|
2484 | 0 | for (size_t i = 0; i < bool_opts_size; i++) { |
2485 | 0 | if (!strcmp(name, bool_opts[i].name)) { |
2486 | 0 | return str_to_bool(value, bool_opts[i].out); |
2487 | 0 | } |
2488 | 0 | } |
2489 | | |
2490 | 0 | return return_error; |
2491 | 0 | } |