1 /*
2 * Copyright (C) 2023 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 "codeclist_core.h"
17 #include <cmath> // fabs
18 #include "avcodec_errors.h"
19 #include "avcodec_log.h"
20 #include "codec_ability_singleton.h"
21
22 namespace {
23 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "CodecListCore"};
24 constexpr float EPSINON = 0.0001;
25 } // namespace
26
27 namespace OHOS {
28 namespace MediaAVCodec {
29 using namespace Media;
CodecListCore()30 CodecListCore::CodecListCore()
31 {
32 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
33 }
34
~CodecListCore()35 CodecListCore::~CodecListCore()
36 {
37 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
38 }
39
CheckBitrate(const Format & format,const CapabilityData & data)40 bool CodecListCore::CheckBitrate(const Format &format, const CapabilityData &data)
41 {
42 int64_t targetBitrate;
43 if (!format.ContainKey("bitrate")) {
44 AVCODEC_LOGD("The bitrate of the format are not specified");
45 return true;
46 }
47 (void)format.GetLongValue("bitrate", targetBitrate);
48 if (data.bitrate.minVal > targetBitrate || data.bitrate.maxVal < targetBitrate) {
49 return false;
50 }
51 return true;
52 }
53
CheckVideoResolution(const Format & format,const CapabilityData & data)54 bool CodecListCore::CheckVideoResolution(const Format &format, const CapabilityData &data)
55 {
56 int32_t targetWidth;
57 int32_t targetHeight;
58 if ((!format.ContainKey("width")) || (!format.ContainKey("height"))) {
59 AVCODEC_LOGD("The width and height of the format are not specified");
60 return true;
61 }
62 (void)format.GetIntValue("width", targetWidth);
63 (void)format.GetIntValue("height", targetHeight);
64 if (data.width.minVal > targetWidth || data.width.maxVal < targetWidth || data.height.minVal > targetHeight ||
65 data.height.maxVal < targetHeight) {
66 return false;
67 }
68 return true;
69 }
70
CheckVideoPixelFormat(const Format & format,const CapabilityData & data)71 bool CodecListCore::CheckVideoPixelFormat(const Format &format, const CapabilityData &data)
72 {
73 int32_t targetPixelFormat;
74 if (!format.ContainKey("pixel_format")) {
75 AVCODEC_LOGD("The pixel_format of the format are not specified");
76 return true;
77 }
78 (void)format.GetIntValue("pixel_format", targetPixelFormat);
79 if (find(data.pixFormat.begin(), data.pixFormat.end(), targetPixelFormat) == data.pixFormat.end()) {
80 return false;
81 }
82 return true;
83 }
84
CheckVideoFrameRate(const Format & format,const CapabilityData & data)85 bool CodecListCore::CheckVideoFrameRate(const Format &format, const CapabilityData &data)
86 {
87 if (!format.ContainKey("frame_rate")) {
88 AVCODEC_LOGD("The frame_rate of the format are not specified");
89 return true;
90 }
91
92 switch (format.GetValueType(std::string_view("frame_rate"))) {
93 case FORMAT_TYPE_INT32: {
94 int32_t targetFrameRateInt;
95 (void)format.GetIntValue("frame_rate", targetFrameRateInt);
96 if (data.frameRate.minVal > targetFrameRateInt || data.frameRate.maxVal < targetFrameRateInt) {
97 return false;
98 }
99 break;
100 }
101 case FORMAT_TYPE_DOUBLE: {
102 double targetFrameRateDouble;
103 (void)format.GetDoubleValue("frame_rate", targetFrameRateDouble);
104 double minValDouble {data.frameRate.minVal};
105 double maxValDouble {data.frameRate.maxVal};
106 if ((minValDouble > targetFrameRateDouble && fabs(minValDouble - targetFrameRateDouble) >= EPSINON) ||
107 (maxValDouble < targetFrameRateDouble && fabs(maxValDouble - targetFrameRateDouble) >= EPSINON)) {
108 return false;
109 }
110 break;
111 }
112 default:
113 break;
114 }
115 return true;
116 }
117
CheckAudioChannel(const Format & format,const CapabilityData & data)118 bool CodecListCore::CheckAudioChannel(const Format &format, const CapabilityData &data)
119 {
120 int32_t targetChannel;
121 if (!format.ContainKey("channel_count")) {
122 AVCODEC_LOGD("The channel_count of the format are not specified");
123 return true;
124 }
125 (void)format.GetIntValue("channel_count", targetChannel);
126 if (data.channels.minVal > targetChannel || data.channels.maxVal < targetChannel) {
127 return false;
128 }
129 return true;
130 }
131
CheckAudioSampleRate(const Format & format,const CapabilityData & data)132 bool CodecListCore::CheckAudioSampleRate(const Format &format, const CapabilityData &data)
133 {
134 int32_t targetSampleRate;
135 if (!format.ContainKey("samplerate")) {
136 AVCODEC_LOGD("The samplerate of the format are not specified");
137 return true;
138 }
139 (void)format.GetIntValue("samplerate", targetSampleRate);
140 if (find(data.sampleRate.begin(), data.sampleRate.end(), targetSampleRate) == data.sampleRate.end()) {
141 return false;
142 }
143 return true;
144 }
145
IsVideoCapSupport(const Format & format,const CapabilityData & data)146 bool CodecListCore::IsVideoCapSupport(const Format &format, const CapabilityData &data)
147 {
148 return CheckVideoResolution(format, data) && CheckVideoPixelFormat(format, data) &&
149 CheckVideoFrameRate(format, data) && CheckBitrate(format, data);
150 }
151
IsAudioCapSupport(const Format & format,const CapabilityData & data)152 bool CodecListCore::IsAudioCapSupport(const Format &format, const CapabilityData &data)
153 {
154 return CheckAudioChannel(format, data) && CheckAudioSampleRate(format, data) && CheckBitrate(format, data);
155 }
156
157 // mime是必要参数
FindCodec(const Format & format,bool isEncoder)158 std::string CodecListCore::FindCodec(const Format &format, bool isEncoder)
159 {
160 std::lock_guard<std::mutex> lock(mutex_);
161 if (!format.ContainKey("codec_mime")) {
162 AVCODEC_LOGD("Get MimeType from format failed");
163 return "";
164 }
165 std::string targetMimeType;
166 (void)format.GetStringValue("codec_mime", targetMimeType);
167
168 AVCodecType codecType = AVCODEC_TYPE_NONE;
169 bool isVideo = targetMimeType.find("video") != std::string::npos;
170 if (isVideo) {
171 codecType = isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
172 } else {
173 codecType = isEncoder ? AVCODEC_TYPE_AUDIO_ENCODER : AVCODEC_TYPE_AUDIO_DECODER;
174 }
175
176 int isVendor = -1;
177 bool isVendorKey = format.ContainKey("codec_vendor_flag");
178 if (isVendorKey) {
179 (void)format.GetIntValue("codec_vendor_flag", isVendor);
180 }
181 std::vector<CapabilityData> capabilityDataArray = CodecAbilitySingleton::GetInstance().GetCapabilityArray();
182 std::unordered_map<std::string, std::vector<size_t>> mimeCapIdxMap =
183 CodecAbilitySingleton::GetInstance().GetMimeCapIdxMap();
184 if (mimeCapIdxMap.find(targetMimeType) == mimeCapIdxMap.end()) {
185 return "";
186 }
187 std::vector<size_t> capsIdx = mimeCapIdxMap.at(targetMimeType);
188 for (auto iter = capsIdx.begin(); iter != capsIdx.end(); iter++) {
189 CapabilityData capsData = capabilityDataArray[*iter];
190 if (capsData.codecType != codecType || capsData.mimeType != targetMimeType ||
191 (isVendorKey && capsData.isVendor != isVendor)) {
192 continue;
193 }
194 if (isVideo) {
195 if (IsVideoCapSupport(format, capsData)) {
196 return capsData.codecName;
197 }
198 } else {
199 if (IsAudioCapSupport(format, capsData)) {
200 return capsData.codecName;
201 }
202 }
203 }
204 return "";
205 }
206
FindEncoder(const Format & format)207 std::string CodecListCore::FindEncoder(const Format &format)
208 {
209 return FindCodec(format, true);
210 }
211
FindDecoder(const Format & format)212 std::string CodecListCore::FindDecoder(const Format &format)
213 {
214 return FindCodec(format, false);
215 }
216
FindCodecType(std::string codecName)217 CodecType CodecListCore::FindCodecType(std::string codecName)
218 {
219 std::lock_guard<std::mutex> lock(mutex_);
220 if (codecName.empty()) {
221 return CodecType::AVCODEC_INVALID;
222 }
223 std::unordered_map<std::string, CodecType> nameCodecTypeMap =
224 CodecAbilitySingleton::GetInstance().GetNameCodecTypeMap();
225 if (nameCodecTypeMap.find(codecName) != nameCodecTypeMap.end()) {
226 return nameCodecTypeMap.at(codecName);
227 }
228 return CodecType::AVCODEC_INVALID;
229 }
230
GetCapability(CapabilityData & capData,const std::string & mime,const bool isEncoder,const AVCodecCategory & category)231 int32_t CodecListCore::GetCapability(CapabilityData &capData, const std::string &mime, const bool isEncoder,
232 const AVCodecCategory &category)
233 {
234 std::lock_guard<std::mutex> lock(mutex_);
235 CHECK_AND_RETURN_RET_LOG(!mime.empty(), AVCS_ERR_INVALID_VAL, "mime is empty");
236 AVCodecType codecType = AVCODEC_TYPE_NONE;
237 bool isVideo = mime.find("video") != std::string::npos;
238 if (isVideo) {
239 codecType = isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
240 } else {
241 codecType = isEncoder ? AVCODEC_TYPE_AUDIO_ENCODER : AVCODEC_TYPE_AUDIO_DECODER;
242 }
243 bool isVendor = (category == AVCodecCategory::AVCODEC_HARDWARE) ? true : false;
244 std::vector<CapabilityData> capsDataArray = CodecAbilitySingleton::GetInstance().GetCapabilityArray();
245 std::unordered_map<std::string, std::vector<size_t>> mimeCapIdxMap =
246 CodecAbilitySingleton::GetInstance().GetMimeCapIdxMap();
247 CHECK_AND_RETURN_RET_LOG(mimeCapIdxMap.find(mime) != mimeCapIdxMap.end(), AVCS_ERR_INVALID_VAL,
248 "mime is not supported, mime: %{public}s", mime.c_str());
249 std::vector<size_t> capsIdx = mimeCapIdxMap.at(mime);
250 for (auto iter = capsIdx.begin(); iter != capsIdx.end(); iter++) {
251 if (capsDataArray[*iter].codecType == codecType && capsDataArray[*iter].mimeType == mime) {
252 if (category != AVCodecCategory::AVCODEC_NONE && capsDataArray[*iter].isVendor != isVendor) {
253 continue;
254 }
255 capData = capsDataArray[*iter];
256 AVCODEC_LOGI("find cap, mime: %{public}s, isEnc: %{public}d, category: %{public}d",
257 mime.c_str(), isEncoder, category);
258 break;
259 }
260 }
261 CHECK_AND_RETURN_RET_LOG(!capData.codecName.empty(), AVCS_ERR_INVALID_VAL,
262 "can not find cap, mime: %{public}s, mimeCapIdx size: %{public}zu, isEnc: %{public}d, category: %{public}d",
263 mime.c_str(), capsIdx.size(), isEncoder, category);
264 return AVCS_ERR_OK;
265 }
266
FindCodecNameArray(const std::string & mime,bool isEncoder)267 std::vector<std::string> CodecListCore::FindCodecNameArray(const std::string &mime, bool isEncoder)
268 {
269 std::lock_guard<std::mutex> lock(mutex_);
270 auto &codecAbility = CodecAbilitySingleton::GetInstance();
271
272 std::unordered_map<std::string, std::vector<size_t>> mimeCapIdxMap = codecAbility.GetMimeCapIdxMap();
273 std::vector<CapabilityData> capabilityArray = codecAbility.GetCapabilityArray();
274 std::vector<std::string> nameArray;
275 auto iter = mimeCapIdxMap.find(mime);
276 CHECK_AND_RETURN_RET_LOG(iter != mimeCapIdxMap.end(), nameArray, "Can not find input mime type, %{public}s.",
277 mime.c_str());
278 AVCodecType codecType = AVCODEC_TYPE_NONE;
279 bool isVideo = mime.find("video") != std::string::npos;
280 if (isVideo) {
281 codecType = isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
282 } else {
283 codecType = isEncoder ? AVCODEC_TYPE_AUDIO_ENCODER : AVCODEC_TYPE_AUDIO_DECODER;
284 }
285
286 for (auto index : iter->second) {
287 if (capabilityArray[index].codecType == codecType) {
288 nameArray.push_back(capabilityArray[index].codecName);
289 }
290 }
291 return nameArray;
292 }
293 } // namespace MediaAVCodec
294 } // namespace OHOS