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