1 /*
2 * Copyright (C) 2022 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 "hdi_init.h"
17 #include <hdf_base.h>
18 #include "media_log.h"
19 #include "media_errors.h"
20 #include "display_type.h"
21 #include "scope_guard.h"
22 #include "hdi_codec_util.h"
23 #include "hdf_remote_service.h"
24 #include "codec_internal.h"
25 #include "servmgr_hdi.h"
26
27 namespace {
28 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "HdiInit"};
29 using namespace OHOS::Media;
30 const std::unordered_map<int32_t, int32_t> AVC_PROFILE_MAP = {
31 {OMX_VIDEO_AVCProfileBaseline, AVC_PROFILE_BASELINE},
32 {OMX_VIDEO_AVCProfileMain, AVC_PROFILE_MAIN},
33 {OMX_VIDEO_AVCProfileHigh, AVC_PROFILE_HIGH},
34 {OMX_VIDEO_AVCProfileExtended, AVC_PROFILE_EXTENDED},
35 };
36
37 const std::unordered_map<int32_t, int32_t> HEVC_PROFILE_MAP = {
38 {CODEC_HEVC_PROFILE_MAIN, HEVC_PROFILE_MAIN},
39 {CODEC_HEVC_PROFILE_MAIN10, HEVC_PROFILE_MAIN_10},
40 {CODEC_HEVC_PROFILE_MAIN_STILL, HEVC_PROFILE_MAIN_STILL},
41 {CODEC_HEVC_PROFILE_MAIN10_HDR10, HEVC_PROFILE_MAIN_10_HDR10},
42 };
43
44 const std::unordered_map<int32_t, int32_t> AVC_LEVEL_MAP = {
45 {OMX_VIDEO_AVCLevel1, AVC_LEVEL_1},
46 {OMX_VIDEO_AVCLevel1b, AVC_LEVEL_1b},
47 {OMX_VIDEO_AVCLevel11, AVC_LEVEL_11},
48 {OMX_VIDEO_AVCLevel12, AVC_LEVEL_12},
49 {OMX_VIDEO_AVCLevel13, AVC_LEVEL_13},
50 {OMX_VIDEO_AVCLevel2, AVC_LEVEL_2},
51 {OMX_VIDEO_AVCLevel21, AVC_LEVEL_21},
52 {OMX_VIDEO_AVCLevel22, AVC_LEVEL_22},
53 {OMX_VIDEO_AVCLevel3, AVC_LEVEL_3},
54 {OMX_VIDEO_AVCLevel31, AVC_LEVEL_31},
55 {OMX_VIDEO_AVCLevel32, AVC_LEVEL_32},
56 {OMX_VIDEO_AVCLevel4, AVC_LEVEL_4},
57 {OMX_VIDEO_AVCLevel41, AVC_LEVEL_41},
58 {OMX_VIDEO_AVCLevel42, AVC_LEVEL_42},
59 {OMX_VIDEO_AVCLevel5, AVC_LEVEL_5},
60 {OMX_VIDEO_AVCLevel51, AVC_LEVEL_51},
61 };
62
63 const std::unordered_map<int32_t, int32_t> HEVC_LEVEL_MAP = {
64 {CODEC_HEVC_MAIN_TIER_LEVEL1, HEVC_LEVEL_1},
65 {CODEC_HEVC_MAIN_TIER_LEVEL2, HEVC_LEVEL_2},
66 {CODEC_HEVC_MAIN_TIER_LEVEL21, HEVC_LEVEL_21},
67 {CODEC_HEVC_MAIN_TIER_LEVEL3, HEVC_LEVEL_3},
68 {CODEC_HEVC_MAIN_TIER_LEVEL31, HEVC_LEVEL_31},
69 {CODEC_HEVC_MAIN_TIER_LEVEL4, HEVC_LEVEL_4},
70 {CODEC_HEVC_MAIN_TIER_LEVEL41, HEVC_LEVEL_41},
71 {CODEC_HEVC_MAIN_TIER_LEVEL5, HEVC_LEVEL_5},
72 {CODEC_HEVC_MAIN_TIER_LEVEL51, HEVC_LEVEL_51},
73 {CODEC_HEVC_MAIN_TIER_LEVEL52, HEVC_LEVEL_52},
74 {CODEC_HEVC_MAIN_TIER_LEVEL6, HEVC_LEVEL_6},
75 {CODEC_HEVC_MAIN_TIER_LEVEL61, HEVC_LEVEL_61},
76 {CODEC_HEVC_MAIN_TIER_LEVEL62, HEVC_LEVEL_62},
77 };
78 constexpr int32_t MAX_COMPONENT_NUM = 1024;
79 }
80
81 namespace OHOS {
82 namespace Media {
83 const std::unordered_map<int32_t, HdiInit::GetProfileLevelsFunc> HdiInit::PROFILE_LEVEL_FUNC_MAP = {
84 {MEDIA_ROLETYPE_VIDEO_AVC, HdiInit::GetH264ProfileLevels},
85 {MEDIA_ROLETYPE_VIDEO_HEVC, HdiInit::GetH265ProfileLevels},
86 };
87
GetInstance()88 HdiInit &HdiInit::GetInstance()
89 {
90 static HdiInit omx;
91 return omx;
92 }
93
HdiInit()94 HdiInit::HdiInit()
95 {
96 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
97 CodecComponentManagerInit();
98 }
99
~HdiInit()100 HdiInit::~HdiInit()
101 {
102 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
103 CodecComponentManagerRelease();
104 }
105
HdiCodecOnRemoteDied(HdfDeathRecipient * deathRecipient,HdfRemoteService * remote)106 static void HdiCodecOnRemoteDied(HdfDeathRecipient *deathRecipient, HdfRemoteService *remote)
107 {
108 (void)deathRecipient;
109 (void)remote;
110 HdiInit::GetInstance().CodecComponentManagerReset();
111 }
112
CodecComponentManagerInit()113 void HdiInit::CodecComponentManagerInit()
114 {
115 MEDIA_LOGD("CodecComponentManagerInit In");
116
117 mgr_ = GetCodecComponentManager();
118 CHECK_AND_RETURN_LOG(mgr_ != nullptr, "GetCodecComponentManager failed");
119
120 HDIServiceManager *serviceMgr = HDIServiceManagerGet();
121 CHECK_AND_RETURN_LOG(serviceMgr != nullptr, "HDIServiceManagerGet failed");
122
123 HdfRemoteService *remoteOmx = serviceMgr->GetService(serviceMgr, CODEC_HDI_OMX_SERVICE_NAME);
124 HDIServiceManagerRelease(serviceMgr);
125 CHECK_AND_RETURN_LOG(remoteOmx != nullptr, "HDIServiceManagerGet failed");
126
127 static HdfDeathRecipient recipient = {
128 .OnRemoteDied = HdiCodecOnRemoteDied,
129 };
130
131 HdfRemoteServiceAddDeathRecipient(remoteOmx, &recipient);
132
133 MEDIA_LOGD("CodecComponentManagerInit End");
134 }
135
CodecComponentManagerReset()136 void HdiInit::CodecComponentManagerReset()
137 {
138 MEDIA_LOGD("CodecComponentManagerReset In");
139
140 std::lock_guard<std::mutex> lock(mutex_);
141 CodecComponentManagerRelease();
142 mgr_ = nullptr;
143 handleMap_.clear();
144
145 MEDIA_LOGD("CodecComponentManagerReset End");
146 }
147
GetCodecType(CodecType hdiType)148 int32_t HdiInit::GetCodecType(CodecType hdiType)
149 {
150 switch (hdiType) {
151 case VIDEO_DECODER:
152 return AVCODEC_TYPE_VIDEO_DECODER;
153 case VIDEO_ENCODER:
154 return AVCODEC_TYPE_VIDEO_ENCODER;
155 case AUDIO_DECODER:
156 return AVCODEC_TYPE_AUDIO_DECODER;
157 case AUDIO_ENCODER:
158 return AVCODEC_TYPE_AUDIO_ENCODER;
159 default:
160 MEDIA_LOGW("Unknow codecType");
161 break;
162 }
163 return AVCODEC_TYPE_NONE;
164 }
165
GetCodecMime(AvCodecRole & role)166 std::string HdiInit::GetCodecMime(AvCodecRole &role)
167 {
168 switch (role) {
169 case MEDIA_ROLETYPE_VIDEO_AVC:
170 return "video/avc";
171 case MEDIA_ROLETYPE_VIDEO_HEVC:
172 return "video/hevc";
173 default:
174 MEDIA_LOGW("Unknow codecRole %{public}d", (int32_t)role);
175 break;
176 }
177 return "invalid";
178 }
179
GetBitrateMode(CodecVideoPortCap & port)180 std::vector<int32_t> HdiInit::GetBitrateMode(CodecVideoPortCap &port)
181 {
182 int32_t index = 0;
183 std::vector<int32_t> bitrate;
184 while (index < BIT_RATE_MODE_NUM && port.bitRatemode[index] != BIT_RATE_MODE_INVALID) {
185 switch (port.bitRatemode[index]) {
186 case BIT_RATE_MODE_VBR:
187 bitrate.push_back(VBR);
188 break;
189 case BIT_RATE_MODE_CBR:
190 bitrate.push_back(CBR);
191 break;
192 case BIT_RATE_MODE_CQ:
193 bitrate.push_back(CQ);
194 break;
195 default:
196 MEDIA_LOGW("Unknow bitrate mode %{public}d", port.bitRatemode[index]);
197 }
198 index++;
199 }
200 return bitrate;
201 }
202
GetMeasuredFrameRate(CodecVideoPortCap & port)203 std::map<ImgSize, Range> HdiInit::GetMeasuredFrameRate(CodecVideoPortCap &port)
204 {
205 int32_t index = 0;
206 std::map<ImgSize, Range> rateMap;
207 const int32_t measureStep = 4;
208 // measuredFrameRate is 0 width 1 height 2 minRate 3 maxRate. So the step is 4.
209 while (index < MEASURED_FRAME_RATE_NUM && port.measuredFrameRate[index] > 0) {
210 ImgSize imageSize(port.measuredFrameRate[index], port.measuredFrameRate[index + 1]);
211 Range range(port.measuredFrameRate[index + 2], port.measuredFrameRate[index + 3]);
212 rateMap[imageSize] = range;
213 index += measureStep;
214 }
215 return rateMap;
216 }
217
GetCodecFormats(CodecVideoPortCap & port)218 std::vector<int32_t> HdiInit::GetCodecFormats(CodecVideoPortCap &port)
219 {
220 int32_t index = 0;
221 std::vector<int32_t> formats;
222 while (index < PIX_FORMAT_NUM && port.supportPixFmts[index] > 0) {
223 switch (port.supportPixFmts[index]) {
224 case PIXEL_FMT_YCBCR_420_SP:
225 formats.push_back(NV12);
226 break;
227 case PIXEL_FMT_YCRCB_420_SP:
228 formats.push_back(NV21);
229 break;
230 case PIXEL_FMT_YCBCR_420_P:
231 formats.push_back(YUVI420);
232 break;
233 case PIXEL_FMT_RGBA_8888:
234 formats.push_back(RGBA);
235 break;
236 default:
237 MEDIA_LOGW("Unknow Format %{public}d", port.supportPixFmts[index]);
238 }
239 index++;
240 }
241
242 return formats;
243 }
244
GetH264ProfileLevels(CodecCompCapability & hdiCap)245 std::map<int32_t, std::vector<int32_t>> HdiInit::GetH264ProfileLevels(CodecCompCapability &hdiCap)
246 {
247 std::map<int32_t, std::vector<int32_t>> profileLevelsMap;
248 int32_t index = 0;
249 while (index < PROFILE_NUM && hdiCap.supportProfiles[index] > 0) {
250 if (AVC_PROFILE_MAP.find(hdiCap.supportProfiles[index]) == AVC_PROFILE_MAP.end()) {
251 MEDIA_LOGW("Unknow AVC profile %{public}d", hdiCap.supportProfiles[index]);
252 break;
253 }
254 int32_t profile = AVC_PROFILE_MAP.at(hdiCap.supportProfiles[index]);
255 if (profileLevelsMap.find(profile) == profileLevelsMap.end()) {
256 profileLevelsMap[profile] = std::vector<int32_t>();
257 }
258 index++;
259 if (AVC_LEVEL_MAP.find(hdiCap.supportProfiles[index]) == AVC_LEVEL_MAP.end()) {
260 MEDIA_LOGW("Unknow AVC level %{public}d", hdiCap.supportProfiles[index]);
261 break;
262 }
263 profileLevelsMap[profile].push_back(AVC_LEVEL_MAP.at(hdiCap.supportProfiles[index]));
264 index++;
265 }
266
267 return profileLevelsMap;
268 }
269
GetH265ProfileLevels(CodecCompCapability & hdiCap)270 std::map<int32_t, std::vector<int32_t>> HdiInit::GetH265ProfileLevels(CodecCompCapability &hdiCap)
271 {
272 std::map<int32_t, std::vector<int32_t>> profileLevelsMap;
273 int32_t index = 0;
274 std::vector<int32_t> formats;
275 while (index < PROFILE_NUM && hdiCap.supportProfiles[index] > 0) {
276 if (HEVC_PROFILE_MAP.find(hdiCap.supportProfiles[index]) == HEVC_PROFILE_MAP.end()) {
277 MEDIA_LOGW("Unknow HEVC profile %{public}d", hdiCap.supportProfiles[index]);
278 break;
279 }
280 int32_t profile = HEVC_PROFILE_MAP.at(hdiCap.supportProfiles[index]);
281 if (profileLevelsMap.find(profile) == profileLevelsMap.end()) {
282 profileLevelsMap[profile] = std::vector<int32_t>();
283 }
284 index++;
285 if (HEVC_LEVEL_MAP.find(hdiCap.supportProfiles[index]) == HEVC_LEVEL_MAP.end()) {
286 MEDIA_LOGW("Unknow HEVC level %{public}d", hdiCap.supportProfiles[index]);
287 break;
288 }
289 profileLevelsMap[profile].push_back(HEVC_LEVEL_MAP.at(hdiCap.supportProfiles[index]));
290 index++;
291 }
292
293 return profileLevelsMap;
294 }
295
GetCodecProfileLevels(CodecCompCapability & hdiCap)296 std::map<int32_t, std::vector<int32_t>> HdiInit::GetCodecProfileLevels(CodecCompCapability &hdiCap)
297 {
298 if (PROFILE_LEVEL_FUNC_MAP.find(hdiCap.role) == PROFILE_LEVEL_FUNC_MAP.end()) {
299 MEDIA_LOGW("Unknow role %{public}d", hdiCap.role);
300 return std::map<int32_t, std::vector<int32_t>>();
301 }
302 return PROFILE_LEVEL_FUNC_MAP.at(hdiCap.role)(hdiCap);
303 }
304
AddHdiCap(CodecCompCapability & hdiCap)305 void HdiInit::AddHdiCap(CodecCompCapability &hdiCap)
306 {
307 MEDIA_LOGI("Add codec name %{public}s", hdiCap.compName);
308 CapabilityData codecCap;
309 codecCap.codecName = hdiCap.compName;
310 codecCap.codecType = GetCodecType(hdiCap.type);
311 codecCap.mimeType = GetCodecMime(hdiCap.role);
312 codecCap.isVendor = !hdiCap.isSoftwareCodec;
313 codecCap.alignment = {hdiCap.port.video.whAlignment.widthAlignment, hdiCap.port.video.whAlignment.heightAlignment};
314 codecCap.bitrateMode = GetBitrateMode(hdiCap.port.video);
315 codecCap.width = {hdiCap.port.video.minSize.width, hdiCap.port.video.maxSize.width};
316 codecCap.height = {hdiCap.port.video.minSize.height, hdiCap.port.video.maxSize.height};
317 codecCap.bitrate = {hdiCap.bitRate.min, hdiCap.bitRate.max};
318 codecCap.frameRate = {hdiCap.port.video.frameRate.min, hdiCap.port.video.frameRate.max};
319 codecCap.format = GetCodecFormats(hdiCap.port.video);
320 codecCap.blockPerFrame = {hdiCap.port.video.blockCount.min, hdiCap.port.video.blockCount.max};
321 codecCap.blockPerSecond = {hdiCap.port.video.blocksPerSecond.min, hdiCap.port.video.blocksPerSecond.max};
322 codecCap.blockSize = {hdiCap.port.video.blockSize.width, hdiCap.port.video.blockSize.height};
323 codecCap.measuredFrameRate = GetMeasuredFrameRate(hdiCap.port.video);
324 codecCap.profileLevelsMap = GetCodecProfileLevels(hdiCap);
325 capabilitys_.push_back(codecCap);
326 }
327
InitCaps()328 void HdiInit::InitCaps()
329 {
330 if (!capabilitys_.empty()) {
331 return;
332 }
333 auto len = mgr_->GetComponentNum();
334 if (len >= MAX_COMPONENT_NUM || len <= 0) {
335 MEDIA_LOGW("Component num is %{public}d", len);
336 return;
337 }
338 CodecCompCapability *hdiCaps = new CodecCompCapability[len];
339 CHECK_AND_RETURN_LOG(hdiCaps != nullptr, "New CodecCompCapability fail");
340 ON_SCOPE_EXIT(0) { delete[] hdiCaps; };
341 auto ret = mgr_->GetComponentCapabilityList(hdiCaps, len);
342 CHECK_AND_RETURN_LOG(ret == HDF_SUCCESS, "GetComponentCapabilityList fail");
343 for (auto i = 0; i < len; ++i) {
344 AddHdiCap(hdiCaps[i]);
345 }
346 }
347
GetCapabilitys()348 std::vector<CapabilityData> HdiInit::GetCapabilitys()
349 {
350 std::lock_guard<std::mutex> lock(mutex_);
351 CHECK_AND_RETURN_RET_LOG(mgr_ != nullptr, capabilitys_, "mgr is nullptr");
352 InitCaps();
353 return capabilitys_;
354 }
355
GetHandle(CodecComponentType ** component,uint32_t & id,std::string name,void * appData,CodecCallbackType * callbacks)356 int32_t HdiInit::GetHandle(CodecComponentType **component, uint32_t &id, std::string name,
357 void *appData, CodecCallbackType *callbacks)
358 {
359 std::lock_guard<std::mutex> lock(mutex_);
360 if (mgr_ == nullptr) {
361 CodecComponentManagerInit();
362 CHECK_AND_RETURN_RET_LOG(mgr_ != nullptr, HDF_FAILURE, "mgr is nullptr");
363 }
364
365 CHECK_AND_RETURN_RET_LOG(component != nullptr, HDF_FAILURE, "component is nullptr");
366 int32_t ret = mgr_->CreateComponent(component, &id, const_cast<char *>(name.c_str()),
367 reinterpret_cast<int64_t>(appData), callbacks);
368 if (ret == HDF_SUCCESS) {
369 handleMap_[*component] = id;
370 }
371
372 return ret;
373 }
374
FreeHandle(CodecComponentType * component,uint32_t id)375 int32_t HdiInit::FreeHandle(CodecComponentType *component, uint32_t id)
376 {
377 CHECK_AND_RETURN_RET_LOG(mgr_ != nullptr, HDF_FAILURE, "mgr_ is nullptr");
378
379 std::lock_guard<std::mutex> lock(mutex_);
380 auto iter = handleMap_.find(component);
381 CHECK_AND_RETURN_RET_LOG(iter != handleMap_.end(), HDF_SUCCESS, "The handle has been released!");
382 CHECK_AND_RETURN_RET_LOG(iter->second == id, HDF_FAILURE, "Handle and id do not match!");
383
384 int32_t ret = mgr_->DestroyComponent(id);
385 if (ret == HDF_SUCCESS) {
386 handleMap_.erase(iter);
387 }
388
389 return ret;
390 }
391 } // namespace Media
392 } // namespace OHOS
393