未验证 提交 30367824 编写于 作者: O openharmony_ci 提交者: Gitee

!19122 Codec指导文档整改

Merge pull request !19122 from 王勃懿/master
...@@ -54,33 +54,33 @@ Codec模块主要完成对视频数据的硬件编解码,将H264等裸流数 ...@@ -54,33 +54,33 @@ Codec模块主要完成对视频数据的硬件编解码,将H264等裸流数
### 接口说明 ### 接口说明
- codec_component_manager.h - icodec_component_manager.h
| 接口名称 | 功能描述 | | 接口名称 | 功能描述 |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------| | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------|
| int32_t (*CreateComponent)(struct CodecComponentType **component, uint32_t *componentId, char *compName, int64_t appData, struct CodecCallbackType *callbacks) | 创建Codec组件实例 | | int32_t CreateComponent(sptr<ICodecComponent>& component, uint32_t& componentId,<br />const std::string& compName, int64_t appData, const sptr<ICodecCallback>& callbacks) | 创建Codec组件实例 |
| int32_t (*DestroyComponent)(uint32_t componentId) | 销毁Codec组件实例 | | int32_t DestoryComponent(uint32_t componentId) | 销毁Codec组件实例 |
- codec_component _if.h - icodec_component.h
| 接口名称 | 功能描述 | | 接口名称 | 功能描述 |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | | ------------------------------------------------------------ | ---------------------- |
| int32_t (*SendCommand)(struct CodecComponentType *self, enum OMX_COMMANDTYPE cmd, uint32_t param, int8_t *cmdData, uint32_t cmdDataLen) | 发送命令给组件 | | int32_t SendCommand(CodecCommandType cmd, uint32_t param, const std::vector<int8_t>& cmdData) | 发送命令给组件 |
| int32_t (*GetParameter)(struct CodecComponentType *self, uint32_t paramIndex, int8_t *paramStruct, uint32_t paramStructLen) | 获取组件参数设置 | | int32_t GetParameter(uint32_t index, const std::vector<int8_t>& inParamStruct, std::vector<int8_t>& outParamStruct) | 获取组件参数设置 |
| int32_t (*SetParameter)(struct CodecComponentType *self, uint32_t index, int8_t *paramStruct, uint32_t paramStructLen) | 设置组件需要的参数 | | int32_t SetParameter(uint32_t index, const std::vector<int8_t>& paramStruct) | 设置组件需要的参数 |
| int32_t (*GetState)(struct CodecComponentType *self, enum OMX_STATETYPE *state) | 获取组件的状态 | | int32_t GetState(CodecStateType& state) | 获取组件的状态 |
| int32_t (*UseBuffer)(struct CodecComponentType *self, uint32_t portIndex, struct OmxCodecBuffer *buffer) | 指定组件端口的buffer | | int32_t UseBuffer(uint32_t portIndex, const OmxCodecBuffer& inBuffer, OmxCodecBuffer& outBuffer) | 指定组件端口的buffer |
| int32_t (*FreeBuffer)(struct CodecComponentType *self, uint32_t portIndex, const struct OmxCodecBuffer *buffer) | 释放buffer | | int32_t FreeBuffer(uint32_t portIndex, const OmxCodecBuffer& buffer) | 释放buffer |
| int32_t (*EmptyThisBuffer)(struct CodecComponentType *self, const struct OmxCodecBuffer *buffer) | 编解码输入待处理buffer | | int32_t EmptyThisBuffer(const OmxCodecBuffer& buffer) | 编解码输入待处理buffer |
| int32_t (*FillThisBuffer)(struct CodecComponentType *self, const struct OmxCodecBuffer *buffer) | 编解码输出填充buffer | | int32_t FillThisBuffer(const OmxCodecBuffer& buffer) | 编解码输出填充buffer |
- codec_callback_if.h - icodec_callback.h
| 接口名称 | 功能描述 | | 接口名称 | 功能描述 |
| ---------------------------------------------------------------------------------------------------------------- |----------------------------------- | | ------------------------------------------------------------ | ---------------------------------- |
| int32_t (*EventHandler)(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct EventInfo *info) | 事件上报 | | int32_t EventHandler(CodecEventType event, const EventInfo& info) | 事件上报 |
| int32_t (*EmptyBufferDone)(struct CodecCallbackType *self, int64_t appData, const struct OmxCodecBuffer *buffer) | 上报输入buffer编码或者解码处理完毕 | | int32_t EmptyBufferDone(int64_t appData, const OmxCodecBuffer& buffer) | 上报输入buffer编码或者解码处理完毕 |
| int32_t (*FillBufferDone)(struct CodecCallbackType *self, int64_t appData, const struct OmxCodecBuffer *buffer) | 上报输出buffer填充完毕 | | int32_t FillBufferDone(int64_t appData, const OmxCodecBuffer& buffer) | 上报输出buffer填充完毕 |
更多接口请参考[Codec驱动仓](https://gitee.com/openharmony/drivers_peripheral/tree/master/codec) 更多接口请参考[Codec驱动仓](https://gitee.com/openharmony/drivers_peripheral/tree/master/codec)
...@@ -88,63 +88,63 @@ Codec模块主要完成对视频数据的硬件编解码,将H264等裸流数 ...@@ -88,63 +88,63 @@ Codec模块主要完成对视频数据的硬件编解码,将H264等裸流数
Codec HDI驱动的开发过程主要包含以下步骤: Codec HDI驱动的开发过程主要包含以下步骤:
#### Driver的注册及初始化 #### Driver的注册及初始化
定义Codec HDI的HdfDriverEntry结构体,该结构体中定义了Driver初始化的方法,填充g_codecComponentDriverEntry结构体,实现Bind、Init、Release函数指针。 定义Codec HDI的HdfDriverEntry结构体,该结构体中定义了Driver初始化的方法,填充g_codeccomponentmanagerDriverEntry结构体,实现Bind、Init、Release函数指针。
```c ```c
struct HdfDriverEntry g_codecComponentDriverEntry = { static struct HdfDriverEntry g_codeccomponentmanagerDriverEntry = {
.moduleVersion = 1, .moduleVersion = 1,
.moduleName = "codec_hdi_omx_server", .moduleName = "codec_component_manager_service",
.Bind = HdfCodecComponentTypeDriverBind, .Bind = HdfCodecComponentManagerDriverBind,
.Init = HdfCodecComponentTypeDriverInit, .Init = HdfCodecComponentManagerDriverInit,
.Release = HdfCodecComponentTypeDriverRelease, .Release = HdfCodecComponentManagerDriverRelease,
}; }; // 将Codec HDI的HdfDriverEntry结构体注册到HDF上
HDF_INIT(g_codecComponentDriverEntry); // 将Codec HDI的HdfDriverEntry结构体注册到HDF上
``` ```
- HdfCodecComponentTypeDriverBind:将HDF中device绑定到CodecComponentTypeHost,将codec service注册到HDF框架。 - HdfCodecComponentManagerDriverBind:将HDF中device绑定到HdfCodecComponentManagerHost,将codec service注册到HDF框架。
```c ```c
int32_t HdfCodecComponentTypeDriverBind(struct HdfDeviceObject *deviceObject) static int HdfCodecComponentManagerDriverBind(struct HdfDeviceObject *deviceObject)
{ {
HDF_LOGI("HdfCodecComponentTypeDriverBind enter."); CODEC_LOGI("HdfCodecComponentManagerDriverBind enter");
struct HdfCodecComponentTypeHost *omxcomponenttypeHost =
(struct HdfCodecComponentTypeHost *)OsalMemAlloc(sizeof(struct HdfCodecComponentTypeHost)); auto *hdfCodecComponentManagerHost = new (std::nothrow) HdfCodecComponentManagerHost;
if (omxcomponenttypeHost == NULL) { if (hdfCodecComponentManagerHost == nullptr) {
HDF_LOGE("HdfCodecComponentTypeDriverBind OsalMemAlloc HdfCodecComponentTypeHost failed!"); CODEC_LOGE("failed to create create HdfCodecComponentManagerHost object");
return HDF_FAILURE; return HDF_FAILURE;
} }
int ret = HdfDeviceObjectSetInterfaceDesc(deviceObject, COMPONENT_MANAGER_SERVICE_DESC);
if (ret != HDF_SUCCESS) { hdfCodecComponentManagerHost->ioService.Dispatch = CodecComponentManagerDriverDispatch;
HDF_LOGE("Failed to set interface desc"); hdfCodecComponentManagerHost->ioService.Open = NULL;
return ret; hdfCodecComponentManagerHost->ioService.Release = NULL;
auto serviceImpl = ICodecComponentManager::Get(true);
if (serviceImpl == nullptr) {
CODEC_LOGE("failed to get of implement service");
delete hdfCodecComponentManagerHost;
return HDF_FAILURE;
} }
omxcomponenttypeHost->ioservice.Dispatch = CodecComponentTypeDriverDispatch; hdfCodecComponentManagerHost->stub =
omxcomponenttypeHost->ioservice.Open = NULL; OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, ICodecComponentManager::GetDescriptor());
omxcomponenttypeHost->ioservice.Release = NULL; if (hdfCodecComponentManagerHost->stub == nullptr) {
omxcomponenttypeHost->service = CodecComponentManagerSerivceGet(); CODEC_LOGE("failed to get stub object");
if (omxcomponenttypeHost->service == NULL) { delete hdfCodecComponentManagerHost;
OsalMemFree(omxcomponenttypeHost);
return HDF_FAILURE; return HDF_FAILURE;
} }
deviceObject->service = &omxcomponenttypeHost->ioservice; deviceObject->service = &hdfCodecComponentManagerHost->ioService;
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
- HdfCodecComponentTypeDriverInit:加载HCS(HDF Configuration Source)中的属性配置。 - HdfCodecComponentManagerDriverInit:加载HCS(HDF Configuration Source)中的属性配置。
```c ```c
int32_t HdfCodecComponentTypeDriverInit(struct HdfDeviceObject *deviceObject) static int HdfCodecComponentManagerDriverInit(struct HdfDeviceObject *deviceObject)
{ {
HDF_LOGI("HdfCodecComponentTypeDriverInit enter."); CODEC_LOGI("HdfCodecComponentManagerDriverInit enter");
if (deviceObject == NULL) { if (DevHostRegisterDumpHost(CodecDfxService::DevCodecHostDump) != HDF_SUCCESS) {
return HDF_FAILURE; CODEC_LOGE("DevHostRegisterDumpHost error!");
}
InitDataNode(deviceObject->property);
if (LoadCapabilityData() != HDF_SUCCESS) {
ClearCapabilityData();
} }
return HDF_SUCCESS; return HDF_SUCCESS;
} }
...@@ -153,14 +153,17 @@ HDF_INIT(g_codecComponentDriverEntry); // 将Codec HDI的HdfDriverEntry结构体 ...@@ -153,14 +153,17 @@ HDF_INIT(g_codecComponentDriverEntry); // 将Codec HDI的HdfDriverEntry结构体
- HdfCodecComponentTypeDriverRelease:释放驱动实例。 - HdfCodecComponentTypeDriverRelease:释放驱动实例。
```c ```c
void HdfCodecComponentTypeDriverRelease(struct HdfDeviceObject *deviceObject) static void HdfCodecComponentManagerDriverRelease(struct HdfDeviceObject *deviceObject)
{ {
HDF_LOGI("HdfCodecComponentTypeDriverRelease enter."); CODEC_LOGI("HdfCodecComponentManagerDriverRelease enter");
struct HdfCodecComponentTypeHost *omxcomponenttypeHost = if (deviceObject->service == nullptr) {
CONTAINER_OF(deviceObject->service, struct HdfCodecComponentTypeHost, ioservice); CODEC_LOGE("HdfCodecComponentManagerDriverRelease not initted");
OmxComponentManagerSeriveRelease(omxcomponenttypeHost->service); return;
OsalMemFree(omxcomponenttypeHost); }
ClearCapabilityData();
auto *hdfCodecComponentManagerHost =
CONTAINER_OF(deviceObject->service, struct HdfCodecComponentManagerHost, ioService);
delete hdfCodecComponentManagerHost;
} }
``` ```
...@@ -177,19 +180,19 @@ vendor/hihope/rk3568/hdf_config/uhdf/ ...@@ -177,19 +180,19 @@ vendor/hihope/rk3568/hdf_config/uhdf/
1. device相关配置 1. device相关配置
在device_info.hcs的codec_host中增加codec_omx_service配置,具体配置如下: 在device_info.hcs的codec_host中增加codec_component_manager_service配置,具体配置如下:
```c ```c
codec :: host { codec :: host {
hostName = "codec_host"; hostName = "codec_host";
priority = 50; priority = 50;
gid = ["codec_host", "uhdf_driver", "vendor_mpp_driver"]; gid = ["codec_host", "uhdf_driver", "vendor_mpp_driver"];
codec_omx_device :: device { codec_omx_idl_device :: device {
device0 :: deviceNode { device0 :: deviceNode {
policy = 2; // 自动加载,非延迟加载 policy = 2; // 自动加载,非延迟加载
priority = 100; // 优先级 priority = 100; // 优先级
moduleName = "libcodec_hdi_omx_server.z.so"; // 驱动的动态库 moduleName = "libcodec_driver.z.so"; // 驱动的动态库
serviceName = "codec_hdi_omx_service"; // 配置驱动的服务名 serviceName = "codec_component_manager_service"; // 配置驱动的服务名
deviceMatchAttr = "codec_component_capabilities"; // 属性配置 deviceMatchAttr = "media_codec_capabilities"; // 属性配置
} }
} }
} }
...@@ -197,7 +200,7 @@ vendor/hihope/rk3568/hdf_config/uhdf/ ...@@ -197,7 +200,7 @@ vendor/hihope/rk3568/hdf_config/uhdf/
2. 支持的组件相关配置 2. 支持的组件相关配置
在media_codec\codec_component_capabilities.hcs中增加组件配置,具体配置如下: 在media_codec\media_codec_capabilities.hcs中增加组件配置,具体配置如下:
```c ```c
/* node name explanation -- HDF_video_hw_enc_avc_rk: /* node name explanation -- HDF_video_hw_enc_avc_rk:
** **
...@@ -228,7 +231,7 @@ vendor/hihope/rk3568/hdf_config/uhdf/ ...@@ -228,7 +231,7 @@ vendor/hihope/rk3568/hdf_config/uhdf/
maxBlocksPerSecond = 0xFFFFFFFF; maxBlocksPerSecond = 0xFFFFFFFF;
blockSizeWidth = 0xFFFFFFFF; blockSizeWidth = 0xFFFFFFFF;
blockSizeHeight = 0xFFFFFFFF; blockSizeHeight = 0xFFFFFFFF;
supportPixelFmts = [28, 24, 30, 22, 7, 3, 14, 13, 20, 26, 27, 12]; // 支持的颜色列表,Display支持的颜色列表 supportPixelFmts = [28, 24, 20, 12]; // 支持的颜色列表,Display支持的颜色列表
measuredFrameRate = [320, 240, 165, 165, 720, 480, 149, 149, 1280, 720, 73, 73, 1920, 1080, 18, 18]; measuredFrameRate = [320, 240, 165, 165, 720, 480, 149, 149, 1280, 720, 73, 73, 1920, 1080, 18, 18];
bitRateMode = [1, 2]; // 比特率模式,BitRateMode bitRateMode = [1, 2]; // 比特率模式,BitRateMode
minFrameRate = 0; // 帧率配置 minFrameRate = 0; // 帧率配置
...@@ -247,34 +250,29 @@ vendor/hihope/rk3568/hdf_config/uhdf/ ...@@ -247,34 +250,29 @@ vendor/hihope/rk3568/hdf_config/uhdf/
1. 初始化,包括接口实例、回调的初始化和对应的组件的初始化; 1. 初始化,包括接口实例、回调的初始化和对应的组件的初始化;
2. 设置编解码参数和配置信息,如视频宽、高和码率等; 2. 设置编解码参数和配置信息,如视频宽、高和码率等;
3. 输入输出Buffer申请; 3. 输入输出Buffer申请;
4. 编解码Buffer流转,使组件进入OMX_Executing状态,并处理相应的回调; 4. 编解码Buffer流转,使组件进入CODEC_STATE_EXECUTING状态,并处理相应的回调;
5. 接口去初始化,销毁buffer,关闭组件并释放所有的接口对象; 5. 接口去初始化,销毁buffer,关闭组件并释放所有的接口对象;
#### 初始化 #### 初始化
初始化过程包括接口的初始化,回调的初始化以及组件的创建。 初始化过程包括接口的初始化,回调的初始化以及组件的创建。
```cpp ```cpp
// 初始化Codec HDI ComponentManager实例 // 初始化Codec HDI ComponentManager实例
omxMgr_ = GetCodecComponentManager(); omxMgr_ = ICodecComponentManager::Get(false);
if ((omxMgr_ == nullptr)) {
HDF_LOGE("%{public}s omxMgr_ is null", __func__);
return false;
}
// 初始化回调 // 初始化回调
callback_ = CodecCallbackTypeStubGetInstance(); callback_ = new CodecHdiCallback(shared_from_this());
if (!omxMgr_ || !callback_) { if ((callback_ == nullptr)) {
FUNC_EXIT_ERR(); HDF_LOGE("%{public}s callback_ is null", __func__);
return false; return false;
} }
// 设置回调函数指针
callback_->EventHandler = &OMXCore::OnEvent;
callback_->EmptyBufferDone = &OMXCore::OnEmptyBufferDone;
callback_->FillBufferDone = &OMXCore::OnFillBufferDone;
// 新建组件实例 // 新建组件实例
uint32_t err = HDF_SUCCESS; err = omxMgr_->CreateComponent(client_, componentId_, compName, reinterpret_cast<int64_t>(this), callback_);
if (codec == codecMime::AVC) { if (err != HDF_SUCCESS) {
err = omxMgr_->CreateComponent(&client_, &componentId_, const_cast<char *>(DECODER_AVC), (int64_t)this, HDF_LOGE("%{public}s failed to CreateComponent", __func__);
callback_); return false;
} else {
err = omxMgr_->CreateComponent(&client_, &componentId_, const_cast<char *>(DECODER_HEVC), (int64_t)this,
callback_);
} }
``` ```
...@@ -283,64 +281,79 @@ Codec HDI编解码参数配置,包括输入输出数据的宽和高,输入 ...@@ -283,64 +281,79 @@ Codec HDI编解码参数配置,包括输入输出数据的宽和高,输入
```cpp ```cpp
// 设置输入端口图片的宽高 // 设置输入端口图片的宽高
OMX_PARAM_PORTDEFINITIONTYPE param; OMX_PARAM_PORTDEFINITIONTYPE param;
InitParam(param); if (util_->InitParam(param) != HDF_SUCCESS) {
param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT; return HDF_FAILURE;
auto err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param)); }
param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_INPUT);
std::vector<int8_t> inVec, outVec;
util_->ObjectToVector(param, inVec);
auto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); HDF_LOGE("%{public}s failed PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__);
return false; return err;
} }
util_->VectorToObject(outVec, param);
HDF_LOGI("PortIndex::PORT_INDEX_INPUT: eCompressionFormat = %{public}d, eColorFormat = %{public}d ", HDF_LOGI("PortIndex::PORT_INDEX_INPUT: eCompressionFormat = %{public}d, eColorFormat = %{public}d ",
param.format.video.eCompressionFormat, param.format.video.eColorFormat); param.format.video.eCompressionFormat, param.format.video.eColorFormat);
param.format.video.nFrameWidth = width_; util_->setParmValue(param, width_, height_, stride_);
param.format.video.nFrameHeight = height_; util_->ObjectToVector(param, inVec);
param.format.video.nStride = width_; err = client_->SetParameter(OMX_IndexParamPortDefinition, inVec);
param.format.video.nSliceHeight = height_;
err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param));
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__);
return false; return err;
} }
// 输出宽、高和格式设置 // 输出宽、高和格式设置
InitParam(param); if (util_->InitParam(param) != HDF_SUCCESS) {
param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_OUTPUT; return HDF_FAILURE;
err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param)); }
param.nPortIndex = static_cast<uint32_t>(PortIndex::PORT_INDEX_OUTPUT);
util_->ObjectToVector(param, inVec);
err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", __func__); HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition",
return false; __func__);
return err;
} }
util_->VectorToObject(outVec, param);
HDF_LOGI("PortIndex::PORT_INDEX_OUTPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", HDF_LOGI("PortIndex::PORT_INDEX_OUTPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
param.format.video.eCompressionFormat, param.format.video.eColorFormat); param.format.video.eCompressionFormat, param.format.video.eColorFormat);
param.format.video.nFrameWidth = width_; util_->setParmValue(param, width_, height_, stride_);
param.format.video.nFrameHeight = height_;
param.format.video.nStride = width_;
param.format.video.nSliceHeight = height_;
param.format.video.eColorFormat = AV_COLOR_FORMAT; // 输出数据格式设置为YUV420SP param.format.video.eColorFormat = AV_COLOR_FORMAT; // 输出数据格式设置为YUV420SP
err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param)); err = client_->SetParameter(OMX_IndexParamPortDefinition, inVec);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition",
__func__); __func__);
return false; return err;
} }
// 设置输入数据为H264/H265格式数据 // 设置输入数据为H264/H265格式数据
OMX_VIDEO_PARAM_PORTFORMATTYPE param; OMX_VIDEO_PARAM_PORTFORMATTYPE param;
InitParam(param); if (util_->InitParam(param) != HDF_SUCCESS) {
return false;
}
param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT; param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT;
auto err = client_->GetParameter(client_, OMX_IndexParamVideoPortFormat, (int8_t *)&param, sizeof(param)); std::vector<int8_t> inVec, outVec;
util_->ObjectToVector(param, inVec);
auto err = client_->GetParameter(OMX_IndexParamVideoPortFormat, inVec, outVec);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__);
return false; return false;
} }
util_->VectorToObject(outVec, param);
HDF_LOGI("set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", HDF_LOGI("set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d",
param.eCompressionFormat, param.eColorFormat); param.eCompressionFormat, param.eColorFormat);
param.xFramerate = FRAME; // 30帧 param.xFramerate = FRAME // 30帧
if (codecMime_ == codecMime::AVC) { if (codecMime_ == codecMime::AVC) {
param.eCompressionFormat = OMX_VIDEO_CodingAVC; // H264 param.eCompressionFormat = OMX_VIDEO_CodingAVC; // H264
} else { } else {
param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingHEVC; // H265 param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)CODEC_OMX_VIDEO_CodingHEVC; // H265
} }
err = client_->SetParameter(client_, OMX_IndexParamVideoPortFormat, (int8_t *)&param, sizeof(param)); util_->ObjectToVector(param, inVec);
err = client_->SetParameter(OMX_IndexParamVideoPortFormat, inVec);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__);
return false; return false;
...@@ -352,90 +365,97 @@ if (err != HDF_SUCCESS) { ...@@ -352,90 +365,97 @@ if (err != HDF_SUCCESS) {
1. 用户通过UseBuffer申请输入输出Buffer,并保存bufferId,后续buffer轮转可以直接通过bufferId来操作。 1. 用户通过UseBuffer申请输入输出Buffer,并保存bufferId,后续buffer轮转可以直接通过bufferId来操作。
2. 用户需要判断对应的端口是否是使能状态,如果不是,需要先将对应的端口设置为使能状态。 2. 用户需要判断对应的端口是否是使能状态,如果不是,需要先将对应的端口设置为使能状态。
3. 用户通过SendCommand将组件的状态为修改为OMX_StateIdle,需要等待其结果通知。 3. 用户通过SendCommand将组件的状态为修改为CODEC_STATE_IDLE,需要等待其结果通知。
```cpp ```cpp
// 输入端口buffer申请 // 输入端口buffer申请
auto ret = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT); auto err = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT);
if (!ret) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_INPUT error", __func__); HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_INPUT error", __func__);
return false; return false;
} }
// 输出端口buffer申请 // 输出端口buffer申请
ret = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT); err = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT);
if (!ret) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT error", __func__); HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT error", __func__);
return false; return false;
} }
// 发送命令使组件进入OMX_StateIdle状态 // 发送命令使组件进入OMX_StateIdle状态
auto err = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); std::vector<int8_t> cmdData;
auto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, cmdData);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SendCommand with OMX_CommandStateSet:OMX_StateIdle", __func__); HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__);
return false; return false;
} }
HDF_LOGI("Wait for OMX_StateIdle status");
this->WaitForStatusChanged();
``` ```
UseBufferOnPort实现如下: UseBufferOnPort实现如下:
```cpp ```cpp
bool CodecHdiDecode::UseBufferOnPort(enum PortIndex portIndex) int32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex)
{ {
HDF_LOGI("%{public}s enter, portIndex = %{public}d", __func__, portIndex); HDF_LOGI("%{public}s enter, portIndex = %{public}d", __func__, portIndex);
int bufferSize = 0; int bufferSize = 0;
int bufferCount = 0; int bufferCount = 0;
bool bPortEnable = false; bool PortEnable = false;
// 获取端口buffer参数 // 获取端口buffer参数
OMX_PARAM_PORTDEFINITIONTYPE param; OMX_PARAM_PORTDEFINITIONTYPE param;
InitParam(param); if (util_->InitParam(param) != HDF_SUCCESS) {
param.nPortIndex = (OMX_U32)portIndex; return HDF_FAILURE;
auto err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)&param, sizeof(param)); }
param.nPortIndex = static_cast<OMX_U32>(portIndex);
std::vector<int8_t> inVec, outVec;
util_->ObjectToVector(param, inVec);
auto err = client_->GetParameter(OMX_IndexParamPortDefinition, inVec, outVec);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]", HDF_LOGE("%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]",
__func__, portIndex); __func__, portIndex);
return false; return err;
} }
util_->VectorToObject(outVec, param);
bufferSize = param.nBufferSize; bufferSize = param.nBufferSize;
bufferCount = param.nBufferCountActual; bufferCount = param.nBufferCountActual;
bPortEnable = param.bEnabled; portEnable = param.bEnabled;
HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], " HDF_LOGI("buffer index [%{public}d], buffer size [%{public}d], "
"buffer count [%{public}d], portEnable[%{public}d], err [%{public}d]", "buffer count [%{public}d], portEnable[%{public}d], ret [%{public}d]",
portIndex, bufferSize, bufferCount, bPortEnable, err); portIndex, bufferSize, bufferCount, portEnable, err);
{
OMX_PARAM_BUFFERSUPPLIERTYPE param;
InitParam(param);
param.nPortIndex = (uint32_t)portIndex;
auto err = client_->GetParameter(client_, OMX_IndexParamCompBufferSupplier, (int8_t *)&param, sizeof(param));
HDF_LOGI("param.eBufferSupplier[%{public}d] isSupply [%{public}d], err [%{public}d]", param.eBufferSupplier,
this->isSupply_, err);
}
// 设置端口buffer // 设置端口buffer
UseBufferOnPort(portIndex, bufferCount, bufferSize); if (useBufferHandle_ && portIndex == PortIndex::PORT_INDEX_OUTPUT) {
err = UseBufferHandle(bufferCount, bufferSize);
} else {
err = UseBufferOnPort(portIndex, bufferCount, bufferSize);
}
// 检查端口是否可用状态 // 检查端口是否可用状态
if (!bPortEnable) { if (!portEnable) {
auto err = client_->SendCommand(client_, OMX_CommandPortEnable, (uint32_t)portIndex, NULL, 0); err = client_->SendCommand(CODEC_COMMAND_PORT_ENABLE, static_cast<uint32_t>(portIndex), {});
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s SendCommand OMX_CommandPortEnable::PortIndex::PORT_INDEX_INPUT error", __func__); HDF_LOGE("%{public}s SendCommand OMX_CommandPortEnable::PortIndex::PORT_INDEX_INPUT error", __func__);
return false; return err;
} }
} }
return true; return HDF_SUCCESS;
} }
bool CodecHdiDecode::UseBufferOnPort(enum PortIndex portIndex, int bufferCount, int bufferSize) int32_t CodecHdiDecode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize)
{ {
if (bufferCount <= 0 || bufferSize <= 0) {
HDF_LOGE("UseBufferOnPort bufferCount <= 0 or bufferSize <= 0");
return HDF_ERR_INVALID_PARAM;
}
for (int i = 0; i < bufferCount; i++) { for (int i = 0; i < bufferCount; i++) {
OmxCodecBuffer *omxBuffer = new OmxCodecBuffer(); std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
memset_s(omxBuffer, sizeof(OmxCodecBuffer), 0, sizeof(OmxCodecBuffer));
omxBuffer->size = sizeof(OmxCodecBuffer); omxBuffer->size = sizeof(OmxCodecBuffer);
omxBuffer->version.s.nVersionMajor = 1; omxBuffer->version.s.nVersionMajor = 1;
omxBuffer->bufferType = BUFFER_TYPE_AVSHARE_MEM_FD; omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
int fd = AshmemCreate(0, bufferSize); int fd = AshmemCreate(0, bufferSize);
shared_ptr<Ashmem> sharedMem = make_shared<Ashmem>(fd, bufferSize); shared_ptr<Ashmem> sharedMem = make_shared<Ashmem>(fd, bufferSize);
omxBuffer->bufferLen = FD_SIZE; omxBuffer->fd = fd;
omxBuffer->buffer = (uint8_t *)(unsigned long)fd; omxBuffer->bufferhandle = nullptr;
omxBuffer->allocLen = bufferSize; omxBuffer->allocLen = bufferSize;
omxBuffer->fenceFd = -1; omxBuffer->fenceFd = -1;
omxBuffer->pts = 0;
omxBuffer->flag = 0;
if (portIndex == PortIndex::PORT_INDEX_INPUT) { if (portIndex == PortIndex::PORT_INDEX_INPUT) {
omxBuffer->type = READ_ONLY_TYPE; // ReadOnly omxBuffer->type = READ_ONLY_TYPE; // ReadOnly
...@@ -444,84 +464,75 @@ bool CodecHdiDecode::UseBufferOnPort(enum PortIndex portIndex, int bufferCount, ...@@ -444,84 +464,75 @@ bool CodecHdiDecode::UseBufferOnPort(enum PortIndex portIndex, int bufferCount,
omxBuffer->type = READ_WRITE_TYPE; omxBuffer->type = READ_WRITE_TYPE;
sharedMem->MapReadOnlyAshmem(); sharedMem->MapReadOnlyAshmem();
} }
auto err = client_->UseBuffer(client_, (uint32_t)portIndex, omxBuffer); OmxCodecBuffer outBuffer;
auto err = client_->UseBuffer((uint32_t)portIndex, *omxBuffer.get(), outBuffer);
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to UseBuffer with portIndex[%{public}d]", __func__, portIndex); HDF_LOGE("%{public}s failed to UseBuffer with portIndex[%{public}d]", __func__, portIndex);
sharedMem->UnmapAshmem(); sharedMem->UnmapAshmem();
sharedMem->CloseAshmem(); sharedMem->CloseAshmem();
sharedMem = nullptr; sharedMem = nullptr;
return false; return err;
} }
omxBuffer->bufferLen = 0; omxBuffer->bufferId = outBuffer.bufferId;
omxBuffer->fd = -1;
HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId); HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId);
BufferInfo *bufferInfo = new BufferInfo; std::shared_ptr<BufferInfo> bufferInfo = std::make_shared<BufferInfo>();
bufferInfo->omxBuffer = omxBuffer; bufferInfo->omxBuffer = omxBuffer;
bufferInfo->avSharedPtr = sharedMem; bufferInfo->avSharedPtr = sharedMem;
bufferInfo->portIndex = portIndex; bufferInfo->portIndex = portIndex;
omxBuffers_.insert(std::make_pair<int, BufferInfo *>(omxBuffer->bufferId, std::move(bufferInfo))); omxBuffers_.emplace(std::make_pair(omxBuffer->bufferId, bufferInfo));
if (portIndex == PortIndex::PORT_INDEX_INPUT) { if (portIndex == PortIndex::PORT_INDEX_INPUT) {
unUsedInBuffers_.push_back(omxBuffer->bufferId); unUsedInBuffers_.push_back(omxBuffer->bufferId);
} else { } else {
unUsedOutBuffers_.push_back(omxBuffer->bufferId); unUsedOutBuffers_.push_back(omxBuffer->bufferId);
} }
int fdret = (int)omxBuffer->buffer;
HDF_LOGI("{bufferID = %{public}d, srcfd = %{public}d, retfd = %{public}d}", omxBuffer->bufferId, fd, fdret);
} }
return true;
return HDF_SUCCESS;
} }
``` ```
#### 编解码Buffer流转 #### 编解码Buffer流转
用户需要先将组件设置为OMX_StateExecuting状态,然后填充输入buffer,读取输出buffer,进行buffer的轮转。 用户需要先将组件设置为CODEC_STATE_EXECUTING状态,然后填充输入buffer,读取输出buffer,进行buffer的轮转。
```cpp ```cpp
// 设置组件进入OMX_StateExecuting状态并开始buffer的轮转 // 设置组件进入OMX_StateExecuting状态并开始buffer的轮转
HDF_LOGI("...command to OMX_StateExecuting...."); HDF_LOGI("...command to CODEC_STATE_EXECUTING....");
auto err = client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateExecuting, NULL, 0); auto err = client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_EXECUTING, {});
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s failed to SendCommand with OMX_CommandStateSet:OMX_StateIdle", __func__); HDF_LOGE("%{public}s failed to SendCommand with CODEC_COMMAND_STATE_SET:CODEC_STATE_IDLE", __func__);
return; return;
} }
// 设置输出buffer填充 // 设置输出buffer填充
for (auto bufferId : unUsedOutBuffers_) { if (!FillAllTheBuffer()) {
HDF_LOGI("fill bufferid [%{public}d]", bufferId); HDF_LOGE("%{public}s FillAllTheBuffer error", __func__);
auto iter = omxBuffers_.find(bufferId);
if (iter != omxBuffers_.end()) {
BufferInfo *bufferInfo = iter->second;
auto err = client_->FillThisBuffer(client_, bufferInfo->pOmxBuffer);
if (err != HDF_SUCCESS) {
HDF_LOGE("FillThisBuffer error");
FUNC_EXIT_ERR();
return; return;
}
}
} }
// 填充输入buffer // 填充输入buffer
bool bEndOfFile = false; auto t1 = std::chrono::system_clock::now();
while (!bEndOfFile) { bool eosFlag = false;
int bufferID = GetFreeBufferId(); while (!eosFlag) {
if (this->exit_) { if (this->exit_) {
break; break;
} }
int bufferID = GetFreeBufferId();
if (bufferID < 0) { if (bufferID < 0) {
usleep(10000); usleep(10000); // 10000 for wait 10ms
continue; continue;
} }
auto iter = omxBuffers_.find(bufferID); auto iter = omxBuffers_.find(bufferID);
if (iter == omxBuffers_.end()) { if (iter == omxBuffers_.end()) {
continue; continue;
} }
BufferInfo *bufferInfo = iter->second; auto bufferInfo = iter->second;
void *sharedAddr = (void *)bufferInfo->avSharedPtr->ReadFromAshmem(0, 0); void *sharedAddr = const_cast<void *>(bufferInfo->avSharedPtr->ReadFromAshmem(0, 0));
bool bEOS = (size_t)this->ReadOnePacket(fpIn_, (char *)sharedAddr, bufferInfo->omxBuffer->filledLen); eosFlag = this->ReadOnePacket(fpIn_, static_cast<char *>(sharedAddr), bufferInfo->omxBuffer->filledLen);
HDF_LOGI("read data size is %{public}d", bufferInfo->omxBuffer->filledLen);
bufferInfo->omxBuffer->offset = 0; bufferInfo->omxBuffer->offset = 0;
if (bEOS) { if (eosFlag) {
bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS; bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS;
bEndOfFile = true;
} }
auto err = client_->EmptyThisBuffer(client_, bufferInfo->omxBuffer); err = client_->EmptyThisBuffer(*bufferInfo->omxBuffer.get());
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("%{public}s EmptyThisBuffer error", __func__); HDF_LOGE("%{public}s EmptyThisBuffer error", __func__);
return; return;
...@@ -529,180 +540,186 @@ while (!bEndOfFile) { ...@@ -529,180 +540,186 @@ while (!bEndOfFile) {
} }
// wait // wait
while (!this->exit_) { while (!this->exit_) {
usleep(10000); usleep(10000); // 10000 for wait 10ms
continue;
} }
// 解码完成后使组件进入OMX_StateIdle状态 // 解码完成后使组件进入OMX_StateIdle状态
client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); auto t2 = std::chrono::system_clock::now();
std::chrono::duration<double> diff = t2 - t1;
HDF_LOGI("cost %{public}f, count=%{public}d", diff.count(), count_);
(void)client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
return;
}
``` ```
当在rk开发板上进行解码时,由于其OMX的实现不支持数据的分帧,所以需要手动分帧,目前简单实现按照起始码0x000001或0x00000001分帧发送到服务端处理。分帧代码如下: 当在rk开发板上进行解码时,由于其OMX的实现不支持数据的分帧,所以需要手动分帧,目前简单实现按照起始码0x000001或0x00000001分帧发送到服务端处理。分帧代码如下:
```cpp ```cpp
// 文件分帧读取实现 // 文件分帧读取实现
bool OMXCore::ReadOnePacket(FILE* fp, char* buf, uint32_t& nFilled) bool CodecHdiDecode::ReadOnePacket(FILE *fp, char *buf, uint32_t &filledCount)
{ {
// 先读取4个字节 // 读取起始码
size_t t = fread(buf, 1, 4, fp); size_t t = fread(buf, 1, START_CODE_SIZE_FRAME, fp);
if (t < 4) { if (t < START_CODE_SIZE_FRAME) {
// 文件读取结束
return true; return true;
} }
size_t filled = 0; char *temp = buf;
filled = 4; temp += START_CODE_SIZE_FRAME;
bool ret = true;
bool bRet = true;
while (!feof(fp)) { while (!feof(fp)) {
fread(buf + filled, 1, 1, fp); (void)fread(temp, 1, 1, fp);
if (buf[filled] == 1) { if (*temp != START_CODE) {
temp++;
continue;
}
// 检查起始码 // 检查起始码
if ((buf[filled - 1] == 0) && if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) &&
(buf[filled - 2] == 0) && (temp[START_CODE_OFFSET_THIRD] == 0)) {
(buf[filled - 3] == 0)) { fseek(fp, -START_CODE_SIZE_FRAME, SEEK_CUR);
fseek(fp, -4, SEEK_CUR); temp -= (START_CODE_SIZE_FRAME - 1);
filled -= 3; ret = false;
bRet = false;
break;
} else if ((buf[filled - 1] == 0) &&
(buf[filled - 2] == 0)) {
fseek(fp, -3, SEEK_CUR);
filled -= 2;
bRet = false;
break; break;
} }
if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) {
fseek(fp, -START_CODE_SIZE_SLICE, SEEK_CUR);
temp -= (START_CODE_SIZE_SLICE - 1);
ret = false;
break;
} }
filled++; temp++;
} }
nFilled = filled; filledCount = (temp - buf);
return bRet; return ret;
} }
``` ```
Codec HDI提供3个回调函数:EventHandler,EmptyBufferDone和FillBufferDone。 Codec HDI提供3个回调函数:EventHandler,EmptyBufferDone和FillBufferDone。
- EventHandler:主要命令完成后的通知,例如:OMX_StateIdle转为OMX_StateExecuting的命令执行成功通知等。 - EventHandler:主要命令完成后的通知,例如:CODEC_STATE_IDLE转为CODEC_STATE_EXECUTING的命令执行成功通知等。
- EmptyBufferDone:输入数据消费完毕,客户端需要重新填入待编解码数据,再次调用EmptyThisBuffer。 - EmptyBufferDone:输入数据消费完毕,客户端需要重新填入待编解码数据,再次调用EmptyThisBuffer。
- FillBufferDone:输出数据填充完毕,客户端需要读取已编码/解码数据,再次调用FillThisBuffer。 - FillBufferDone:输出数据填充完毕,客户端需要读取已编码/解码数据,再次调用FillThisBuffer。
```cpp ```cpp
// EmptyBufferDone回调处理示例 // EmptyBufferDone回调处理示例
int32_t OMXCore::OnEmptyBufferDone(struct CodecCallbackType *self, int8_t *pAppData, uint32_t pAppDataLen, int32_t CodecHdiDecode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer)
const struct OmxCodecBuffer *pBuffer)
{
HDF_LOGI("onEmptyBufferDone: pBuffer.bufferID [%{public}d]", pBuffer->bufferId);
g_core->OnEmptyBufferDone(pBuffer);
return HDF_SUCCESS;
}
int32_t OMXCore::OnEmptyBufferDone(const struct OmxCodecBuffer *pBuffer)
{ {
unique_lock<mutex> ulk(mLockInputBuffers_); HDF_LOGI("OnEmptyBufferDone, bufferId [%{public}d]", buffer.bufferId);
unUsedInBuffers_.push_back(pBuffer->bufferId); unique_lock<mutex> ulk(lockInputBuffers_);
unUsedInBuffers_.push_back(buffer.bufferId);
return HDF_SUCCESS; return HDF_SUCCESS;
} }
// FillBufferDone回调处理示例 // FillBufferDone回调处理示例
int32_t OMXCore::OnFillBufferDone(struct CodecCallbackType *self, int8_t *pAppData, uint32_t pAppDataLen, int32_t CodecHdiDecode::OnFillBufferDone(const struct OmxCodecBuffer &buffer)
struct OmxCodecBuffer *pBuffer)
{ {
HDF_LOGI("onFillBufferDone: pBuffer.bufferID [%{public}d]", pBuffer->bufferId); HDF_LOGI("OnFillBufferDone, bufferId [%{public}d]", buffer.bufferId);
g_core->OnFillBufferDone(pBuffer); if (exit_) {
return HDF_SUCCESS;
}
int32_t OMXCore::onFillBufferDone(struct OmxCodecBuffer* pBuffer)
{
// 根据bufferID找到buffer
if (bExit_) {
return HDF_SUCCESS; return HDF_SUCCESS;
} }
auto iter = omxBuffers_.find(pBuffer->bufferId); auto iter = omxBuffers_.find(buffer.bufferId);
if (iter == omxBuffers_.end() || !iter->second) { if ((iter == omxBuffers_.end()) || (iter->second == nullptr)) {
return HDF_SUCCESS; return HDF_SUCCESS;
} }
// 取出输出的数据 count_++;
BufferInfo *pBufferInfo = iter->second; // read buffer
const void *addr = pBufferInfo->avSharedPtr->ReadFromAshmem(pBuffer->filledLen, pBuffer->offset); auto bufferInfo = iter->second;
// 解码数据保存到文件 if (bufferInfo->avSharedPtr != nullptr) {
fwrite(addr, 1, pBuffer->filledLen, fpOut_.get()); const void *addr = bufferInfo->avSharedPtr->ReadFromAshmem(buffer.filledLen, buffer.offset);
fflush(fpOut_.get()); (void)fwrite(addr, 1, buffer.filledLen, fpOut_);
// 重置buffer数据 } else if (bufferInfo->bufferHandle != nullptr && gralloc_ != nullptr) {
pBuffer->offset = 0; gralloc_->Mmap(*bufferInfo->bufferHandle);
pBuffer->filledLen = 0; (void)fwrite(bufferInfo->bufferHandle->virAddr, 1, buffer.filledLen, fpOut_);
if (pBuffer->flag == OMX_BUFFERFLAG_EOS) { gralloc_->Unmap(*bufferInfo->bufferHandle);
// 结束 }
bExit_ = true;
(void)fflush(fpOut_);
if (buffer.flag == OMX_BUFFERFLAG_EOS) {
// end
exit_ = true;
HDF_LOGI("OnFillBufferDone the END coming"); HDF_LOGI("OnFillBufferDone the END coming");
return HDF_SUCCESS; return HDF_SUCCESS;
} }
// 再次调用FillThisBuffer // call fillthisbuffer again
auto err = client_->FillThisBuffer(client_, pBufferInfo->pOmxBuffer); auto err = client_->FillThisBuffer(*bufferInfo->omxBuffer.get());
if (err != HDF_SUCCESS) { if (err != HDF_SUCCESS) {
HDF_LOGE("FillThisBuffer error"); HDF_LOGE("%{public}s FillThisBuffer error", __func__);
return HDF_SUCCESS; return HDF_SUCCESS;
} }
return HDF_SUCCESS; return HDF_SUCCESS;
} }
// EventHandler示例 // EventHandler示例
int32_t CodecHdiDecode::OnEvent(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct EventInfo *info) int32_t CodecHdiDecode::EventHandler(CodecEventType event, const EventInfo &info)
{ {
HDF_LOGI("onEvent: appData[0x%{public}p], eEvent [%{public}d], "
"nData1[%{public}d]", info->appData, event, info->data1);
switch (event) { switch (event) {
case OMX_EventCmdComplete: { case CODEC_EVENT_CMD_COMPLETE: {
OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE)info->data1; CodecCommandType cmd = (CodecCommandType)info.data1;
if (OMX_CommandStateSet == cmd) { if (CODEC_COMMAND_STATE_SET == cmd) {
HDF_LOGI("OMX_CommandStateSet reached, status is %{public}d", info->data2); HDF_LOGI("CODEC_COMMAND_STATE_SET reached, status is %{public}d", info.data2);
g_core->onStatusChanged(); this->OnStatusChanged();
} }
break; break;
} }
case OMX_EventPortSettingsChanged: {
HDF_LOGI("OMX_EventPortSeetingsChanged reached");
this->HandleEventPortSettingsChanged(info.data1, info.data2);
}
default: default:
break; break;
} }
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
#### 接口去初始化 #### 接口去初始化
组件关闭前,需要将组件状态修改为OMX_StateIdle,然后开始释放输入输出Buffer,再将组件状态修改为OMX_StateLoaded,最后再调用DestoryComponent去关闭组件。 组件关闭前,需要将组件状态修改为CODEC_STATE_IDLE,然后开始释放输入输出Buffer,再将组件状态修改为CODEC_STATE_LOADED,最后再调用DestoryComponent去关闭组件。
##### Buffer释放示例 ##### Buffer释放示例
```cpp ```cpp
// 发送命令使组件进入OMX_StateLoaded状态 // 发送命令使组件进入OMX_StateLoaded状态
client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateLoaded, nullptr, 0); client_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_LOADED, {});
// 释放所有申请的buffer // 释放所有申请的buffer
auto iter = omxBuffers_.begin(); auto iter = omxBuffers_.begin();
while (iter != omxBuffers_.end()) { while (iter != omxBuffers_.end()) {
BufferInfo *bufferInfo = iter->second; auto bufferInfo = iter->second;
client_->FreeBuffer(client_, (uint32_t)bufferInfo->portIndex, bufferInfo->omxBuffer); iter = omxBuffers_.erase(iter);
delete bufferInfo; (void)client_->FreeBuffer((uint32_t)bufferInfo->portIndex, *bufferInfo->omxBuffer.get());
iter++; bufferInfo = nullptr;
} }
omxBuffers_.clear();
unUsedInBuffers_.clear(); unUsedInBuffers_.clear();
unUsedOutBuffers_.clear(); unUsedOutBuffers_.clear();
enum OMX_STATETYPE status;
client_->GetState(client_, &status);
// buffer释放后组件即进入OMX_StateLoaded状态 // buffer释放后组件即进入OMX_StateLoaded状态
if (status != OMX_StateLoaded) { CodecStateType status = CODEC_STATE_INVALID;
int32_t err = HDF_SUCCESS;
int32_t tryCount = 3;
do {
err = client_->GetState(status);
if (err != HDF_SUCCESS) {
HDF_LOGE("%s GetState error [%{public}x]", __func__, err);
break;
}
if (status != CODEC_STATE_LOADED) {
HDF_LOGI("Wait for OMX_StateLoaded status"); HDF_LOGI("Wait for OMX_StateLoaded status");
this->WaitForStatusChanged(); this->WaitForStatusChanged();
} else { }
HDF_LOGI(" status is %{public}d", status); tryCount--;
} } while ((status != CODEC_STATE_LOADED) && (tryCount > 0));
``` ```
##### 组件实例释放示例 ##### 组件实例释放示例
```cpp ```cpp
// 组件实例释放 // 组件实例释放
void OMXCore::Release() { void CodecHdiDecode::Release()
omxMgr_->DestoryComponent(client_); {
omxMgr_->DestoryComponent(componentId_);
client_ = nullptr; client_ = nullptr;
CodecComponentManagerRelease(); callback_ = nullptr;
omxMgr_ = nullptr;
} }
``` ```
...@@ -747,7 +764,6 @@ OpenMax对AVCC格式的数据处理,第一帧一定要是extra_data,可能 ...@@ -747,7 +764,6 @@ OpenMax对AVCC格式的数据处理,第一帧一定要是extra_data,可能
1. 输出端口的xFramerate参数未正常设置。 1. 输出端口的xFramerate参数未正常设置。
2. 如果设置了参数OMX_VIDEO_PARAM_AVCTYPE,请检查此参数是否正确。 2. 如果设置了参数OMX_VIDEO_PARAM_AVCTYPE,请检查此参数是否正确。
**解决办法** **解决办法**
请看编码时codec_host的日志,搜索“encode params init settings”,确认是否出现异常的参数。如果是framerate为0,则是原因1,需要将正常的framerate左移16位;如果是其它参数异常,可能是原因2,需要检查其相应的参数。 请看编码时codec_host的日志,搜索“encode params init settings”,确认是否出现异常的参数。如果是framerate为0,则是原因1,需要将正常的framerate左移16位;如果是其它参数异常,可能是原因2,需要检查其相应的参数。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册