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 if (mime.empty()) {
236 return AVCS_ERR_INVALID_VAL;
237 }
238 AVCodecType codecType = AVCODEC_TYPE_NONE;
239 bool isVideo = mime.find("video") != std::string::npos;
240 if (isVideo) {
241 codecType = isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
242 } else {
243 codecType = isEncoder ? AVCODEC_TYPE_AUDIO_ENCODER : AVCODEC_TYPE_AUDIO_DECODER;
244 }
245 bool isVendor = (category == AVCodecCategory::AVCODEC_HARDWARE) ? true : false;
246 std::vector<CapabilityData> capsDataArray = CodecAbilitySingleton::GetInstance().GetCapabilityArray();
247 std::unordered_map<std::string, std::vector<size_t>> mimeCapIdxMap =
248 CodecAbilitySingleton::GetInstance().GetMimeCapIdxMap();
249 if (mimeCapIdxMap.find(mime) == mimeCapIdxMap.end()) {
250 return AVCS_ERR_INVALID_VAL;
251 }
252 std::vector<size_t> capsIdx = mimeCapIdxMap.at(mime);
253 for (auto iter = capsIdx.begin(); iter != capsIdx.end(); iter++) {
254 if (capsDataArray[*iter].codecType == codecType && capsDataArray[*iter].mimeType == mime) {
255 if (category != AVCodecCategory::AVCODEC_NONE && capsDataArray[*iter].isVendor != isVendor) {
256 continue;
257 }
258 capData = capsDataArray[*iter];
259 AVCODEC_LOGI("Get capability of codec successful: %{public}s", mime.c_str());
260 break;
261 }
262 }
263 return AVCS_ERR_OK;
264 }
265
FindCodecNameArray(const std::string & mime,bool isEncoder)266 std::vector<std::string> CodecListCore::FindCodecNameArray(const std::string &mime, bool isEncoder)
267 {
268 std::lock_guard<std::mutex> lock(mutex_);
269 auto &codecAbility = CodecAbilitySingleton::GetInstance();
270
271 std::unordered_map<std::string, std::vector<size_t>> mimeCapIdxMap = codecAbility.GetMimeCapIdxMap();
272 std::vector<CapabilityData> capabilityArray = codecAbility.GetCapabilityArray();
273 std::vector<std::string> nameArray;
274 auto iter = mimeCapIdxMap.find(mime);
275 CHECK_AND_RETURN_RET_LOG(iter != mimeCapIdxMap.end(), nameArray, "Can not find input mime type, %{public}s.",
276 mime.c_str());
277 AVCodecType codecType = AVCODEC_TYPE_NONE;
278 bool isVideo = mime.find("video") != std::string::npos;
279 if (isVideo) {
280 codecType = isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
281 } else {
282 codecType = isEncoder ? AVCODEC_TYPE_AUDIO_ENCODER : AVCODEC_TYPE_AUDIO_DECODER;
283 }
284
285 for (auto index : iter->second) {
286 if (capabilityArray[index].codecType == codecType) {
287 nameArray.push_back(capabilityArray[index].codecName);
288 }
289 }
290 return nameArray;
291 }
292 } // namespace MediaAVCodec
293 } // namespace OHOS