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