• 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 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 &param,
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 &param)
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