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