Files
drivers_peripheral/codec/test/demo/v2.0/src/codec_hdi_encode.cpp
T
qijinquan e4e65f820a feat: Add extend for HEVC and MPEG4
Signed-off-by: qijinquan <qijinquan@kaihong.com>
2022-10-21 10:37:52 +08:00

795 lines
27 KiB
C++

/*
* Copyright 2022 Shenzhen Kaihong DID Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "codec_hdi_encode.h"
#include <hdf_log.h>
#include <securec.h>
#include <unistd.h>
#include "codec_omx_ext.h"
using namespace std;
using namespace OHOS;
#define HDF_LOG_TAG codec_omx_hdi_enc
OHOS::HDI::Display::V1_0::IDisplayGralloc *CodecHdiEncode::gralloc_ = nullptr;
namespace {
constexpr int32_t FRAME = 30 << 16;
constexpr int32_t BUFFER_COUNT = 10;
constexpr int32_t BITRATE = 3000000;
constexpr int32_t FD_SIZE = sizeof(int);
constexpr const char *ENCODER_AVC = "OMX.rk.video_encoder.avc";
}
#define AV_COLOR_FORMAT (OMX_COLOR_FORMATTYPE)CODEC_COLOR_FORMAT_RGBA8888
static CodecHdiEncode *g_core = nullptr;
CodecHdiEncode::CodecHdiEncode() : fpIn_(nullptr), fpOut_(nullptr)
{
client_ = nullptr;
callback_ = nullptr;
omxMgr_ = nullptr;
exit_ = false;
useBufferHandle_ = false;
width_ = 0;
height_ = 0;
componentId_ = 0;
color_ = ColorFormat::YUV420SP;
omxColorFormat_ = OMX_COLOR_FormatYUV420SemiPlanar;
}
CodecHdiEncode::~CodecHdiEncode()
{
if (fpOut_ != nullptr) {
fclose(fpOut_);
fpOut_ = nullptr;
}
if (fpIn_ != nullptr) {
fclose(fpIn_);
fpIn_ = nullptr;
}
}
void CodecHdiEncode::WaitForStatusChanged()
{
unique_lock<mutex> autoLock(statusLock_);
statusCondition_.wait(autoLock);
}
void CodecHdiEncode::OnStatusChanged()
{
statusCondition_.notify_one();
}
bool CodecHdiEncode::ReadOneFrame(FILE *fp, char *buf, uint32_t &filledCount)
{
bool ret = false;
filledCount = fread(buf, 1, GetInputBufferSize(), fp);
if (feof(fp)) {
ret = true;
}
return ret;
}
bool CodecHdiEncode::Init(CommandOpt &opt)
{
this->width_ = opt.width;
this->height_ = opt.height;
this->stride_ = AlignUp(width_);
this->useBufferHandle_ = opt.useBuffer;
HDF_LOGI("width[%{public}d], height[%{public}d]", width_, height_);
// gralloc init
gralloc_ = OHOS::HDI::Display::V1_0::IDisplayGralloc::Get();
color_ = opt.colorForamt;
if (color_ == ColorFormat::RGBA8888) {
omxColorFormat_ = AV_COLOR_FORMAT;
} else if (color_ == ColorFormat::BGRA8888) {
omxColorFormat_ = OMX_COLOR_Format32bitBGRA8888;
}
fpIn_ = fopen(opt.fileInput.c_str(), "rb");
fpOut_ = fopen(opt.fileOutput.c_str(), "wb+");
if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) {
HDF_LOGE("%{public}s:failed to open file %{public}s or %{public}s", __func__, opt.fileInput.c_str(),
opt.fileOutput.c_str());
return false;
}
// Interface init
omxMgr_ = GetCodecComponentManager();
callback_ = CodecCallbackTypeStubGetInstance();
if ((omxMgr_ == nullptr) || (callback_ == nullptr)) {
HDF_LOGE("%{public}s:omxMgr_ or callback_ is null", __func__);
return false;
}
// set the callback
callback_->EventHandler = &CodecHdiEncode::OnEvent;
callback_->EmptyBufferDone = &CodecHdiEncode::OnEmptyBufferDone;
callback_->FillBufferDone = &CodecHdiEncode::OnFillBufferDone;
// create a component
auto err =
omxMgr_->CreateComponent(&client_, &componentId_, const_cast<char *>(ENCODER_AVC), (int64_t)this, callback_);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to CreateComponent", __func__);
return false;
}
// get version
struct CompVerInfo verInfo;
(void)memset_s(&verInfo, sizeof(verInfo), 0, sizeof(verInfo));
err = client_->GetComponentVersion(client_, &verInfo);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to CreateComponent", __func__);
return false;
}
return true;
}
bool CodecHdiEncode::Configure()
{
if (client_ == nullptr) {
return false;
}
// set input width, height and COLOR, set output port width and height
if (ConfigPortDefine() != HDF_SUCCESS) {
HDF_LOGE("%{public}s ConfigPortDefine error", __func__);
return false;
}
if (ConfigBitMode() != HDF_SUCCESS) {
HDF_LOGE("%{public}s ConfigBitMode error", __func__);
return false;
}
if (CheckAndUseBufferHandle() != HDF_SUCCESS) {
HDF_LOGE("%{public}s ConfigUseBufferHandle error", __func__);
return false;
}
return true;
}
int32_t CodecHdiEncode::CheckAndUseBufferHandle()
{
if (!useBufferHandle_) {
return HDF_SUCCESS;
}
SupportBufferType param;
InitParamInOhos(param);
param.portIndex = (uint32_t)PortIndex::PORT_INDEX_OUTPUT;
auto err = client_->GetParameter(client_, OMX_IndexParamSupportBufferType, (int8_t *)&param, sizeof(param));
HDF_LOGI(
"OMX_GetParameter:OMX_IndexParamSupportBufferType:PORT_INDEX_OUTPUT, err [%{public}x], bufferTypes[%{public}d]",
err, param.bufferTypes);
if (err != HDF_SUCCESS) {
return err;
}
InitParamInOhos(param);
param.portIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT;
err = client_->GetParameter(client_, OMX_IndexParamSupportBufferType, (int8_t *)&param, sizeof(param));
HDF_LOGI(
"OMX_GetParameter:OMX_IndexParamSupportBufferType:PORT_INDEX_INPUT, err [%{public}x], bufferTypes[%{public}d]",
err, param.bufferTypes);
if (err != HDF_SUCCESS) {
return err;
}
GetBufferHandleUsageParams usage;
InitParamInOhos(usage);
usage.portIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT;
err = client_->GetParameter(client_, OMX_IndexParamGetBufferHandleUsage, (int8_t *)&usage, sizeof(usage));
HDF_LOGI(
"OMX_GetParameter:OMX_IndexParamGetBufferHandleUsage:PORT_INDEX_INPUT, err [%{public}x], usage[%{public}d]",
err, usage.usage);
if (err != HDF_SUCCESS) {
return err;
}
UseBufferType type;
InitParamInOhos(type);
type.portIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT;
type.bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
err = client_->SetParameter(client_, OMX_IndexParamUseBufferType, (int8_t *)&type, sizeof(type));
HDF_LOGI("OMX_SetParameter:OMX_IndexParamUseBufferType:PORT_INDEX_INPUT, err [%{public}x]", err);
return err;
}
bool CodecHdiEncode::UseBuffers()
{
// command to IDLE
auto err = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SendCommand with OMX_CommandStateSet:OMX_StateIdle", __func__);
return false;
}
// use buffer on input port
err = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s UseBufferOnPort PORT_INDEX_INPUT error", __func__);
return false;
}
// use buffer on output port
err = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s UseBufferOnPort PORT_INDEX_OUTPUT error", __func__);
return false;
}
if (useBufferHandle_ && CreateBufferHandle() != HDF_SUCCESS) {
HDF_LOGE("%{public}s CreateBufferHandle error", __func__);
return false;
}
// wait executing state
OMX_STATETYPE status;
err = client_->GetState(client_, &status);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s GetState err [%{public}x]", __func__, err);
return false;
}
// wait loaded
if (status != OMX_StateIdle) {
HDF_LOGI("Wait for OMX_StateLoaded status");
this->WaitForStatusChanged();
} else {
HDF_LOGI(" status is %{public}d", status);
}
return true;
}
int32_t CodecHdiEncode::UseBufferOnPort(PortIndex portIndex)
{
HDF_LOGI("%{public}s enter, portIndex = %{public}d", __func__, portIndex);
int bufferSize = 0;
int bufferCount = 0;
bool portEnable = false;
OMX_PARAM_PORTDEFINITIONTYPE param;
InitParam(param);
param.nPortIndex = (uint32_t)portIndex;
auto err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]",
__func__, portIndex);
return err;
}
bufferSize = param.nBufferSize;
bufferCount = param.nBufferCountActual;
portEnable = param.bEnabled;
HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], buffer count [%{public}d], "
"portEnable[%{public}d], err [%{public}d]",
portIndex, bufferSize, bufferCount, portEnable, err);
{
OMX_PARAM_BUFFERSUPPLIERTYPE param;
InitParam(param);
param.nPortIndex = (uint32_t)portIndex;
err = client_->GetParameter(client_, OMX_IndexParamCompBufferSupplier, (int8_t *)&param, sizeof(param));
HDF_LOGI("param.eBufferSupplier[%{public}d] err [%{public}d]", param.eBufferSupplier, err);
}
if (portIndex == PortIndex::PORT_INDEX_INPUT) {
bufferSize = GetInputBufferSize();
} else if (bufferSize == 0) {
bufferSize = width_ * height_;
HDF_LOGI("bufferSize[%{public}d], width[%{public}d], height[%{public}d]", bufferSize, width_, height_);
}
if (useBufferHandle_ && portIndex == PortIndex::PORT_INDEX_INPUT) {
err = UseDynaBuffer(bufferCount, bufferSize);
} else {
err = UseBufferOnPort(portIndex, bufferCount, bufferSize);
}
if (err != HDF_SUCCESS) {
return err;
}
// if port is disable, changed to enable
if (!portEnable) {
err = client_->SendCommand(client_, OMX_CommandPortEnable, (uint32_t)portIndex, NULL, 0);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s SendCommand OMX_CommandPortEnable::PORT_INDEX_INPUT error", __func__);
return err;
}
}
return HDF_SUCCESS;
}
int32_t CodecHdiEncode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize)
{
if (bufferCount <= 0 || bufferSize <= 0) {
return HDF_ERR_INVALID_PARAM;
}
for (int i = 0; i < bufferCount; i++) {
auto omxBuffer = std::make_shared<OmxCodecBuffer>();
omxBuffer->size = sizeof(OmxCodecBuffer);
omxBuffer->version.s.nVersionMajor = 1;
omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
int fd = AshmemCreate(0, bufferSize);
shared_ptr<Ashmem> spSharedMem = make_shared<Ashmem>(fd, bufferSize);
omxBuffer->bufferLen = FD_SIZE;
omxBuffer->buffer = (uint8_t *)(unsigned long)fd;
omxBuffer->allocLen = bufferSize;
omxBuffer->fenceFd = -1;
omxBuffer->pts = 0;
omxBuffer->flag = 0;
if (portIndex == PortIndex::PORT_INDEX_INPUT) {
omxBuffer->type = READ_ONLY_TYPE;
spSharedMem->MapReadAndWriteAshmem();
} else {
omxBuffer->type = READ_WRITE_TYPE;
spSharedMem->MapReadOnlyAshmem();
}
auto err = client_->UseBuffer(client_, (uint32_t)portIndex, omxBuffer.get());
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to UseBuffer with portIndex[%{public}d]", __func__, portIndex);
spSharedMem->UnmapAshmem();
spSharedMem->CloseAshmem();
spSharedMem = nullptr;
return err;
}
omxBuffer->bufferLen = 0;
HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId);
auto bufferInfo = std::make_shared<BufferInfo>();
bufferInfo->omxBuffer = omxBuffer;
bufferInfo->avSharedPtr = spSharedMem;
bufferInfo->portIndex = portIndex;
omxBuffers_.insert(std::make_pair(omxBuffer->bufferId, bufferInfo));
if (portIndex == PortIndex::PORT_INDEX_INPUT) {
unUsedInBuffers_.push_back(omxBuffer->bufferId);
} else {
unUsedOutBuffers_.push_back(omxBuffer->bufferId);
}
}
return HDF_SUCCESS;
}
int32_t CodecHdiEncode::UseDynaBuffer(int bufferCount, int bufferSize)
{
if (bufferCount <= 0 || bufferSize <= 0) {
return HDF_ERR_INVALID_PARAM;
}
for (int i = 0; i < bufferCount; i++) {
auto omxBuffer = std::make_shared<OmxCodecBuffer>();
omxBuffer->size = sizeof(OmxCodecBuffer);
omxBuffer->version.s.nVersionMajor = 1;
omxBuffer->bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
omxBuffer->bufferLen = 0;
omxBuffer->buffer = nullptr;
omxBuffer->allocLen = bufferSize;
omxBuffer->fenceFd = -1;
omxBuffer->pts = 0;
omxBuffer->flag = 0;
auto err = client_->UseBuffer(client_, (uint32_t)PortIndex::PORT_INDEX_INPUT, omxBuffer.get());
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to UseBuffer with PORT_INDEX_INPUT", __func__);
return err;
}
omxBuffer->bufferLen = 0;
HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId);
auto bufferInfo = std::make_shared<BufferInfo>();
bufferInfo->omxBuffer = omxBuffer;
bufferInfo->portIndex = PortIndex::PORT_INDEX_INPUT;
omxBuffers_.insert(std::make_pair(omxBuffer->bufferId, bufferInfo));
unUsedInBuffers_.push_back(omxBuffer->bufferId);
}
return HDF_SUCCESS;
}
void CodecHdiEncode::FreeBuffers()
{
// send command to loaded state
(void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateLoaded, nullptr, 0);
// All the buffer must be released, otherwise the component will wait
auto iter = omxBuffers_.begin();
while (iter != omxBuffers_.end()) {
auto bufferInfo = iter->second;
(void)client_->FreeBuffer(client_, (uint32_t)bufferInfo->portIndex, bufferInfo->omxBuffer.get());
iter = omxBuffers_.erase(iter);
}
unUsedInBuffers_.clear();
unUsedOutBuffers_.clear();
OMX_STATETYPE status;
auto err = client_->GetState(client_, &status);
if (err != HDF_SUCCESS) {
HDF_LOGE("%s GetState error [%{public}x]", __func__, err);
return;
}
// wait
if (status != OMX_StateLoaded) {
HDF_LOGI("Wait for OMX_StateLoaded status");
this->WaitForStatusChanged();
} else {
HDF_LOGI(" status is %{public}d", status);
}
}
void CodecHdiEncode::Release()
{
omxMgr_->DestroyComponent(componentId_);
CodecComponentTypeRelease(client_);
client_ = nullptr;
CodecComponentManagerRelease();
}
bool CodecHdiEncode::FillAllTheBuffer()
{
for (auto bufferId : unUsedOutBuffers_) {
HDF_LOGI("fill bufferid [%{public}d]", bufferId);
auto iter = omxBuffers_.find(bufferId);
if (iter != omxBuffers_.end()) {
auto bufferInfo = iter->second;
auto err = client_->FillThisBuffer(client_, bufferInfo->omxBuffer.get());
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s FillThisBuffer error", __func__);
return false;
}
}
}
return true;
}
int CodecHdiEncode::GetFreeBufferId()
{
int bufferID = -1;
unique_lock<mutex> ulk(lockInputBuffers_);
size_t nSize = this->unUsedInBuffers_.size();
if (nSize > 0) {
bufferID = unUsedInBuffers_.front();
unUsedInBuffers_.pop_front();
}
return bufferID;
}
void CodecHdiEncode::Run()
{
auto err = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateExecuting, NULL, 0);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SendCommand with OMX_CommandStateSet:OMX_StateIdle", __func__);
return;
}
if (!FillAllTheBuffer()) {
HDF_LOGE("%{public}s FillAllTheBuffer error", __func__);
return;
}
bool endFlag = false;
while (!endFlag) {
int bufferID = GetFreeBufferId();
if (this->exit_) {
break;
}
if (bufferID < 0) {
usleep(10000); // 10000: sleep time 10ms
continue;
}
auto iter = omxBuffers_.find(bufferID);
if (iter == omxBuffers_.end()) {
continue;
}
auto bufferInfo = iter->second;
if (!FillCodecBuffer(bufferInfo, endFlag)) {
break;
}
err = client_->EmptyThisBuffer(client_, bufferInfo->omxBuffer.get());
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s EmptyThisBuffer error", __func__);
return;
}
}
while (!this->exit_) {
usleep(10000); // 10000: sleep time 10ms
continue;
}
(void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0);
return;
}
bool CodecHdiEncode::FillCodecBuffer(std::shared_ptr<BufferInfo> bufferInfo, bool &endFlag)
{
if (gralloc_ == nullptr) {
HDF_LOGE("%{public}s gralloc_ is null", __func__);
return false;
}
if (useBufferHandle_) {
int bufferHandleId = freeBufferHandles_.front();
if (bufferHandleId < 0 || bufferHandleId >= BUFFER_COUNT) {
HDF_LOGE("%{public}s bufferHandleId [%{public}d]", __func__, bufferHandleId);
return false;
}
freeBufferHandles_.pop_front();
bufferInfo->bufferHandleId = bufferHandleId;
BufferHandle *bufferHandle = bufferHandles_[bufferHandleId];
if (bufferHandle != nullptr) {
gralloc_->Mmap(*bufferHandle);
endFlag = this->ReadOneFrame(fpIn_, (char *)bufferHandle->virAddr, bufferInfo->omxBuffer->filledLen);
bufferInfo->omxBuffer->filledLen = bufferHandle->stride * bufferHandle->height;
gralloc_->Unmap(*bufferHandle);
bufferInfo->omxBuffer->buffer = (uint8_t *)bufferHandle;
bufferInfo->omxBuffer->bufferLen =
sizeof(BufferHandle) + sizeof(int32_t) * (bufferHandle->reserveFds + bufferHandle->reserveInts);
}
} else {
// read data from ashmem
void *sharedAddr = (void *)bufferInfo->avSharedPtr->ReadFromAshmem(0, 0);
endFlag = this->ReadOneFrame(fpIn_, (char *)sharedAddr, bufferInfo->omxBuffer->filledLen);
}
bufferInfo->omxBuffer->offset = 0;
if (endFlag) {
bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS;
}
return true;
}
int32_t CodecHdiEncode::CreateBufferHandle()
{
if (gralloc_ == nullptr) {
HDF_LOGE("%{public}s gralloc_ is null", __func__);
return HDF_ERR_INVALID_PARAM;
}
PixelFormat pixForamt = PIXEL_FMT_YCBCR_420_SP;
if (color_ == ColorFormat::RGBA8888) {
pixForamt = PIXEL_FMT_RGBA_8888;
} else if (color_ == ColorFormat::BGRA8888) {
pixForamt = PIXEL_FMT_BGRA_8888;
}
AllocInfo alloc = {.width = this->stride_,
.height = this->height_,
.usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA,
.format = pixForamt};
int32_t err = HDF_SUCCESS;
for (size_t i = 0; i < BUFFER_COUNT; i++) {
BufferHandle *bufferHandle = nullptr;
err = gralloc_->AllocMem(alloc, bufferHandle);
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s AllocMem fail", __func__);
return err;
}
bufferHandles_.emplace(std::make_pair(i, bufferHandle));
freeBufferHandles_.push_back(i);
}
return err;
}
int32_t CodecHdiEncode::OnEvent(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct EventInfo *info)
{
HDF_LOGI("OnEvent: pAppData[%{public} " PRId64 "], eEvent [%{public}d], nData1[%{public}d]", info->appData, event,
info->data1);
switch (event) {
case OMX_EventCmdComplete: {
OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE)info->data1;
if (OMX_CommandStateSet == cmd) {
HDF_LOGI("OMX_CommandStateSet reached");
g_core->OnStatusChanged();
}
break;
}
default:
break;
}
return HDF_SUCCESS;
}
int32_t CodecHdiEncode::OnEmptyBufferDone(struct CodecCallbackType *self, int64_t appData,
const struct OmxCodecBuffer *buffer)
{
HDF_LOGI("OnEmptyBufferDone: pBuffer.bufferID [%{public}d]", buffer->bufferId);
return g_core->OnEmptyBufferDone(*buffer);
}
int32_t CodecHdiEncode::OnFillBufferDone(struct CodecCallbackType *self, int64_t appData,
const struct OmxCodecBuffer *buffer)
{
HDF_LOGI("OnFillBufferDone: pBuffer.bufferID [%{public}d]", buffer->bufferId);
return g_core->OnFillBufferDone(*buffer);
}
uint32_t CodecHdiEncode::GetInputBufferSize()
{
if (color_ == ColorFormat::YUV420SP) {
return (width_ * height_ * 3 / 2); // 3:byte alignment, 2:byte alignment
} else {
return (width_ * height_ * 4); // 4: byte alignment for RGBA or BGRA
}
}
int32_t CodecHdiEncode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer)
{
unique_lock<mutex> ulk(lockInputBuffers_);
unUsedInBuffers_.push_back(buffer.bufferId);
if (useBufferHandle_) {
auto bufferInfo = omxBuffers_[buffer.bufferId];
freeBufferHandles_.push_back(bufferInfo->bufferHandleId);
}
return HDF_SUCCESS;
}
int32_t CodecHdiEncode::OnFillBufferDone(const struct OmxCodecBuffer &buffer)
{
if (exit_) {
return HDF_SUCCESS;
}
auto iter = omxBuffers_.find(buffer.bufferId);
if (iter == omxBuffers_.end() || !iter->second) {
return HDF_SUCCESS;
}
auto bufferInfo = iter->second;
const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset);
// save to file
(void)fwrite(addr, 1, buffer.filledLen, fpOut_);
(void)fflush(fpOut_);
if (buffer.flag == OMX_BUFFERFLAG_EOS) {
exit_ = true;
HDF_LOGI("OnFillBufferDone the END coming");
return HDF_SUCCESS;
}
auto err = client_->FillThisBuffer(client_, bufferInfo->omxBuffer.get());
if (err != HDF_SUCCESS) {
HDF_LOGE("FillThisBuffer error");
return HDF_SUCCESS;
}
return HDF_SUCCESS;
}
int32_t CodecHdiEncode::ConfigPortDefine()
{
OMX_PARAM_PORTDEFINITIONTYPE param;
InitParam(param);
param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT;
auto err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to GetParameter with PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition",
__func__);
return err;
}
HDF_LOGI("PORT_INDEX_INPUT: eCompressionFormat = %{public}d, eColorFormat=%{public}d",
param.format.video.eCompressionFormat, param.format.video.eColorFormat);
param.format.video.nFrameWidth = width_;
param.format.video.nFrameHeight = height_;
param.format.video.nStride = stride_;
param.format.video.nSliceHeight = height_;
param.format.video.eColorFormat = omxColorFormat_;
err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SetParameter with PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition",
__func__);
return err;
}
InitParam(param);
param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_OUTPUT;
err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to GetParameter with PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition",
__func__);
return err;
}
HDF_LOGI("PORT_INDEX_OUTPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
param.format.video.eCompressionFormat, param.format.video.eColorFormat);
param.format.video.nFrameWidth = width_;
param.format.video.nFrameHeight = height_;
param.format.video.nStride = stride_;
param.format.video.nSliceHeight = height_;
err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SetParameter with PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition",
__func__);
return err;
}
return HDF_SUCCESS;
}
int32_t CodecHdiEncode::ConfigBitMode()
{
OMX_VIDEO_PARAM_PORTFORMATTYPE param;
InitParam(param);
param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_OUTPUT;
auto err = client_->GetParameter(client_, OMX_IndexParamVideoPortFormat, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) {
HDF_LOGE("failed to GetParameter with PORT_INDEX_OUTPUT, index is OMX_IndexParamVideoPortFormat");
return err;
}
HDF_LOGI("set Format PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
param.eCompressionFormat, param.eColorFormat);
param.xFramerate = FRAME;
param.eCompressionFormat = OMX_VIDEO_CodingAVC;
err = client_->SetParameter(client_, OMX_IndexParamVideoPortFormat, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SetParameter with PORT_INDEX_INPUT, index is OMX_IndexParamVideoPortFormat",
__func__);
return err;
}
OMX_VIDEO_PARAM_BITRATETYPE biteType;
InitParam(biteType);
biteType.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_OUTPUT;
err = client_->GetParameter(client_, OMX_IndexParamVideoBitrate, (int8_t *)&biteType, sizeof(biteType));
if (err != OMX_ErrorNone) {
HDF_LOGE("%{public}s OMX_GetParameter portindex = PORT_INDEX_OUTPUT, err[%{public}d]", __func__, err);
return err;
}
HDF_LOGI("get PORT_INDEX_OUTPUT:OMX_IndexParamVideoBitrate, bit_mode[%{public}d], biterate:[%{publicd}d]",
biteType.eControlRate, biteType.nTargetBitrate);
biteType.eControlRate = OMX_Video_ControlRateConstant;
biteType.nTargetBitrate = BITRATE;
err = client_->SetParameter(client_, OMX_IndexParamVideoBitrate, (int8_t *)&biteType, sizeof(biteType));
if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SetParameter with PORT_INDEX_OUTPUT, index is OMX_IndexParamVideoPortFormat",
__func__);
return err;
}
return HDF_SUCCESS;
}
int main(int argc, char *argv[])
{
CommandOpt opt;
CommandParse parse;
if (!parse.Parse(argc, argv, opt)) {
return 0;
}
if (g_core == nullptr) {
g_core = new CodecHdiEncode();
}
if (!g_core->Init(opt)) {
delete g_core;
g_core = nullptr;
return HDF_FAILURE;
}
if (!g_core->Configure()) {
delete g_core;
g_core = nullptr;
return HDF_FAILURE;
}
if (!g_core->UseBuffers()) {
delete g_core;
g_core = nullptr;
return HDF_FAILURE;
}
g_core->Run();
g_core->FreeBuffers();
g_core->Release();
delete g_core;
g_core = nullptr;
}