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 "hcodec_list.h"
17 #include <map>
18 #include <numeric>
19 #include "syspara/parameters.h"
20 #include "utils/hdf_base.h"
21 #include "hcodec_log.h"
22 #include "type_converter.h"
23 #include "avcodec_info.h"
24
25 namespace OHOS::MediaAVCodec {
26 using namespace std;
27 using namespace OHOS::HDI::Codec::V1_0;
28
IsPassthrough()29 bool IsPassthrough()
30 {
31 static bool usePassthrough = OHOS::system::GetBoolParameter("hcodec.usePassthrough", true);
32 LOGI("%{public}s mode", usePassthrough ? "passthrough" : "ipc");
33 return usePassthrough;
34 }
35
GetManager()36 sptr<ICodecComponentManager> GetManager()
37 {
38 static sptr<ICodecComponentManager> compMgr = ICodecComponentManager::Get(IsPassthrough());
39 return compMgr;
40 }
41
GetCapList()42 vector<CodecCompCapability> GetCapList()
43 {
44 sptr<ICodecComponentManager> mnger = GetManager();
45 if (mnger == nullptr) {
46 LOGE("failed to create codec component manager");
47 return {};
48 }
49 int32_t compCnt = 0;
50 int32_t ret = mnger->GetComponentNum(compCnt);
51 if (ret != HDF_SUCCESS || compCnt <= 0) {
52 LOGE("failed to query component number, ret=%{public}d", ret);
53 return {};
54 }
55 std::vector<CodecCompCapability> capList(compCnt);
56 ret = mnger->GetComponentCapabilityList(capList, compCnt);
57 if (ret != HDF_SUCCESS) {
58 LOGE("failed to query component capability list, ret=%{public}d", ret);
59 return {};
60 }
61 if (capList.empty()) {
62 LOGE("GetComponentCapabilityList return empty");
63 } else {
64 LOGI("GetComponentCapabilityList return %{public}zu components", capList.size());
65 }
66 return capList;
67 }
68
GetCapabilityList(std::vector<CapabilityData> & caps)69 int32_t HCodecList::GetCapabilityList(std::vector<CapabilityData>& caps)
70 {
71 caps.clear();
72 vector<CodecCompCapability> capList = GetCapList();
73 for (const CodecCompCapability& one : capList) {
74 if (IsSupportedVideoCodec(one)) {
75 caps.emplace_back(HdiCapToUserCap(one));
76 }
77 }
78 return AVCS_ERR_OK;
79 }
80
IsSupportedVideoCodec(const CodecCompCapability & hdiCap)81 bool HCodecList::IsSupportedVideoCodec(const CodecCompCapability &hdiCap)
82 {
83 if (hdiCap.role == MEDIA_ROLETYPE_VIDEO_AVC || hdiCap.role == MEDIA_ROLETYPE_VIDEO_HEVC) {
84 return true;
85 }
86 return false;
87 }
88
HdiCapToUserCap(const CodecCompCapability & hdiCap)89 CapabilityData HCodecList::HdiCapToUserCap(const CodecCompCapability &hdiCap)
90 {
91 const CodecVideoPortCap& hdiVideoCap = hdiCap.port.video;
92 CapabilityData userCap;
93 userCap.codecName = hdiCap.compName;
94 userCap.codecType = TypeConverter::HdiCodecTypeToInnerCodecType(hdiCap.type).value_or(AVCODEC_TYPE_NONE);
95 userCap.mimeType = TypeConverter::HdiRoleToMime(hdiCap.role);
96 userCap.isVendor = true;
97 userCap.maxInstance = hdiCap.maxInst;
98 userCap.bitrate = {hdiCap.bitRate.min, hdiCap.bitRate.max};
99 userCap.alignment = {hdiVideoCap.whAlignment.widthAlignment, hdiVideoCap.whAlignment.heightAlignment};
100 userCap.width = {hdiVideoCap.minSize.width, hdiVideoCap.maxSize.width};
101 userCap.height = {hdiVideoCap.minSize.height, hdiVideoCap.maxSize.height};
102 userCap.frameRate = {hdiVideoCap.frameRate.min, hdiVideoCap.frameRate.max};
103 userCap.blockPerFrame = {hdiVideoCap.blockCount.min, hdiVideoCap.blockCount.max};
104 userCap.blockPerSecond = {hdiVideoCap.blocksPerSecond.min, hdiVideoCap.blocksPerSecond.max};
105 userCap.blockSize = {hdiVideoCap.blockSize.width, hdiVideoCap.blockSize.height};
106 userCap.pixFormat = GetSupportedFormat(hdiVideoCap);
107 userCap.bitrateMode = GetSupportedBitrateMode(hdiVideoCap);
108 userCap.profileLevelsMap = GetCodecProfileLevels(hdiCap);
109 userCap.measuredFrameRate = GetMeasuredFrameRate(hdiVideoCap);
110 userCap.supportSwapWidthHeight = hdiCap.canSwapWidthHeight;
111 LOGI("----- codecName: %{public}s -----", userCap.codecName.c_str());
112 LOGI("codecType: %{public}d, mimeType: %{public}s, maxInstance %{public}d",
113 userCap.codecType, userCap.mimeType.c_str(), userCap.maxInstance);
114 LOGI("bitrate: [%{public}d, %{public}d], alignment: [%{public}d x %{public}d]",
115 userCap.bitrate.minVal, userCap.bitrate.maxVal, userCap.alignment.width, userCap.alignment.height);
116 LOGI("width: [%{public}d, %{public}d], height: [%{public}d, %{public}d]",
117 userCap.width.minVal, userCap.width.maxVal, userCap.height.minVal, userCap.height.maxVal);
118 LOGI("frameRate: [%{public}d, %{public}d], blockSize: [%{public}d x %{public}d]",
119 userCap.frameRate.minVal, userCap.frameRate.maxVal, userCap.blockSize.width, userCap.blockSize.height);
120 LOGI("blockPerFrame: [%{public}d, %{public}d], blockPerSecond: [%{public}d, %{public}d]",
121 userCap.blockPerFrame.minVal, userCap.blockPerFrame.maxVal,
122 userCap.blockPerSecond.minVal, userCap.blockPerSecond.maxVal);
123 return userCap;
124 }
125
GetSupportedBitrateMode(const CodecVideoPortCap & hdiVideoCap)126 vector<int32_t> HCodecList::GetSupportedBitrateMode(const CodecVideoPortCap& hdiVideoCap)
127 {
128 vector<int32_t> vec;
129 for (BitRateMode mode : hdiVideoCap.bitRatemode) {
130 optional<VideoEncodeBitrateMode> innerMode = TypeConverter::HdiBitrateModeToInnerMode(mode);
131 if (innerMode.has_value()) {
132 vec.push_back(innerMode.value());
133 }
134 }
135 return vec;
136 }
137
GetSupportedFormat(const CodecVideoPortCap & hdiVideoCap)138 vector<int32_t> HCodecList::GetSupportedFormat(const CodecVideoPortCap& hdiVideoCap)
139 {
140 vector<int32_t> vec;
141 for (int32_t fmt : hdiVideoCap.supportPixFmts) {
142 optional<VideoPixelFormat> innerFmt =
143 TypeConverter::DisplayFmtToInnerFmt(static_cast<GraphicPixelFormat>(fmt));
144 if (innerFmt.has_value()) {
145 vec.push_back(innerFmt.value());
146 }
147 }
148 return vec;
149 }
150
GetMeasuredFrameRate(const CodecVideoPortCap & hdiVideoCap)151 map<ImgSize, Range> HCodecList::GetMeasuredFrameRate(const CodecVideoPortCap& hdiVideoCap)
152 {
153 enum MeasureStep {
154 WIDTH = 0,
155 HEIGHT = 1,
156 MIN_RATE = 2,
157 MAX_RATE = 3,
158 STEP_BUTT = 4
159 };
160 map<ImgSize, Range> userRateMap;
161 for (size_t index = 0; index < hdiVideoCap.measuredFrameRate.size(); index += STEP_BUTT) {
162 if (hdiVideoCap.measuredFrameRate[index] <= 0) {
163 continue;
164 }
165 ImgSize imageSize(hdiVideoCap.measuredFrameRate[index + WIDTH], hdiVideoCap.measuredFrameRate[index + HEIGHT]);
166 Range range(hdiVideoCap.measuredFrameRate[index + MIN_RATE], hdiVideoCap.measuredFrameRate[index + MAX_RATE]);
167 userRateMap[imageSize] = range;
168 }
169 return userRateMap;
170 }
171
GetCodecProfileLevels(const CodecCompCapability & hdiCap)172 map<int32_t, vector<int32_t>> HCodecList::GetCodecProfileLevels(const CodecCompCapability& hdiCap)
173 {
174 map<int32_t, vector<int32_t>> userProfileLevelMap;
175 for (size_t i = 0; i + 1 < hdiCap.supportProfiles.size(); i += 2) { // 2 means profile & level pair
176 int32_t profile = hdiCap.supportProfiles[i];
177 int32_t maxLevel = hdiCap.supportProfiles[i + 1];
178 optional<int32_t> innerProfile;
179 optional<int32_t> innerLevel;
180 if (hdiCap.role == MEDIA_ROLETYPE_VIDEO_AVC) {
181 innerProfile = TypeConverter::OmxAvcProfileToInnerProfile(static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile));
182 innerLevel = TypeConverter::OmxAvcLevelToInnerLevel(static_cast<OMX_VIDEO_AVCLEVELTYPE>(maxLevel));
183 } else if (hdiCap.role == MEDIA_ROLETYPE_VIDEO_HEVC) {
184 innerProfile = TypeConverter::OmxHevcProfileToInnerProfile(static_cast<CodecHevcProfile>(profile));
185 innerLevel = TypeConverter::OmxHevcLevelToInnerLevel(static_cast<CodecHevcLevel>(maxLevel));
186 }
187 if (innerProfile.has_value() && innerLevel.has_value() && innerLevel.value() >= 0) {
188 vector<int32_t> allLevel(innerLevel.value() + 1);
189 std::iota(allLevel.begin(), allLevel.end(), 0);
190 userProfileLevelMap[innerProfile.value()] = allLevel;
191 LOGI("role %{public}d support (inner) profile %{public}d and level up to %{public}d",
192 hdiCap.role, innerProfile.value(), innerLevel.value());
193 }
194 }
195 return userProfileLevelMap;
196 }
197 } // namespace OHOS::MediaAVCodec