diff --git a/codec/hal/BUILD.gn b/codec/hal/BUILD.gn index 78169225935497204dc04258b6914b6817ceabec..bf39bdf5fee06bc49064916676ec1e98ee35a68d 100644 --- a/codec/hal/BUILD.gn +++ b/codec/hal/BUILD.gn @@ -83,11 +83,19 @@ ohos_shared_library("libcodec_hdi_omx_client") { ohos_shared_library("libcodec_hdi_omx_service_impl") { include_dirs = [ "//drivers/adapter/uhdf2/include/hdi", + "//drivers/peripheral/codec/hal/v2.0/hdi_impl/include", "//drivers/peripheral/codec/interfaces/include", "//drivers/peripheral/codec/hal/include", "//third_party/openmax/api/1.1.2", + "//drivers/peripheral/base", + ] + sources = [ + "src/codec_adapter.cpp", + "src/codec_component_type_service.c", + "v2.0/hdi_impl/src/component_mgr.cpp", + "v2.0/hdi_impl/src/component_node.cpp", + "v2.0/hdi_impl/src/component_node_mgr.cpp", ] - sources = [ "src/codec_component_type_service.c" ] if (is_standard_system) { external_deps = [ diff --git a/codec/hal/include/codec_adapter_interface.h b/codec/hal/include/codec_adapter_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..63aee1ae6afb3385419fc128c6f5f8699e2842f0 --- /dev/null +++ b/codec/hal/include/codec_adapter_interface.h @@ -0,0 +1,114 @@ +/* + * 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. + */ + +#ifndef CODEC_OMX_ADAPTER_INTERFACE_H +#define CODEC_OMX_ADAPTER_INTERFACE_H +#include "codec_callback_if.h" +#include "codec_types.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create a component by name. + */ +extern int32_t OMXAdapterCreateComponent(OMX_HANDLETYPE *compHandle, char *compName, int8_t *appData, + int32_t appDataSize, struct CodecCallbackType *callbacks); +/** + * @brief Release the componet by handle. + */ +extern int32_t OmxAdapterDestoryComponent(OMX_HANDLETYPE compHandle); +/** + * @brief Get the version of the component. + */ +extern int32_t OmxAdapterComponentVersion(OMX_HANDLETYPE compHandle, struct CompVerInfo *verInfo); +/** + * @brief Send command to the component. + */ +extern int32_t OmxAdapterSendCommand(OMX_HANDLETYPE compHandle, enum OMX_COMMANDTYPE cmd, uint32_t param, + int8_t *cmdData, uint32_t cmdDataLen); +/** + * @brief Get the parameter by index. + */ +extern int32_t OmxAdapterGetParameter(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE paramIndex, int8_t *param, + uint32_t paramLen); +/** + * @brief Set the parameter by index. + */ +extern int32_t OmxAdapterSetParameter(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE index, int8_t *param, + uint32_t paramLen); +/** + * @brief Get the config by index. + * + * This func can be invoked when the component is in any state except the OMX_StateInvalid state. + */ +extern int32_t OmxAdapterGetConfig(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE index, int8_t *config, + uint32_t configLen); +extern int32_t OmxAdapterSetConfig(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE index, int8_t *config, + uint32_t configLen); +extern int32_t OmxAdapterGetExtensionIndex(OMX_HANDLETYPE compHandle, const char *parameterName, + enum OMX_INDEXTYPE *indexType); +extern int32_t OmxAdapterGetState(OMX_HANDLETYPE compHandle, enum OMX_STATETYPE *state); +/** + * @brief Set up tunneled communication between an output port and an input port. + */ +extern int32_t OmxAdapterComponentTunnelRequest(OMX_HANDLETYPE compHandle, uint32_t port, + int32_t omxHandleTypeTunneledComp, uint32_t tunneledPort, + struct OMX_TUNNELSETUPTYPE *tunnelSetup); +/** + * @brief The component uses a buffer already allocated by the IL client. + */ +extern int32_t OmxAdapterUseBuffer(OMX_HANDLETYPE compHandle, uint32_t portIndex, struct OmxCodecBuffer *omxBuffer); +/** + * @brief The component allocate a buffer. + */ +extern int32_t OmxAdapterAllocateBuffer(OMX_HANDLETYPE compHandle, uint32_t portIndex, + struct OmxCodecBuffer *omxBuffer); +/** + * @brief The component free the buffer. + */ +extern int32_t OmxAdapterFreeBuffer(OMX_HANDLETYPE compHandle, uint32_t portIndex, struct OmxCodecBuffer *omxBuffer); +/** + * @brief Send a filled buffer to the input port of the component. + */ +extern int32_t OmxAdapterEmptyThisBuffer(OMX_HANDLETYPE compHandle, struct OmxCodecBuffer *omxBuffer); +/** + * @brief Send a empty buffer to the output port of the component. + */ +extern int32_t OmxAdapterFillThisBuffer(OMX_HANDLETYPE compHandle, struct OmxCodecBuffer *omxBuffer); +/** + * @brief Set the callback. + */ +extern int32_t OmxAdapterSetCallbacks(OMX_HANDLETYPE compHandle, struct CodecCallbackType *omxCallback, int8_t *appData, + uint32_t appDataLen); +/** + * @brief DeInit the component. + */ +extern int32_t OmxAdapterDeInit(OMX_HANDLETYPE compHandle); +/** + * @brief The component use the buffer allocated in EGL. + */ +extern int32_t OmxAdapterUseEglImage(OMX_HANDLETYPE compHandle, struct OmxCodecBuffer *buffer, uint32_t portIndex, + int8_t *eglImage, uint32_t eglImageLen); +/** + * @brief Get the role of the component. + */ +extern int32_t OmxAdapterComponentRoleEnum(OMX_HANDLETYPE compHandle, uint8_t *role, uint32_t roleLen, uint32_t index); + +#ifdef __cplusplus +}; +#endif + +#endif // CODEC_OMX_ADAPTER_INTERFACE_H \ No newline at end of file diff --git a/codec/hal/src/codec_adapter.cpp b/codec/hal/src/codec_adapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e20eb93dc5449c481bb2cc1e28b478dce4f20829 --- /dev/null +++ b/codec/hal/src/codec_adapter.cpp @@ -0,0 +1,132 @@ +/* + * 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_adapter_interface.h" +#include "component_node_mgr.h" +using namespace OHOS::Codec::Omx; + +static ComponentNodeMgr g_mgr; +#ifdef __cplusplus +extern "C" { +#endif + +int32_t OMXAdapterCreateComponent(OMX_HANDLETYPE *compHandle, char *compName, int8_t *appData, int32_t appDataSize, + struct CodecCallbackType *callbacks) +{ + return g_mgr.CreateComponent(compHandle, compName, appData, appDataSize, callbacks); +} + +int32_t OmxAdapterDestoryComponent(OMX_HANDLETYPE compHandle) +{ + return g_mgr.DestoryComponent(compHandle); +} + +int32_t OmxAdapterComponentVersion(OMX_HANDLETYPE compHandle, struct CompVerInfo *verInfo) +{ + return g_mgr.GetComponentVersion(compHandle, *verInfo); +} + +int32_t OmxAdapterSendCommand(OMX_HANDLETYPE compHandle, enum OMX_COMMANDTYPE cmd, uint32_t param, int8_t *cmdData, + uint32_t cmdDataLen) +{ + return g_mgr.SendCommand(compHandle, cmd, param, cmdData, cmdDataLen); +} + +int32_t OmxAdapterGetParameter(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE paramIndex, int8_t *param, + uint32_t paramLen) +{ + return g_mgr.GetParameter(compHandle, paramIndex, param, paramLen); +} + +int32_t OmxAdapterSetParameter(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE index, int8_t *param, uint32_t paramLen) +{ + return g_mgr.SetParameter(compHandle, index, param, paramLen); +} + +int32_t OmxAdapterGetConfig(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE index, int8_t *config, uint32_t configLen) +{ + return g_mgr.GetConfig(compHandle, index, config, configLen); +} + +int32_t OmxAdapterSetConfig(OMX_HANDLETYPE compHandle, enum OMX_INDEXTYPE index, int8_t *config, uint32_t configLen) +{ + return g_mgr.SetConfig(compHandle, index, config, configLen); +} + +int32_t OmxAdapterGetExtensionIndex(OMX_HANDLETYPE compHandle, const char *parameterName, enum OMX_INDEXTYPE *indexType) +{ + return g_mgr.GetExtensionIndex(compHandle, parameterName, indexType); +} + +int32_t OmxAdapterGetState(OMX_HANDLETYPE compHandle, enum OMX_STATETYPE *state) +{ + return g_mgr.GetState(compHandle, state); +} + +int32_t OmxAdapterComponentTunnelRequest(OMX_HANDLETYPE compHandle, uint32_t port, int32_t omxHandleTypeTunneledComp, + uint32_t tunneledPort, struct OMX_TUNNELSETUPTYPE *tunnelSetup) +{ + return g_mgr.ComponentTunnelRequest(compHandle, port, omxHandleTypeTunneledComp, tunneledPort, tunnelSetup); +} + +int32_t OmxAdapterUseBuffer(OMX_HANDLETYPE compHandle, uint32_t portIndex, struct OmxCodecBuffer *omxBuffer) +{ + return g_mgr.UseBuffer(compHandle, portIndex, *omxBuffer); +} + +int32_t OmxAdapterAllocateBuffer(OMX_HANDLETYPE compHandle, uint32_t portIndex, struct OmxCodecBuffer *omxBuffer) +{ + return g_mgr.AllocateBuffer(compHandle, portIndex, *omxBuffer); +} + +int32_t OmxAdapterFreeBuffer(OMX_HANDLETYPE compHandle, uint32_t portIndex, struct OmxCodecBuffer *omxBuffer) +{ + return g_mgr.FreeBuffer(compHandle, portIndex, *omxBuffer); +} + +int32_t OmxAdapterEmptyThisBuffer(OMX_HANDLETYPE compHandle, struct OmxCodecBuffer *omxBuffer) +{ + return g_mgr.EmptyThisBuffer(compHandle, *omxBuffer); +} + +int32_t OmxAdapterFillThisBuffer(OMX_HANDLETYPE compHandle, struct OmxCodecBuffer *omxBuffer) +{ + return g_mgr.FillThisBuffer(compHandle, *omxBuffer); +} + +int32_t OmxAdapterSetCallbacks(OMX_HANDLETYPE compHandle, struct CodecCallbackType *omxCallback, int8_t *appData, + uint32_t appDataLen) +{ + return g_mgr.SetCallbacks(compHandle, omxCallback, appData, appDataLen); +} + +int32_t OmxAdapterDeInit(OMX_HANDLETYPE compHandle) +{ + return g_mgr.DeInit(compHandle); +} + +int32_t OmxAdapterUseEglImage(OMX_HANDLETYPE compHandle, struct OmxCodecBuffer *buffer, uint32_t portIndex, + int8_t *eglImage, uint32_t eglImageLen) +{ + return g_mgr.UseEglImage(compHandle, *buffer, portIndex, eglImage, eglImageLen); +} + +int32_t OmxAdapterComponentRoleEnum(OMX_HANDLETYPE compHandle, uint8_t *role, uint32_t roleLen, uint32_t index) +{ + return g_mgr.ComponentRoleEnum(compHandle, role, roleLen, index); +} +#ifdef __cplusplus +}; +#endif diff --git a/codec/hal/src/codec_component_type_service.c b/codec/hal/src/codec_component_type_service.c index 7738edc4f265aeaebef58d6fd5e263d8078a0171..4cda2f3c1558473ff879e0b635b6c9c7e56d00e0 100644 --- a/codec/hal/src/codec_component_type_service.c +++ b/codec/hal/src/codec_component_type_service.c @@ -13,9 +13,14 @@ * limitations under the License. */ -#include "codec_component_type_service.h" #include #include +#include +#include +#include +#include "codec_adapter_interface.h" +#include "codec_component_type_stub.h" +#include "codec_component_type_service.h" #define HDF_LOG_TAG codec_hdi_server @@ -23,68 +28,81 @@ int32_t OmxManagerCreateComponent(OMX_HANDLETYPE *compHandle, char *compName, vo struct CodecCallbackType *callbacks) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + return OMXAdapterCreateComponent(compHandle, compName, (int8_t*)appData, appDataSize, callbacks); } int32_t OmxManagerDestroyComponent(OMX_HANDLETYPE compHandle) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + return OmxAdapterDestoryComponent(compHandle); } int32_t CodecComponentTypeGetComponentVersion(struct CodecComponentType *self, struct CompVerInfo *verInfo) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterComponentVersion(stub->componentHandle, verInfo); } int32_t CodecComponentTypeSendCommand(struct CodecComponentType *self, enum OMX_COMMANDTYPE cmd, uint32_t param, int8_t *cmdData, uint32_t cmdDataLen) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterSendCommand(stub->componentHandle, cmd, param, cmdData, cmdDataLen); } int32_t CodecComponentTypeGetParameter(struct CodecComponentType *self, uint32_t paramIndex, int8_t *paramStruct, uint32_t paramStructLen) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterGetParameter(stub->componentHandle, paramIndex, paramStruct, paramStructLen); } int32_t CodecComponentTypeSetParameter(struct CodecComponentType *self, uint32_t index, int8_t *paramStruct, uint32_t paramStructLen) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterSetParameter(stub->componentHandle, index, paramStruct, paramStructLen); } int32_t CodecComponentTypeGetConfig(struct CodecComponentType *self, uint32_t index, int8_t *cfgStruct, uint32_t cfgStructLen) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterGetConfig(stub->componentHandle, index, cfgStruct, cfgStructLen); } int32_t CodecComponentTypeSetConfig(struct CodecComponentType *self, uint32_t index, int8_t *cfgStruct, uint32_t cfgStructLen) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterSetConfig(stub->componentHandle, index, cfgStruct, cfgStructLen); } int32_t CodecComponentTypeGetExtensionIndex(struct CodecComponentType *self, const char *paramName, uint32_t *indexType) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterGetExtensionIndex(stub->componentHandle, paramName, (enum OMX_INDEXTYPE *)indexType); } -int32_t CodecComponentTypeGetState(struct CodecComponentType *self, - enum OMX_STATETYPE *state) +int32_t CodecComponentTypeGetState(struct CodecComponentType *self, enum OMX_STATETYPE *state) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterGetState(stub->componentHandle, state); } int32_t CodecComponentTypeComponentTunnelRequest(struct CodecComponentType *self, @@ -92,69 +110,85 @@ int32_t CodecComponentTypeComponentTunnelRequest(struct CodecComponentType *self struct OMX_TUNNELSETUPTYPE *tunnelSetup) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterComponentTunnelRequest(stub->componentHandle, port, tunneledComp, tunneledPort, tunnelSetup); } int32_t CodecComponentTypeUseBuffer(struct CodecComponentType *self, uint32_t portIndex, struct OmxCodecBuffer *buffer) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterUseBuffer(stub->componentHandle, portIndex, buffer); } int32_t CodecComponentTypeAllocateBuffer(struct CodecComponentType *self, uint32_t portIndex, struct OmxCodecBuffer *buffer) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterAllocateBuffer(stub->componentHandle, portIndex, buffer); } int32_t CodecComponentTypeFreeBuffer(struct CodecComponentType *self, uint32_t portIndex, const struct OmxCodecBuffer *buffer) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterFreeBuffer(stub->componentHandle, portIndex, (struct OmxCodecBuffer *)buffer); } int32_t CodecComponentTypeEmptyThisBuffer(struct CodecComponentType *self, const struct OmxCodecBuffer *buffer) { - HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterEmptyThisBuffer(stub->componentHandle, (struct OmxCodecBuffer *)buffer); } int32_t CodecComponentTypeFillThisBuffer(struct CodecComponentType *self, const struct OmxCodecBuffer *buffer) { - HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterFillThisBuffer(stub->componentHandle, (struct OmxCodecBuffer *)buffer); } int32_t CodecComponentTypeSetCallbacks(struct CodecComponentType *self, struct CodecCallbackType* callback, int8_t *appData, uint32_t appDataLen) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterSetCallbacks(stub->componentHandle, callback, appData, appDataLen); } int32_t CodecComponentTypeComponentDeInit(struct CodecComponentType *self) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterDeInit(stub->componentHandle); } int32_t CodecComponentTypeUseEglImage(struct CodecComponentType *self, struct OmxCodecBuffer *buffer, uint32_t portIndex, int8_t *eglImage, uint32_t eglImageLen) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterUseEglImage(stub->componentHandle, buffer, portIndex, eglImage, eglImageLen); } int32_t CodecComponentTypeComponentRoleEnum(struct CodecComponentType *self, uint8_t *role, uint32_t roleLen, uint32_t index) { HDF_LOGI("%{public}s, service impl!", __func__); - return HDF_SUCCESS; + + struct CodecComponentTypeStub *stub = (struct CodecComponentTypeStub *)self; + return OmxAdapterComponentRoleEnum(stub->componentHandle, role, roleLen, index); } void CodecComponentTypeServiceConstruct(struct OmxComponentManager *manager, struct CodecComponentType *instance) diff --git a/codec/hal/src/codec_types.c b/codec/hal/src/codec_types.c index 6e64c413e9c1a70b2e848746d5a5ef835f7b895f..f0c95abda2f0747c58565e0ffb4c322e1a0edf36 100644 --- a/codec/hal/src/codec_types.c +++ b/codec/hal/src/codec_types.c @@ -78,7 +78,7 @@ static bool CodecBufferMarshalling(struct HdfSBuf *data, const struct OmxCodecBu } if (dataBlock->bufferType == BUFFER_TYPE_AVSHARE_MEM_FD) { - int32_t fd = (int32_t)dataBlock->buffer; + int fd = (int)dataBlock->buffer; if (!HdfSbufWriteFileDescriptor(data, fd)) { HDF_LOGE("%{public}s: write fd failed!", __func__); return false; @@ -171,7 +171,7 @@ static bool CodecBufferUnmarshalling(struct HdfSBuf *data, struct OmxCodecBuffer return true; } if (dataBlock->bufferType == BUFFER_TYPE_AVSHARE_MEM_FD) { - int32_t fd = HdfSbufReadFileDescriptor(data); + int fd = HdfSbufReadFileDescriptor(data); if (fd < 0) { HDF_LOGE("%{public}s: read fd failed!", __func__); return false; diff --git a/codec/hal/v2.0/hdi_impl/src/component_mgr.cpp b/codec/hal/v2.0/hdi_impl/src/component_mgr.cpp index 9f43557e762a8fb6ca08bb932ba3992a341691a8..af0882acc875ec6fcce336f59adde98bca68ca91 100644 --- a/codec/hal/v2.0/hdi_impl/src/component_mgr.cpp +++ b/codec/hal/v2.0/hdi_impl/src/component_mgr.cpp @@ -105,7 +105,7 @@ int32_t ComponentMgr::EnumerateComponentsByIndex(uint32_t index, char *component { size_t componentNum = componentNameAndObjectPoint_.size(); if (index >= componentNum) { - HDF_LOGE("%{public}s index [%{public}d] > componentNum [%{public}d]", __func__, index, componentNum); + HDF_LOGE("%{public}s index [%{public}d] > componentNum [%{public}zu]", __func__, index, componentNum); return OMX_ErrorInvalidComponentName; } std::string &compName = componentNameAndObjectPoint_[index].componentName; diff --git a/codec/hal/v2.0/hdi_impl/src/component_node.cpp b/codec/hal/v2.0/hdi_impl/src/component_node.cpp index cb1141f8fd980b65b29d54aeb26e749a0b618aa2..e536eaa34caff6685989ba3feeb0e435ba869999 100644 --- a/codec/hal/v2.0/hdi_impl/src/component_node.cpp +++ b/codec/hal/v2.0/hdi_impl/src/component_node.cpp @@ -114,8 +114,6 @@ ComponentNode::~ComponentNode() omxCallback_ = nullptr; } - HDF_LOGI("%{public}s bufferInfoMap_.size()=[%{public}d],bufferHeaderMap_.size()=[%{public}d]", __func__, - bufferInfoMap_.size(), bufferHeaderMap_.size()); bufferInfoMap_.clear(); bufferHeaderMap_.clear(); bufferIdCount_ = 0; @@ -214,7 +212,8 @@ int32_t ComponentNode::ComponentTunnelRequest(uint32_t port, int32_t omxHandleTy return OMX_ErrorInvalidComponent; } OMX_COMPONENTTYPE *comType = static_cast(comp_); - return comType->ComponentTunnelRequest(comp_, port, (OMX_HANDLETYPE)omxHandleTypeTunneledComp, tunneledPort, + unsigned long tunneledComp = (unsigned long)omxHandleTypeTunneledComp; + return comType->ComponentTunnelRequest(comp_, port, (OMX_HANDLETYPE)tunneledComp, tunneledPort, tunnelSetup); } @@ -442,7 +441,7 @@ int32_t ComponentNode::AllocateBuffer(uint32_t portIndex, struct OmxCodecBuffer int sharedFD = AshmemCreate(nullptr, bufferHdrType->nAllocLen); std::shared_ptr sharedMemory = std::make_shared(sharedFD, bufferHdrType->nAllocLen); SaveBufferInfo(buffer, bufferHdrType, sharedMemory); - buffer.buffer = (uint8_t *)&sharedFD; + buffer.buffer = (uint8_t *)(unsigned long)sharedFD; buffer.bufferLen = FD_SIZE; return OMX_ErrorNone; } @@ -609,7 +608,7 @@ void ComponentNode::CheckBuffer(struct OmxCodecBuffer &buffer) { if ((buffer.buffer != nullptr) && (buffer.bufferType == BUFFER_TYPE_AVSHARE_MEM_FD) && (buffer.bufferLen == FD_SIZE)) { - int fd = reinterpret_cast(buffer.buffer); + int fd = (int)reinterpret_cast(buffer.buffer); close(fd); buffer.buffer = 0; buffer.bufferLen = 0; @@ -630,8 +629,6 @@ BufferInfoSPtr ComponentNode::GetBufferInfoByHeader(OMX_BUFFERHEADERTYPE *buffer } uint32_t nBufferID = iterHead->second; - HDF_LOGI("%{public}s buffer[%{public}p], nBufferID[%{public}d], ", __func__, buffer, nBufferID); - auto iter = bufferInfoMap_.find(nBufferID); if (iter == bufferInfoMap_.end()) { HDF_LOGE("%{public}s can not find bufferInfo by nBufferID = %{public}d", __func__, nBufferID); @@ -704,7 +701,7 @@ int32_t ComponentNode::UseSharedBuffer(struct OmxCodecBuffer &omxCodecBuffer, ui return err; } - int shardFd = reinterpret_cast(omxCodecBuffer.buffer); + int shardFd = (int)reinterpret_cast(omxCodecBuffer.buffer); if (shardFd < 0) { HDF_LOGE("%{public}s error, shardFd < 0", __func__); return err; @@ -744,7 +741,7 @@ int32_t ComponentNode::UseHandleBuffer(struct OmxCodecBuffer &omxCodecBuffer, ui int32_t err = OMX_ErrorUndefined; if (sizeof(BufferHandle) != omxCodecBuffer.bufferLen) { - HDF_LOGE("%{public}s error, BufferHandle size = %{public}d, omxBuffer.ptrSize = %{public}d ", __func__, + HDF_LOGE("%{public}s error, BufferHandle size = %{public}zu, omxBuffer.ptrSize = %{public}d ", __func__, sizeof(BufferHandle), omxCodecBuffer.bufferLen); return err; } diff --git a/codec/hal/v2.0/hdi_impl/src/component_node_mgr.cpp b/codec/hal/v2.0/hdi_impl/src/component_node_mgr.cpp index 30cf6feab607bd9274c553851ffe0efebb9385e8..72331a9d8cc88d034627cac049b215c34b545827 100644 --- a/codec/hal/v2.0/hdi_impl/src/component_node_mgr.cpp +++ b/codec/hal/v2.0/hdi_impl/src/component_node_mgr.cpp @@ -54,7 +54,7 @@ int32_t ComponentNodeMgr::CreateComponent(OMX_HANDLETYPE *compHandle, char *comp node = nullptr; return err; } - HDF_LOGI("%{public}s ceate component handle [%{public}d] ", __func__, (int)comp); + HDF_LOGI("%{public}s ceate component handle [%{public}p] ", __func__, comp); *compHandle = (OMX_HANDLETYPE)comp; node->SetHandle((OMX_HANDLETYPE)comp); diff --git a/codec/test/BUILD.gn b/codec/test/BUILD.gn index 783a437f96b37fdc0592740bd0d0fff91d76d368..772309a1ab29265b0da2fb3b5fd7ecd97a760af9 100644 --- a/codec/test/BUILD.gn +++ b/codec/test/BUILD.gn @@ -13,5 +13,8 @@ group("hdf_test_media_codec") { testonly = true - deps = [ "unittest:hdf_unittest_codec" ] + deps = [ + "demo/v2.0:codec_hdi_omx_demo", + "unittest:hdf_unittest_codec", + ] } diff --git a/codec/test/demo/v2.0/BUILD.gn b/codec/test/demo/v2.0/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..450c2480bdc77a4c6a369d7e7e13e97d9836a89f --- /dev/null +++ b/codec/test/demo/v2.0/BUILD.gn @@ -0,0 +1,98 @@ +# Copyright (c) 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. + +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") +ohos_executable("codec_hdi_omx_decode") { + include_dirs = [ + "./include", + "//drivers/peripheral/codec/hal/include", + "//drivers/adapter/uhdf2/include/hdi", + "//drivers/peripheral/codec/omx/include", + "//drivers/peripheral/codec/interfaces/include", + "//drivers/peripheral/codec/hal/config/capability_config/include", + "//drivers/peripheral/codec/hal/config/common/include", + "//utils/native/base/include", + "//third_party/openmax/api/1.1.2", + ] + + cflags_cc = [ "-DRK" ] + + sources = [ "src/codec_hdi_decode.cpp" ] + + deps = [ + "//drivers/adapter/uhdf2/hdi:libhdi", + "//drivers/adapter/uhdf2/host:libhdf_host", + "//drivers/adapter/uhdf2/ipc:libhdf_ipc_adapter", + "//drivers/adapter/uhdf2/utils:libhdf_utils", + "//drivers/peripheral/codec/hal:libcodec_hdi_omx_callback_type_service_impl", + "//drivers/peripheral/codec/hal:libcodec_hdi_omx_client", + "//third_party/bounds_checking_function:libsec_shared", + "//utils/native/base:utils", + ] + + if (is_standard_system) { + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + } else { + external_deps = [ "hilog:libhilog" ] + } + install_enable = false + install_images = [ chipset_base_dir ] + subsystem_name = "hdf" + part_name = "codec_device_driver" +} + +ohos_executable("codec_hdi_omx_encode") { + include_dirs = [ + "./include", + "//drivers/peripheral/codec/hal/include", + "//drivers/adapter/uhdf2/include/hdi", + "//drivers/peripheral/codec/omx/include", + "//drivers/peripheral/codec/interfaces/include", + "//drivers/peripheral/codec/hal/config/capability_config/include", + "//drivers/peripheral/codec/hal/config/common/include", + "//utils/native/base/include", + "//third_party/openmax/api/1.1.2", + ] + + cflags_cc = [ "-DRK" ] + + sources = [ "src/codec_hdi_encode.cpp" ] + + deps = [ + "//drivers/adapter/uhdf2/hdi:libhdi", + "//drivers/adapter/uhdf2/host:libhdf_host", + "//drivers/adapter/uhdf2/ipc:libhdf_ipc_adapter", + "//drivers/adapter/uhdf2/utils:libhdf_utils", + "//drivers/peripheral/codec/hal:libcodec_hdi_omx_callback_type_service_impl", + "//drivers/peripheral/codec/hal:libcodec_hdi_omx_client", + "//third_party/bounds_checking_function:libsec_shared", + "//utils/native/base:utils", + ] + + if (is_standard_system) { + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + } else { + external_deps = [ "hilog:libhilog" ] + } + install_enable = false + install_images = [ chipset_base_dir ] + subsystem_name = "hdf" + part_name = "codec_device_driver" +} +group("codec_hdi_omx_demo") { + deps = [ + ":codec_hdi_omx_decode", + ":codec_hdi_omx_encode", + ] +} diff --git a/codec/test/demo/v2.0/include/codec_hdi_decode.h b/codec/test/demo/v2.0/include/codec_hdi_decode.h new file mode 100644 index 0000000000000000000000000000000000000000..1e041b9590494f7b1a6f52945bcfc4235cf4769a --- /dev/null +++ b/codec/test/demo/v2.0/include/codec_hdi_decode.h @@ -0,0 +1,137 @@ +/* + * 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. + */ + +#ifndef CODEC_HDI_DECODE_H +#define CODEC_HDI_DECODE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "codec_callback_type_service.h" +#include "codec_callback_type_stub.h" +#include "codec_component_manager.h" +#include "codec_component_type.h" +#include "codec_types.h" + +enum class codecMime { AVC, HEVC }; + +enum class PortIndex { PORT_INDEX_INPUT = 0, PORT_INDEX_OUTPUT = 1 }; + +struct inParameters { + codecMime codec = codecMime::AVC; + std::string path; + unsigned int width = 144; + unsigned int height = 176; +}; + +struct privateApp { + codecMime codec = codecMime::AVC; + unsigned int width = 640; + unsigned int height = 480; + OMX_COLOR_FORMATTYPE format = OMX_COLOR_FormatYUV420SemiPlanar; + OMX_U32 framerate = 30; + OMX_HANDLETYPE handle; + OMX_PTR pAppData = nullptr; + bool isSupply_ = false; +}; + +using OmxCodecBuffer = struct OmxCodecBuffer; +struct BufferInfo { + std::shared_ptr omxBuffer; + std::shared_ptr avSharedPtr; + PortIndex portIndex; + BufferInfo() + { + omxBuffer = nullptr; + avSharedPtr = nullptr; + portIndex = PortIndex::PORT_INDEX_INPUT; + } + ~BufferInfo() + { + omxBuffer = nullptr; + if (avSharedPtr) { + avSharedPtr->UnmapAshmem(); + avSharedPtr->CloseAshmem(); + avSharedPtr = nullptr; + } + portIndex = PortIndex::PORT_INDEX_INPUT; + } +}; +using BufferInfo = struct BufferInfo; +class CodecHdiDecode { +public: + explicit CodecHdiDecode(); + ~CodecHdiDecode(); + bool Init(int width, int height, std::string &filename, codecMime codec); + bool Configure(); + bool UseBuffers(); + void FreeBuffers(); + void Run(); + void Release(); + static int32_t OnEvent(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct EventInfo *info); + static int32_t OnEmptyBufferDone(struct CodecCallbackType *self, int8_t *appData, uint32_t appDataLen, + const struct OmxCodecBuffer *buffer); + static int32_t OnFillBufferDone(struct CodecCallbackType *self, int8_t *appData, uint32_t appDataLen, + struct OmxCodecBuffer *buffer); + template inline void InitParam(T ¶m) + { + memset_s(¶m, sizeof(param), 0x0, sizeof(param)); + param.nSize = sizeof(param); + param.nVersion.s.nVersionMajor = 1; // mVersion.s.nVersionMajor; + } + void WaitForStatusChanged(); + void onStatusChanged(); + bool ReadOnePacket(FILE *fp, char *buf, size_t &filledCount); + +private: + int32_t UseBufferOnPort(PortIndex portIndex); + int32_t UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize); + int32_t OnEmptyBufferDone(const struct OmxCodecBuffer &buffer); + int32_t OnFillBufferDone(struct OmxCodecBuffer &buffer); + int GetYuvSize(); + int32_t ConfigPortDefine(); + bool FillAllTheBuffer(); + int GetFreeBufferId(); + +private: + FILE *fpIn_; // input file + FILE *fpOut_; + unsigned int width_; + unsigned int height_; + struct CodecComponentType *client_; + struct CodecCallbackType *callback_; + struct CodecComponentManager *omxMgr_; + std::map> omxBuffers_; // key is buferid + std::list unUsedInBuffers_; + std::list unUsedOutBuffers_; + std::mutex lockInputBuffers_; + std::condition_variable statusCondition_; + std::mutex statusLock_; + bool exit_; + bool isSupply_; + codecMime codecMime_; +}; +#endif /* CODEC_HDI_DECODE_H */ \ No newline at end of file diff --git a/codec/test/demo/v2.0/include/codec_hdi_encode.h b/codec/test/demo/v2.0/include/codec_hdi_encode.h new file mode 100644 index 0000000000000000000000000000000000000000..1a83ddf6119905e87b8db24d06ed4c26a668b1e3 --- /dev/null +++ b/codec/test/demo/v2.0/include/codec_hdi_encode.h @@ -0,0 +1,120 @@ +/* + * 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. + */ + +#ifndef CODEC_HDI_ENCODE_H +#define CODEC_HDI_ENCODE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "codec_callback_type_service.h" +#include "codec_callback_type_stub.h" +#include "codec_component_manager.h" +#include "codec_component_type.h" +#include "codec_types.h" + +enum class codecMime { AVC }; + +enum class PortIndex { PORT_INDEX_INPUT = 0, PORT_INDEX_OUTPUT = 1 }; + +struct BufferInfo { + std::shared_ptr omxBuffer; + std::shared_ptr avSharedPtr; + PortIndex portIndex; + BufferInfo() + { + omxBuffer = nullptr; + avSharedPtr = nullptr; + portIndex = PortIndex::PORT_INDEX_INPUT; + } + ~BufferInfo() + { + omxBuffer = nullptr; + if (avSharedPtr) { + avSharedPtr->UnmapAshmem(); + avSharedPtr->CloseAshmem(); + avSharedPtr = nullptr; + } + portIndex = PortIndex::PORT_INDEX_INPUT; + } +}; +using BufferInfo = struct BufferInfo; +class CodecHdiEncode { +public: + CodecHdiEncode(); + ~CodecHdiEncode(); + + bool Init(int width, int height, std::string &filename); + bool Configure(); + bool UseBuffers(); + int32_t UseBufferOnPort(PortIndex portIndex); + void FreeBuffers(); + void Run(); + void Release(); + static int32_t OnEvent(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct EventInfo *info); + + static int32_t OnEmptyBufferDone(struct CodecCallbackType *self, int8_t *appData, uint32_t appDataLen, + const struct OmxCodecBuffer *buffer); + static int32_t OnFillBufferDone(struct CodecCallbackType *self, int8_t *appData, uint32_t appDataLen, + struct OmxCodecBuffer *buffer); + template inline void InitParam(T ¶m) + { + memset_s(¶m, sizeof(param), 0x0, sizeof(param)); + param.nSize = sizeof(param); + param.nVersion.s.nVersionMajor = 1; + } + void WaitForStatusChanged(); + void onStatusChanged(); + bool ReadOneFrame(FILE *fp, char *buf, size_t &filledCount); + +private: + int32_t OnEmptyBufferDone(const struct OmxCodecBuffer &buffer); + int32_t OnFillBufferDone(struct OmxCodecBuffer &buffer); + int32_t ConfigBitMode(); + int32_t UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize); + bool FillAllTheBuffer(); + int GetFreeBufferId(); + int32_t ConfigPortDefine(); + +private: + FILE *fpIn_; // input file + FILE *fpOut_; + unsigned int width_; + unsigned int height_; + struct CodecComponentType *client_; + struct CodecCallbackType *callback_; + struct CodecComponentManager *omxMgr_; + std::map> omxBuffers_; // key is bufferID + std::list unUsedInBuffers_; + std::list unUsedOutBuffers_; + std::mutex lockInputBuffers_; + std::condition_variable statusCondition_; + std::mutex statusLock_; + bool exit_; + bool isSupply_; +}; + +#endif // CODEC_HDI_ENCODE_H \ No newline at end of file diff --git a/codec/test/demo/v2.0/src/codec_hdi_decode.cpp b/codec/test/demo/v2.0/src/codec_hdi_decode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..932d380e820ab72df8d7c5fca7b6720853cb5972 --- /dev/null +++ b/codec/test/demo/v2.0/src/codec_hdi_decode.cpp @@ -0,0 +1,629 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include "codec_hdi_decode.h" + +using namespace std; +using namespace OHOS; + +constexpr int32_t FD_SIZE = 4; +constexpr int32_t FRAME = 30 << 16; +constexpr int32_t PARAM_LEN = 5; +constexpr int32_t denominator = 2; +constexpr int32_t numerator = 3; +constexpr int32_t START_CODE_OFFSET_ONE = -1; +constexpr int32_t START_CODE_OFFSET_SEC = -2; +constexpr int32_t START_CODE_OFFSET_THIRD = -3; +constexpr int32_t START_CODE_SIZE_FRAME = 4; +constexpr int32_t START_CODE_SIZE_SLICE = 3; +constexpr char START_CODE = 0x1; +constexpr const char *decoder_avc = "OMX.rk.video_decoder.avc"; +constexpr const char *decoder_hevc = "OMX.rk.video_decoder.avc"; + +#define HDF_LOG_TAG codec_omx_hdi_dec + +#define AV_COLOR_FORMAT OMX_COLOR_FormatYUV420SemiPlanar + +static CodecHdiDecode *g_core = nullptr; +CodecHdiDecode::CodecHdiDecode() : fpIn_(nullptr), fpOut_(nullptr) +{ + client_ = nullptr; + callback_ = nullptr; + omxMgr_ = nullptr; + exit_ = false; + isSupply_ = false; + width_ = 0; + height_ = 0; + codecMime_ = codecMime::AVC; +} + +CodecHdiDecode::~CodecHdiDecode() +{ + if (fpOut_ != nullptr) { + fclose(fpOut_); + fpOut_ = nullptr; + } + + if (fpIn_ != nullptr) { + fclose(fpIn_); + fpIn_ = nullptr; + } +} + +void CodecHdiDecode::WaitForStatusChanged() +{ + unique_lock autoLock(statusLock_); + statusCondition_.wait(autoLock); +} + +void CodecHdiDecode::onStatusChanged() +{ + statusCondition_.notify_one(); +} + +int CodecHdiDecode::GetYuvSize() +{ + return width_ * height_ * numerator / denominator; +} + +bool CodecHdiDecode::ReadOnePacket(FILE *fp, char *buf, size_t &filledCount) +{ + // read start code first + size_t t = fread(buf, 1, START_CODE_SIZE_FRAME, fp); + if (t < START_CODE_SIZE_FRAME) { + return true; + } + char *temp = buf; + temp += START_CODE_SIZE_FRAME; + bool ret = true; + while (!feof(fp)) { + t = fread(temp, 1, 1, fp); + if (*temp == START_CODE) { + // check start code + 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; + } else 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; + } + } + temp++; + } + filledCount = (temp - buf); + return ret; +} + +bool CodecHdiDecode::Init(int width, int height, std::string &filename, codecMime codec) +{ + this->width_ = width; + this->height_ = height; + this->codecMime_ = codec; + HDF_LOGI("width[%{public}d], height[%{public}d]", width_, height_); + fpIn_ = fopen(filename.c_str(), "rb"); + fpOut_ = fopen("/data/out.yuv", "wb+"); + if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) { + HDF_LOGE("%{public}s failed to open file %{public}s", __func__, filename.c_str()); + return false; + } + + omxMgr_ = GetCodecComponentManager(); + + callback_ = CodecCallbackTypeStubGetInstance(); + if ((omxMgr_ == nullptr) || (callback_ == nullptr)) { + HDF_LOGE("%{public}s omxMgr_ is null or callback_ is null", __func__); + return false; + } + + callback_->EventHandler = &CodecHdiDecode::OnEvent; + callback_->EmptyBufferDone = &CodecHdiDecode::OnEmptyBufferDone; + callback_->FillBufferDone = &CodecHdiDecode::OnFillBufferDone; + + int32_t err = HDF_SUCCESS; + if (codec == codecMime::AVC) { + err = omxMgr_->CreateComponent(&client_, const_cast(decoder_avc), 0, 0, callback_); + } else { + err = omxMgr_->CreateComponent(&client_, const_cast(decoder_hevc), 0, 0, callback_); + } + + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed to CreateComponent", __func__); + return false; + } + + 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; +} + +int32_t CodecHdiDecode::ConfigPortDefine() +{ + // set width and height on input port + OMX_PARAM_PORTDEFINITIONTYPE param; + InitParam(param); + param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT; + auto err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)¶m, sizeof(param)); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); + return err; + } + 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 *)¶m, sizeof(param)); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT, index is OMX_IndexParamPortDefinition", __func__); + return err; + } + + // set width, height and color format on output port + InitParam(param); + param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_OUTPUT; + err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)¶m, sizeof(param)); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", + __func__); + return err; + } + 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_; + param.format.video.eColorFormat = AV_COLOR_FORMAT; // YUV420SP + err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)¶m, sizeof(param)); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_OUTPUT, index is OMX_IndexParamPortDefinition", + __func__); + return err; + } + return err; +} +bool CodecHdiDecode::Configure() +{ + if (ConfigPortDefine() != HDF_SUCCESS) { + return false; + } + + OMX_VIDEO_PARAM_PORTFORMATTYPE param; + InitParam(param); + param.nPortIndex = (uint32_t)PortIndex::PORT_INDEX_INPUT; + auto err = client_->GetParameter(client_, OMX_IndexParamVideoPortFormat, (int8_t *)¶m, sizeof(param)); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); + return false; + } + HDF_LOGI("set Format PortIndex::PORT_INDEX_INPUT eCompressionFormat = %{public}d, eColorFormat=%{public}d", + param.eCompressionFormat, param.eColorFormat); + param.xFramerate = FRAME; // 30fps,Q16 format + if (codecMime_ == codecMime::AVC) { + param.eCompressionFormat = OMX_VIDEO_CodingAVC; // H264 + } else { + param.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingHEVC; // H265 + } + + err = client_->SetParameter(client_, OMX_IndexParamVideoPortFormat, (int8_t *)¶m, sizeof(param)); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s failed with PortIndex::PORT_INDEX_INPUT", __func__); + return false; + } + return true; +} + +bool CodecHdiDecode::UseBuffers() +{ + HDF_LOGI("...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; + } + + err = UseBufferOnPort(PortIndex::PORT_INDEX_INPUT); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_INPUT error", __func__); + return false; + } + + err = UseBufferOnPort(PortIndex::PORT_INDEX_OUTPUT); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s UseBufferOnPort PortIndex::PORT_INDEX_OUTPUT error", __func__); + return false; + } + + HDF_LOGI("Wait for OMX_StateIdle status"); + enum OMX_STATETYPE status; + err = client_->GetState(client_, &status); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s GetState err [%{public}x]", __func__, err); + return false; + } + 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 CodecHdiDecode::UseBufferOnPort(PortIndex portIndex, int bufferCount, int bufferSize) +{ + if (bufferCount <= 0 || bufferSize <= 0) { + return HDF_ERR_INVALID_PARAM; + } + for (int i = 0; i < bufferCount; i++) { + std::shared_ptr omxBuffer = std::make_shared(); + omxBuffer->size = sizeof(OmxCodecBuffer); + omxBuffer->version.s.nVersionMajor = 1; + omxBuffer->bufferType = BUFFER_TYPE_AVSHARE_MEM_FD; + int fd = AshmemCreate(0, bufferSize); + shared_ptr sharedMem = make_shared(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; + sharedMem->MapReadAndWriteAshmem(); + } else { + omxBuffer->type = READ_WRITE_TYPE; + sharedMem->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); + sharedMem->UnmapAshmem(); + sharedMem->CloseAshmem(); + sharedMem = nullptr; + return err; + } + omxBuffer->bufferLen = 0; + HDF_LOGI("UseBuffer returned bufferID [%{public}d]", omxBuffer->bufferId); + + std::shared_ptr bufferInfo = std::make_shared(); + bufferInfo->omxBuffer = omxBuffer; + bufferInfo->avSharedPtr = sharedMem; + bufferInfo->portIndex = portIndex; + 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); + } + } + + return HDF_SUCCESS; +} + +int32_t CodecHdiDecode::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 = (OMX_U32)portIndex; + auto err = client_->GetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)¶m, 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 *)¶m, sizeof(param)); + HDF_LOGI("param.eBufferSupplier[%{public}d] isSupply [%{public}d], err [%{public}d]", param.eBufferSupplier, + this->isSupply_, err); + } + err = UseBufferOnPort(portIndex, bufferCount, bufferSize); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s UseBufferOnPort err[%{public}x]", __func__, err); + return err; + } + // set port 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::PortIndex::PORT_INDEX_INPUT error", __func__); + return err; + } + } + return HDF_SUCCESS; +} + +void CodecHdiDecode::FreeBuffers() +{ + // command to loaded + (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateLoaded, nullptr, 0); + + // release all the buffers + auto iter = omxBuffers_.begin(); + while (iter != omxBuffers_.end()) { + auto bufferInfo = iter->second; + iter = omxBuffers_.erase(iter); + (void)client_->FreeBuffer(client_, (uint32_t)bufferInfo->portIndex, bufferInfo->omxBuffer.get()); + bufferInfo = nullptr; + } + + unUsedInBuffers_.clear(); + unUsedOutBuffers_.clear(); + + enum OMX_STATETYPE status; + auto err = client_->GetState(client_, &status); + if (err != HDF_SUCCESS) { + HDF_LOGE("%s GetState error [%{public}x]", __func__, err); + return; + } + // wait loaded + if (status != OMX_StateLoaded) { + HDF_LOGI("Wait for OMX_StateLoaded status"); + this->WaitForStatusChanged(); + } else { + HDF_LOGI(" status is %{public}d", status); + } +} + +void CodecHdiDecode::Release() +{ + omxMgr_->DestoryComponent(client_); + client_ = nullptr; + CodecComponentManagerRelease(); +} + +bool CodecHdiDecode::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 CodecHdiDecode::GetFreeBufferId() +{ + int bufferID = -1; + unique_lock ulk(lockInputBuffers_); + size_t nSize = this->unUsedInBuffers_.size(); + if (nSize > 0) { + bufferID = unUsedInBuffers_.front(); + unUsedInBuffers_.pop_front(); + } + return bufferID; +} + +void CodecHdiDecode::Run() +{ + HDF_LOGI("...command to OMX_StateExecuting...."); + 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 eosFlag = false; + while (!eosFlag) { + HDF_LOGI(" inputput run"); + int bufferID = GetFreeBufferId(); + if (this->exit_) { + break; + } + if (bufferID < 0) { + usleep(10000); + continue; + } + auto iter = omxBuffers_.find(bufferID); + if (iter == omxBuffers_.end()) { + continue; + } + auto bufferInfo = iter->second; + void *sharedAddr = (void *)bufferInfo->avSharedPtr->ReadFromAshmem(0, 0); + eosFlag = (size_t)this->ReadOnePacket(fpIn_, (char *)sharedAddr, bufferInfo->omxBuffer->filledLen); + HDF_LOGI("read data size is %{public}d", bufferInfo->omxBuffer->filledLen); + bufferInfo->omxBuffer->offset = 0; + if (eosFlag) { + bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS; + } + err = client_->EmptyThisBuffer(client_, bufferInfo->omxBuffer.get()); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s EmptyThisBuffer error", __func__); + return; + } + } + // wait + while (!this->exit_) { + usleep(10000); + continue; + } + // command to IDLE + (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); + return; +} +int32_t CodecHdiDecode::OnEvent(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct 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->onStatusChanged(); + } + break; + } + + default: + break; + } + + return HDF_SUCCESS; +} + +int32_t CodecHdiDecode::OnEmptyBufferDone(struct CodecCallbackType *self, int8_t *appData, uint32_t appDataLen, + const struct OmxCodecBuffer *buffer) +{ + HDF_LOGI("onEmptyBufferDone: pBuffer.bufferID [%{public}d]", buffer->bufferId); + return g_core->OnEmptyBufferDone(*buffer); +} + +int32_t CodecHdiDecode::OnFillBufferDone(struct CodecCallbackType *self, int8_t *appData, uint32_t appDataLen, + struct OmxCodecBuffer *buffer) +{ + HDF_LOGI("onFillBufferDone: pBuffer.bufferID [%{public}d]", buffer->bufferId); + return g_core->OnFillBufferDone(*buffer); +} + +int32_t CodecHdiDecode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer) +{ + unique_lock ulk(lockInputBuffers_); + unUsedInBuffers_.push_back(buffer.bufferId); + return HDF_SUCCESS; +} + +int32_t CodecHdiDecode::OnFillBufferDone(struct OmxCodecBuffer &buffer) +{ + if (exit_) { + return HDF_SUCCESS; + } + + auto iter = omxBuffers_.find(buffer.bufferId); + if ((iter == omxBuffers_.end()) || (iter->second == nullptr)) { + return HDF_SUCCESS; + } + // read buffer + 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_); + // reset buffer + buffer.offset = 0; + buffer.filledLen = 0; + if (buffer.flag == OMX_BUFFERFLAG_EOS) { + // end + exit_ = true; + HDF_LOGI("OnFillBufferDone the END coming"); + return HDF_SUCCESS; + } + // call fillthisbuffer again + auto err = client_->FillThisBuffer(client_, bufferInfo->omxBuffer.get()); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s FillThisBuffer error", __func__); + return HDF_SUCCESS; + } + return HDF_SUCCESS; +} +int main(int argc, char *argv[]) +{ + if (argc < PARAM_LEN) { + HDF_LOGE("usage AVC width_ heigh filename"); + return 0; + } + std::string codecString = argv[1]; + codecMime codec = codecMime::AVC; + if (strcmp(codecString.c_str(), "avc") == 0 || strcmp(codecString.c_str(), "AVC") == 0) { + codec = codecMime::AVC; + } else if (strcmp(codecString.c_str(), "hevc") == 0 || strcmp(codecString.c_str(), "HEVC") == 0) { + codec = codecMime::HEVC; + } else { + return 0; + } + + int width = atoi(argv[2]); + int height = atoi(argv[3]); + string filename = argv[4]; + + if (g_core == nullptr) { + g_core = new CodecHdiDecode(); + } + // Init width, height, input file + if (!g_core->Init(width, height, filename, codec)) { + 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; +} \ No newline at end of file diff --git a/codec/test/demo/v2.0/src/codec_hdi_encode.cpp b/codec/test/demo/v2.0/src/codec_hdi_encode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca471c23c12d96d8045113e5a4ed12b619822165 --- /dev/null +++ b/codec/test/demo/v2.0/src/codec_hdi_encode.cpp @@ -0,0 +1,614 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include "codec_hdi_encode.h" + +using namespace std; +using namespace OHOS; + +#define HDF_LOG_TAG codec_omx_hdi_enc +constexpr int32_t FRAME = 30 << 16; +constexpr int32_t BITRATE = 3000000; +constexpr int32_t PARAM_LEN = 5; +constexpr int32_t FD_SIZE = 4; +constexpr const char *encoder_avc = "OMX.rk.video_encoder.avc"; +#define AV_COLOR_FORMAT OMX_COLOR_FormatYUV420SemiPlanar + +constexpr int32_t denominator = 2; +constexpr int32_t numerator = 3; +static CodecHdiEncode *g_core = nullptr; +CodecHdiEncode::CodecHdiEncode() : fpIn_(nullptr), fpOut_(nullptr) +{ + client_ = nullptr; + callback_ = nullptr; + omxMgr_ = nullptr; + exit_ = false; + isSupply_ = false; + width_ = 0; + height_ = 0; +} + +CodecHdiEncode::~CodecHdiEncode() +{ + if (fpOut_ != nullptr) { + fclose(fpOut_); + fpOut_ = nullptr; + } + if (fpIn_ != nullptr) { + fclose(fpIn_); + fpIn_ = nullptr; + } +} + +void CodecHdiEncode::WaitForStatusChanged() +{ + unique_lock autoLock(statusLock_); + statusCondition_.wait(autoLock); +} + +void CodecHdiEncode::onStatusChanged() +{ + statusCondition_.notify_one(); +} + +bool CodecHdiEncode::ReadOneFrame(FILE *fp, char *buf, size_t &filledCount) +{ + bool ret = false; + filledCount = fread(buf, 1, width_ * height_ * numerator / denominator, fp); + if (feof(fp)) { + ret = true; + } + return ret; +} + +bool CodecHdiEncode::Init(int width, int height, std::string &filename) +{ + this->width_ = width; + this->height_ = height; + HDF_LOGI("width[%{public}d], height[%{public}d]", width_, height_); + fpIn_ = fopen(filename.c_str(), "rb"); + fpOut_ = fopen("/data/out.h264", "wb+"); + if ((fpIn_ == nullptr) || (fpOut_ == nullptr)) { + HDF_LOGE("failed to open file %{public}s", filename.c_str()); + return false; + } + // Interface init + omxMgr_ = GetCodecComponentManager(); + // init callback object + callback_ = CodecCallbackTypeStubGetInstance(); + if ((omxMgr_ == nullptr) || (callback_ == nullptr)) { + return false; + } + HDF_LOGI("callback_ [0x%{public}p]", callback_); + // set the callback + callback_->EventHandler = &CodecHdiEncode::OnEvent; + callback_->EmptyBufferDone = &CodecHdiEncode::OnEmptyBufferDone; + callback_->FillBufferDone = &CodecHdiEncode::OnFillBufferDone; + + // create a component + auto err = omxMgr_->CreateComponent(&client_, const_cast(encoder_avc), 0, 0, 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 ouput 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; + } + return true; +} + +bool CodecHdiEncode::UseBuffers() +{ + // commad 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; + } + + // wait executing state + enum 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 *)¶m, 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 *)¶m, sizeof(param)); + HDF_LOGI("param.eBufferSupplier[%{public}d] isSupply [%{public}d], err [%{public}d]", param.eBufferSupplier, + this->isSupply_, err); + } + + if (portIndex == PortIndex::PORT_INDEX_INPUT) { + bufferSize = width_ * height_ * numerator / denominator; + } else if (bufferSize == 0) { + bufferSize = width_ * height_; + HDF_LOGI("bufferSize[%{public}d], width[%{public}d], height[%{public}d]", bufferSize, width_, height_); + } + + 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(); + omxBuffer->size = sizeof(OmxCodecBuffer); + omxBuffer->version.s.nVersionMajor = 1; + omxBuffer->bufferType = BUFFER_TYPE_AVSHARE_MEM_FD; + int fd = AshmemCreate(0, bufferSize); + shared_ptr spSharedMem = make_shared(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->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; +} +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(); + + enum 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_->DestoryComponent(client_); + + // DestoryComponent has released client_ and omx component calls DeInit + 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 ulk(lockInputBuffers_); + size_t nSize = this->unUsedInBuffers_.size(); + if (nSize > 0) { + bufferID = unUsedInBuffers_.front(); + unUsedInBuffers_.pop_front(); + } + return bufferID; +} + +void CodecHdiEncode::Run() +{ + HDF_LOGI("...command to OMX_StateExecuting...."); + 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) { + HDF_LOGI(" inputput run"); + int bufferID = GetFreeBufferId(); + if (this->exit_) { + break; + } + if (bufferID < 0) { + usleep(10000); + continue; + } + auto iter = omxBuffers_.find(bufferID); + if (iter == omxBuffers_.end()) { + continue; + } + auto bufferInfo = iter->second; + // read data from ashmem + void *sharedAddr = (void *)bufferInfo->avSharedPtr->ReadFromAshmem(0, 0); + endFlag = this->ReadOneFrame(fpIn_, (char *)sharedAddr, bufferInfo->omxBuffer->filledLen); + HDF_LOGI("read data size is %{public}d", bufferInfo->omxBuffer->filledLen); + bufferInfo->omxBuffer->offset = 0; + if (endFlag) { + bufferInfo->omxBuffer->flag = OMX_BUFFERFLAG_EOS; + } + err = client_->EmptyThisBuffer(client_, bufferInfo->omxBuffer.get()); + if (err != HDF_SUCCESS) { + HDF_LOGE("%{public}s EmptyThisBuffer error", __func__); + return; + } + } + while (!this->exit_) { + usleep(10000); + continue; + } + (void)client_->SendCommand(client_, OMX_CommandStateSet, OMX_StateIdle, NULL, 0); + return; +} + +int32_t CodecHdiEncode::OnEvent(struct CodecCallbackType *self, enum OMX_EVENTTYPE event, struct EventInfo *info) +{ + HDF_LOGI("OnEvent: pAppData[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"); + g_core->onStatusChanged(); + } + break; + } + + default: + break; + } + + return HDF_SUCCESS; +} + +int32_t CodecHdiEncode::OnEmptyBufferDone(struct CodecCallbackType *self, int8_t *appData, uint32_t appDataLen, + 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, int8_t *appData, uint32_t appDataLen, + struct OmxCodecBuffer *buffer) +{ + HDF_LOGI("OnFillBufferDone: pBuffer.bufferID [%{public}d]", buffer->bufferId); + return g_core->OnFillBufferDone(*buffer); +} + +int32_t CodecHdiEncode::OnEmptyBufferDone(const struct OmxCodecBuffer &buffer) +{ + unique_lock ulk(lockInputBuffers_); + unUsedInBuffers_.push_back(buffer.bufferId); + return HDF_SUCCESS; +} + +int32_t CodecHdiEncode::OnFillBufferDone(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_); + buffer.offset = 0; + buffer.filledLen = 0; + 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 *)¶m, 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 = width_; + param.format.video.nSliceHeight = height_; + param.format.video.eColorFormat = AV_COLOR_FORMAT; + err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)¶m, 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 *)¶m, 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 = width_; + param.format.video.nSliceHeight = height_; + err = client_->SetParameter(client_, OMX_IndexParamPortDefinition, (int8_t *)¶m, 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 *)¶m, 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 *)¶m, 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_->SetParameter(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[]) +{ + if (argc < PARAM_LEN) { + HDF_LOGE("usage AVC width heigh filename"); + return 0; + } + int width = atoi(argv[2]); + int height = atoi(argv[3]); + string filename = argv[4]; + + if (g_core == nullptr) { + g_core = new CodecHdiEncode(); + } + + if (!g_core->Init(width, height, filename)) { + 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; +} \ No newline at end of file