1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "codec_param_checker.h"
17 #include <unordered_map>
18 #include <vector>
19 #include <memory>
20 #include <string>
21 #include <algorithm>
22 #include "avcodec_log.h"
23 #include "avcodec_errors.h"
24 #include "avcodec_trace.h"
25 #include "codec_ability_singleton.h"
26 #include "media_description.h"
27 #include "meta/meta_key.h"
28 #include "temporal_scalability.h"
29 #include "meta/video_types.h"
30 #include "surface_type.h"
31
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "CodecParamChecker"};
34 using namespace OHOS::Media;
35 using namespace OHOS::MediaAVCodec;
36
37 constexpr int32_t DEFAULT_QUALITY = 50;
38 constexpr int32_t DEFAULT_I_FRAME_INTERVAL = 1000;
39
40 const std::unordered_map<CodecScenario, std::string_view> CODEC_SCENARIO_TO_STRING = {
41 {CodecScenario::CODEC_SCENARIO_ENC_NORMAL, "encoder normal"},
42 {CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY, "encoder temporal scalability"},
43 {CodecScenario::CODEC_SCENARIO_ENC_ENABLE_B_FRAME, "encoder enable b frame"},
44 {CodecScenario::CODEC_SCENARIO_DEC_NORMAL, "decoder normal"},
45 };
46
PrintParam(bool paramExist,const std::string_view tag,T value)47 template<class T> void PrintParam(bool paramExist, const std::string_view tag, T value)
48 {
49 if (!paramExist) {
50 return;
51 }
52 using namespace std::string_literals;
53 std::string logMsg = "Param "s + tag.data() + " set, value: "s + std::to_string(value);
54 AVCODEC_LOGI("%{public}s", logMsg.c_str());
55 }
56
PrintParam(bool paramExist,const std::string_view tag,T value1,T value2)57 template<class T> void PrintParam(bool paramExist, const std::string_view tag, T value1, T value2)
58 {
59 if (!paramExist) {
60 return;
61 }
62 using namespace std::string_literals;
63 std::string logMsg = "Param "s + tag.data() + " set, value: "s +
64 std::to_string(value1) + " - " + std::to_string(value2);
65 AVCODEC_LOGI("%{public}s", logMsg.c_str());
66 }
67
PrintCodecScenario(CodecScenario scenario)68 inline void PrintCodecScenario(CodecScenario scenario)
69 {
70 auto scenarioName = CODEC_SCENARIO_TO_STRING.find(scenario);
71 if (scenarioName != CODEC_SCENARIO_TO_STRING.end()) {
72 AVCODEC_LOGI("Codec scenario is %{public}s", scenarioName->second.data());
73 } else {
74 AVCODEC_LOGI("Codec scenario is %{public}d", scenario);
75 }
76 }
77
IsSupported(std::vector<T> cap,T value)78 template<class T> bool IsSupported(std::vector<T> cap, T value)
79 {
80 return std::find(cap.begin(), cap.end(), value) != cap.end();
81 }
82
83 // Video scenario checker
84 std::optional<CodecScenario> TemporalScalabilityChecker(CapabilityData &capData, const Format &format,
85 AVCodecType codecType);
86 std::optional<CodecScenario> BFrameScenarioChecker(CapabilityData &capData, const Format &format,
87 AVCodecType codecType);
88
89 // Video codec checker
90 int32_t ResolutionChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
91 int32_t PixelFormatChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
92 int32_t FramerateChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
93 int32_t BitrateAndQualityChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
94 int32_t VideoProfileChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
95 int32_t RotationChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
96 int32_t QPChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
97 int32_t IFrameIntervalChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
98 int32_t TemporalGopSizeChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
99 int32_t TemporalGopReferenceModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
100 int32_t UniformlyScaledReferenceChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
101 int32_t ColorPrimariesChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
102 int32_t TransferCharacteristicsChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
103 int32_t MatrixCoefficientsChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
104 int32_t LTRFrameCountChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
105 int32_t ScalingModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
106 int32_t PostProcessingChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
107 int32_t BFrameParamChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
108
109 // Checkers list define
110 using ScenarioCheckerType =
111 std::optional<CodecScenario> (*)(CapabilityData &capData, const Format &format, AVCodecType codecType);
112 using ParamCheckerType = int32_t (*)(CapabilityData &capData, Format &format, CodecScenario scenario);
113 using ScenarioCheckerListType = std::vector<ScenarioCheckerType>;
114 using ParamCheckerListType = std::vector<ParamCheckerType>;
115 const ParamCheckerListType VIDEO_ENCODER_CONFIGURE_CHECKER_LIST = {
116 ResolutionChecker,
117 PixelFormatChecker,
118 FramerateChecker,
119 BitrateAndQualityChecker,
120 VideoProfileChecker,
121 QPChecker,
122 IFrameIntervalChecker,
123 ColorPrimariesChecker,
124 TransferCharacteristicsChecker,
125 MatrixCoefficientsChecker,
126 LTRFrameCountChecker,
127 BFrameParamChecker,
128 };
129
130 const ParamCheckerListType VIDEO_ENCODER_TEMPORAL_SCALABILITY_CONFIGURE_CHECKER_LIST = {
131 ResolutionChecker,
132 PixelFormatChecker,
133 FramerateChecker,
134 BitrateAndQualityChecker,
135 VideoProfileChecker,
136 QPChecker,
137 IFrameIntervalChecker,
138 TemporalGopSizeChecker,
139 TemporalGopReferenceModeChecker,
140 UniformlyScaledReferenceChecker,
141 ColorPrimariesChecker,
142 TransferCharacteristicsChecker,
143 MatrixCoefficientsChecker,
144 LTRFrameCountChecker,
145 };
146
147 const ParamCheckerListType VIDEO_DECODER_CONFIGURE_CHECKER_LIST = {
148 ResolutionChecker,
149 PixelFormatChecker,
150 FramerateChecker,
151 RotationChecker,
152 ScalingModeChecker,
153 PostProcessingChecker,
154 };
155
156 const ParamCheckerListType VIDEO_ENCODER_PARAMETER_CHECKER_LIST = {
157 FramerateChecker,
158 BitrateAndQualityChecker,
159 QPChecker,
160 };
161
162 const ParamCheckerListType VIDEO_DECODER_PARAMETER_CHECKER_LIST = {};
163
164 const ScenarioCheckerListType VIDEO_SCENARIO_CHECKER_LIST = {
165 BFrameScenarioChecker,
166 TemporalScalabilityChecker,
167 };
168
169 const std::vector<std::string_view> FORMAT_MERGE_LIST = {
170 MediaDescriptionKey::MD_KEY_BITRATE,
171 MediaDescriptionKey::MD_KEY_QUALITY,
172 MediaDescriptionKey::MD_KEY_FRAME_RATE,
173 Tag::VIDEO_ENCODER_QP_MIN,
174 Tag::VIDEO_ENCODER_QP_MAX,
175 };
176
177 // Checkers table
178 const std::unordered_map<CodecScenario, ParamCheckerListType> CONFIGURE_CHECKERS_TABLE = {
179 {CodecScenario::CODEC_SCENARIO_ENC_NORMAL, VIDEO_ENCODER_CONFIGURE_CHECKER_LIST},
180 {CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY, VIDEO_ENCODER_TEMPORAL_SCALABILITY_CONFIGURE_CHECKER_LIST},
181 {CodecScenario::CODEC_SCENARIO_ENC_ENABLE_B_FRAME, VIDEO_ENCODER_CONFIGURE_CHECKER_LIST},
182 {CodecScenario::CODEC_SCENARIO_DEC_NORMAL, VIDEO_DECODER_CONFIGURE_CHECKER_LIST},
183 };
184
185 const std::unordered_map<CodecScenario, ParamCheckerListType> PARAMETER_CHECKERS_TABLE = {
186 {CodecScenario::CODEC_SCENARIO_ENC_NORMAL, VIDEO_ENCODER_PARAMETER_CHECKER_LIST},
187 {CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY, VIDEO_ENCODER_PARAMETER_CHECKER_LIST},
188 {CodecScenario::CODEC_SCENARIO_ENC_ENABLE_B_FRAME, VIDEO_ENCODER_PARAMETER_CHECKER_LIST},
189 {CodecScenario::CODEC_SCENARIO_DEC_NORMAL, VIDEO_DECODER_PARAMETER_CHECKER_LIST},
190 };
191
192 // Checkers implementation
TemporalScalabilityChecker(CapabilityData & capData,const Format & format,AVCodecType codecType)193 std::optional<CodecScenario> TemporalScalabilityChecker(CapabilityData &capData, const Format &format,
194 AVCodecType codecType)
195 {
196 int32_t enable = 0;
197 std::optional<CodecScenario> scenario = std::nullopt;
198 bool enableExist = format.GetIntValue(Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, enable);
199 bool temporalGopSizeExist = format.ContainKey(Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE);
200 bool modeExist = format.ContainKey(Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE);
201 PrintParam(enableExist, Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, enable);
202
203 if (codecType == AVCODEC_TYPE_VIDEO_DECODER) {
204 if (enableExist || temporalGopSizeExist || modeExist) {
205 AVCODEC_LOGW("Temporal scalability is only supported in video encoder!");
206 }
207 return scenario;
208 }
209 if (!enableExist || !enable) {
210 if (temporalGopSizeExist || modeExist) {
211 AVCODEC_LOGW("Please enable key VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY!");
212 }
213 return scenario;
214 }
215 CHECK_AND_RETURN_RET_LOGW(capData.featuresMap.count(
216 static_cast<int32_t>(AVCapabilityFeature::VIDEO_ENCODER_TEMPORAL_SCALABILITY)),
217 scenario, "Not support temporal scalability");
218
219 scenario = CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY;
220 return scenario;
221 }
222
BFrameScenarioChecker(CapabilityData & capData,const Format & format,AVCodecType codecType)223 std::optional<CodecScenario> BFrameScenarioChecker(CapabilityData &capData, const Format &format,
224 AVCodecType codecType)
225 {
226 int32_t enable = 0;
227 int32_t temporalEnable = 0;
228 std::optional<CodecScenario> scenario = std::nullopt;
229 bool enableExist = format.GetIntValue(Tag::VIDEO_ENCODER_ENABLE_B_FRAME, enable);
230 bool temporalEnableExist = format.GetIntValue(Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, temporalEnable);
231 PrintParam(enableExist, Tag::VIDEO_ENCODER_ENABLE_B_FRAME, enable);
232
233 if (codecType == AVCODEC_TYPE_VIDEO_DECODER) {
234 if (enableExist) {
235 AVCODEC_LOGW("B-frame mode is only supported in video encoder!");
236 }
237 return scenario;
238 }
239 if (!enableExist || !enable) {
240 AVCODEC_LOGW("Please enable key VIDEO_ENCODER_ENABLE_B_FRAME or set a correct value!");
241 return scenario;
242 }
243 CHECK_AND_RETURN_RET_LOGW(capData.featuresMap.count(
244 static_cast<int32_t>(AVCapabilityFeature::VIDEO_ENCODER_B_FRAME)),
245 scenario, "Not support B-frame");
246
247 if (temporalEnableExist && temporalEnable) {
248 AVCODEC_LOGW("B-frame and temporalscalability encoding are not compatible, using B-frame mode by default!");
249 }
250 scenario = CodecScenario::CODEC_SCENARIO_ENC_ENABLE_B_FRAME;
251 return scenario;
252 }
253
ResolutionChecker(CapabilityData & capData,Format & format,CodecScenario scenario)254 int32_t ResolutionChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
255 {
256 (void)scenario;
257 int32_t width = 0;
258 int32_t height = 0;
259 bool widthExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width);
260 bool heightExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height);
261 CHECK_AND_RETURN_RET_LOG(widthExist && heightExist, AVCS_ERR_INVALID_VAL, "Key param missing, width or height");
262 PrintParam(widthExist && heightExist, "resolution", width, height);
263
264 bool resolutionValid = true;
265 if (capData.supportSwapWidthHeight) {
266 AVCODEC_LOGI("Codec support swap width and height");
267 resolutionValid = (capData.width.InRange(width) && capData.height.InRange(height)) ||
268 (capData.width.InRange(height) && capData.height.InRange(width));
269 } else {
270 resolutionValid = capData.width.InRange(width) && capData.height.InRange(height);
271 }
272 CHECK_AND_RETURN_RET_LOG(resolutionValid, AVCS_ERR_INVALID_VAL,
273 "Param invalid, resolution: %{public}d*%{public}d, range: [%{public}d*%{public}d]-[%{public}d*%{public}d]",
274 width, height, capData.width.minVal, capData.height.minVal, capData.width.maxVal, capData.height.maxVal);
275 return AVCS_ERR_OK;
276 }
277
PixelFormatChecker(CapabilityData & capData,Format & format,CodecScenario scenario)278 int32_t PixelFormatChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
279 {
280 (void)scenario;
281 int32_t pixelFormat;
282 bool paramExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, pixelFormat);
283 if (!paramExist || pixelFormat == static_cast<int32_t>(VideoPixelFormat::SURFACE_FORMAT)) {
284 return AVCS_ERR_OK;
285 }
286 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, pixelFormat);
287
288 bool paramValid = IsSupported(capData.pixFormat, pixelFormat);
289 CHECK_AND_RETURN_RET_LOG(paramValid, AVCS_ERR_UNSUPPORT,
290 "Param invalid, %{public}s: %{public}d, please check codec capabilities",
291 MediaDescriptionKey::MD_KEY_PIXEL_FORMAT.data(), pixelFormat); // Invalid pixel format
292
293 return AVCS_ERR_OK;
294 }
295
FramerateChecker(CapabilityData & capData,Format & format,CodecScenario scenario)296 int32_t FramerateChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
297 {
298 (void)capData;
299 (void)scenario;
300 double framerate;
301 bool paramExist = format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, framerate);
302 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_FRAME_RATE, framerate);
303 if (paramExist == false) {
304 return AVCS_ERR_OK;
305 }
306
307 bool paramValid = framerate > 0 ? true : false;
308 CHECK_AND_RETURN_RET_LOG(paramValid, AVCS_ERR_CODEC_PARAM_INCORRECT,
309 "Param invalid, %{public}s: %{public}.2f, should be greater than 0",
310 MediaDescriptionKey::MD_KEY_FRAME_RATE.data(), framerate); // Invalid framerate
311
312 return AVCS_ERR_OK;
313 }
314
CheckBitrateAndQualityParamRange(CapabilityData & capData,Format & format)315 bool CheckBitrateAndQualityParamRange(CapabilityData &capData, Format &format)
316 {
317 int64_t bitrate;
318 int32_t quality;
319 if (format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitrate)) {
320 bool bitrateValid = capData.bitrate.InRange(bitrate);
321 CHECK_AND_RETURN_RET_LOG(bitrateValid, false,
322 "Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
323 MediaDescriptionKey::MD_KEY_BITRATE.data(), static_cast<int32_t>(bitrate),
324 capData.bitrate.minVal, capData.bitrate.maxVal);
325 }
326
327 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality)) {
328 bool qualityValid = capData.encodeQuality.InRange(quality);
329 CHECK_AND_RETURN_RET_LOG(qualityValid, false,
330 "Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
331 MediaDescriptionKey::MD_KEY_QUALITY.data(), quality,
332 capData.encodeQuality.minVal, capData.encodeQuality.maxVal);
333 }
334 return true;
335 }
336
ReplaceMaxBitrateWithBitrate(Format & format)337 void ReplaceMaxBitrateWithBitrate(Format &format)
338 {
339 int64_t bitrate;
340 bool bitrateExist = format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitrate);
341 if (bitrateExist) {
342 AVCODEC_LOGW("Param %{public}s invalid in SQR bitrate mode, param %{public}s will be used instead",
343 MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE.data(),
344 MediaDescriptionKey::MD_KEY_BITRATE.data());
345 format.PutLongValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, bitrate);
346 }
347 }
348
349 /*
350 return
351 false: SQR is not set successfully. If the mode is SQR, convert to VBR and ignore sqrfactor、max_bitrate
352 true : SQR is set successfully
353 */
CheckSqrMode(CapabilityData & capData,Format & format)354 bool CheckSqrMode(CapabilityData &capData, Format &format)
355 {
356 int64_t bitrate;
357 int64_t maxBitrate;
358 int32_t quality;
359 int32_t sqrFactor;
360 int32_t bitrateMode;
361 bool bitrateExist = format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitrate);
362 bool maxBitrateExist = format.GetLongValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, maxBitrate);
363 bool qualityExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality);
364 bool sqrFactorExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR, sqrFactor);
365 bool bitrateModeExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
366 PrintParam(sqrFactorExist, MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR, sqrFactor);
367 PrintParam(maxBitrateExist, MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, maxBitrate);
368
369 if (!bitrateModeExist || bitrateMode != VideoEncodeBitrateMode::SQR) {
370 return false;
371 }
372
373 if (IsSupported(capData.bitrateMode, static_cast<int32_t>(VideoEncodeBitrateMode::SQR))) {
374 if (sqrFactorExist && !capData.sqrFactor.InRange(sqrFactor)) {
375 AVCODEC_LOGW("Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
376 MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR.data(), static_cast<int32_t>(sqrFactor),
377 capData.sqrFactor.minVal, capData.sqrFactor.maxVal);
378 } else {
379 if (bitrateExist && !capData.bitrate.InRange(bitrate)) {
380 AVCODEC_LOGW("Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
381 MediaDescriptionKey::MD_KEY_BITRATE.data(), static_cast<int32_t>(bitrate),
382 capData.bitrate.minVal, capData.bitrate.maxVal);
383 format.RemoveKey(MediaDescriptionKey::MD_KEY_BITRATE);
384 }
385 if (maxBitrateExist && !capData.maxBitrate.InRange(maxBitrate)) {
386 AVCODEC_LOGW("Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
387 MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE.data(), static_cast<int32_t>(maxBitrate),
388 capData.maxBitrate.minVal, capData.maxBitrate.maxVal);
389 format.RemoveKey(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE);
390 ReplaceMaxBitrateWithBitrate(format);
391 }
392 if (qualityExist) {
393 AVCODEC_LOGW("Param invalid, in SQR mode but set quality!");
394 format.RemoveKey(MediaDescriptionKey::MD_KEY_QUALITY);
395 }
396 return true;
397 }
398 }
399 format.RemoveKey(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE);
400 format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, VideoEncodeBitrateMode::VBR);
401 format.RemoveKey(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR);
402 format.RemoveKey(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE);
403 AVCODEC_LOGW("Param invalid, convert the mode to VBR!");
404 return false;
405 }
406
CheckBitrateModeSupport(CapabilityData & capData,Format & format)407 bool CheckBitrateModeSupport(CapabilityData &capData, Format &format)
408 {
409 int32_t bitrateMode;
410 int32_t quality;
411 bool qualityExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality);
412 // 1) set mode which may be not supported
413 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode)) {
414 CHECK_AND_RETURN_RET_LOG(IsSupported(capData.bitrateMode, bitrateMode),
415 false, "Param invalid, %{public}s: %{public}d not supported",
416 MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE.data(), bitrateMode); // Invalid bitrate mode
417 if (!qualityExist && bitrateMode == VideoEncodeBitrateMode::CQ) {
418 format.PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, DEFAULT_QUALITY);
419 AVCODEC_LOGW("In CQ mode but not set quality, set default quality: %{public}d", DEFAULT_QUALITY);
420 }
421 } else { // 2) set params whose corresponding mode may be not supported
422 if (qualityExist &&
423 IsSupported(capData.bitrateMode, static_cast<int32_t>(VideoEncodeBitrateMode::CQ))) {
424 format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, VideoEncodeBitrateMode::CQ);
425 }
426 }
427 return true;
428 }
429
BitrateAndQualityChecker(CapabilityData & capData,Format & format,CodecScenario scenario)430 int32_t BitrateAndQualityChecker(CapabilityData &capData, Format &format, [[maybe_unused]] CodecScenario scenario)
431 {
432 int64_t bitrate;
433 int32_t quality;
434 int32_t bitrateMode;
435 bool bitrateExist = format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitrate);
436 bool qualityExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality);
437 bool bitrateModeExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
438 PrintParam(bitrateExist, MediaDescriptionKey::MD_KEY_BITRATE, bitrate);
439 PrintParam(qualityExist, MediaDescriptionKey::MD_KEY_QUALITY, quality);
440 PrintParam(bitrateModeExist, MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
441
442 /* CHECK: set SQR */
443 if (CheckSqrMode(capData, format)) {
444 return AVCS_ERR_OK;
445 }
446
447 /* CHECK: set VBR\CBR\CQ or set no mode */
448 format.RemoveKey(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR);
449 format.RemoveKey(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE);
450
451 // 1. conflict
452 // 1)conlict between (key)params
453 CHECK_AND_RETURN_RET_LOG(!(qualityExist && (bitrateExist)),
454 AVCS_ERR_CODEC_PARAM_INCORRECT, "Param invalid, quality and some other param mutually include");
455 // 2)conlict between (key)params and mode
456 if (bitrateModeExist) {
457 CHECK_AND_RETURN_RET_LOG(!(bitrateExist && bitrateMode == VideoEncodeBitrateMode::CQ),
458 AVCS_ERR_CODEC_PARAM_INCORRECT, "Param invalid, in CQ mode but set bitrate or max_bitrate!");
459
460 CHECK_AND_RETURN_RET_LOG(!(qualityExist && bitrateMode != VideoEncodeBitrateMode::CQ),
461 AVCS_ERR_CODEC_PARAM_INCORRECT, "Param invalid, not in CQ mode but set quality!");
462 }
463
464 // 2. not supported (no conflicts between params by default)
465 CHECK_AND_RETURN_RET_LOG(CheckBitrateModeSupport(capData, format), AVCS_ERR_CODEC_PARAM_INCORRECT,
466 "mode not supported!");
467
468 // 3 param range
469 CHECK_AND_RETURN_RET_LOG(CheckBitrateAndQualityParamRange(capData, format), AVCS_ERR_CODEC_PARAM_INCORRECT,
470 "param val not in range!");
471
472 return AVCS_ERR_OK;
473 }
474
VideoProfileChecker(CapabilityData & capData,Format & format,CodecScenario scenario)475 int32_t VideoProfileChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
476 {
477 (void)scenario;
478 int32_t profile;
479 bool paramExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, profile);
480 if (paramExist == false) {
481 return AVCS_ERR_OK;
482 }
483 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_PROFILE, profile);
484
485 bool paramValid = IsSupported(capData.profiles, profile);
486 CHECK_AND_RETURN_RET_LOG(paramValid, AVCS_ERR_CODEC_PARAM_INCORRECT,
487 "Param invalid, %{public}s: %{public}d, please check codec capabilities",
488 MediaDescriptionKey::MD_KEY_PROFILE.data(), profile); // Invalid profile
489
490 return AVCS_ERR_OK;
491 }
492
RotationChecker(CapabilityData & capData,Format & format,CodecScenario scenario)493 int32_t RotationChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
494 {
495 (void)capData;
496 (void)scenario;
497 int32_t rotation;
498 bool paramExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, rotation);
499 if (paramExist == false) {
500 return AVCS_ERR_OK;
501 }
502 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, rotation);
503
504 // valid rotation: 0, 90, 180, 270
505 CHECK_AND_RETURN_RET_LOG(rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270,
506 AVCS_ERR_CODEC_PARAM_INCORRECT, "Param invalid, %{public}s: %{public}d, only support {0, 90, 180, 270}",
507 MediaDescriptionKey::MD_KEY_ROTATION_ANGLE.data(), rotation); // Invalid rotation
508
509 return AVCS_ERR_OK;
510 }
511
PostProcessingChecker(CapabilityData & capData,Format & format,CodecScenario scenario)512 int32_t PostProcessingChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
513 {
514 if (scenario != CodecScenario::CODEC_SCENARIO_DEC_NORMAL) {
515 return AVCS_ERR_OK;
516 }
517 int32_t colorSpace;
518 bool hasColorSpace = format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_DECODER_OUTPUT_COLOR_SPACE, colorSpace);
519 if (!hasColorSpace) {
520 return AVCS_ERR_OK;
521 }
522 CHECK_AND_RETURN_RET_LOG((colorSpace >= 0) && // 0: OH_COLORSAPCE_NONE
523 (colorSpace <= 31), // 31: OH_COLORSPACE_DISPLAY_BT2020_PQ
524 AVCS_ERR_INVALID_VAL, "The output color space %{public}d is invaild", colorSpace);
525 CHECK_AND_RETURN_RET_LOG(capData.mimeType == CodecMimeType::VIDEO_HEVC && capData.isVendor,
526 AVCS_ERR_VIDEO_UNSUPPORT_COLOR_SPACE_CONVERSION,
527 "colorspace conversion is not available for the codec.");
528
529 constexpr int32_t colorSpaceBt709Limited = 8; // see OH_COLORSPACE_BT709_LIMITED in native_buffer.h;
530 constexpr int32_t colorSpaceP3Full = 12; // see OH_COLORSPACE_P3_FULL in native_buffer.h;
531 CHECK_AND_RETURN_RET_LOG(colorSpace == colorSpaceBt709Limited || colorSpace == colorSpaceP3Full,
532 AVCS_ERR_VIDEO_UNSUPPORT_COLOR_SPACE_CONVERSION,
533 "The output color space %{public}d is not supported", colorSpace);
534 PrintParam(true, MediaDescriptionKey::MD_KEY_VIDEO_DECODER_OUTPUT_COLOR_SPACE, colorSpace);
535
536 return AVCS_ERR_OK;
537 }
538
QPChecker(CapabilityData & capData,Format & format,CodecScenario scenario)539 int32_t QPChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
540 {
541 (void)capData;
542 (void)scenario;
543 constexpr int32_t MAX_QP = 51;
544 int32_t qpMin;
545 int32_t qpMax;
546 bool qpMinExist = format.GetIntValue(Tag::VIDEO_ENCODER_QP_MIN, qpMin);
547 bool qpMaxExist = format.GetIntValue(Tag::VIDEO_ENCODER_QP_MAX, qpMax);
548 if (!qpMinExist && !qpMaxExist) {
549 return AVCS_ERR_OK;
550 }
551 CHECK_AND_RETURN_RET_LOG(!(qpMinExist != qpMaxExist), AVCS_ERR_INVALID_VAL,
552 "Param invalid, QPmin and QPmax are expected to be set in pairs in format");
553 PrintParam(qpMinExist && qpMaxExist, "QP", qpMin, qpMax);
554
555 CHECK_AND_RETURN_RET_LOG(qpMin >= 0 && qpMin <= qpMax, AVCS_ERR_INVALID_VAL,
556 "Param invalid, QP range: %{public}d-%{public}d", qpMin, qpMax);
557 CHECK_AND_RETURN_RET_LOG(qpMax <= MAX_QP && qpMax >= qpMin, AVCS_ERR_INVALID_VAL,
558 "Param invalid, QP range: %{public}d-%{public}d", qpMin, qpMax);
559
560 return AVCS_ERR_OK;
561 }
562
IFrameIntervalChecker(CapabilityData & capData,Format & format,CodecScenario scenario)563 int32_t IFrameIntervalChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
564 {
565 (void)capData;
566 (void)scenario;
567
568 int32_t iFrameInterval;
569 bool iFrameIntervalExist = format.GetIntValue(Tag::VIDEO_I_FRAME_INTERVAL, iFrameInterval);
570 PrintParam(iFrameIntervalExist, Tag::VIDEO_I_FRAME_INTERVAL, iFrameInterval);
571 if (!iFrameIntervalExist) {
572 format.PutIntValue(Tag::VIDEO_I_FRAME_INTERVAL, DEFAULT_I_FRAME_INTERVAL);
573 }
574
575 return AVCS_ERR_OK;
576 }
577
TemporalGopSizeChecker(CapabilityData & capData,Format & format,CodecScenario scenario)578 int32_t TemporalGopSizeChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
579 {
580 (void)capData;
581 (void)scenario;
582 int32_t gopSize;
583 int32_t temporalGopSize;
584 double frameRate;
585 int32_t iFrameInterval;
586
587 bool frameRateExist = format.GetDoubleValue(Tag::VIDEO_FRAME_RATE, frameRate);
588 bool iFrameIntervalExist = format.GetIntValue(Tag::VIDEO_I_FRAME_INTERVAL, iFrameInterval);
589 CHECK_AND_RETURN_RET_LOG(!(iFrameIntervalExist && iFrameInterval == 0), AVCS_ERR_INVALID_VAL,
590 "Not support all key frame in temporal scalability");
591
592 if (!frameRateExist) {
593 frameRate = DEFAULT_FRAMERATE;
594 format.PutDoubleValue(Tag::VIDEO_FRAME_RATE, DEFAULT_FRAMERATE);
595 }
596 if (!iFrameIntervalExist) {
597 iFrameInterval = DEFAULT_I_FRAME_INTERVAL;
598 format.PutIntValue(Tag::VIDEO_I_FRAME_INTERVAL, DEFAULT_I_FRAME_INTERVAL);
599 }
600 gopSize = iFrameInterval < 0 ? INT32_MAX : static_cast<int32_t>(frameRate * iFrameInterval / 1000); // 1000: ms to s
601 CHECK_AND_RETURN_RET_LOG(gopSize > MIN_TEMPORAL_GOPSIZE, AVCS_ERR_INVALID_VAL,
602 "Unsuppoted gop size, should be greater than %{public}d!", MIN_TEMPORAL_GOPSIZE);
603 format.PutIntValue("video_encoder_gop_size", gopSize);
604
605 bool temporalGopSizeExist = format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
606 if (!temporalGopSizeExist) {
607 return AVCS_ERR_OK;
608 }
609 PrintParam(temporalGopSizeExist, Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
610 CHECK_AND_RETURN_RET_LOG(temporalGopSize >= MIN_TEMPORAL_GOPSIZE, AVCS_ERR_INVALID_VAL,
611 "Param invalid, %{public}s: %{public}d, expect greater or equal than %{public}d",
612 Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize, MIN_TEMPORAL_GOPSIZE);
613 CHECK_AND_RETURN_RET_LOG(temporalGopSize < gopSize, AVCS_ERR_INVALID_VAL,
614 "Param invalid, %{public}s: %{public}d, expect less than gop_size: %{public}d",
615 Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize, gopSize);
616
617 return AVCS_ERR_OK;
618 }
619
TemporalGopReferenceModeChecker(CapabilityData & capData,Format & format,CodecScenario scenario)620 int32_t TemporalGopReferenceModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
621 {
622 (void)capData;
623 (void)scenario;
624 int32_t mode;
625 bool modeExist = format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
626 if (!modeExist) {
627 return AVCS_ERR_OK;
628 }
629 PrintParam(modeExist, Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
630
631 using namespace OHOS::Media::Plugins;
632 if (mode < static_cast<int32_t>(TemporalGopReferenceMode::ADJACENT_REFERENCE) ||
633 mode >= static_cast<int32_t>(TemporalGopReferenceMode::UNKNOWN)) {
634 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
635 return AVCS_ERR_INVALID_VAL;
636 }
637 return AVCS_ERR_OK;
638 }
639
UniformlyScaledReferenceChecker(CapabilityData & capData,Format & format,CodecScenario scenario)640 int32_t UniformlyScaledReferenceChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
641 {
642 (void)capData;
643 (void)scenario;
644 int32_t mode = -1;
645 format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
646 using namespace OHOS::Media::Plugins;
647 if (mode == static_cast<int32_t>(TemporalGopReferenceMode::UNIFORMLY_SCALED_REFERENCE)) {
648 int32_t temporalGopSize;
649 bool temporalGopSizeExist = format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
650 if (!temporalGopSizeExist) {
651 return AVCS_ERR_OK;
652 }
653 CHECK_AND_RETURN_RET_LOG(temporalGopSize == MIN_TEMPORAL_GOPSIZE || temporalGopSize == DEFAULT_TEMPORAL_GOPSIZE,
654 AVCS_ERR_INVALID_VAL,
655 "Current temporal reference mode param invalid, %{public}s: %{public}d, expect 2 or 4",
656 Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
657 }
658 return AVCS_ERR_OK;
659 }
660
ColorPrimariesChecker(CapabilityData & capData,Format & format,CodecScenario scenario)661 int32_t ColorPrimariesChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
662 {
663 (void)capData;
664 (void)scenario;
665 int32_t colorPrimaries;
666 bool colorPrimariesExist = format.GetIntValue(Tag::VIDEO_COLOR_PRIMARIES, colorPrimaries);
667 if (!colorPrimariesExist) {
668 return AVCS_ERR_OK;
669 }
670 PrintParam(colorPrimariesExist, Tag::VIDEO_COLOR_PRIMARIES, colorPrimaries);
671
672 if (colorPrimaries < static_cast<int32_t>(ColorPrimary::COLOR_PRIMARY_BT709) ||
673 colorPrimaries > static_cast<int32_t>(ColorPrimary::COLOR_PRIMARY_P3D65)) {
674 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_COLOR_PRIMARIES, colorPrimaries);
675 return AVCS_ERR_INVALID_VAL;
676 }
677 return AVCS_ERR_OK;
678 }
679
TransferCharacteristicsChecker(CapabilityData & capData,Format & format,CodecScenario scenario)680 int32_t TransferCharacteristicsChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
681 {
682 (void)capData;
683 (void)scenario;
684 int32_t transferCharacteristics;
685 bool transferCharacteristicsExist = format.GetIntValue(Tag::VIDEO_COLOR_TRC, transferCharacteristics);
686 if (!transferCharacteristicsExist) {
687 return AVCS_ERR_OK;
688 }
689 PrintParam(transferCharacteristicsExist, Tag::VIDEO_COLOR_TRC, transferCharacteristics);
690
691 if (transferCharacteristics < static_cast<int32_t>(TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709) ||
692 transferCharacteristics > static_cast<int32_t>(TransferCharacteristic::TRANSFER_CHARACTERISTIC_HLG)) {
693 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_COLOR_TRC, transferCharacteristics);
694 return AVCS_ERR_INVALID_VAL;
695 }
696 return AVCS_ERR_OK;
697 }
698
MatrixCoefficientsChecker(CapabilityData & capData,Format & format,CodecScenario scenario)699 int32_t MatrixCoefficientsChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
700 {
701 (void)capData;
702 (void)scenario;
703 int32_t matrixCoefficients;
704 bool matrixCoefficientsExist = format.GetIntValue(Tag::VIDEO_COLOR_MATRIX_COEFF, matrixCoefficients);
705 if (!matrixCoefficientsExist) {
706 return AVCS_ERR_OK;
707 }
708 PrintParam(matrixCoefficientsExist, Tag::VIDEO_COLOR_MATRIX_COEFF, matrixCoefficients);
709
710 if (matrixCoefficients < static_cast<int32_t>(MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY) ||
711 matrixCoefficients > static_cast<int32_t>(MatrixCoefficient::MATRIX_COEFFICIENT_ICTCP)) {
712 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_COLOR_MATRIX_COEFF, matrixCoefficients);
713 return AVCS_ERR_INVALID_VAL;
714 }
715 return AVCS_ERR_OK;
716 }
717
LTRFrameCountChecker(CapabilityData & capData,Format & format,CodecScenario scenario)718 int32_t LTRFrameCountChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
719 {
720 int32_t ltrFrameCount;
721 bool ltrFrameCountExist = format.GetIntValue(Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, ltrFrameCount);
722 if (!ltrFrameCountExist) {
723 return AVCS_ERR_OK;
724 }
725 PrintParam(ltrFrameCountExist, Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, ltrFrameCount);
726
727 CHECK_AND_RETURN_RET_LOG(scenario != CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY,
728 AVCS_ERR_UNSUPPORT, "Param invalid, not supported to set LTR frame count in temporal scalability scenario");
729
730 auto ltrCap =
731 capData.featuresMap.find(static_cast<int32_t>(AVCapabilityFeature::VIDEO_ENCODER_LONG_TERM_REFERENCE));
732 if (ltrCap == capData.featuresMap.end()) {
733 AVCODEC_LOGW("Not support LTR but set LTR frame count");
734 format.RemoveKey(Tag::VIDEO_ENCODER_LTR_FRAME_COUNT);
735 return AVCS_ERR_OK;
736 }
737 int32_t maxLTRFrameCount = 0;
738 bool maxLTRFrameCountExist =
739 ltrCap->second.GetIntValue(Tag::FEATURE_PROPERTY_VIDEO_ENCODER_MAX_LTR_FRAME_COUNT, maxLTRFrameCount);
740 CHECK_AND_RETURN_RET_LOG(maxLTRFrameCountExist, AVCS_ERR_UNKNOWN, "Max LTR frame count not defined");
741
742 CHECK_AND_RETURN_RET_LOG(ltrFrameCount >= 0 && ltrFrameCount <= maxLTRFrameCount, AVCS_ERR_INVALID_VAL,
743 "Param invalid, LTR frame count range: %{public}d-%{public}d", 0, maxLTRFrameCount);
744
745 return AVCS_ERR_OK;
746 }
747
ScalingModeChecker(CapabilityData & capData,Format & format,CodecScenario scenario)748 int32_t ScalingModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
749 {
750 (void)capData;
751 (void)scenario;
752 int32_t scalingMode;
753 bool scalingModeExist = format.GetIntValue(Tag::VIDEO_SCALE_TYPE, scalingMode);
754 if (!scalingModeExist) {
755 return AVCS_ERR_OK;
756 }
757 PrintParam(scalingModeExist, Tag::VIDEO_SCALE_TYPE, scalingMode);
758
759 if (scalingMode < static_cast<int32_t>(OHOS::ScalingMode::SCALING_MODE_SCALE_TO_WINDOW) ||
760 scalingMode > static_cast<int32_t>(OHOS::ScalingMode::SCALING_MODE_SCALE_CROP)) {
761 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_SCALE_TYPE, scalingMode);
762 return AVCS_ERR_INVALID_VAL;
763 }
764 return AVCS_ERR_OK;
765 }
766
BFrameParamChecker(CapabilityData & capData,Format & format,CodecScenario scenario)767 int32_t BFrameParamChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
768 {
769 (void)scenario;
770 int32_t mode;
771 int32_t cond = -1;
772 int32_t maxBFrameCount = -1;
773 auto bFrameCap =
774 capData.featuresMap.find(static_cast<int32_t>(AVCapabilityFeature::VIDEO_ENCODER_B_FRAME));
775 if (bFrameCap == capData.featuresMap.end()) {
776 AVCODEC_LOGW("Not support AVCapabilityFeature::VIDEO_ENCODER_B_FRAME");
777 format.RemoveKey(Tag::VIDEO_ENCODE_B_FRAME_GOP_MODE);
778 return AVCS_ERR_OK;
779 }
780 bool condExist = format.GetIntValue(Tag::VIDEO_ENCODER_ENABLE_B_FRAME, cond);
781 if (!condExist || cond <= 0) {
782 format.RemoveKey(Tag::VIDEO_ENCODE_B_FRAME_GOP_MODE);
783 AVCODEC_LOGE("Encoder B-frame key VIDEO_ENCODER_ENABLE_B_FRAME not exist or param illegal!");
784 return AVCS_ERR_OK;
785 }
786 PrintParam(condExist, Tag::VIDEO_ENCODER_ENABLE_B_FRAME, cond);
787 bool modeExist = format.GetIntValue(Tag::VIDEO_ENCODE_B_FRAME_GOP_MODE, mode);
788 if (!modeExist) {
789 AVCODEC_LOGW("undefine VIDEO_ENCODE_B_FRAME_GOP_MODE, default to ADAPTIVE_B_MODE");
790 mode = static_cast<int32_t>(Plugins::VideoEncodeBFrameGopMode::VIDEO_ENCODE_GOP_ADAPTIVE_B_MODE);
791 }
792 PrintParam(modeExist, Tag::VIDEO_ENCODE_B_FRAME_GOP_MODE, mode);
793 format.PutIntValue(Tag::VIDEO_ENCODE_B_FRAME_GOP_MODE, mode);
794 bool maxBFrameExist = format.GetIntValue(Tag::VIDEO_ENCODER_MAX_B_FRAME, maxBFrameCount);
795 if (maxBFrameExist) {
796 AVCODEC_LOGE("UnSupported config VIDEO_ENCODER_MAX_B_FRAME!");
797 format.RemoveKey(Tag::VIDEO_ENCODER_MAX_B_FRAME);
798 }
799 return AVCS_ERR_OK;
800 }
801
SQRDynamicParameterCheck(CapabilityData & capData,const Format & format,Format & oldFormat)802 void SQRDynamicParameterCheck(CapabilityData &capData, const Format &format, Format &oldFormat)
803 {
804 int32_t bitrateMode;
805 bool bitrateModeExist = oldFormat.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
806 if (!bitrateModeExist || bitrateMode != VideoEncodeBitrateMode::SQR) {
807 return;
808 }
809 int64_t maxBitrate;
810 int32_t sqrFactor;
811 bool maxBitrateExist = format.GetLongValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, maxBitrate);
812 bool sqrFactorExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR, sqrFactor);
813 if (sqrFactorExist && !capData.sqrFactor.InRange(sqrFactor)) {
814 AVCODEC_LOGW("Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
815 MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR.data(), static_cast<int32_t>(sqrFactor),
816 capData.sqrFactor.minVal, capData.sqrFactor.maxVal);
817 }
818 if (maxBitrateExist && !capData.maxBitrate.InRange(maxBitrate)) {
819 AVCODEC_LOGW("Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
820 MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE.data(), static_cast<int32_t>(maxBitrate),
821 capData.maxBitrate.minVal, capData.maxBitrate.maxVal);
822 }
823 }
824 } // namespace
825
826 namespace OHOS {
827 namespace MediaAVCodec {
CheckConfigureValid(Media::Format & format,const std::string & codecName,CodecScenario scenario)828 int32_t CodecParamChecker::CheckConfigureValid(Media::Format &format, const std::string &codecName,
829 CodecScenario scenario)
830 {
831 AVCODEC_SYNC_TRACE;
832 auto capData = CodecAbilitySingleton::GetInstance().GetCapabilityByName(codecName);
833 CHECK_AND_RETURN_RET_LOG(capData != std::nullopt,
834 AVCS_ERR_INVALID_OPERATION, "Get codec capability from codec list failed");
835
836 auto checkers = CONFIGURE_CHECKERS_TABLE.find(scenario);
837 CHECK_AND_RETURN_RET_LOG(checkers != CONFIGURE_CHECKERS_TABLE.end(), AVCS_ERR_UNSUPPORT,
838 "This scenario can not find any checkers");
839
840 int32_t result = AVCS_ERR_OK;
841 for (const auto &checker : checkers->second) {
842 auto ret = checker(capData.value(), format, scenario);
843 if (ret == AVCS_ERR_CODEC_PARAM_INCORRECT) {
844 result = AVCS_ERR_CODEC_PARAM_INCORRECT;
845 }
846 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK || ret == AVCS_ERR_CODEC_PARAM_INCORRECT,
847 ret, "Param check failed");
848 }
849 return result;
850 }
851
CheckParameterValid(const Media::Format & format,Media::Format & oldFormat,const std::string & codecName,CodecScenario scenario)852 int32_t CodecParamChecker::CheckParameterValid(const Media::Format &format, Media::Format &oldFormat,
853 const std::string &codecName, CodecScenario scenario)
854 {
855 AVCODEC_SYNC_TRACE;
856 auto capData = CodecAbilitySingleton::GetInstance().GetCapabilityByName(codecName);
857 CHECK_AND_RETURN_RET_LOG(capData != std::nullopt,
858 AVCS_ERR_INVALID_OPERATION, "Get codec capability from codec list failed");
859
860 auto checkers = PARAMETER_CHECKERS_TABLE.find(scenario);
861 CHECK_AND_RETURN_RET_LOG(checkers != PARAMETER_CHECKERS_TABLE.end(), AVCS_ERR_UNSUPPORT,
862 "This scenario can not find any checkers");
863
864 SQRDynamicParameterCheck(capData.value(), format, oldFormat);
865
866 MergeFormat(format, oldFormat);
867
868 for (const auto &checker : checkers->second) {
869 auto ret = checker(capData.value(), oldFormat, scenario);
870 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Param check failed");
871 }
872 return AVCS_ERR_OK;
873 }
874
CheckCodecScenario(const Media::Format & format,AVCodecType codecType,const std::string & codecName)875 std::optional<CodecScenario> CodecParamChecker::CheckCodecScenario(const Media::Format &format, AVCodecType codecType,
876 const std::string &codecName)
877 {
878 auto capData = CodecAbilitySingleton::GetInstance().GetCapabilityByName(codecName);
879 CHECK_AND_RETURN_RET_LOG(capData != std::nullopt,
880 std::nullopt, "Get codec capability from codec list failed");
881
882 CodecScenario scenario = CodecScenario::CODEC_SCENARIO_DEC_NORMAL;
883 if (codecType == AVCODEC_TYPE_VIDEO_ENCODER) {
884 scenario = CodecScenario::CODEC_SCENARIO_ENC_NORMAL;
885 }
886
887 for (const auto& checker : VIDEO_SCENARIO_CHECKER_LIST) {
888 auto ret = checker(capData.value(), format, codecType);
889 if (ret == std::nullopt) {
890 continue;
891 }
892 scenario = ret.value();
893 break;
894 }
895
896 PrintCodecScenario(scenario);
897 return scenario;
898 }
899
MergeFormat(const Media::Format & format,Media::Format & oldFormat)900 void CodecParamChecker::MergeFormat(const Media::Format &format, Media::Format &oldFormat)
901 {
902 for (const auto& key : FORMAT_MERGE_LIST) {
903 if (!format.ContainKey(key)) {
904 continue;
905 }
906 auto keyType = format.GetValueType(key);
907 switch (keyType) {
908 case FORMAT_TYPE_INT32: {
909 int32_t value;
910 format.GetIntValue(key, value);
911 oldFormat.PutIntValue(key, value);
912 break;
913 }
914 case FORMAT_TYPE_INT64: {
915 int64_t value;
916 format.GetLongValue(key, value);
917 oldFormat.PutLongValue(key, value);
918 break;
919 }
920 case FORMAT_TYPE_FLOAT: {
921 float value;
922 format.GetFloatValue(key, value);
923 oldFormat.PutFloatValue(key, value);
924 break;
925 }
926 case FORMAT_TYPE_DOUBLE: {
927 double value;
928 format.GetDoubleValue(key, value);
929 oldFormat.PutDoubleValue(key, value);
930 break;
931 }
932 case FORMAT_TYPE_STRING: {
933 std::string value;
934 format.GetStringValue(key, value);
935 oldFormat.PutStringValue(key, value);
936 break;
937 }
938 default:
939 break;
940 }
941 }
942 }
943 } // namespace MediaAVCodec
944 } // namespace OHOS