• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }