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