• 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 "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