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 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 <cstdio>
17 #include <unistd.h>
18 #include "codec_function_utils.h"
19
20 #define HDF_LOG_TAG codec_hdi_test
21
22 using namespace std;
23 using namespace OHOS::HDI::Codec::V1_0;
24 using namespace OHOS::HDI::Display::Buffer::V1_0;
25 using namespace OHOS::HDI::Display::Composer::V1_0;
26 IDisplayBuffer *FunctionUtil::buffer_ = nullptr;
27
FunctionUtil(CodecVersionType version)28 FunctionUtil::FunctionUtil(CodecVersionType version)
29 {
30 buffer_ = IDisplayBuffer::Get();
31 version_ = version;
32 }
33
~FunctionUtil()34 FunctionUtil::~FunctionUtil()
35 {
36 buffer_ = nullptr;
37 }
38
AlignUp(uint32_t width)39 uint32_t FunctionUtil::AlignUp(uint32_t width)
40 {
41 return (((width) + ALIGNMENT - 1) & (~(ALIGNMENT - 1)));
42 }
43
InitOmxCodecBuffer(OmxCodecBuffer & buffer,CodecBufferType type)44 void FunctionUtil::InitOmxCodecBuffer(OmxCodecBuffer &buffer, CodecBufferType type)
45 {
46 buffer.bufferType = type;
47 buffer.fenceFd = ERROE_FENCEFD;
48 buffer.version = version_;
49 buffer.allocLen = BUFFER_SIZE;
50 buffer.fd = FD_DEFAULT;
51 buffer.bufferhandle = nullptr;
52 buffer.pts = 0;
53 buffer.flag = 0;
54 buffer.size = sizeof(OmxCodecBuffer);
55 buffer.type = READ_ONLY_TYPE;
56 }
57
InitCodecBufferWithAshMem(enum PortIndex port,int bufferSize,shared_ptr<OmxCodecBuffer> omxBuffer,shared_ptr<OHOS::Ashmem> sharedMem)58 void FunctionUtil::InitCodecBufferWithAshMem(enum PortIndex port, int bufferSize, shared_ptr<OmxCodecBuffer> omxBuffer,
59 shared_ptr<OHOS::Ashmem> sharedMem)
60 {
61 InitOmxCodecBuffer(*omxBuffer.get(), CODEC_BUFFER_TYPE_AVSHARE_MEM_FD);
62 omxBuffer->fd = sharedMem->GetAshmemFd();
63 omxBuffer->allocLen = bufferSize;
64 if (port == PortIndex::INDEX_INPUT) {
65 omxBuffer->type = READ_ONLY_TYPE;
66 sharedMem->MapReadAndWriteAshmem();
67 } else {
68 omxBuffer->type = READ_WRITE_TYPE;
69 sharedMem->MapReadOnlyAshmem();
70 }
71 }
72
InitBufferHandleParameter(sptr<ICodecComponent> component,OMX_PARAM_PORTDEFINITIONTYPE & param,uint32_t port,CodecBufferType bufferType)73 bool FunctionUtil::InitBufferHandleParameter(sptr<ICodecComponent> component, OMX_PARAM_PORTDEFINITIONTYPE ¶m,
74 uint32_t port, CodecBufferType bufferType)
75 {
76 InitParam(param);
77 param.nPortIndex = port;
78 std::vector<int8_t> inParam, outParam;
79 ObjectToVector(param, inParam);
80 auto ret = component->GetParameter(OMX_IndexParamPortDefinition, inParam, outParam);
81 if (ret != HDF_SUCCESS) {
82 HDF_LOGE("GetParameter OMX_IndexParamPortDefinition error");
83 return false;
84 }
85
86 VectorToObject(outParam, param);
87 param.format.video.nFrameWidth = WIDTH;
88 param.format.video.nFrameHeight = HEIGHT;
89 param.format.video.nStride = AlignUp(WIDTH);
90 param.format.video.nSliceHeight = HEIGHT;
91 param.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
92 std::vector<int8_t> enc;
93 ObjectToVector(param, enc);
94 ret = component->SetParameter(OMX_IndexParamPortDefinition, enc);
95 if (ret != HDF_SUCCESS) {
96 HDF_LOGE("SetParameter OMX_IndexParamPortDefinition error");
97 return false;
98 }
99
100 std::vector<int8_t> data;
101 UseBufferType type;
102 type.size = sizeof(UseBufferType);
103 type.version.s.nVersionMajor = 1;
104 type.portIndex = port;
105 type.bufferType = bufferType;
106 ObjectToVector(type, data);
107 ret = component->SetParameter(OMX_IndexParamUseBufferType, data);
108 if (ret != HDF_SUCCESS) {
109 HDF_LOGE("SetParameter OMX_IndexParamUseBufferType error");
110 return false;
111 }
112 return true;
113 }
114
FillCodecBufferWithBufferHandle(shared_ptr<OmxCodecBuffer> omxBuffer)115 bool FunctionUtil::FillCodecBufferWithBufferHandle(shared_ptr<OmxCodecBuffer> omxBuffer)
116 {
117 AllocInfo alloc = {.width = WIDTH,
118 .height = HEIGHT,
119 .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
120 .format = PIXEL_FMT_YCBCR_420_SP};
121
122 BufferHandle *bufferHandle = nullptr;
123 if (buffer_ == nullptr) {
124 HDF_LOGE("buffer_ is nullptr");
125 return false;
126 }
127 auto ret = buffer_->AllocMem(alloc, bufferHandle);
128 if (ret != HDF_SUCCESS) {
129 HDF_LOGE("AllocMem error");
130 return false;
131 }
132 omxBuffer->bufferhandle = new NativeBuffer(bufferHandle);
133 return true;
134 }
135
UseDynaBuffer(sptr<ICodecComponent> component,enum PortIndex port,int bufferCount,int bufferSize)136 bool FunctionUtil::UseDynaBuffer(sptr<ICodecComponent> component, enum PortIndex port, int bufferCount,
137 int bufferSize)
138 {
139 if (bufferCount <= 0 || bufferSize <= 0) {
140 HDF_LOGE("bufferCount <= 0 or bufferSize <= 0");
141 return false;
142 }
143
144 for (int i = 0; i < bufferCount; i++) {
145 auto omxBuffer = std::make_shared<OmxCodecBuffer>();
146 InitOmxCodecBuffer(*omxBuffer.get(), CODEC_BUFFER_TYPE_DYNAMIC_HANDLE);
147 omxBuffer->allocLen = WIDTH * HEIGHT * NUMERATOR / DENOMINATOR;
148
149 OmxCodecBuffer outBuffer;
150 auto ret = component->UseBuffer(static_cast<uint32_t>(port), *omxBuffer.get(), outBuffer);
151 if (ret != HDF_SUCCESS) {
152 HDF_LOGE("UseBuffer error");
153 return false;
154 }
155
156 omxBuffer->bufferId = outBuffer.bufferId;
157 auto bufferInfo = std::make_shared<BufferInfo>();
158 bufferInfo->omxBuffer = omxBuffer;
159 inputBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
160 }
161 return true;
162 }
163
UseHandleBuffer(sptr<ICodecComponent> component,enum PortIndex port,int bufferCount,int bufferSize)164 bool FunctionUtil::UseHandleBuffer(sptr<ICodecComponent> component, enum PortIndex port,
165 int bufferCount, int bufferSize)
166 {
167 if (bufferCount <= 0 || bufferSize <= 0) {
168 HDF_LOGE("bufferCount <= 0 or bufferSize <= 0");
169 return false;
170 }
171
172 for (int i = 0; i < bufferCount; i++) {
173 auto omxBuffer = std::make_shared<OmxCodecBuffer>();
174 InitOmxCodecBuffer(*omxBuffer.get(), CODEC_BUFFER_TYPE_HANDLE);
175 FillCodecBufferWithBufferHandle(omxBuffer);
176 omxBuffer->allocLen = WIDTH * HEIGHT * NUMERATOR / DENOMINATOR;
177
178 OmxCodecBuffer outBuffer;
179 auto ret = component->UseBuffer(static_cast<uint32_t>(port), *omxBuffer.get(), outBuffer);
180 if (ret != HDF_SUCCESS) {
181 HDF_LOGE("UseBuffer error");
182 return false;
183 }
184
185 omxBuffer->bufferId = outBuffer.bufferId;
186 auto bufferInfo = std::make_shared<BufferInfo>();
187 bufferInfo->omxBuffer = omxBuffer;
188 outputBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
189 }
190 return true;
191 }
192
UseBufferOnPort(sptr<ICodecComponent> component,enum PortIndex port,int32_t bufferCount,int32_t bufferSize)193 bool FunctionUtil::UseBufferOnPort(sptr<ICodecComponent> component, enum PortIndex port,
194 int32_t bufferCount, int32_t bufferSize)
195 {
196 for (int i = 0; i < bufferCount; i++) {
197 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
198 int fd = OHOS::AshmemCreate(0, bufferSize);
199 shared_ptr<OHOS::Ashmem> sharedMem = make_shared<OHOS::Ashmem>(fd, bufferSize);
200 InitCodecBufferWithAshMem(port, bufferSize, omxBuffer, sharedMem);
201 OmxCodecBuffer outBuffer;
202 auto err = component->UseBuffer(static_cast<uint32_t>(port), *omxBuffer.get(), outBuffer);
203 if (err != HDF_SUCCESS) {
204 HDF_LOGE("UseBuffer error");
205 sharedMem->UnmapAshmem();
206 sharedMem->CloseAshmem();
207 return false;
208 }
209
210 omxBuffer->bufferId = outBuffer.bufferId;
211 omxBuffer->fd = FD_DEFAULT;
212 std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>();
213 bufferInfo->omxBuffer = omxBuffer;
214 bufferInfo->sharedMem = sharedMem;
215 if (port == PortIndex::INDEX_INPUT) {
216 inputBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
217 } else {
218 outputBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
219 }
220 }
221 return true;
222 }
223
AllocateBufferOnPort(sptr<ICodecComponent> component,enum PortIndex port,int32_t bufferCount,int32_t bufferSize)224 bool FunctionUtil::AllocateBufferOnPort(sptr<ICodecComponent> component, enum PortIndex port,
225 int32_t bufferCount, int32_t bufferSize)
226 {
227 for (int i = 0; i < bufferCount; i++) {
228 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
229 InitOmxCodecBuffer(*omxBuffer.get(), CODEC_BUFFER_TYPE_AVSHARE_MEM_FD);
230 omxBuffer->allocLen = bufferSize;
231 if (port == PortIndex::INDEX_INPUT) {
232 omxBuffer->type = READ_ONLY_TYPE;
233 } else {
234 omxBuffer->type = READ_WRITE_TYPE;
235 }
236
237 OmxCodecBuffer outBuffer;
238 auto err = component->AllocateBuffer(static_cast<uint32_t>(port), *omxBuffer.get(), outBuffer);
239 if (err != HDF_SUCCESS) {
240 HDF_LOGE("AllocateBuffer error");
241 return false;
242 }
243 omxBuffer->type = outBuffer.type;
244 omxBuffer->bufferId = outBuffer.bufferId;
245
246 int fd = outBuffer.fd;
247 shared_ptr<OHOS::Ashmem> sharedMem = make_shared<OHOS::Ashmem>(fd, bufferSize);
248
249 std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>();
250 bufferInfo->omxBuffer = omxBuffer;
251 bufferInfo->sharedMem = sharedMem;
252 if (port == PortIndex::INDEX_INPUT) {
253 sharedMem->MapReadAndWriteAshmem();
254 inputBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
255 } else {
256 sharedMem->MapReadOnlyAshmem();
257 outputBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
258 }
259 }
260 return true;
261 }
262
FreeBufferOnPort(sptr<ICodecComponent> component,enum PortIndex port)263 bool FunctionUtil::FreeBufferOnPort(sptr<ICodecComponent> component, enum PortIndex port)
264 {
265 std::map<int32_t, std::shared_ptr<BufferInfo>> &buffer = inputBuffers_;
266 if (port == PortIndex::INDEX_OUTPUT) {
267 buffer = outputBuffers_;
268 }
269 for (auto [bufferId, bufferInfo] : buffer) {
270 auto ret = component->FreeBuffer(static_cast<uint32_t>(port), *bufferInfo->omxBuffer.get());
271 if (ret != HDF_SUCCESS) {
272 HDF_LOGE("FreeBuffer error");
273 return false;
274 }
275 }
276 buffer.clear();
277 return true;
278 }
279
GetPortParameter(sptr<ICodecComponent> component,PortIndex index,OMX_PARAM_PORTDEFINITIONTYPE & param)280 int32_t FunctionUtil::GetPortParameter(sptr<ICodecComponent> component, PortIndex index,
281 OMX_PARAM_PORTDEFINITIONTYPE ¶m)
282 {
283 InitParam(param);
284 param.nPortIndex = static_cast<OMX_U32>(index);
285 std::vector<int8_t> inParam;
286 ObjectToVector(param, inParam);
287
288 std::vector<int8_t> outParam;
289 auto ret = component->GetParameter(OMX_IndexParamPortDefinition, inParam, outParam);
290 VectorToObject(outParam, param);
291 return ret;
292 }
293
FillAndEmptyAllBuffer(sptr<ICodecComponent> component,CodecBufferType type)294 bool FunctionUtil::FillAndEmptyAllBuffer(sptr<ICodecComponent> component, CodecBufferType type)
295 {
296 auto iter = outputBuffers_.begin();
297 if (iter != outputBuffers_.end()) {
298 auto ret = component->FillThisBuffer(*iter->second->omxBuffer.get());
299 if (ret != HDF_SUCCESS) {
300 HDF_LOGE("FillThisBuffer error");
301 return false;
302 }
303 }
304 iter = inputBuffers_.begin();
305 if (iter != inputBuffers_.end()) {
306 auto bufferInfo = iter->second;
307 if (type == CODEC_BUFFER_TYPE_DYNAMIC_HANDLE) {
308 FillCodecBufferWithBufferHandle(bufferInfo->omxBuffer);
309 }
310 auto ret = component->EmptyThisBuffer(*bufferInfo->omxBuffer.get());
311 if (ret != HDF_SUCCESS) {
312 HDF_LOGE("EmptyThisBuffer error");
313 return false;
314 }
315 }
316 return true;
317 }
318
WaitState(sptr<ICodecComponent> component,CodecStateType objState)319 bool FunctionUtil::WaitState(sptr<ICodecComponent> component, CodecStateType objState)
320 {
321 CodecStateType state = CODEC_STATE_INVALID;
322 uint32_t count = 0;
323 do {
324 usleep(WAIT_TIME);
325 auto ret = component->GetState(state);
326 if (ret != HDF_SUCCESS) {
327 HDF_LOGE("EmptyThisBuffer error");
328 return false;
329 }
330 count++;
331 } while (state != objState && count <= MAX_WAIT);
332 return true;
333 }
334
335