• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *>(&param), 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(&param, 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 *>(&param), 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(&param, 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 *>(&param), 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(&param, 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 *>(&param),
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(&param, 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 *>(&param),
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 *>(&param),
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 *>(&param),
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 *>(&param),
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 *>(&param),
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