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