• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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