1 /*
2 * Copyright (c) 2024 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 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 #include "codec_heif_encode_service.h"
16 #include "codec_log_wrapper.h"
17 #include "hdf_base.h"
18 #include "hdf_remote_service.h"
19 #include "v1_0/display_composer_type.h"
20 #include "v1_0/imapper.h"
21 #include "v1_1/imetadata.h"
22 #include <dlfcn.h>
23 #include <unistd.h>
24 #include <mutex>
25
26 namespace OHOS {
27 namespace HDI {
28 namespace Codec {
29 namespace Image {
30 namespace V2_0 {
31 using GetCodecHeifHwi = ICodecHeifHwi*(*)();
32
33 std::mutex g_mapperMtx;
34 std::mutex g_metaMtx;
35 sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> g_mapperService;
36 sptr<OHOS::HDI::Display::Buffer::V1_1::IMetadata> g_metaService;
37
GetMapperService()38 sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> GetMapperService()
39 {
40 std::lock_guard<std::mutex> lk(g_mapperMtx);
41 if (g_mapperService) {
42 return g_mapperService;
43 }
44 g_mapperService = OHOS::HDI::Display::Buffer::V1_0::IMapper::Get(true);
45 if (g_mapperService) {
46 CODEC_LOGI("get IMapper succ");
47 return g_mapperService;
48 }
49 CODEC_LOGE("get IMapper failed");
50 return nullptr;
51 }
52
GetMetaService()53 sptr<OHOS::HDI::Display::Buffer::V1_1::IMetadata> GetMetaService()
54 {
55 std::lock_guard<std::mutex> lk(g_metaMtx);
56 if (g_metaService) {
57 return g_metaService;
58 }
59 g_metaService = OHOS::HDI::Display::Buffer::V1_1::IMetadata::Get(true);
60 if (g_metaService) {
61 CODEC_LOGI("get IMetadata succ");
62 return g_metaService;
63 }
64 CODEC_LOGE("get IMetadata failed");
65 return nullptr;
66 }
67
BufferDestructor(BufferHandle * handle)68 void BufferDestructor(BufferHandle* handle)
69 {
70 if (handle == nullptr) {
71 return;
72 }
73 sptr<OHOS::HDI::Display::Buffer::V1_0::IMapper> mapper = GetMapperService();
74 if (mapper == nullptr) {
75 return;
76 }
77 sptr<NativeBuffer> buffer = new NativeBuffer();
78 buffer->SetBufferHandle(handle, true);
79 mapper->FreeMem(buffer);
80 }
81
ReWrapNativeBuffer(sptr<NativeBuffer> & buffer)82 bool ReWrapNativeBuffer(sptr<NativeBuffer>& buffer)
83 {
84 if (buffer == nullptr) {
85 return true;
86 }
87 BufferHandle* handle = buffer->Move();
88 if (handle == nullptr) {
89 return true;
90 }
91 buffer->SetBufferHandle(handle, true, BufferDestructor);
92 sptr<OHOS::HDI::Display::Buffer::V1_1::IMetadata> meta = GetMetaService();
93 if (meta == nullptr) {
94 return false;
95 }
96 int32_t ret = meta->RegisterBuffer(buffer);
97 if (ret != Display::Composer::V1_0::DISPLAY_SUCCESS &&
98 ret != Display::Composer::V1_0::DISPLAY_NOT_SUPPORT) {
99 CODEC_LOGE("RegisterBuffer failed, ret = %{public}d", ret);
100 return false;
101 }
102 return true;
103 }
104
CodecHeifEncodeService()105 CodecHeifEncodeService::CodecHeifEncodeService()
106 {
107 isIPCMode_ = (HdfRemoteGetCallingPid() == getpid() ? false : true);
108 }
109
~CodecHeifEncodeService()110 CodecHeifEncodeService::~CodecHeifEncodeService()
111 {
112 heifHwi_ = nullptr;
113 libHeif_ = nullptr;
114 }
115
LoadVendorLib()116 bool CodecHeifEncodeService::LoadVendorLib()
117 {
118 std::lock_guard<std::mutex> lk(mutex_);
119 if (heifHwi_) {
120 return true;
121 }
122 if (libHeif_ == nullptr) {
123 void *handle = dlopen(CODEC_HEIF_VDI_LIB_NAME, RTLD_LAZY);
124 if (handle == nullptr) {
125 CODEC_LOGE("failed to load vendor lib");
126 return false;
127 }
128 libHeif_ = std::shared_ptr<void>(handle, dlclose);
129 }
130 auto func = reinterpret_cast<GetCodecHeifHwi>(dlsym(libHeif_.get(), "GetCodecHeifHwi"));
131 if (func == nullptr) {
132 CODEC_LOGE("failed to load symbol from vendor lib");
133 return false;
134 }
135 heifHwi_ = func();
136 if (heifHwi_ == nullptr) {
137 CODEC_LOGE("failed to create heif hardware encoder");
138 return false;
139 }
140 return true;
141 }
142
ReWrapNativeBufferInImageItem(const std::vector<ImageItem> & inputImgs)143 bool CodecHeifEncodeService::ReWrapNativeBufferInImageItem(const std::vector<ImageItem>& inputImgs)
144 {
145 if (!isIPCMode_) {
146 return true;
147 }
148
149 for (const auto &image : inputImgs) {
150 if (!ReWrapNativeBuffer(const_cast<ImageItem &>(image).pixelBuffer)) {
151 return false;
152 }
153 }
154
155 return true;
156 }
157
DoHeifEncode(const std::vector<ImageItem> & inputImgs,const std::vector<MetaItem> & inputMetas,const std::vector<ItemRef> & refs,const SharedBuffer & output,uint32_t & filledLen)158 int32_t CodecHeifEncodeService::DoHeifEncode(const std::vector<ImageItem>& inputImgs,
159 const std::vector<MetaItem>& inputMetas,
160 const std::vector<ItemRef>& refs,
161 const SharedBuffer& output, uint32_t& filledLen)
162 {
163 if (!LoadVendorLib()) {
164 return HDF_FAILURE;
165 }
166
167 if (!ReWrapNativeBufferInImageItem(inputImgs)) {
168 return HDF_FAILURE;
169 }
170
171 SharedBuffer outputToReturn = output;
172 int32_t ret = (heifHwi_->DoHeifEncode)(inputImgs, inputMetas, refs, outputToReturn);
173 filledLen = outputToReturn.filledLen;
174 auto releaseRes = [](int fd) {
175 if (fd > 0) {
176 close(fd);
177 }
178 };
179 for (auto one : inputImgs) {
180 releaseRes(one.sharedProperties.fd);
181 }
182 for (auto one : inputMetas) {
183 releaseRes(one.data.fd);
184 }
185 releaseRes(output.fd);
186 return ret;
187 }
188 } // V2_0
189 } // Image
190 } // Codec
191 } // HDI
192 } // OHOS