Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
30367824
D
Docs
项目概览
OpenHarmony
/
Docs
大约 2 年 前同步成功
通知
161
Star
293
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
30367824
编写于
6月 06, 2023
作者:
O
openharmony_ci
提交者:
Gitee
6月 06, 2023
浏览文件
操作
浏览文件
下载
差异文件
!19122 Codec指导文档整改
Merge pull request !19122 from 王勃懿/master
上级
6b9117ed
d03d9deb
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
306 addition
and
290 deletion
+306
-290
zh-cn/device-dev/driver/driver-peripherals-codec-des.md
zh-cn/device-dev/driver/driver-peripherals-codec-des.md
+306
-290
未找到文件。
zh-cn/device-dev/driver/driver-peripherals-codec-des.md
浏览文件 @
30367824
...
...
@@ -54,33 +54,33 @@ Codec模块主要完成对视频数据的硬件编解码,将H264等裸流数
### 接口说明
-
codec_component_manager.h
-
i
codec_component_manager.h
| 接口名称 | 功能描述 |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------|
| int32_t
(
*CreateComponent)(struct CodecComponentType **component, uint32_t *
componentId, char
*compName, int64_t appData, struct CodecCallbackType *
callbacks) | 创建Codec组件实例 |
| int32_t
(
*
DestroyComponent)(uint32_t componentId)
| 销毁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
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
(
*GetParameter)(struct CodecComponentType *
self, uint32_t paramIndex, int8_t
*
paramStruct, uint32_t paramStructLen) | 获取组件参数设置
|
| int32_t
(
*SetParameter)(struct CodecComponentType *
self, uint32_t index, int8_t
*
paramStruct, uint32_t paramStructLen) | 设置组件需要的参数
|
| int32_t
(
*GetState)(struct CodecComponentType *
self, enum OMX_STATETYPE
*
state) | 获取组件的状态
|
| int32_t
(
*UseBuffer)(struct CodecComponentType *
self, uint32_t portIndex, struct OmxCodecBuffer
*
buffer) | 指定组件端口的buffer
|
| int32_t
(
*FreeBuffer)(struct CodecComponentType *
self, uint32_t portIndex, const struct OmxCodecBuffer
*
buffer) | 释放buffer
|
| int32_t
(
*EmptyThisBuffer)(struct CodecComponentType *
self, const struct OmxCodecBuffer
*
buffer) | 编解码输入待处理buffer
|
| int32_t
(
*FillThisBuffer)(struct CodecComponentType *
self, const struct OmxCodecBuffer
*
buffer) | 编解码输出填充buffer
|
-
codec_callback_if
.h
| ------------------------------------------------------------
|
---------------------- |
| int32_t
SendCommand(CodecCommandType cmd, uint32_t param, const std::vector
<int8_t>
& cmdData) | 发送命令给组件
|
| int32_t
GetParameter(uint32_t index, const std::vector
<int8_t>
& inParamStruct, std::vector
<int8_t>
& outParamStruct) | 获取组件参数设置
|
| int32_t
SetParameter(uint32_t index, const std::vector
<int8_t>
& paramStruct) | 设置组件需要的参数
|
| int32_t
GetState(CodecStateType& state) | 获取组件的状态
|
| int32_t
UseBuffer(uint32_t portIndex, const OmxCodecBuffer& inBuffer, OmxCodecBuffer& outBuffer) | 指定组件端口的buffer
|
| int32_t
FreeBuffer(uint32_t portIndex, const OmxCodecBuffer& buffer) | 释放buffer
|
| int32_t
EmptyThisBuffer(const OmxCodecBuffer& buffer) | 编解码输入待处理buffer
|
| int32_t
FillThisBuffer(const OmxCodecBuffer& buffer) | 编解码输出填充buffer
|
-
icodec_callback
.h
| 接口名称 | 功能描述 |
| ------------------------------------------------------------
---------------------------------------------------- |----------------------------------- |
| int32_t
(
*EventHandler)(struct CodecCallbackType *
self, enum OMX_EVENTTYPE event, struct EventInfo
*
info) | 事件上报 |
| int32_t
(
*EmptyBufferDone)(struct CodecCallbackType *
self, int64_t appData, const struct OmxCodecBuffer
*
buffer) | 上报输入buffer编码或者解码处理完毕 |
| int32_t
(
*FillBufferDone)(struct CodecCallbackType *
self, int64_t appData, const struct OmxCodecBuffer
*
buffer) | 上报输出buffer填充完毕 |
| ------------------------------------------------------------
| ---------------------------------- |
| int32_t
EventHandler(CodecEventType event, const EventInfo& info) | 事件上报 |
| int32_t
EmptyBufferDone(int64_t appData, const OmxCodecBuffer& buffer) | 上报输入buffer编码或者解码处理完毕 |
| int32_t
FillBufferDone(int64_t appData, const OmxCodecBuffer& buffer) | 上报输出buffer填充完毕 |
更多接口请参考
[
Codec驱动仓
](
https://gitee.com/openharmony/drivers_peripheral/tree/master/codec
)
。
...
...
@@ -88,63 +88,63 @@ Codec模块主要完成对视频数据的硬件编解码,将H264等裸流数
Codec HDI驱动的开发过程主要包含以下步骤:
#### Driver的注册及初始化
定义Codec HDI的HdfDriverEntry结构体,该结构体中定义了Driver初始化的方法,填充g_codec
Component
DriverEntry结构体,实现Bind、Init、Release函数指针。
定义Codec HDI的HdfDriverEntry结构体,该结构体中定义了Driver初始化的方法,填充g_codec
componentmanager
DriverEntry结构体,实现Bind、Init、Release函数指针。
```
c
st
ruct
HdfDriverEntry
g_codecComponent
DriverEntry
=
{
st
atic
struct
HdfDriverEntry
g_codeccomponentmanager
DriverEntry
=
{
.
moduleVersion
=
1
,
.
moduleName
=
"codec_hdi_omx_server"
,
.
Bind
=
HdfCodecComponentTypeDriverBind
,
.
Init
=
HdfCodecComponentTypeDriverInit
,
.
Release
=
HdfCodecComponentTypeDriverRelease
,
};
HDF_INIT
(
g_codecComponentDriverEntry
);
// 将Codec HDI的HdfDriverEntry结构体注册到HDF上
.
moduleName
=
"codec_component_manager_service"
,
.
Bind
=
HdfCodecComponentManagerDriverBind
,
.
Init
=
HdfCodecComponentManagerDriverInit
,
.
Release
=
HdfCodecComponentManagerDriverRelease
,
};
// 将Codec HDI的HdfDriverEntry结构体注册到HDF上
```
-
HdfCodecComponent
TypeDriverBind:将HDF中device绑定到CodecComponentType
Host,将codec service注册到HDF框架。
-
HdfCodecComponent
ManagerDriverBind:将HDF中device绑定到HdfCodecComponentManager
Host,将codec service注册到HDF框架。
```c
int32_t HdfCodecComponentType
DriverBind(struct HdfDeviceObject *deviceObject)
static int HdfCodecComponentManager
DriverBind(struct HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfCodecComponentTypeDriverBind enter.
");
struct HdfCodecComponentTypeHost *omxcomponenttypeHost =
(struct HdfCodecComponentTypeHost *)OsalMemAlloc(sizeof(struct HdfCodecComponentTypeHost))
;
if (
omxcomponenttypeHost == NULL
) {
HDF_LOGE("HdfCodecComponentTypeDriverBind OsalMemAlloc HdfCodecComponentTypeHost failed!
");
CODEC_LOGI("HdfCodecComponentManagerDriverBind enter
");
auto *hdfCodecComponentManagerHost = new (std::nothrow) HdfCodecComponentManagerHost
;
if (
hdfCodecComponentManagerHost == nullptr
) {
CODEC_LOGE("failed to create create HdfCodecComponentManagerHost object
");
return HDF_FAILURE;
}
int ret = HdfDeviceObjectSetInterfaceDesc(deviceObject, COMPONENT_MANAGER_SERVICE_DESC);
if (ret != HDF_SUCCESS) {
HDF_LOGE("Failed to set interface desc");
return ret;
hdfCodecComponentManagerHost->ioService.Dispatch = CodecComponentManagerDriverDispatch;
hdfCodecComponentManagerHost->ioService.Open = NULL;
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;
omxcomponenttypeHost->ioservice.Open = NULL;
omxcomponenttypeHost->ioservice.Release = NULL;
omxcomponenttypeHost->service = CodecComponentManagerSerivceGet();
if (omxcomponenttypeHost->service == NULL) {
OsalMemFree(omxcomponenttypeHost);
hdfCodecComponentManagerHost->stub =
OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, ICodecComponentManager::GetDescriptor());
if (hdfCodecComponentManagerHost->stub == nullptr) {
CODEC_LOGE("failed to get stub object");
delete hdfCodecComponentManagerHost;
return HDF_FAILURE;
}
deviceObject->service = &
omxcomponenttypeHost->ios
ervice;
deviceObject->service = &
hdfCodecComponentManagerHost->ioS
ervice;
return HDF_SUCCESS;
}
```
-
HdfCodecComponent
Type
DriverInit:加载HCS(HDF Configuration Source)中的属性配置。
-
HdfCodecComponent
Manager
DriverInit:加载HCS(HDF Configuration Source)中的属性配置。
```c
int32_t HdfCodecComponentType
DriverInit(struct HdfDeviceObject *deviceObject)
static int HdfCodecComponentManager
DriverInit(struct HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfCodecComponentTypeDriverInit enter.");
if (deviceObject == NULL) {
return HDF_FAILURE;
}
InitDataNode(deviceObject->property);
if (LoadCapabilityData() != HDF_SUCCESS) {
ClearCapabilityData();
CODEC_LOGI("HdfCodecComponentManagerDriverInit enter");
if (DevHostRegisterDumpHost(CodecDfxService::DevCodecHostDump) != HDF_SUCCESS) {
CODEC_LOGE("DevHostRegisterDumpHost error!");
}
return HDF_SUCCESS;
}
...
...
@@ -153,14 +153,17 @@ HDF_INIT(g_codecComponentDriverEntry); // 将Codec HDI的HdfDriverEntry结构体
-
HdfCodecComponentTypeDriverRelease:释放驱动实例。
```c
void HdfCodecComponentType
DriverRelease(struct HdfDeviceObject *deviceObject)
static void HdfCodecComponentManager
DriverRelease(struct HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfCodecComponentTypeDriverRelease enter.");
struct HdfCodecComponentTypeHost *omxcomponenttypeHost =
CONTAINER_OF(deviceObject->service, struct HdfCodecComponentTypeHost, ioservice);
OmxComponentManagerSeriveRelease(omxcomponenttypeHost->service);
OsalMemFree(omxcomponenttypeHost);
ClearCapabilityData();
CODEC_LOGI("HdfCodecComponentManagerDriverRelease enter");
if (deviceObject->service == nullptr) {
CODEC_LOGE("HdfCodecComponentManagerDriverRelease not initted");
return;
}
auto *hdfCodecComponentManagerHost =
CONTAINER_OF(deviceObject->service, struct HdfCodecComponentManagerHost, ioService);
delete hdfCodecComponentManagerHost;
}
```
...
...
@@ -177,19 +180,19 @@ vendor/hihope/rk3568/hdf_config/uhdf/
1.
device相关配置
在device_info.hcs的codec_host中增加codec_
omx
_service配置,具体配置如下:
在device_info.hcs的codec_host中增加codec_
component_manager
_service配置,具体配置如下:
```c
codec :: host {
hostName = "codec_host";
priority = 50;
gid = ["codec_host", "uhdf_driver", "vendor_mpp_driver"];
codec_omx_device :: device {
codec_omx_
idl_
device :: device {
device0 :: deviceNode {
policy = 2; // 自动加载,非延迟加载
priority = 100; // 优先级
moduleName = "libcodec_
hdi_omx_server.z.so";
// 驱动的动态库
serviceName = "codec_
hdi_omx_service";
// 配置驱动的服务名
deviceMatchAttr = "
codec_component_capabilities";
// 属性配置
moduleName = "libcodec_
driver.z.so";
// 驱动的动态库
serviceName = "codec_
component_manager_service";
// 配置驱动的服务名
deviceMatchAttr = "
media_codec_capabilities";
// 属性配置
}
}
}
...
...
@@ -197,7 +200,7 @@ vendor/hihope/rk3568/hdf_config/uhdf/
2.
支持的组件相关配置
在media_codec\
codec_component
_capabilities.hcs中增加组件配置,具体配置如下:
在media_codec\
media_codec
_capabilities.hcs中增加组件配置,具体配置如下:
```c
/* node name explanation -- HDF_video_hw_enc_avc_rk:
**
...
...
@@ -228,7 +231,7 @@ vendor/hihope/rk3568/hdf_config/uhdf/
maxBlocksPerSecond = 0xFFFFFFFF;
blockSizeWidth = 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];
bitRateMode = [1, 2]; // 比特率模式,BitRateMode
minFrameRate = 0; // 帧率配置
...
...
@@ -247,34 +250,29 @@ vendor/hihope/rk3568/hdf_config/uhdf/
1.
初始化,包括接口实例、回调的初始化和对应的组件的初始化;
2.
设置编解码参数和配置信息,如视频宽、高和码率等;
3.
输入输出Buffer申请;
4.
编解码Buffer流转,使组件进入
OMX_Executing
状态,并处理相应的回调;
4.
编解码Buffer流转,使组件进入
CODEC_STATE_EXECUTING
状态,并处理相应的回调;
5.
接口去初始化,销毁buffer,关闭组件并释放所有的接口对象;
#### 初始化
初始化过程包括接口的初始化,回调的初始化以及组件的创建。
```
cpp
// 初始化Codec HDI ComponentManager实例
omxMgr_
=
GetCodecComponentManager
();
omxMgr_
=
ICodecComponentManager
::
Get
(
false
);
if
((
omxMgr_
==
nullptr
))
{
HDF_LOGE
(
"%{public}s omxMgr_ is null"
,
__func__
);
return
false
;
}
// 初始化回调
callback_
=
CodecCallbackTypeStubGetInstance
(
);
if
(
!
omxMgr_
||
!
callback_
)
{
FUNC_EXIT_ERR
(
);
callback_
=
new
CodecHdiCallback
(
shared_from_this
()
);
if
(
(
callback_
==
nullptr
)
)
{
HDF_LOGE
(
"%{public}s callback_ is null"
,
__func__
);
return
false
;
}
// 设置回调函数指针
callback_
->
EventHandler
=
&
OMXCore
::
OnEvent
;
callback_
->
EmptyBufferDone
=
&
OMXCore
::
OnEmptyBufferDone
;
callback_
->
FillBufferDone
=
&
OMXCore
::
OnFillBufferDone
;
// 新建组件实例
uint32_t
err
=
HDF_SUCCESS
;
if
(
codec
==
codecMime
::
AVC
)
{
err
=
omxMgr_
->
CreateComponent
(
&
client_
,
&
componentId_
,
const_cast
<
char
*>
(
DECODER_AVC
),
(
int64_t
)
this
,
callback_
);
}
else
{
err
=
omxMgr_
->
CreateComponent
(
&
client_
,
&
componentId_
,
const_cast
<
char
*>
(
DECODER_HEVC
),
(
int64_t
)
this
,
callback_
);
err
=
omxMgr_
->
CreateComponent
(
client_
,
componentId_
,
compName
,
reinterpret_cast
<
int64_t
>
(
this
),
callback_
);
if
(
err
!=
HDF_SUCCESS
)
{
HDF_LOGE
(
"%{public}s failed to CreateComponent"
,
__func__
);
return
false
;
}
```
...
...
@@ -283,64 +281,79 @@ Codec HDI编解码参数配置,包括输入输出数据的宽和高,输入
```
cpp
// 设置输入端口图片的宽高
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
(
util_
->
InitParam
(
param
)
!=
HDF_SUCCESS
)
{
return
HDF_FAILURE
;
}
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
)
{
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 "
,
param
.
format
.
video
.
eCompressionFormat
,
param
.
format
.
video
.
eColorFormat
);
param
.
format
.
video
.
nFrameWidth
=
width_
;
param
.
format
.
video
.
nFrameHeight
=
height_
;
param
.
format
.
video
.
nStride
=
width_
;
param
.
format
.
video
.
nSliceHeight
=
height_
;
err
=
client_
->
SetParameter
(
client_
,
OMX_IndexParamPortDefinition
,
(
int8_t
*
)
&
param
,
sizeof
(
param
));
util_
->
setParmValue
(
param
,
width_
,
height_
,
stride_
);
util_
->
ObjectToVector
(
param
,
inVec
);
err
=
client_
->
SetParameter
(
OMX_IndexParamPortDefinition
,
inVec
);
if
(
err
!=
HDF_SUCCESS
)
{
HDF_LOGE
(
"%{public}s failed with PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition"
,
__func__
);
return
false
;
return
err
;
}
// 输出宽、高和格式设置
InitParam
(
param
);
param
.
nPortIndex
=
(
uint32_t
)
PortIndex
::
PORT_INDEX_OUTPUT
;
err
=
client_
->
GetParameter
(
client_
,
OMX_IndexParamPortDefinition
,
(
int8_t
*
)
&
param
,
sizeof
(
param
));
if
(
util_
->
InitParam
(
param
)
!=
HDF_SUCCESS
)
{
return
HDF_FAILURE
;
}
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
)
{
HDF_LOGE
(
"%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition"
,
__func__
);
return
false
;
HDF_LOGE
(
"%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition"
,
__func__
);
return
err
;
}
util_
->
VectorToObject
(
outVec
,
param
);
HDF_LOGI
(
"PortIndex::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
=
width_
;
param
.
format
.
video
.
nSliceHeight
=
height_
;
util_
->
setParmValue
(
param
,
width_
,
height_
,
stride_
);
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
)
{
HDF_LOGE
(
"%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition"
,
__func__
);
return
false
;
return
err
;
}
// 设置输入数据为H264/H265格式数据
OMX_VIDEO_PARAM_PORTFORMATTYPE
param
;
InitParam
(
param
);
if
(
util_
->
InitParam
(
param
)
!=
HDF_SUCCESS
)
{
return
false
;
}
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
)
{
HDF_LOGE
(
"%{public}s failed with PortIndex::PORT_INDEX_INPUT"
,
__func__
);
return
false
;
}
util_
->
VectorToObject
(
outVec
,
param
);
HDF_LOGI
(
"set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d"
,
param
.
eCompressionFormat
,
param
.
eColorFormat
);
param
.
xFramerate
=
FRAME
;
// 30帧
param
.
xFramerate
=
FRAME
// 30帧
if
(
codecMime_
==
codecMime
::
AVC
)
{
param
.
eCompressionFormat
=
OMX_VIDEO_CodingAVC
;
// H264
}
else
{
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
)
{
HDF_LOGE
(
"%{public}s failed with PortIndex::PORT_INDEX_INPUT"
,
__func__
);
return
false
;
...
...
@@ -352,90 +365,97 @@ if (err != HDF_SUCCESS) {
1.
用户通过UseBuffer申请输入输出Buffer,并保存bufferId,后续buffer轮转可以直接通过bufferId来操作。
2.
用户需要判断对应的端口是否是使能状态,如果不是,需要先将对应的端口设置为使能状态。
3.
用户通过SendCommand将组件的状态为修改为
OMX_StateIdle
,需要等待其结果通知。
3.
用户通过SendCommand将组件的状态为修改为
CODEC_STATE_IDLE
,需要等待其结果通知。
```
cpp
// 输入端口buffer申请
auto
ret
=
UseBufferOnPort
(
PortIndex
::
PORT_INDEX_INPUT
);
if
(
!
ret
)
{
auto
err
=
UseBufferOnPort
(
PortIndex
::
PORT_INDEX_INPUT
);
if
(
err
!=
HDF_SUCCESS
)
{
HDF_LOGE
(
"%{public}s UseBufferOnPort PortIndex::PORT_INDEX_INPUT error"
,
__func__
);
return
false
;
}
// 输出端口buffer申请
ret
=
UseBufferOnPort
(
PortIndex
::
PORT_INDEX_OUTPUT
);
if
(
!
ret
)
{
err
=
UseBufferOnPort
(
PortIndex
::
PORT_INDEX_OUTPUT
);
if
(
err
!=
HDF_SUCCESS
)
{
HDF_LOGE
(
"%{public}s UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT error"
,
__func__
);
return
false
;
}
// 发送命令使组件进入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
)
{
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
;
}
HDF_LOGI
(
"Wait for OMX_StateIdle status"
);
this
->
WaitForStatusChanged
();
```
UseBufferOnPort实现如下:
```
cpp
bool
CodecHdiDecode
::
UseBufferOnPort
(
enum
PortIndex
portIndex
)
int32_t
CodecHdiDecode
::
UseBufferOnPort
(
PortIndex
portIndex
)
{
HDF_LOGI
(
"%{public}s enter, portIndex = %{public}d"
,
__func__
,
portIndex
);
int
bufferSize
=
0
;
int
bufferCount
=
0
;
bool
b
PortEnable
=
false
;
bool
PortEnable
=
false
;
// 获取端口buffer参数
OMX_PARAM_PORTDEFINITIONTYPE
param
;
InitParam
(
param
);
param
.
nPortIndex
=
(
OMX_U32
)
portIndex
;
auto
err
=
client_
->
GetParameter
(
client_
,
OMX_IndexParamPortDefinition
,
(
int8_t
*
)
&
param
,
sizeof
(
param
));
if
(
util_
->
InitParam
(
param
)
!=
HDF_SUCCESS
)
{
return
HDF_FAILURE
;
}
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
)
{
HDF_LOGE
(
"%{public}s failed to GetParameter with OMX_IndexParamPortDefinition : portIndex[%{public}d]"
,
__func__
,
portIndex
);
return
false
;
return
err
;
}
util_
->
VectorToObject
(
outVec
,
param
);
bufferSize
=
param
.
nBufferSize
;
bufferCount
=
param
.
nBufferCountActual
;
bP
ortEnable
=
param
.
bEnabled
;
p
ortEnable
=
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
,
bPortEnable
,
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 count [%{public}d], portEnable[%{public}d], ret [%{public}d]"
,
portIndex
,
bufferSize
,
bufferCount
,
portEnable
,
err
);
// 设置端口buffer
UseBufferOnPort
(
portIndex
,
bufferCount
,
bufferSize
);
if
(
useBufferHandle_
&&
portIndex
==
PortIndex
::
PORT_INDEX_OUTPUT
)
{
err
=
UseBufferHandle
(
bufferCount
,
bufferSize
);
}
else
{
err
=
UseBufferOnPort
(
portIndex
,
bufferCount
,
bufferSize
);
}
// 检查端口是否可用状态
if
(
!
bP
ortEnable
)
{
auto
err
=
client_
->
SendCommand
(
client_
,
OMX_CommandPortEnable
,
(
uint32_t
)
portIndex
,
NULL
,
0
);
if
(
!
p
ortEnable
)
{
err
=
client_
->
SendCommand
(
CODEC_COMMAND_PORT_ENABLE
,
static_cast
<
uint32_t
>
(
portIndex
),
{}
);
if
(
err
!=
HDF_SUCCESS
)
{
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
++
)
{
OmxCodecBuffer
*
omxBuffer
=
new
OmxCodecBuffer
();
memset_s
(
omxBuffer
,
sizeof
(
OmxCodecBuffer
),
0
,
sizeof
(
OmxCodecBuffer
));
std
::
shared_ptr
<
OmxCodecBuffer
>
omxBuffer
=
std
::
make_shared
<
OmxCodecBuffer
>
();
omxBuffer
->
size
=
sizeof
(
OmxCodecBuffer
);
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
);
shared_ptr
<
Ashmem
>
sharedMem
=
make_shared
<
Ashmem
>
(
fd
,
bufferSize
);
omxBuffer
->
bufferLen
=
FD_SIZE
;
omxBuffer
->
buffer
=
(
uint8_t
*
)(
unsigned
long
)
fd
;
omxBuffer
->
fd
=
fd
;
omxBuffer
->
buffer
handle
=
nullptr
;
omxBuffer
->
allocLen
=
bufferSize
;
omxBuffer
->
fenceFd
=
-
1
;
omxBuffer
->
pts
=
0
;
omxBuffer
->
flag
=
0
;
if
(
portIndex
==
PortIndex
::
PORT_INDEX_INPUT
)
{
omxBuffer
->
type
=
READ_ONLY_TYPE
;
// ReadOnly
...
...
@@ -444,84 +464,75 @@ bool CodecHdiDecode::UseBufferOnPort(enum PortIndex portIndex, int bufferCount,
omxBuffer
->
type
=
READ_WRITE_TYPE
;
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
)
{
HDF_LOGE
(
"%{public}s failed to UseBuffer with portIndex[%{public}d]"
,
__func__
,
portIndex
);
sharedMem
->
UnmapAshmem
();
sharedMem
->
CloseAshmem
();
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
);
BufferInfo
*
bufferInfo
=
new
BufferInfo
;
std
::
shared_ptr
<
BufferInfo
>
bufferInfo
=
std
::
make_shared
<
BufferInfo
>
()
;
bufferInfo
->
omxBuffer
=
omxBuffer
;
bufferInfo
->
avSharedPtr
=
sharedMem
;
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
)
{
unUsedInBuffers_
.
push_back
(
omxBuffer
->
bufferId
);
}
else
{
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流转
用户需要先将组件设置为
OMX_StateExecuting
状态,然后填充输入buffer,读取输出buffer,进行buffer的轮转。
用户需要先将组件设置为
CODEC_STATE_EXECUTING
状态,然后填充输入buffer,读取输出buffer,进行buffer的轮转。
```
cpp
// 设置组件进入OMX_StateExecuting状态并开始buffer的轮转
HDF_LOGI
(
"...command to
OMX_StateExecuting
...."
);
auto
err
=
client_
->
SendCommand
(
client_
,
OMX_CommandStateSet
,
OMX_StateExecuting
,
NULL
,
0
);
HDF_LOGI
(
"...command to
CODEC_STATE_EXECUTING
...."
);
auto
err
=
client_
->
SendCommand
(
CODEC_COMMAND_STATE_SET
,
CODEC_STATE_EXECUTING
,
{}
);
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
;
}
// 设置输出buffer填充
for
(
auto
bufferId
:
unUsedOutBuffers_
)
{
HDF_LOGI
(
"fill bufferid [%{public}d]"
,
bufferId
);
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
();
if
(
!
FillAllTheBuffer
())
{
HDF_LOGE
(
"%{public}s FillAllTheBuffer error"
,
__func__
);
return
;
}
}
}
// 填充输入buffer
bool
bEndOfFile
=
false
;
while
(
!
bEndOfFile
)
{
int
bufferID
=
GetFreeBufferId
();
auto
t1
=
std
::
chrono
::
system_clock
::
now
()
;
bool
eosFlag
=
false
;
while
(
!
eosFlag
)
{
if
(
this
->
exit_
)
{
break
;
}
int
bufferID
=
GetFreeBufferId
();
if
(
bufferID
<
0
)
{
usleep
(
10000
);
usleep
(
10000
);
// 10000 for wait 10ms
continue
;
}
auto
iter
=
omxBuffers_
.
find
(
bufferID
);
if
(
iter
==
omxBuffers_
.
end
())
{
continue
;
}
BufferInfo
*
bufferInfo
=
iter
->
second
;
void
*
sharedAddr
=
(
void
*
)
bufferInfo
->
avSharedPtr
->
ReadFromAshmem
(
0
,
0
);
bool
bEOS
=
(
size_t
)
this
->
ReadOnePacket
(
fpIn_
,
(
char
*
)
sharedAddr
,
bufferInfo
->
omxBuffer
->
filledLen
);
HDF_LOGI
(
"read data size is %{public}d"
,
bufferInfo
->
omxBuffer
->
filledLen
);
auto
bufferInfo
=
iter
->
second
;
void
*
sharedAddr
=
const_cast
<
void
*>
(
bufferInfo
->
avSharedPtr
->
ReadFromAshmem
(
0
,
0
));
eosFlag
=
this
->
ReadOnePacket
(
fpIn_
,
static_cast
<
char
*>
(
sharedAddr
),
bufferInfo
->
omxBuffer
->
filledLen
);
bufferInfo
->
omxBuffer
->
offset
=
0
;
if
(
bEOS
)
{
if
(
eosFlag
)
{
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
)
{
HDF_LOGE
(
"%{public}s EmptyThisBuffer error"
,
__func__
);
return
;
...
...
@@ -529,180 +540,186 @@ while (!bEndOfFile) {
}
// wait
while
(
!
this
->
exit_
)
{
usleep
(
10000
);
continue
;
usleep
(
10000
);
// 10000 for wait 10ms
}
// 解码完成后使组件进入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分帧发送到服务端处理。分帧代码如下:
```
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
);
if
(
t
<
4
)
{
// 文件读取结束
// 读取起始码
size_t
t
=
fread
(
buf
,
1
,
START_CODE_SIZE_FRAME
,
fp
);
if
(
t
<
START_CODE_SIZE_FRAME
)
{
return
true
;
}
size_t
filled
=
0
;
filled
=
4
;
bool
bRet
=
true
;
char
*
temp
=
buf
;
temp
+=
START_CODE_SIZE_FRAME
;
bool
ret
=
true
;
while
(
!
feof
(
fp
))
{
fread
(
buf
+
filled
,
1
,
1
,
fp
);
if
(
buf
[
filled
]
==
1
)
{
(
void
)
fread
(
temp
,
1
,
1
,
fp
);
if
(
*
temp
!=
START_CODE
)
{
temp
++
;
continue
;
}
// 检查起始码
if
((
buf
[
filled
-
1
]
==
0
)
&&
(
buf
[
filled
-
2
]
==
0
)
&&
(
buf
[
filled
-
3
]
==
0
))
{
fseek
(
fp
,
-
4
,
SEEK_CUR
);
filled
-=
3
;
bRet
=
false
;
break
;
}
else
if
((
buf
[
filled
-
1
]
==
0
)
&&
(
buf
[
filled
-
2
]
==
0
))
{
fseek
(
fp
,
-
3
,
SEEK_CUR
);
filled
-=
2
;
bRet
=
false
;
if
((
temp
[
START_CODE_OFFSET_ONE
]
==
0
)
&&
(
temp
[
START_CODE_OFFSET_SEC
]
==
0
)
&&
(
temp
[
START_CODE_OFFSET_THIRD
]
==
0
))
{
fseek
(
fp
,
-
START_CODE_SIZE_FRAME
,
SEEK_CUR
);
temp
-=
(
START_CODE_SIZE_FRAME
-
1
);
ret
=
false
;
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
;
return
bR
et
;
filledCount
=
(
temp
-
buf
)
;
return
r
et
;
}
```
Codec HDI提供3个回调函数:EventHandler,EmptyBufferDone和FillBufferDone。
-
EventHandler:主要命令完成后的通知,例如:
OMX_StateIdle转为OMX_StateExecuting
的命令执行成功通知等。
-
EventHandler:主要命令完成后的通知,例如:
CODEC_STATE_IDLE转为CODEC_STATE_EXECUTING
的命令执行成功通知等。
-
EmptyBufferDone:输入数据消费完毕,客户端需要重新填入待编解码数据,再次调用EmptyThisBuffer。
-
FillBufferDone:输出数据填充完毕,客户端需要读取已编码/解码数据,再次调用FillThisBuffer。
```
cpp
// EmptyBufferDone回调处理示例
int32_t
OMXCore
::
OnEmptyBufferDone
(
struct
CodecCallbackType
*
self
,
int8_t
*
pAppData
,
uint32_t
pAppDataLen
,
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
)
int32_t
CodecHdiDecode
::
OnEmptyBufferDone
(
const
struct
OmxCodecBuffer
&
buffer
)
{
unique_lock
<
mutex
>
ulk
(
mLockInputBuffers_
);
unUsedInBuffers_
.
push_back
(
pBuffer
->
bufferId
);
HDF_LOGI
(
"OnEmptyBufferDone, bufferId [%{public}d]"
,
buffer
.
bufferId
);
unique_lock
<
mutex
>
ulk
(
lockInputBuffers_
);
unUsedInBuffers_
.
push_back
(
buffer
.
bufferId
);
return
HDF_SUCCESS
;
}
// FillBufferDone回调处理示例
int32_t
OMXCore
::
OnFillBufferDone
(
struct
CodecCallbackType
*
self
,
int8_t
*
pAppData
,
uint32_t
pAppDataLen
,
struct
OmxCodecBuffer
*
pBuffer
)
int32_t
CodecHdiDecode
::
OnFillBufferDone
(
const
struct
OmxCodecBuffer
&
buffer
)
{
HDF_LOGI
(
"onFillBufferDone: pBuffer.bufferID [%{public}d]"
,
pBuffer
->
bufferId
);
g_core
->
OnFillBufferDone
(
pBuffer
);
return
HDF_SUCCESS
;
}
int32_t
OMXCore
::
onFillBufferDone
(
struct
OmxCodecBuffer
*
pBuffer
)
{
// 根据bufferID找到buffer
if
(
bExit_
)
{
HDF_LOGI
(
"OnFillBufferDone, bufferId [%{public}d]"
,
buffer
.
bufferId
);
if
(
exit_
)
{
return
HDF_SUCCESS
;
}
auto
iter
=
omxBuffers_
.
find
(
pBuffer
->
bufferId
);
if
(
iter
==
omxBuffers_
.
end
()
||
!
iter
->
second
)
{
auto
iter
=
omxBuffers_
.
find
(
buffer
.
bufferId
);
if
(
(
iter
==
omxBuffers_
.
end
())
||
(
iter
->
second
==
nullptr
)
)
{
return
HDF_SUCCESS
;
}
// 取出输出的数据
BufferInfo
*
pBufferInfo
=
iter
->
second
;
const
void
*
addr
=
pBufferInfo
->
avSharedPtr
->
ReadFromAshmem
(
pBuffer
->
filledLen
,
pBuffer
->
offset
);
// 解码数据保存到文件
fwrite
(
addr
,
1
,
pBuffer
->
filledLen
,
fpOut_
.
get
());
fflush
(
fpOut_
.
get
());
// 重置buffer数据
pBuffer
->
offset
=
0
;
pBuffer
->
filledLen
=
0
;
if
(
pBuffer
->
flag
==
OMX_BUFFERFLAG_EOS
)
{
// 结束
bExit_
=
true
;
count_
++
;
// read buffer
auto
bufferInfo
=
iter
->
second
;
if
(
bufferInfo
->
avSharedPtr
!=
nullptr
)
{
const
void
*
addr
=
bufferInfo
->
avSharedPtr
->
ReadFromAshmem
(
buffer
.
filledLen
,
buffer
.
offset
);
(
void
)
fwrite
(
addr
,
1
,
buffer
.
filledLen
,
fpOut_
);
}
else
if
(
bufferInfo
->
bufferHandle
!=
nullptr
&&
gralloc_
!=
nullptr
)
{
gralloc_
->
Mmap
(
*
bufferInfo
->
bufferHandle
);
(
void
)
fwrite
(
bufferInfo
->
bufferHandle
->
virAddr
,
1
,
buffer
.
filledLen
,
fpOut_
);
gralloc_
->
Unmap
(
*
bufferInfo
->
bufferHandle
);
}
(
void
)
fflush
(
fpOut_
);
if
(
buffer
.
flag
==
OMX_BUFFERFLAG_EOS
)
{
// end
exit_
=
true
;
HDF_LOGI
(
"OnFillBufferDone the END coming"
);
return
HDF_SUCCESS
;
}
//
再次调用FillThisBuffer
auto
err
=
client_
->
FillThisBuffer
(
client_
,
pBufferInfo
->
pOmxBuffer
);
//
call fillthisbuffer again
auto
err
=
client_
->
FillThisBuffer
(
*
bufferInfo
->
omxBuffer
.
get
()
);
if
(
err
!=
HDF_SUCCESS
)
{
HDF_LOGE
(
"
FillThisBuffer error"
);
HDF_LOGE
(
"
%{public}s FillThisBuffer error"
,
__func__
);
return
HDF_SUCCESS
;
}
return
HDF_SUCCESS
;
}
// 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
)
{
case
OMX_EventCmdComplete
:
{
OMX_COMMANDTYPE
cmd
=
(
OMX_COMMANDTYPE
)
info
->
data1
;
if
(
OMX_CommandStateSet
==
cmd
)
{
HDF_LOGI
(
"
OMX_CommandStateSet reached, status is %{public}d"
,
info
->
data2
);
g_core
->
o
nStatusChanged
();
case
CODEC_EVENT_CMD_COMPLETE
:
{
CodecCommandType
cmd
=
(
CodecCommandType
)
info
.
data1
;
if
(
CODEC_COMMAND_STATE_SET
==
cmd
)
{
HDF_LOGI
(
"
CODEC_COMMAND_STATE_SET reached, status is %{public}d"
,
info
.
data2
);
this
->
O
nStatusChanged
();
}
break
;
}
case
OMX_EventPortSettingsChanged
:
{
HDF_LOGI
(
"OMX_EventPortSeetingsChanged reached"
);
this
->
HandleEventPortSettingsChanged
(
info
.
data1
,
info
.
data2
);
}
default:
break
;
}
return
HDF_SUCCESS
;
}
```
#### 接口去初始化
组件关闭前,需要将组件状态修改为
OMX_StateIdle,然后开始释放输入输出Buffer,再将组件状态修改为OMX_StateLoaded
,最后再调用DestoryComponent去关闭组件。
组件关闭前,需要将组件状态修改为
CODEC_STATE_IDLE,然后开始释放输入输出Buffer,再将组件状态修改为CODEC_STATE_LOADED
,最后再调用DestoryComponent去关闭组件。
##### Buffer释放示例
```
cpp
// 发送命令使组件进入OMX_StateLoaded状态
client_
->
SendCommand
(
client_
,
OMX_CommandStateSet
,
OMX_StateLoaded
,
nullptr
,
0
);
client_
->
SendCommand
(
CODEC_COMMAND_STATE_SET
,
CODEC_STATE_LOADED
,
{}
);
// 释放所有申请的buffer
auto
iter
=
omxBuffers_
.
begin
();
while
(
iter
!=
omxBuffers_
.
end
())
{
BufferInfo
*
bufferInfo
=
iter
->
second
;
client_
->
FreeBuffer
(
client_
,
(
uint32_t
)
bufferInfo
->
portIndex
,
bufferInfo
->
omxBuff
er
);
delete
bufferInfo
;
iter
++
;
auto
bufferInfo
=
iter
->
second
;
iter
=
omxBuffers_
.
erase
(
it
er
);
(
void
)
client_
->
FreeBuffer
((
uint32_t
)
bufferInfo
->
portIndex
,
*
bufferInfo
->
omxBuffer
.
get
())
;
bufferInfo
=
nullptr
;
}
omxBuffers_
.
clear
();
unUsedInBuffers_
.
clear
();
unUsedOutBuffers_
.
clear
();
enum
OMX_STATETYPE
status
;
client_
->
GetState
(
client_
,
&
status
);
// 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"
);
this
->
WaitForStatusChanged
();
}
else
{
HDF_LOGI
(
" status is %{public}d"
,
status
)
;
}
}
tryCount
--
;
}
while
((
status
!=
CODEC_STATE_LOADED
)
&&
(
tryCount
>
0
));
```
##### 组件实例释放示例
```
cpp
// 组件实例释放
void
OMXCore
::
Release
()
{
omxMgr_
->
DestoryComponent
(
client_
);
void
CodecHdiDecode
::
Release
()
{
omxMgr_
->
DestoryComponent
(
componentId_
);
client_
=
nullptr
;
CodecComponentManagerRelease
();
callback_
=
nullptr
;
omxMgr_
=
nullptr
;
}
```
...
...
@@ -747,7 +764,6 @@ OpenMax对AVCC格式的数据处理,第一帧一定要是extra_data,可能
1.
输出端口的xFramerate参数未正常设置。
2.
如果设置了参数OMX_VIDEO_PARAM_AVCTYPE,请检查此参数是否正确。
**解决办法**
请看编码时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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录