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