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