1 /*
2 * Copyright 2023 Shenzhen Kaihong DID 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 "codec_hdi_encode.h"
17 #include <securec.h>
18 #include <unistd.h>
19 #include "codec_omx_ext.h"
20 #include "hdf_log.h"
21 #include "v1_0/display_composer_type.h"
22 #include "v1_0/display_buffer_type.h"
23 #include "v1_0/include/idisplay_buffer.h"
24 using namespace std;
25 using namespace OHOS;
26 using OHOS::sptr;
27 using OHOS::HDI::Base::NativeBuffer;
28 using namespace OHOS::HDI::Codec::V1_0;
29 using namespace OHOS::HDI::Display::Buffer::V1_0;
30 using namespace OHOS::HDI::Display::Composer::V1_0;
31 #define HDF_LOG_TAG codec_omx_hdi_enc
32 #define AV_COLOR_FORMAT OMX_COLOR_FormatYUV420SemiPlanar
33 IDisplayBuffer *CodecHdiEncode::gralloc_ = nullptr;
34 CodecUtil *CodecHdiEncode::util_;
35 namespace {
36 constexpr uint32_t FRAME = 30 << 16;
37 constexpr uint32_t BUFFER_COUNT = 10;
38 constexpr uint32_t BITRATE = 3000000;
39 constexpr uint32_t DENOMINATOR = 2;
40 constexpr uint32_t NUMERATOR = 3;
41 } // namespace
CodecHdiEncode()42 CodecHdiEncode::CodecHdiEncode() : fpIn_(nullptr), fpOut_(nullptr)
43 {
44 client_ = nullptr;
45 callback_ = nullptr;
46 omxMgr_ = nullptr;
47 exit_ = false;
48 useBufferHandle_ = false;
49 width_ = 0;
50 height_ = 0;
51 componentId_ = 0;
52 }
53
~CodecHdiEncode()54 CodecHdiEncode::~CodecHdiEncode()
55 {
56 if (fpOut_ != nullptr) {
57 fclose(fpOut_);
58 fpOut_ = nullptr;
59 }
60 if (fpIn_ != nullptr) {
61 fclose(fpIn_);
62 fpIn_ = nullptr;
63 }
64 }
65
WaitForStatusChanged()66 void CodecHdiEncode::WaitForStatusChanged()
67 {
68 unique_lock<mutex> autoLock(statusLock_);
69 statusCondition_.wait(autoLock);
70 }
71
OnStatusChanged()72 void CodecHdiEncode::OnStatusChanged()
73 {
74 statusCondition_.notify_one();
75 }
76
ReadOneFrame(FILE * fp,char * buf,uint32_t & filledCount)77 bool CodecHdiEncode::ReadOneFrame(FILE *fp, char *buf, uint32_t &filledCount)
78 {
79 bool ret = false;
80 size_t t = fread(buf, 1, width_ * height_ * NUMERATOR / DENOMINATOR, fp);
81 if (feof(fp)) {
82 ret = true;
83 }
84 filledCount = static_cast<uint32_t>(t);
85 return ret;
86 }
87
Init(const CommandOpt & opt)88 bool CodecHdiEncode::Init(const CommandOpt &opt)
89 {
90 this->width_ = opt.width;
91 this->height_ = opt.height;
92 this->stride_ = AlignUp(width_);
93 this->useBufferHandle_ = opt.useBuffer;
94 HDF_LOGI("width[%{public}d], height[%{public}d]", width_, height_);
95 // gralloc init
96 gralloc_ = IDisplayBuffer::Get();
97 fpIn_ = fopen(opt.fileInput.c_str(), "rb");
98 fpOut_ = fopen(opt.fileOutput.c_str(), "wb+");
99 if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) {
100 HDF_LOGE("%{public}s:failed to open file %{public}s or %{public}s", __func__, opt.fileInput.c_str(),
101 opt.fileOutput.c_str());
102 return false;
103 }
104 // Interface init
105 omxMgr_ = OHOS::HDI::Codec::V1_0::ICodecComponentManager::Get();
106 callback_ = new CodecHdiCallback(shared_from_this());
107 if ((omxMgr_ == nullptr) || (callback_ == nullptr)) {
108 HDF_LOGE("%{public}s:omxMgr_ or callback_ is null", __func__);
109 return false;
110 }
111 std::string compName("");
112 auto err = GetComponentName(compName);
113 if (err != HDF_SUCCESS) {
114 HDF_LOGE("%{public}s failed to GetComponentName", __func__);
115 return false;
116 }
117 // create a component
118 err = omxMgr_->CreateComponent(client_, componentId_, compName, reinterpret_cast<int64_t>(this), callback_);
119 if (err != HDF_SUCCESS) {
120 HDF_LOGE("%{public}s failed to CreateComponent", __func__);
121 return false;
122 }
123 // get version
124 struct OHOS::HDI::Codec::V1_0::CompVerInfo verInfo;
125 err = memset_s(&verInfo, sizeof(verInfo), 0, sizeof(verInfo));
126 if (err != EOK) {
127 HDF_LOGE("%{public}s: memset_s verInfo err [%{public}d].", __func__, err);
128 return false;
129 }
130 err = client_->GetComponentVersion(verInfo);
131 if (err != HDF_SUCCESS) {
132 HDF_LOGE("%{public}s failed to CreateComponent", __func__);
133 return false;
134 }
135
136 return true;
137 }
138
Configure()139 bool CodecHdiEncode::Configure()
140 {
141 if (client_ == nullptr) {
142 return false;
143 }
144 // set input width, height and COLOR, set ouput port width and height
145 if (ConfigPortDefine() != HDF_SUCCESS) {
146 HDF_LOGE("%{public}s ConfigPortDefine error", __func__);
147 return false;
148 }
149 if (ConfigBitMode() != HDF_SUCCESS) {
150 HDF_LOGE("%{public}s ConfigBitMode error", __func__);
151 return false;
152 }
153 if (CheckAndUseBufferHandle() != HDF_SUCCESS) {
154 HDF_LOGE("%{public}s ConfigUseBufferHandle error", __func__);
155 return false;
156 }
157
158 return true;
159 }
160
CheckAndUseBufferHandle()161 int32_t CodecHdiEncode::CheckAndUseBufferHandle()
162 {
163 if (!useBufferHandle_) {
164 return HDF_SUCCESS;
165 }
166
167 SupportBufferType param;
168 if (util_->InitParamInOhos(param) != HDF_SUCCESS) {
169 return HDF_FAILURE;
170 }
171 param.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT);
172 std::vector<int8_t> inVec, outVec;
173 util_->ObjectToVector(param, inVec);
174
175 auto err = client_->GetParameter(OMX_IndexParamSupportBufferType, inVec, outVec);
176 if (err != HDF_SUCCESS) {
177 HDF_LOGE("%{public}s failed with PORT_INDEX_OUTPUT, index is OMX_IndexParamSupportBufferType", __func__);
178 return err;
179 }
180 util_->VectorToObject(outVec, param);
181
182 if (util_->InitParamInOhos(param) != HDF_SUCCESS) {
183 return HDF_FAILURE;
184 }
185 param.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT);
186 util_->ObjectToVector(param, inVec);
187 err = client_->GetParameter(OMX_IndexParamSupportBufferType, inVec, outVec);
188 if (err != HDF_SUCCESS) {
189 HDF_LOGE("%{public}s failed with PORT_INDEX_INPUT, index is OMX_IndexParamSupportBufferType", __func__);
190 return err;
191 }
192 util_->VectorToObject(outVec, param);
193
194 GetBufferHandleUsageParams usage;
195 if (util_->InitParamInOhos(usage) != HDF_SUCCESS) {
196 return HDF_FAILURE;
197 }
198 usage.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT);
199 util_->ObjectToVector(usage, inVec);
200 err = client_->GetParameter(OMX_IndexParamGetBufferHandleUsage, inVec, outVec);
201 if (err != HDF_SUCCESS) {
202 HDF_LOGE("%{public}s failed with PORT_INDEX_INPUT, index is OMX_IndexParamGetBufferHandleUsage", __func__);
203 return err;
204 }
205 util_->VectorToObject(outVec, usage);
206
207 UseBufferType type;
208 if (util_->InitParamInOhos(type) != HDF_SUCCESS) {
209 return HDF_FAILURE;
210 }
211 type.portIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT);
212 type.bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
213 util_->ObjectToVector(type, inVec);
214 err = client_->SetParameter(OMX_IndexParamUseBufferType, inVec);
215 if (err != HDF_SUCCESS) {
216 HDF_LOGE("%{public}s failed with PORT_INDEX_INPUT, index is OMX_IndexParamUseBufferType", __func__);
217 return err;
218 }
219 return err;
220 }
221
UseBuffers()222 bool CodecHdiEncode::UseBuffers()
223 {
224 // commad to IDLE
225 auto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
226 if (err != HDF_SUCCESS) {
227 HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__);
228 return false;
229 }
230
231 // use buffer on input port
232 err = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT);
233 if (err != HDF_SUCCESS) {
234 HDF_LOGE("%{public}s UseBufferOnPort PORT_INDEX_INPUT error", __func__);
235 return false;
236 }
237
238 // use buffer on output port
239 err = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT);
240 if (err != HDF_SUCCESS) {
241 HDF_LOGE("%{public}s UseBufferOnPort PORT_INDEX_OUTPUT error", __func__);
242 return false;
243 }
244
245 if (useBufferHandle_ && CreateBufferHandle() != HDF_SUCCESS) {
246 HDF_LOGE("%{public}s CreateBufferHandle error", __func__);
247 return false;
248 }
249
250 // wait executing state
251 CodecStateType status = CODEC_STATE_INVALID;
252 err = client_->GetState(status);
253 if (err != HDF_SUCCESS) {
254 HDF_LOGE("%{public}s GetState err [%{public}x]", __func__, err);
255 return false;
256 }
257
258 // wait loaded
259 if (status != CODEC_STATE_IDLE) {
260 HDF_LOGI("Wait for CODEC_STATE_LOADED status");
261 this->WaitForStatusChanged();
262 } else {
263 HDF_LOGI(" status is %{public}d", status);
264 }
265 return true;
266 }
267
UseBufferOnPort(PortIndex portIndex)268 int32_t CodecHdiEncode::UseBufferOnPort(PortIndex portIndex)
269 {
270 HDF_LOGI("%{public}s enter, portIndex = %{public}d", __func__, portIndex);
271 int bufferSize = 0;
272 int bufferCount = 0;
273 bool portEnable = false;
274
275 OMX_PARAM_PORTDEFINITIONTYPE param;
276 if (util_->InitParam(param) != HDF_SUCCESS) {
277 return HDF_FAILURE;
278 }
279 param.nPortIndex = static_cast<uint32_t>(portIndex);
280 std::vector<int8_t> inVec, outVec;
281 util_->ObjectToVector(param, inVec);
282 auto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
283 if (err != HDF_SUCCESS) {
284 HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]",
285 __func__, portIndex);
286 return err;
287 }
288 util_->VectorToObject(outVec, param);
289
290 bufferSize = param.nBufferSize;
291 bufferCount = param.nBufferCountActual;
292 portEnable = param.bEnabled;
293 HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], buffer count [%{public}d], "
294 "portEnable[%{public}d], ret [%{public}d]",
295 portIndex, bufferSize, bufferCount, portEnable, err);
296 if (portIndex == PortIndex::PORT_INDEX_INPUT) {
297 bufferSize = width_ * height_ * NUMERATOR / DENOMINATOR;
298 } else if (bufferSize == 0) {
299 bufferSize = width_ * height_;
300 HDF_LOGI("bufferSize[%{public}d], width[%{public}d], height[%{public}d]", bufferSize, width_, height_);
301 }
302 if (useBufferHandle_ && portIndex == PortIndex::PORT_INDEX_INPUT) {
303 err = UseDynaBuffer(bufferCount, bufferSize);
304 } else {
305 err = UseBufferOnPort(portIndex, bufferCount, bufferSize);
306 }
307
308 if (err != HDF_SUCCESS) {
309 return err;
310 }
311
312 // if port is disable, changed to enable
313 if (!portEnable) {
314 err = client_->SendCommand(CODEC_COMMAND_PORT_ENABLE, static_cast<uint32_t>(portIndex), {});
315 if (err != HDF_SUCCESS) {
316 HDF_LOGE("%{public}s SendCommand OMX_CommandPortEnable::PORT_INDEX_INPUT error", __func__);
317 return err;
318 }
319 }
320
321 return HDF_SUCCESS;
322 }
323
UseBufferOnPort(PortIndex portIndex,int bufferCount,int bufferSize)324 int32_t CodecHdiEncode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize)
325 {
326 if (bufferCount <= 0 || bufferSize <= 0) {
327 return HDF_ERR_INVALID_PARAM;
328 }
329
330 for (int i = 0; i < bufferCount; i++) {
331 auto omxBuffer = std::make_shared<OmxCodecBuffer>();
332 omxBuffer->size = sizeof(OmxCodecBuffer);
333 omxBuffer->version.version.majorVersion = 1;
334 omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
335 int fd = AshmemCreate(0, bufferSize);
336 shared_ptr<Ashmem> spSharedMem = make_shared<Ashmem>(fd, bufferSize);
337 omxBuffer->fd = fd;
338 omxBuffer->bufferhandle = nullptr;
339 omxBuffer->allocLen = bufferSize;
340 omxBuffer->fenceFd = -1;
341 omxBuffer->pts = 0;
342 omxBuffer->flag = 0;
343 if (portIndex == PortIndex::PORT_INDEX_INPUT) {
344 omxBuffer->type = OHOS::HDI::Codec::V1_0::READ_ONLY_TYPE;
345 spSharedMem->MapReadAndWriteAshmem();
346 } else {
347 omxBuffer->type = OHOS::HDI::Codec::V1_0::READ_WRITE_TYPE;
348 spSharedMem->MapReadOnlyAshmem();
349 }
350 OmxCodecBuffer outBuffer;
351 auto err = client_->UseBuffer(static_cast<uint32_t>(portIndex), *omxBuffer.get(), outBuffer);
352 if (err != HDF_SUCCESS) {
353 HDF_LOGE("%{public}s failed to UseBuffer with portIndex[%{public}d]", __func__, portIndex);
354 spSharedMem->UnmapAshmem();
355 spSharedMem->CloseAshmem();
356 spSharedMem = nullptr;
357 return err;
358 }
359
360 omxBuffer->bufferId = outBuffer.bufferId;
361 HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId);
362
363 auto bufferInfo = std::make_shared<BufferInfo>();
364 bufferInfo->omxBuffer = omxBuffer;
365 bufferInfo->avSharedPtr = spSharedMem;
366 bufferInfo->portIndex = portIndex;
367 omxBuffers_.insert(std::make_pair(omxBuffer->bufferId, bufferInfo));
368 if (portIndex == PortIndex::PORT_INDEX_INPUT) {
369 unUsedInBuffers_.push_back(omxBuffer->bufferId);
370 } else {
371 unUsedOutBuffers_.push_back(omxBuffer->bufferId);
372 }
373 }
374 return HDF_SUCCESS;
375 }
376
UseDynaBuffer(int bufferCount,int bufferSize)377 int32_t CodecHdiEncode::UseDynaBuffer(int bufferCount, int bufferSize)
378 {
379 if (bufferCount <= 0 || bufferSize <= 0) {
380 return HDF_ERR_INVALID_PARAM;
381 }
382
383 for (int i = 0; i < bufferCount; i++) {
384 auto omxBuffer = std::make_shared<OmxCodecBuffer>();
385 omxBuffer->size = sizeof(OmxCodecBuffer);
386 omxBuffer->version.version.majorVersion = 1;
387 omxBuffer->bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
388 omxBuffer->fd = -1;
389 omxBuffer->bufferhandle = nullptr;
390 omxBuffer->allocLen = bufferSize;
391 omxBuffer->fenceFd = -1;
392 omxBuffer->pts = 0;
393 omxBuffer->flag = 0;
394
395 OmxCodecBuffer outBuffer;
396 auto err = client_->UseBuffer(static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT),
397 *omxBuffer.get(), outBuffer);
398 if (err != HDF_SUCCESS) {
399 HDF_LOGE("%{public}s failed to UseBuffer with PORT_INDEX_INPUT", __func__);
400 return err;
401 }
402
403 omxBuffer->bufferId = outBuffer.bufferId;
404 HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId);
405
406 auto bufferInfo = std::make_shared<BufferInfo>();
407 bufferInfo->omxBuffer = omxBuffer;
408 bufferInfo->portIndex = PortIndex::PORT_INDEX_INPUT;
409 omxBuffers_.insert(std::make_pair(omxBuffer->bufferId, bufferInfo));
410 unUsedInBuffers_.push_back(omxBuffer->bufferId);
411 }
412 return HDF_SUCCESS;
413 }
414
FreeBuffers()415 void CodecHdiEncode::FreeBuffers()
416 {
417 // send command to loaded state
418 (void)client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_LOADED, {});
419
420 // All the buffer must be released, otherwise the component will wait
421 auto iter = omxBuffers_.begin();
422 while (iter != omxBuffers_.end()) {
423 auto bufferInfo = iter->second;
424 (void)client_->FreeBuffer(static_cast<uint32_t>(bufferInfo->portIndex), *bufferInfo->omxBuffer.get());
425 iter = omxBuffers_.erase(iter);
426 }
427 unUsedInBuffers_.clear();
428 unUsedOutBuffers_.clear();
429
430 CodecStateType status = CODEC_STATE_INVALID;
431 int32_t tryCount = 3;
432 do {
433 int32_t err = client_->GetState(status);
434 if (err != HDF_SUCCESS) {
435 HDF_LOGE("%s GetState error [%{public}x]", __func__, err);
436 break;
437 }
438 if (status != CODEC_STATE_LOADED) {
439 HDF_LOGI("Wait for OMX_StateLoaded status");
440 this->WaitForStatusChanged();
441 }
442 tryCount--;
443 } while ((status != CODEC_STATE_LOADED) && (tryCount > 0));
444 }
445
Release()446 void CodecHdiEncode::Release()
447 {
448 omxMgr_->DestroyComponent(componentId_);
449 client_ = nullptr;
450 callback_ = nullptr;
451 omxMgr_ = nullptr;
452 }
453
FillAllTheBuffer()454 bool CodecHdiEncode::FillAllTheBuffer()
455 {
456 for (auto bufferId : unUsedOutBuffers_) {
457 HDF_LOGI("fill bufferid [%{public}d]", bufferId);
458 auto iter = omxBuffers_.find(bufferId);
459 if (iter != omxBuffers_.end()) {
460 auto bufferInfo = iter->second;
461 auto err = client_->FillThisBuffer(*bufferInfo->omxBuffer.get());
462 if (err != HDF_SUCCESS) {
463 HDF_LOGE("%{public}s FillThisBuffer error", __func__);
464 return false;
465 }
466 }
467 }
468 return true;
469 }
470
GetFreeBufferId()471 int CodecHdiEncode::GetFreeBufferId()
472 {
473 int bufferID = -1;
474 unique_lock<mutex> ulk(lockInputBuffers_);
475 size_t nSize = this->unUsedInBuffers_.size();
476 if (nSize != 0) {
477 bufferID = unUsedInBuffers_.front();
478 unUsedInBuffers_.pop_front();
479 }
480 return bufferID;
481 }
482
GetComponentName(std::string & compName)483 int32_t CodecHdiEncode::GetComponentName(std::string &compName)
484 {
485 OHOS::HDI::Codec::V1_0::AvCodecRole role = OHOS::HDI::Codec::V1_0::AvCodecRole::MEDIA_ROLETYPE_VIDEO_AVC;
486 int32_t count = 0;
487 auto err = omxMgr_->GetComponentNum(count);
488 if (err != HDF_SUCCESS || count <= 0) {
489 HDF_LOGE("%{public}s GetComponentNum return %{public}d, count = %{public}d", __func__, err, count);
490 return HDF_FAILURE;
491 }
492 std::vector<CodecCompCapability> caps;
493 err = omxMgr_->GetComponentCapabilityList(caps, count);
494 if (err != HDF_SUCCESS) {
495 HDF_LOGE("%{public}s GetComponentCapabilityList return %{public}d", __func__, err);
496 return err;
497 }
498 err = HDF_FAILURE;
499 for (auto cap : caps) {
500 if (cap.type == OHOS::HDI::Codec::V1_0::CodecType::VIDEO_ENCODER && cap.role == role) {
501 compName = cap.compName;
502 err = HDF_SUCCESS;
503 }
504 }
505 return err;
506 }
507
Run()508 void CodecHdiEncode::Run()
509 {
510 auto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_EXECUTING, {});
511 if (err != HDF_SUCCESS) {
512 HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__);
513 return;
514 }
515 if (!FillAllTheBuffer()) {
516 HDF_LOGE("%{public}s FillAllTheBuffer error", __func__);
517 return;
518 }
519 bool endFlag = false;
520 while (!endFlag) {
521 int bufferID = GetFreeBufferId();
522 if (this->exit_) {
523 break;
524 }
525 if (bufferID < 0) {
526 usleep(10000); // 10000 for wait 10ms
527 continue;
528 }
529 auto iter = omxBuffers_.find(bufferID);
530 if (iter == omxBuffers_.end()) {
531 continue;
532 }
533 auto bufferInfo = iter->second;
534 if (!FillCodecBuffer(bufferInfo, endFlag)) {
535 break;
536 }
537 err = client_->EmptyThisBuffer(*bufferInfo->omxBuffer.get());
538 bufferInfo->omxBuffer->bufferhandle = nullptr;
539 if (err != HDF_SUCCESS) {
540 HDF_LOGE("%{public}s EmptyThisBuffer error", __func__);
541 return;
542 }
543 }
544 while (!this->exit_) {
545 usleep(10000); // 10000 for wait 10ms
546 }
547 (void)client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
548 return;
549 }
550
FillCodecBuffer(std::shared_ptr<BufferInfo> bufferInfo,bool & endFlag)551 bool CodecHdiEncode::FillCodecBuffer(std::shared_ptr<BufferInfo> bufferInfo, bool &endFlag)
552 {
553 if (gralloc_ == nullptr) {
554 HDF_LOGE("%{public}s gralloc_ is null", __func__);
555 return false;
556 }
557 if (useBufferHandle_) {
558 int bufferHandleId = freeBufferHandles_.front();
559 if (bufferHandleId < 0 || bufferHandleId >= BUFFER_COUNT) {
560 HDF_LOGE("%{public}s bufferHandleId [%{public}d]", __func__, bufferHandleId);
561 return false;
562 }
563 freeBufferHandles_.pop_front();
564 bufferInfo->bufferHandleId = bufferHandleId;
565 BufferHandle *bufferHandle = bufferHandles_[bufferHandleId];
566 if (bufferHandle != nullptr) {
567 gralloc_->Mmap(*bufferHandle);
568 endFlag = this->ReadOneFrame(fpIn_, static_cast<char *>(bufferHandle->virAddr),
569 bufferInfo->omxBuffer->filledLen);
570 gralloc_->Unmap(*bufferHandle);
571 bufferInfo->omxBuffer->bufferhandle = new NativeBuffer(bufferHandle);
572 }
573 } else {
574 // read data from ashmem
575 void *sharedAddr = const_cast<void *>(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0));
576 endFlag = this->ReadOneFrame(fpIn_, static_cast<char *>(sharedAddr), bufferInfo->omxBuffer->filledLen);
577 }
578 bufferInfo->omxBuffer->offset = 0;
579 if (endFlag) {
580 bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS;
581 }
582
583 return true;
584 }
585
CreateBufferHandle()586 int32_t CodecHdiEncode::CreateBufferHandle()
587 {
588 if (gralloc_ == nullptr) {
589 HDF_LOGE("%{public}s gralloc_ is null", __func__);
590 return HDF_ERR_INVALID_PARAM;
591 }
592
593 AllocInfo alloc = {.width = this->stride_,
594 .height = this->height_,
595 .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
596 .format = PIXEL_FMT_YCBCR_420_SP};
597
598 int32_t err = HDF_SUCCESS;
599 for (uint32_t i = 0; i < BUFFER_COUNT; i++) {
600 BufferHandle *bufferHandle = nullptr;
601 err = gralloc_->AllocMem(alloc, bufferHandle);
602 if (err != HDF_SUCCESS) {
603 HDF_LOGE("%{public}s AllocMem fail", __func__);
604 return err;
605 }
606 bufferHandles_.emplace(std::make_pair(i, bufferHandle));
607 freeBufferHandles_.push_back(i);
608 }
609 return err;
610 }
611
EventHandler(OHOS::HDI::Codec::V1_0::CodecEventType event,const OHOS::HDI::Codec::V1_0::EventInfo & info)612 int32_t CodecHdiEncode::EventHandler(OHOS::HDI::Codec::V1_0::CodecEventType event,
613 const OHOS::HDI::Codec::V1_0::EventInfo &info)
614 {
615 if (event == CODEC_EVENT_CMD_COMPLETE) {
616 CodecCommandType cmd = (CodecCommandType)info.data1;
617 if (CODEC_COMMAND_STATE_SET == cmd) {
618 HDF_LOGI("CODEC_COMMAND_STATE_SET reached, status is %{public}d", info.data2);
619 this->OnStatusChanged();
620 }
621 }
622
623 return HDF_SUCCESS;
624 }
625
OnEmptyBufferDone(const struct OmxCodecBuffer & buffer)626 int32_t CodecHdiEncode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer)
627 {
628 HDF_LOGI("OnEmptyBufferDone, bufferId [%{public}d]", buffer.bufferId);
629 unique_lock<mutex> ulk(lockInputBuffers_);
630 unUsedInBuffers_.push_back(buffer.bufferId);
631 if (useBufferHandle_) {
632 auto bufferInfo = omxBuffers_[buffer.bufferId];
633 freeBufferHandles_.push_back(bufferInfo->bufferHandleId);
634 }
635
636 return HDF_SUCCESS;
637 }
638
OnFillBufferDone(const struct OmxCodecBuffer & buffer)639 int32_t CodecHdiEncode::OnFillBufferDone(const struct OmxCodecBuffer &buffer)
640 {
641 HDF_LOGI("OnFillBufferDone, bufferId [%{public}d]", buffer.bufferId);
642 if (exit_) {
643 return HDF_SUCCESS;
644 }
645
646 auto iter = omxBuffers_.find(buffer.bufferId);
647 if (iter == omxBuffers_.end() || !iter->second) {
648 return HDF_SUCCESS;
649 }
650
651 auto bufferInfo = iter->second;
652 const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset);
653 // save to file
654 (void)fwrite(addr, 1, buffer.filledLen, fpOut_);
655 (void)fflush(fpOut_);
656
657 if (buffer.flag & OMX_BUFFERFLAG_EOS) {
658 exit_ = true;
659 HDF_LOGI("OnFillBufferDone the END coming");
660 return HDF_SUCCESS;
661 }
662 auto err = client_->FillThisBuffer(*bufferInfo->omxBuffer.get());
663 if (err != HDF_SUCCESS) {
664 HDF_LOGE("FillThisBuffer error");
665 return HDF_SUCCESS;
666 }
667 return HDF_SUCCESS;
668 }
669
ConfigPortDefine()670 int32_t CodecHdiEncode::ConfigPortDefine()
671 {
672 OMX_PARAM_PORTDEFINITIONTYPE param;
673 if (util_->InitParam(param) != HDF_SUCCESS) {
674 return HDF_FAILURE;
675 }
676 param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT);
677 std::vector<int8_t> inVec, outVec;
678 util_->ObjectToVector(param, inVec);
679 auto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
680 if (err != HDF_SUCCESS) {
681 HDF_LOGE("%{public}s failed to GetParameter with PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition",
682 __func__);
683 return err;
684 }
685 util_->VectorToObject(outVec, param);
686
687 HDF_LOGI("PORT_INDEX_INPUT: eCompressionFormat = %{public}d, eColorFormat=%{public}d",
688 param.format.video.eCompressionFormat, param.format.video.eColorFormat);
689 util_->setParmValue(param, width_, height_, stride_);
690 param.format.video.eColorFormat = AV_COLOR_FORMAT;
691 util_->ObjectToVector(param, inVec);
692 err = client_->SetParameter(OMX_IndexParamPortDefinition, inVec);
693 if (err != HDF_SUCCESS) {
694 HDF_LOGE("%{public}s failed to SetParameter with INPUT, OMX_IndexParamPortDefinition", __func__);
695 return err;
696 }
697
698 if (util_->InitParam(param) != HDF_SUCCESS) {
699 return HDF_FAILURE;
700 }
701 param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT);
702 util_->ObjectToVector(param, inVec);
703 err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
704 if (err != HDF_SUCCESS) {
705 HDF_LOGE("%{public}s failed to GetParameter with OUTPUT, OMX_IndexParamPortDefinition", __func__);
706 return err;
707 }
708 util_->VectorToObject(outVec, param);
709
710 HDF_LOGI("PORT_INDEX_OUTPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
711 param.format.video.eCompressionFormat, param.format.video.eColorFormat);
712 util_->setParmValue(param, width_, height_, stride_);
713 util_->ObjectToVector(param, inVec);
714 err = client_->SetParameter(OMX_IndexParamPortDefinition, inVec);
715 if (err != HDF_SUCCESS) {
716 HDF_LOGE("%{public}s failed to SetParameter with PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition",
717 __func__);
718 return err;
719 }
720 return HDF_SUCCESS;
721 }
722
ConfigBitMode()723 int32_t CodecHdiEncode::ConfigBitMode()
724 {
725 OMX_VIDEO_PARAM_PORTFORMATTYPE param;
726 if (util_->InitParam(param) != HDF_SUCCESS) {
727 return HDF_FAILURE;
728 }
729 param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT);
730 std::vector<int8_t> inVec, outVec;
731 util_->ObjectToVector(param, inVec);
732 auto err = client_->GetParameter(OMX_IndexParamVideoPortFormat, inVec, outVec);
733 if (err != HDF_SUCCESS) {
734 HDF_LOGE("failed to GetParameter with PORT_INDEX_OUTPUT, index is OMX_IndexParamVideoPortFormat");
735 return err;
736 }
737 util_->VectorToObject(outVec, param);
738
739 HDF_LOGI("set Format PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
740 param.eCompressionFormat, param.eColorFormat);
741 param.xFramerate = FRAME;
742 param.eCompressionFormat = OMX_VIDEO_CodingAVC;
743
744 util_->ObjectToVector(param, inVec);
745 err = client_->SetParameter(OMX_IndexParamVideoPortFormat, inVec);
746 if (err != HDF_SUCCESS) {
747 HDF_LOGE("%{public}s failed to SetParameter with PORT_INDEX_INPUT, index is OMX_IndexParamVideoPortFormat",
748 __func__);
749 return err;
750 }
751
752 OMX_VIDEO_PARAM_BITRATETYPE bitRate;
753 util_->InitParam(bitRate);
754 bitRate.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT);
755 util_->ObjectToVector(bitRate, inVec);
756 err = client_->GetParameter(OMX_IndexParamVideoBitrate, inVec, outVec);
757 if (err != OMX_ErrorNone) {
758 HDF_LOGE("%{public}s OMX_GetParameter portindex = PORT_INDEX_OUTPUT, err[%{public}d]", __func__, err);
759 return err;
760 }
761 util_->VectorToObject(outVec, bitRate);
762 HDF_LOGI("get PORT_INDEX_OUTPUT:OMX_IndexParamVideoBitrate, bit_mode[%{public}d], biterate:[%{publicd}d]",
763 bitRate.eControlRate, bitRate.nTargetBitrate);
764
765 bitRate.eControlRate = OMX_Video_ControlRateConstant;
766 bitRate.nTargetBitrate = BITRATE;
767 util_->ObjectToVector(bitRate, inVec);
768 err = client_->SetParameter(OMX_IndexParamVideoBitrate, inVec);
769 if (err != HDF_SUCCESS) {
770 HDF_LOGE("%{public}s failed to SetParameter with PORT_INDEX_OUTPUT, index is OMX_IndexParamVideoPortFormat",
771 __func__);
772 return err;
773 }
774 return HDF_SUCCESS;
775 }
776
main(int argc,char * argv[])777 int main(int argc, char *argv[])
778 {
779 CommandOpt opt;
780 CommandParse parse;
781 if (!parse.Parse(argc, argv, opt)) {
782 return 0;
783 }
784 auto core = std::make_shared<CodecHdiEncode>();
785 if (!core->Init(opt)) {
786 core = nullptr;
787 return HDF_FAILURE;
788 }
789
790 if (!core->Configure()) {
791 core = nullptr;
792 return HDF_FAILURE;
793 }
794
795 if (!core->UseBuffers()) {
796 core = nullptr;
797 return HDF_FAILURE;
798 }
799
800 core->Run();
801
802 core->FreeBuffers();
803
804 core->Release();
805 core = nullptr;
806 }