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 "meta/meta_key.h"
26 #include "codec_ability_singleton.h"
27 #include "media_description.h"
28 #include "meta/meta_key.h"
29 #include "temporal_scalability.h"
30 #include "meta/video_types.h"
31 #include "surface_type.h"
32
33 namespace {
34 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "CodecParamChecker"};
35 using namespace OHOS::Media;
36 using namespace OHOS::MediaAVCodec;
37
38 constexpr int32_t DEFAULT_QUALITY = 50;
39 constexpr int32_t DEFAULT_I_FRAME_INTERVAL = 1000;
40
41 const std::unordered_map<CodecScenario, std::string_view> CODEC_SCENARIO_TO_STRING = {
42 {CodecScenario::CODEC_SCENARIO_ENC_NORMAL, "encoder normal"},
43 {CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY, "encoder temporal scalability"},
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
87 // Video codec checker
88 int32_t ResolutionChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
89 int32_t PixelFormatChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
90 int32_t FramerateChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
91 int32_t BitrateAndQualityChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
92 int32_t VideoProfileChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
93 int32_t RotaitonChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
94 int32_t QPChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
95 int32_t IFrameIntervalChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
96 int32_t TemporalGopSizeChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
97 int32_t TemporalGopReferenceModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
98 int32_t UniformlyScaledReferenceChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
99 int32_t ColorPrimariesChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
100 int32_t TransferCharacteristicsChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
101 int32_t MatrixCoefficientsChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
102 int32_t LTRFrameCountChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
103 int32_t ScalingModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
104 int32_t PostProcessingChecker(CapabilityData &capData, Format &format, CodecScenario scenario);
105
106 // Checkers list define
107 using ScenarioCheckerType =
108 std::optional<CodecScenario> (*)(CapabilityData &capData, const Format &format, AVCodecType codecType);
109 using ParamCheckerType = int32_t (*)(CapabilityData &capData, Format &format, CodecScenario scenario);
110 using ScenarioCheckerListType = std::vector<ScenarioCheckerType>;
111 using ParamCheckerListType = std::vector<ParamCheckerType>;
112 const ParamCheckerListType VIDEO_ENCODER_CONFIGURE_CHECKER_LIST = {
113 ResolutionChecker,
114 PixelFormatChecker,
115 FramerateChecker,
116 BitrateAndQualityChecker,
117 VideoProfileChecker,
118 QPChecker,
119 IFrameIntervalChecker,
120 ColorPrimariesChecker,
121 TransferCharacteristicsChecker,
122 MatrixCoefficientsChecker,
123 LTRFrameCountChecker,
124 };
125
126 const ParamCheckerListType VIDEO_ENCODER_TEMPORAL_SCALABILITY_CONFIGURE_CHECKER_LIST = {
127 ResolutionChecker,
128 PixelFormatChecker,
129 FramerateChecker,
130 BitrateAndQualityChecker,
131 VideoProfileChecker,
132 QPChecker,
133 IFrameIntervalChecker,
134 TemporalGopSizeChecker,
135 TemporalGopReferenceModeChecker,
136 UniformlyScaledReferenceChecker,
137 ColorPrimariesChecker,
138 TransferCharacteristicsChecker,
139 MatrixCoefficientsChecker,
140 LTRFrameCountChecker,
141 };
142
143 const ParamCheckerListType VIDEO_DECODER_CONFIGURE_CHECKER_LIST = {
144 ResolutionChecker,
145 PixelFormatChecker,
146 FramerateChecker,
147 RotaitonChecker,
148 ScalingModeChecker,
149 PostProcessingChecker,
150 };
151
152 const ParamCheckerListType VIDEO_ENCODER_PARAMETER_CHECKER_LIST = {
153 FramerateChecker,
154 BitrateAndQualityChecker,
155 QPChecker,
156 };
157
158 const ParamCheckerListType VIDEO_DECODER_PARAMETER_CHECKER_LIST = {};
159
160 const ScenarioCheckerListType VIDEO_SCENARIO_CHECKER_LIST = {
161 TemporalScalabilityChecker,
162 };
163
164 const std::vector<std::string_view> FORMAT_MERGE_LIST = {
165 MediaDescriptionKey::MD_KEY_BITRATE,
166 MediaDescriptionKey::MD_KEY_QUALITY,
167 MediaDescriptionKey::MD_KEY_FRAME_RATE,
168 Tag::VIDEO_ENCODER_QP_MIN,
169 Tag::VIDEO_ENCODER_QP_MAX,
170 };
171
172 // Checkers table
173 const std::unordered_map<CodecScenario, ParamCheckerListType> CONFIGURE_CHECKERS_TABLE = {
174 {CodecScenario::CODEC_SCENARIO_ENC_NORMAL, VIDEO_ENCODER_CONFIGURE_CHECKER_LIST},
175 {CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY, VIDEO_ENCODER_TEMPORAL_SCALABILITY_CONFIGURE_CHECKER_LIST},
176 {CodecScenario::CODEC_SCENARIO_DEC_NORMAL, VIDEO_DECODER_CONFIGURE_CHECKER_LIST},
177 };
178
179 const std::unordered_map<CodecScenario, ParamCheckerListType> PARAMETER_CHECKERS_TABLE = {
180 {CodecScenario::CODEC_SCENARIO_ENC_NORMAL, VIDEO_ENCODER_PARAMETER_CHECKER_LIST},
181 {CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY, VIDEO_ENCODER_PARAMETER_CHECKER_LIST},
182 {CodecScenario::CODEC_SCENARIO_DEC_NORMAL, VIDEO_DECODER_PARAMETER_CHECKER_LIST},
183 };
184
185 // Checkers implementation
TemporalScalabilityChecker(CapabilityData & capData,const Format & format,AVCodecType codecType)186 std::optional<CodecScenario> TemporalScalabilityChecker(CapabilityData &capData, const Format &format,
187 AVCodecType codecType)
188 {
189 int32_t enable = 0;
190 std::optional<CodecScenario> scenario = std::nullopt;
191 bool enableExist = format.GetIntValue(Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, enable);
192 bool temporalGopSizeExist = format.ContainKey(Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE);
193 bool modeExist = format.ContainKey(Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE);
194 PrintParam(enableExist, Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, enable);
195
196 if (codecType == AVCODEC_TYPE_VIDEO_DECODER) {
197 if (enableExist || temporalGopSizeExist || modeExist) {
198 AVCODEC_LOGW("Temporal scalability is only supported in video encoder!");
199 }
200 return scenario;
201 }
202 if (!enableExist || !enable) {
203 if (temporalGopSizeExist || modeExist) {
204 AVCODEC_LOGW("Please enable key VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY!");
205 }
206 return scenario;
207 }
208 CHECK_AND_RETURN_RET_LOGW(capData.featuresMap.count(
209 static_cast<int32_t>(AVCapabilityFeature::VIDEO_ENCODER_TEMPORAL_SCALABILITY)),
210 scenario, "Not support temporal scalability");
211
212 scenario = CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY;
213 return scenario;
214 }
215
ResolutionChecker(CapabilityData & capData,Format & format,CodecScenario scenario)216 int32_t ResolutionChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
217 {
218 (void)scenario;
219 int32_t width = 0;
220 int32_t height = 0;
221 bool widthExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width);
222 bool heightExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height);
223 CHECK_AND_RETURN_RET_LOG(widthExist && heightExist, AVCS_ERR_INVALID_VAL, "Key param missing, width or height");
224 PrintParam(widthExist && heightExist, "resolution", width, height);
225
226 bool resolutionValid = true;
227 if (capData.supportSwapWidthHeight) {
228 AVCODEC_LOGI("Codec support swap width and height");
229 resolutionValid = (capData.width.InRange(width) && capData.height.InRange(height)) ||
230 (capData.width.InRange(height) && capData.height.InRange(width));
231 } else {
232 resolutionValid = capData.width.InRange(width) && capData.height.InRange(height);
233 }
234 CHECK_AND_RETURN_RET_LOG(resolutionValid, AVCS_ERR_INVALID_VAL,
235 "Param invalid, resolution: %{public}d*%{public}d, range: [%{public}d*%{public}d]-[%{public}d*%{public}d]",
236 width, height, capData.width.minVal, capData.height.minVal, capData.width.maxVal, capData.height.maxVal);
237 return AVCS_ERR_OK;
238 }
239
PixelFormatChecker(CapabilityData & capData,Format & format,CodecScenario scenario)240 int32_t PixelFormatChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
241 {
242 (void)scenario;
243 int32_t pixelFormat;
244 bool paramExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, pixelFormat);
245 if (!paramExist || pixelFormat == static_cast<int32_t>(VideoPixelFormat::SURFACE_FORMAT)) {
246 return AVCS_ERR_OK;
247 }
248 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, pixelFormat);
249
250 bool paramValid = IsSupported(capData.pixFormat, pixelFormat);
251 CHECK_AND_RETURN_RET_LOG(paramValid, AVCS_ERR_UNSUPPORT,
252 "Param invalid, %{public}s: %{public}d, please check codec capabilities",
253 MediaDescriptionKey::MD_KEY_PIXEL_FORMAT.data(), pixelFormat); // Invalid pixel format
254
255 return AVCS_ERR_OK;
256 }
257
FramerateChecker(CapabilityData & capData,Format & format,CodecScenario scenario)258 int32_t FramerateChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
259 {
260 (void)capData;
261 (void)scenario;
262 double framerate;
263 bool paramExist = format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, framerate);
264 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_FRAME_RATE, framerate);
265 if (paramExist == false) {
266 return AVCS_ERR_OK;
267 }
268
269 bool paramValid = framerate > 0 ? true : false;
270 CHECK_AND_RETURN_RET_LOG(paramValid, AVCS_ERR_CODEC_PARAM_INCORRECT,
271 "Param invalid, %{public}s: %{public}.2f, should be greater than 0",
272 MediaDescriptionKey::MD_KEY_FRAME_RATE.data(), framerate); // Invalid framerate
273
274 return AVCS_ERR_OK;
275 }
276
BitrateAndQualityChecker(CapabilityData & capData,Format & format,CodecScenario scenario)277 int32_t BitrateAndQualityChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
278 {
279 (void)scenario;
280 int64_t bitrate;
281 int32_t quality;
282 int32_t bitrateMode;
283 bool bitrateExist = format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitrate);
284 bool qualityExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality);
285 bool bitrateModeExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
286 PrintParam(bitrateExist, MediaDescriptionKey::MD_KEY_BITRATE, bitrate);
287 PrintParam(qualityExist, MediaDescriptionKey::MD_KEY_QUALITY, quality);
288 PrintParam(bitrateModeExist, MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
289
290 CHECK_AND_RETURN_RET_LOG(!(bitrateExist && qualityExist), AVCS_ERR_CODEC_PARAM_INCORRECT,
291 "Param invalid, bitrate and quality mutually include"); // bitrate and quality mutually include
292
293 if (bitrateExist) {
294 bool bitrateValid = capData.bitrate.InRange(bitrate);
295 CHECK_AND_RETURN_RET_LOG(bitrateValid, AVCS_ERR_CODEC_PARAM_INCORRECT,
296 "Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
297 MediaDescriptionKey::MD_KEY_BITRATE.data(), static_cast<int32_t>(bitrate),
298 capData.bitrate.minVal, capData.bitrate.maxVal);
299 }
300 if (qualityExist) {
301 bool qualityValid = capData.encodeQuality.InRange(quality);
302 CHECK_AND_RETURN_RET_LOG(qualityValid, AVCS_ERR_CODEC_PARAM_INCORRECT,
303 "Param invalid, %{public}s: %{public}d, range: %{public}d-%{public}d",
304 MediaDescriptionKey::MD_KEY_QUALITY.data(), quality,
305 capData.encodeQuality.minVal, capData.encodeQuality.maxVal);
306 }
307 if (bitrateModeExist) {
308 bool bitrateModeValid = IsSupported(capData.bitrateMode, bitrateMode);
309 CHECK_AND_RETURN_RET_LOG(bitrateModeValid, AVCS_ERR_CODEC_PARAM_INCORRECT,
310 "Param invalid, %{public}s: %{public}d",
311 MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE.data(), bitrateMode); // Invalid bitrate mode
312 CHECK_AND_RETURN_RET_LOG(!(bitrateExist && bitrateMode == VideoEncodeBitrateMode::CQ),
313 AVCS_ERR_CODEC_PARAM_INCORRECT, "Param invalid, in CQ mode but set bitrate!");
314 CHECK_AND_RETURN_RET_LOG(!(qualityExist && bitrateMode != VideoEncodeBitrateMode::CQ),
315 AVCS_ERR_CODEC_PARAM_INCORRECT, "Param invalid, not in CQ mode but set quality!");
316 if (!qualityExist && bitrateMode == VideoEncodeBitrateMode::CQ) {
317 format.PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, DEFAULT_QUALITY);
318 AVCODEC_LOGW("In CQ mode but not set quality, set default quality: %{public}d", DEFAULT_QUALITY);
319 }
320 } else {
321 if (qualityExist && IsSupported(capData.bitrateMode, static_cast<int32_t>(VideoEncodeBitrateMode::CQ))) {
322 bitrateMode = VideoEncodeBitrateMode::CQ;
323 format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
324 }
325 }
326
327 return AVCS_ERR_OK;
328 }
329
VideoProfileChecker(CapabilityData & capData,Format & format,CodecScenario scenario)330 int32_t VideoProfileChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
331 {
332 (void)scenario;
333 int32_t profile;
334 bool paramExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, profile);
335 if (paramExist == false) {
336 return AVCS_ERR_OK;
337 }
338 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_PROFILE, profile);
339
340 bool paramValid = IsSupported(capData.profiles, profile);
341 CHECK_AND_RETURN_RET_LOG(paramValid, AVCS_ERR_CODEC_PARAM_INCORRECT,
342 "Param invalid, %{public}s: %{public}d, please check codec capabilities",
343 MediaDescriptionKey::MD_KEY_PROFILE.data(), profile); // Invalid profile
344
345 return AVCS_ERR_OK;
346 }
347
RotaitonChecker(CapabilityData & capData,Format & format,CodecScenario scenario)348 int32_t RotaitonChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
349 {
350 (void)capData;
351 (void)scenario;
352 int32_t rotation;
353 bool paramExist = format.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, rotation);
354 if (paramExist == false) {
355 return AVCS_ERR_OK;
356 }
357 PrintParam(paramExist, MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, rotation);
358
359 // valid rotation: 0, 90, 180, 270
360 CHECK_AND_RETURN_RET_LOG(rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270,
361 AVCS_ERR_CODEC_PARAM_INCORRECT, "Param invalid, %{public}s: %{public}d, only support {0, 90, 180, 270}",
362 MediaDescriptionKey::MD_KEY_ROTATION_ANGLE.data(), rotation); // Invalid rotation
363
364 return AVCS_ERR_OK;
365 }
366
PostProcessingChecker(CapabilityData & capData,Format & format,CodecScenario scenario)367 int32_t PostProcessingChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
368 {
369 if (scenario != CodecScenario::CODEC_SCENARIO_DEC_NORMAL) {
370 return AVCS_ERR_OK;
371 }
372 int32_t colorSpace;
373 bool hasColorSpace = format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_DECODER_OUTPUT_COLOR_SPACE, colorSpace);
374 if (!hasColorSpace) {
375 return AVCS_ERR_OK;
376 }
377 CHECK_AND_RETURN_RET_LOG((colorSpace >= 0) && // 0: OH_COLORSAPCE_NONE
378 (colorSpace <= 31), // 31: OH_COLORSPACE_DISPLAY_BT2020_PQ
379 AVCS_ERR_INVALID_VAL, "The output color space %{public}d is invaild", colorSpace);
380 CHECK_AND_RETURN_RET_LOG(capData.mimeType == CodecMimeType::VIDEO_HEVC && capData.isVendor,
381 AVCS_ERR_VIDEO_UNSUPPORT_COLOR_SPACE_CONVERSION,
382 "colorspace conversion is not available for the codec.");
383
384 constexpr int32_t colorSpaceBt709Limited = 8; // see OH_COLORSPACE_BT709_LIMITED in native_buffer.h;
385 CHECK_AND_RETURN_RET_LOG(colorSpace == colorSpaceBt709Limited, AVCS_ERR_VIDEO_UNSUPPORT_COLOR_SPACE_CONVERSION,
386 "The output color space %{public}d is not supported", colorSpace);
387 PrintParam(true, MediaDescriptionKey::MD_KEY_VIDEO_DECODER_OUTPUT_COLOR_SPACE, colorSpace);
388
389 return AVCS_ERR_OK;
390 }
391
QPChecker(CapabilityData & capData,Format & format,CodecScenario scenario)392 int32_t QPChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
393 {
394 (void)capData;
395 (void)scenario;
396 constexpr int32_t MAX_QP = 51;
397 int32_t qpMin;
398 int32_t qpMax;
399 bool qpMinExist = format.GetIntValue(Tag::VIDEO_ENCODER_QP_MIN, qpMin);
400 bool qpMaxExist = format.GetIntValue(Tag::VIDEO_ENCODER_QP_MAX, qpMax);
401 if (!qpMinExist && !qpMaxExist) {
402 return AVCS_ERR_OK;
403 }
404 CHECK_AND_RETURN_RET_LOG(!(qpMinExist != qpMaxExist), AVCS_ERR_INVALID_VAL,
405 "Param invalid, QPmin and QPmax are expected to be set in pairs in format");
406 PrintParam(qpMinExist && qpMaxExist, "QP", qpMin, qpMax);
407
408 CHECK_AND_RETURN_RET_LOG(qpMin >= 0 && qpMin <= qpMax, AVCS_ERR_INVALID_VAL,
409 "Param invalid, QP range: %{public}d-%{public}d", qpMin, qpMax);
410 CHECK_AND_RETURN_RET_LOG(qpMax <= MAX_QP && qpMax >= qpMin, AVCS_ERR_INVALID_VAL,
411 "Param invalid, QP range: %{public}d-%{public}d", qpMin, qpMax);
412
413 return AVCS_ERR_OK;
414 }
415
IFrameIntervalChecker(CapabilityData & capData,Format & format,CodecScenario scenario)416 int32_t IFrameIntervalChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
417 {
418 (void)capData;
419 (void)scenario;
420
421 int32_t iFrameInterval;
422 bool iFrameIntervalExist = format.GetIntValue(Tag::VIDEO_I_FRAME_INTERVAL, iFrameInterval);
423 PrintParam(iFrameIntervalExist, Tag::VIDEO_I_FRAME_INTERVAL, iFrameInterval);
424 if (!iFrameIntervalExist) {
425 format.PutIntValue(Tag::VIDEO_I_FRAME_INTERVAL, DEFAULT_I_FRAME_INTERVAL);
426 }
427
428 return AVCS_ERR_OK;
429 }
430
TemporalGopSizeChecker(CapabilityData & capData,Format & format,CodecScenario scenario)431 int32_t TemporalGopSizeChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
432 {
433 (void)capData;
434 (void)scenario;
435 int32_t gopSize;
436 int32_t temporalGopSize;
437 double frameRate;
438 int32_t iFrameInterval;
439
440 bool frameRateExist = format.GetDoubleValue(Tag::VIDEO_FRAME_RATE, frameRate);
441 bool iFrameIntervalExist = format.GetIntValue(Tag::VIDEO_I_FRAME_INTERVAL, iFrameInterval);
442 CHECK_AND_RETURN_RET_LOG(!(iFrameIntervalExist && iFrameInterval == 0), AVCS_ERR_INVALID_VAL,
443 "Not support all key frame in temporal scalability");
444
445 if (!frameRateExist) {
446 frameRate = DEFAULT_FRAMERATE;
447 format.PutDoubleValue(Tag::VIDEO_FRAME_RATE, DEFAULT_FRAMERATE);
448 }
449 if (!iFrameIntervalExist) {
450 iFrameInterval = DEFAULT_I_FRAME_INTERVAL;
451 format.PutIntValue(Tag::VIDEO_I_FRAME_INTERVAL, DEFAULT_I_FRAME_INTERVAL);
452 }
453 gopSize = iFrameInterval < 0 ? INT32_MAX : static_cast<int32_t>(frameRate * iFrameInterval / 1000); // 1000: ms to s
454 CHECK_AND_RETURN_RET_LOG(gopSize > MIN_TEMPORAL_GOPSIZE, AVCS_ERR_INVALID_VAL,
455 "Unsuppoted gop size, should be greater than %{public}d!", MIN_TEMPORAL_GOPSIZE);
456 format.PutIntValue("video_encoder_gop_size", gopSize);
457
458 bool temporalGopSizeExist = format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
459 if (!temporalGopSizeExist) {
460 return AVCS_ERR_OK;
461 }
462 PrintParam(temporalGopSizeExist, Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
463 CHECK_AND_RETURN_RET_LOG(temporalGopSize >= MIN_TEMPORAL_GOPSIZE, AVCS_ERR_INVALID_VAL,
464 "Param invalid, %{public}s: %{public}d, expect greater or equal than %{public}d",
465 Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize, MIN_TEMPORAL_GOPSIZE);
466 CHECK_AND_RETURN_RET_LOG(temporalGopSize < gopSize, AVCS_ERR_INVALID_VAL,
467 "Param invalid, %{public}s: %{public}d, expect less than gop_size: %{public}d",
468 Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize, gopSize);
469
470 return AVCS_ERR_OK;
471 }
472
TemporalGopReferenceModeChecker(CapabilityData & capData,Format & format,CodecScenario scenario)473 int32_t TemporalGopReferenceModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
474 {
475 (void)capData;
476 (void)scenario;
477 int32_t mode;
478 bool modeExist = format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
479 if (!modeExist) {
480 return AVCS_ERR_OK;
481 }
482 PrintParam(modeExist, Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
483
484 using namespace OHOS::Media::Plugins;
485 if (mode < static_cast<int32_t>(TemporalGopReferenceMode::ADJACENT_REFERENCE) ||
486 mode >= static_cast<int32_t>(TemporalGopReferenceMode::UNKNOWN)) {
487 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
488 return AVCS_ERR_INVALID_VAL;
489 }
490 return AVCS_ERR_OK;
491 }
492
UniformlyScaledReferenceChecker(CapabilityData & capData,Format & format,CodecScenario scenario)493 int32_t UniformlyScaledReferenceChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
494 {
495 (void)capData;
496 (void)scenario;
497 int32_t mode = -1;
498 format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, mode);
499 using namespace OHOS::Media::Plugins;
500 if (mode == static_cast<int32_t>(TemporalGopReferenceMode::UNIFORMLY_SCALED_REFERENCE)) {
501 int32_t temporalGopSize;
502 bool temporalGopSizeExist = format.GetIntValue(Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
503 if (!temporalGopSizeExist) {
504 return AVCS_ERR_OK;
505 }
506 CHECK_AND_RETURN_RET_LOG(temporalGopSize == MIN_TEMPORAL_GOPSIZE || temporalGopSize == DEFAULT_TEMPORAL_GOPSIZE,
507 AVCS_ERR_INVALID_VAL,
508 "Current temporal reference mode param invalid, %{public}s: %{public}d, expect 2 or 4",
509 Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
510 }
511 return AVCS_ERR_OK;
512 }
513
ColorPrimariesChecker(CapabilityData & capData,Format & format,CodecScenario scenario)514 int32_t ColorPrimariesChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
515 {
516 (void)capData;
517 (void)scenario;
518 int32_t colorPrimaries;
519 bool colorPrimariesExist = format.GetIntValue(Tag::VIDEO_COLOR_PRIMARIES, colorPrimaries);
520 if (!colorPrimariesExist) {
521 return AVCS_ERR_OK;
522 }
523 PrintParam(colorPrimariesExist, Tag::VIDEO_COLOR_PRIMARIES, colorPrimaries);
524
525 if (colorPrimaries < static_cast<int32_t>(ColorPrimary::COLOR_PRIMARY_BT709) ||
526 colorPrimaries > static_cast<int32_t>(ColorPrimary::COLOR_PRIMARY_P3D65)) {
527 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_COLOR_PRIMARIES, colorPrimaries);
528 return AVCS_ERR_INVALID_VAL;
529 }
530 return AVCS_ERR_OK;
531 }
532
TransferCharacteristicsChecker(CapabilityData & capData,Format & format,CodecScenario scenario)533 int32_t TransferCharacteristicsChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
534 {
535 (void)capData;
536 (void)scenario;
537 int32_t transferCharacteristics;
538 bool transferCharacteristicsExist = format.GetIntValue(Tag::VIDEO_COLOR_TRC, transferCharacteristics);
539 if (!transferCharacteristicsExist) {
540 return AVCS_ERR_OK;
541 }
542 PrintParam(transferCharacteristicsExist, Tag::VIDEO_COLOR_TRC, transferCharacteristics);
543
544 if (transferCharacteristics < static_cast<int32_t>(TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709) ||
545 transferCharacteristics > static_cast<int32_t>(TransferCharacteristic::TRANSFER_CHARACTERISTIC_HLG)) {
546 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_COLOR_TRC, transferCharacteristics);
547 return AVCS_ERR_INVALID_VAL;
548 }
549 return AVCS_ERR_OK;
550 }
551
MatrixCoefficientsChecker(CapabilityData & capData,Format & format,CodecScenario scenario)552 int32_t MatrixCoefficientsChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
553 {
554 (void)capData;
555 (void)scenario;
556 int32_t matrixCoefficients;
557 bool matrixCoefficientsExist = format.GetIntValue(Tag::VIDEO_COLOR_MATRIX_COEFF, matrixCoefficients);
558 if (!matrixCoefficientsExist) {
559 return AVCS_ERR_OK;
560 }
561 PrintParam(matrixCoefficientsExist, Tag::VIDEO_COLOR_MATRIX_COEFF, matrixCoefficients);
562
563 if (matrixCoefficients < static_cast<int32_t>(MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY) ||
564 matrixCoefficients > static_cast<int32_t>(MatrixCoefficient::MATRIX_COEFFICIENT_ICTCP)) {
565 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_COLOR_MATRIX_COEFF, matrixCoefficients);
566 return AVCS_ERR_INVALID_VAL;
567 }
568 return AVCS_ERR_OK;
569 }
570
LTRFrameCountChecker(CapabilityData & capData,Format & format,CodecScenario scenario)571 int32_t LTRFrameCountChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
572 {
573 int32_t ltrFrameCount;
574 bool ltrFrameCountExist = format.GetIntValue(Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, ltrFrameCount);
575 if (!ltrFrameCountExist) {
576 return AVCS_ERR_OK;
577 }
578 PrintParam(ltrFrameCountExist, Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, ltrFrameCount);
579
580 CHECK_AND_RETURN_RET_LOG(scenario != CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY,
581 AVCS_ERR_UNSUPPORT, "Param invalid, not supported to set LTR frame count in temporal scalability scenario");
582
583 auto ltrCap =
584 capData.featuresMap.find(static_cast<int32_t>(AVCapabilityFeature::VIDEO_ENCODER_LONG_TERM_REFERENCE));
585 if (ltrCap == capData.featuresMap.end()) {
586 AVCODEC_LOGW("Not support LTR but set LTR frame count");
587 format.RemoveKey(Tag::VIDEO_ENCODER_LTR_FRAME_COUNT);
588 return AVCS_ERR_OK;
589 }
590 int32_t maxLTRFrameCount = 0;
591 bool maxLTRFrameCountExist =
592 ltrCap->second.GetIntValue(Tag::FEATURE_PROPERTY_VIDEO_ENCODER_MAX_LTR_FRAME_COUNT, maxLTRFrameCount);
593 CHECK_AND_RETURN_RET_LOG(maxLTRFrameCountExist, AVCS_ERR_UNKNOWN, "Max LTR frame count not defined");
594
595 CHECK_AND_RETURN_RET_LOG(ltrFrameCount >= 0 && ltrFrameCount <= maxLTRFrameCount, AVCS_ERR_INVALID_VAL,
596 "Param invalid, LTR frame count range: %{public}d-%{public}d", 0, maxLTRFrameCount);
597
598 return AVCS_ERR_OK;
599 }
600
ScalingModeChecker(CapabilityData & capData,Format & format,CodecScenario scenario)601 int32_t ScalingModeChecker(CapabilityData &capData, Format &format, CodecScenario scenario)
602 {
603 (void)capData;
604 (void)scenario;
605 int32_t scalingMode;
606 bool scalingModeExist = format.GetIntValue(Tag::VIDEO_SCALE_TYPE, scalingMode);
607 if (!scalingModeExist) {
608 return AVCS_ERR_OK;
609 }
610 PrintParam(scalingModeExist, Tag::VIDEO_SCALE_TYPE, scalingMode);
611
612 if (scalingMode < static_cast<int32_t>(OHOS::ScalingMode::SCALING_MODE_SCALE_TO_WINDOW) ||
613 scalingMode > static_cast<int32_t>(OHOS::ScalingMode::SCALING_MODE_SCALE_CROP)) {
614 AVCODEC_LOGE("Param invalid, %{public}s: %{public}d", Tag::VIDEO_SCALE_TYPE, scalingMode);
615 return AVCS_ERR_INVALID_VAL;
616 }
617 return AVCS_ERR_OK;
618 }
619 } // namespace
620
621 namespace OHOS {
622 namespace MediaAVCodec {
CheckConfigureValid(Media::Format & format,const std::string & codecName,CodecScenario scenario)623 int32_t CodecParamChecker::CheckConfigureValid(Media::Format &format, const std::string &codecName,
624 CodecScenario scenario)
625 {
626 AVCODEC_SYNC_TRACE;
627 auto capData = CodecAbilitySingleton::GetInstance().GetCapabilityByName(codecName);
628 CHECK_AND_RETURN_RET_LOG(capData != std::nullopt,
629 AVCS_ERR_INVALID_OPERATION, "Get codec capability from codec list failed");
630
631 auto checkers = CONFIGURE_CHECKERS_TABLE.find(scenario);
632 CHECK_AND_RETURN_RET_LOG(checkers != CONFIGURE_CHECKERS_TABLE.end(), AVCS_ERR_UNSUPPORT,
633 "This scenario can not find any checkers");
634
635 int32_t result = AVCS_ERR_OK;
636 for (const auto &checker : checkers->second) {
637 auto ret = checker(capData.value(), format, scenario);
638 if (ret == AVCS_ERR_CODEC_PARAM_INCORRECT) {
639 result = AVCS_ERR_CODEC_PARAM_INCORRECT;
640 }
641 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK || ret == AVCS_ERR_CODEC_PARAM_INCORRECT,
642 ret, "Param check failed");
643 }
644 return result;
645 }
646
CheckParameterValid(const Media::Format & format,Media::Format & oldFormat,const std::string & codecName,CodecScenario scenario)647 int32_t CodecParamChecker::CheckParameterValid(const Media::Format &format, Media::Format &oldFormat,
648 const std::string &codecName, CodecScenario scenario)
649 {
650 AVCODEC_SYNC_TRACE;
651 auto capData = CodecAbilitySingleton::GetInstance().GetCapabilityByName(codecName);
652 CHECK_AND_RETURN_RET_LOG(capData != std::nullopt,
653 AVCS_ERR_INVALID_OPERATION, "Get codec capability from codec list failed");
654
655 auto checkers = PARAMETER_CHECKERS_TABLE.find(scenario);
656 CHECK_AND_RETURN_RET_LOG(checkers != PARAMETER_CHECKERS_TABLE.end(), AVCS_ERR_UNSUPPORT,
657 "This scenario can not find any checkers");
658
659 MergeFormat(format, oldFormat);
660
661 for (const auto &checker : checkers->second) {
662 auto ret = checker(capData.value(), oldFormat, scenario);
663 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Param check failed");
664 }
665 return AVCS_ERR_OK;
666 }
667
CheckCodecScenario(const Media::Format & format,AVCodecType codecType,const std::string & codecName)668 std::optional<CodecScenario> CodecParamChecker::CheckCodecScenario(const Media::Format &format, AVCodecType codecType,
669 const std::string &codecName)
670 {
671 auto capData = CodecAbilitySingleton::GetInstance().GetCapabilityByName(codecName);
672 CHECK_AND_RETURN_RET_LOG(capData != std::nullopt,
673 std::nullopt, "Get codec capability from codec list failed");
674
675 CodecScenario scenario = CodecScenario::CODEC_SCENARIO_DEC_NORMAL;
676 if (codecType == AVCODEC_TYPE_VIDEO_ENCODER) {
677 scenario = CodecScenario::CODEC_SCENARIO_ENC_NORMAL;
678 }
679
680 for (const auto& checker : VIDEO_SCENARIO_CHECKER_LIST) {
681 auto ret = checker(capData.value(), format, codecType);
682 if (ret == std::nullopt) {
683 continue;
684 }
685 scenario = ret.value();
686 break;
687 }
688
689 PrintCodecScenario(scenario);
690 return scenario;
691 }
692
MergeFormat(const Media::Format & format,Media::Format & oldFormat)693 void CodecParamChecker::MergeFormat(const Media::Format &format, Media::Format &oldFormat)
694 {
695 for (const auto& key : FORMAT_MERGE_LIST) {
696 if (!format.ContainKey(key)) {
697 continue;
698 }
699 auto keyType = format.GetValueType(key);
700 switch (keyType) {
701 case FORMAT_TYPE_INT32: {
702 int32_t value;
703 format.GetIntValue(key, value);
704 oldFormat.PutIntValue(key, value);
705 break;
706 }
707 case FORMAT_TYPE_INT64: {
708 int64_t value;
709 format.GetLongValue(key, value);
710 oldFormat.PutLongValue(key, value);
711 break;
712 }
713 case FORMAT_TYPE_FLOAT: {
714 float value;
715 format.GetFloatValue(key, value);
716 oldFormat.PutFloatValue(key, value);
717 break;
718 }
719 case FORMAT_TYPE_DOUBLE: {
720 double value;
721 format.GetDoubleValue(key, value);
722 oldFormat.PutDoubleValue(key, value);
723 break;
724 }
725 case FORMAT_TYPE_STRING: {
726 std::string value;
727 format.GetStringValue(key, value);
728 oldFormat.PutStringValue(key, value);
729 break;
730 }
731 default:
732 break;
733 }
734 }
735 }
736 } // namespace MediaAVCodec
737 } // namespace OHOS