update vpe

Signed-off-by: liushang <liushang2@huawei.com>
This commit is contained in:
liushang
2025-04-07 18:31:00 +08:00
parent 3109562fe4
commit eccff2c776
201 changed files with 8110 additions and 11372 deletions
+1
View File
@@ -18,5 +18,6 @@ group("video_processing_engine_packages") {
public_deps = [
"framework:videoprocessingengine",
"services:videoprocessingservice"
"services:videoprocessingserviceimpl"
]
}
+20 -7
View File
@@ -38,13 +38,14 @@
"safwk",
"samgr",
"eventhandler",
"libxml2",
"skia",
"egl",
"opengles",
"bounds_checking_function",
"opencl-headers"
],
"third_party": [
"skia",
"egl",
"opengles"
]
},
"build": {
@@ -75,12 +76,23 @@
}
},
{
"name": "//foundation/multimedia/video_processing_engine/services:videoprocessingservice_idl_headers",
"type": "so",
"name": "//foundation/multimedia/video_processing_engine/services:videoprocessingservice",
"header": {
"header_files": [
"video_processing_service_manager_proxy.h"
"video_processing_client.h"
],
"header_base": "//foundation/multimedia/video_processing_engine/services"
"header_base": "//foundation/multimedia/video_processing_engine/services/include"
}
},
{
"type": "so",
"name": "//foundation/multimedia/video_processing_engine/services:videoprocessingserviceimpl",
"header": {
"header_files": [
"ivideo_processing_algorithm.h"
],
"header_base": "//foundation/multimedia/video_processing_engine/services/algorithm/include"
}
},
{
@@ -135,7 +147,8 @@
"test": [
"//foundation/multimedia/video_processing_engine/test:demo_test",
"//foundation/multimedia/video_processing_engine/test:unit_test",
"//foundation/multimedia/video_processing_engine/test:module_test"
"//foundation/multimedia/video_processing_engine/test:module_test",
"//foundation/multimedia/video_processing_engine/test:fuzz_test"
]
}
}
+2
View File
@@ -34,6 +34,8 @@ DETAIL_ENHANCER_DIR = "$ALGORITHM_DIR/detail_enhancer"
DETAIL_ENHANCER_VIDEO_DIR = "$ALGORITHM_DIR/detail_enhancer_video"
VIDEO_REFRESHRATE_PREDICTION_DIR = "$ALGORITHM_DIR/video_variable_refresh_rate"
SERVICES_DIR = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services"
#CAPI
CAPI_IMAGE_DIR = "$FRAMEWORK_DIR/capi/image_processing"
CAPI_COLORSPACE_CONVERTER_DIR = "$CAPI_IMAGE_DIR/colorspace_converter"
+41 -20
View File
@@ -28,6 +28,7 @@ config("export_config") {
"$COLORSPACE_CONVERTER_DISPLAY_DIR/include",
"$VIDEO_REFRESHRATE_PREDICTION_DIR/include",
"$ALGORITHM_DIR/common/include",
"$CONTRAST_ENHANCER_DIR/include",
"$METADATA_GENERATOR_VIDEO_DIR/include",
"$ALGORITHM_EXTENSION_MANAGER_DIR/include",
"$ALGORITHM_EXTENSION_SKIA_DIR/include",
@@ -68,6 +69,7 @@ config("video_process_config") {
"$COLORSPACE_CONVERTER_DIR/include",
"$COLORSPACE_CONVERTER_DISPLAY_DIR/include",
"$COLORSPACE_CONVERTER_VIDEO_DIR/include",
"$CONTRAST_ENHANCER_DIR/include",
"$METADATA_GENERATOR_DIR/include",
"$METADATA_GENERATOR_VIDEO_DIR/include",
"$DETAIL_ENHANCER_VIDEO_DIR/include",
@@ -79,6 +81,8 @@ config("video_process_config") {
"$INTERFACES_INNER_API_DIR",
"$INTERFACES_INNER_API_DIR/module",
"$INTERFACES_DIR/plugin",
"$SERVICES_DIR/include",
"$SERVICES_DIR/utils/include",
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services/include",
"${target_gen_dir}/../services/",
]
@@ -155,7 +159,16 @@ ohos_shared_library("videoprocessingengine") {
configs = [ ":video_process_config" ]
public_configs = [ ":export_config" ]
include_dirs = []
include_dirs = [
"$DFX_DIR/include",
"$METADATA_GENERATOR_DIR/include",
"$METADATA_GENERATOR_VIDEO_DIR/include",
"$VIDEO_REFRESHRATE_PREDICTION_DIR/include",
"$ALGORITHM_DIR/common/include",
"$ALGORITHM_DIR/extension_manager/include",
"$COLORSPACE_CONVERTER_DIR/include",
"$COLORSPACE_CONVERTER_VIDEO_DIR/include",
]
sources = [
"$AIHDR_ENHANCER_DIR/aihdr_enhancer_fwk.cpp",
@@ -166,7 +179,6 @@ ohos_shared_library("videoprocessingengine") {
"$ALGORITHM_DIR/common/algorithm_video_common.cpp",
"$ALGORITHM_DIR/common/algorithm_video_impl.cpp",
"$ALGORITHM_DIR/common/frame_info.cpp",
"$ALGORITHM_DIR/common/vpe_parse_metadata.cpp",
"$ALGORITHM_DIR/extension_manager/extension_manager.cpp",
"$ALGORITHM_DIR/extension_manager/utils.cpp",
"$COLORSPACE_CONVERTER_DIR/colorspace_converter_fwk.cpp",
@@ -178,24 +190,25 @@ ohos_shared_library("videoprocessingengine") {
"$DETAIL_ENHANCER_VIDEO_DIR/detail_enhancer_video_fwk.cpp",
"$DETAIL_ENHANCER_VIDEO_DIR/detail_enhancer_video_impl.cpp",
"$VIDEO_REFRESHRATE_PREDICTION_DIR/video_refreshrate_prediction_fwk.cpp",
"$CONTRAST_ENHANCER_DIR/contrast_enhancer_image_fwk.cpp",
"$DFX_DIR/vpe_trace.cpp",
"$DFX_DIR/vpe_log.cpp",
#client
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services/src/video_processing_client.cpp",
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services/src/video_processing_load_callback.cpp",
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services/src/surface_buffer_info.cpp",
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services/utils/surface_buffer_info.cpp",
"${target_gen_dir}/../services/video_processing_service_manager_proxy.cpp",
"${target_gen_dir}/../services/video_processing_service_manager_stub.cpp",
"$ALGORITHM_COMMON_DIR/image_opencl_wrapper.cpp",
"$ALGORITHM_COMMON_DIR/image_openclsetup.cpp",
"$ALGORITHM_EXTENSION_SKIA_DIR/skia_impl.cpp",
"$ALGORITHM_EXTENSION_SKIA_DIR/skia_impl.cpp"
]
deps = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services:videoprocessingservice_interface",
":aihdr_engine",
":ai_super_resolution",
":extream_vision_engine"
":extream_vision_engine",
]
if (has_skia) {
@@ -204,27 +217,27 @@ ohos_shared_library("videoprocessingengine") {
external_deps = [
"c_utils:utils",
"drivers_interface_display:display_commontype_idl_headers",
"drivers_interface_display:libdisplay_commontype_proxy_2.1",
"graphic_2d:2d_graphics",
"graphic_2d:EGL",
"graphic_2d:GLESv3",
"graphic_surface:surface",
"graphic_surface:sync_fence",
"hilog:libhilog",
"hitrace:hitrace_meter",
"init:libbegetutil",
"hdf_core:libhdi",
"hdf_core:libhdf_host",
"hdf_core:libhdf_ipc_adapter",
"hdf_core:libhdf_utils",
#"hdf_core:hdf_posix_osal",
"graphic_2d:2d_graphics",
"hdf_core:libhdi",
"hilog:libhilog",
"hitrace:hitrace_meter",
"image_framework:image_native",
"init:libbegetutil",
"ipc:ipc_single",
"media_foundation:media_foundation",
"safwk:system_ability_fwk",
"samgr:samgr_proxy",
"media_foundation:media_foundation",
"graphic_2d:EGL",
"graphic_2d:GLESv3",
"skia:skia_canvaskit",
"opencl-headers:libcl",
"bounds_checking_function:libsec_static",
"opencl-headers:libcl"
]
subsystem_name = "multimedia"
@@ -288,6 +301,7 @@ ohos_shared_library("image_processing") {
#Common
"$DFX_DIR/include",
"$ALGORITHM_COMMON_DIR/include",
"$SERVICES_DIR/utils/include",
#CAPI implementation
"$CAPI_IMAGE_DIR/include",
"$CAPI_IMAGE_DETAIL_ENHANCER_DIR/include",
@@ -328,8 +342,9 @@ ohos_shared_library("image_processing") {
"hilog:libhilog",
"hitrace:hitrace_meter",
"image_framework:image_native",
"image_framework:pixelmap",
"drivers_interface_display:libdisplay_commontype_proxy_2.1",
"ipc:ipc_single",
"image_framework:pixelmap",
"media_foundation:media_foundation",
"safwk:system_ability_fwk",
"samgr:samgr_proxy",
@@ -371,6 +386,7 @@ ohos_shared_library("video_processing") {
#Common
"$DFX_DIR/include",
"$ALGORITHM_COMMON_DIR/include",
"$SERVICES_DIR/utils/include",
#CAPI implementation
"$CAPI_VIDEO_DIR/include",
"$CAPI_VIDEO_DIR/aihdr_enhancer/include",
@@ -414,7 +430,12 @@ ohos_shared_library("video_processing") {
"hitrace:hitrace_meter",
"ipc:ipc_single",
"media_foundation:media_foundation",
"drivers_interface_display:display_commontype_idl_headers",
"drivers_interface_display:libdisplay_commontype_proxy_2.1",
"graphic_2d:libgraphic_utils",
"graphic_2d:librender_service_client",
"ipc:ipc_single",
"safwk:system_ability_fwk",
"samgr:samgr_proxy",
]
if (has_skia) {
@@ -468,7 +489,7 @@ ohos_shared_library("detailEnhancer") {
"image_framework:image_native",
"image_framework:pixelmap",
"image_framework:image",
"drivers_interface_display:display_commontype_idl_headers",
"drivers_interface_display:libdisplay_commontype_proxy_2.1",
]
output_name = "libdetailenhancer_napi"
@@ -507,7 +528,7 @@ ohos_shared_library("videoprocessingenginenapi") {
cflags = VIDEO_PROCESSING_ENGINE_CFLAGS
external_deps = [
"c_utils:utils",
"drivers_interface_display:display_commontype_idl_headers",
"drivers_interface_display:libdisplay_commontype_proxy_2.1",
"graphic_surface:surface",
"hilog:libhilog",
"hitrace:hitrace_meter",
@@ -204,7 +204,7 @@ sptr<Surface> AihdrEnhancerVideoImpl::CreateInputSurface()
sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
CHECK_AND_RETURN_RET_LOG(producerSurface != nullptr, nullptr, "CreateSurfaceAsProducer fail");
producerSurface->SetDefaultUsage(BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_HW_RENDER |
BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE);
BUFFER_USAGE_MEM_DMA);
inputSurface_->SetQueueSize(inBufferCnt_);
state_ = VPEAlgoState::CONFIGURING;
@@ -249,7 +249,10 @@ int32_t AihdrEnhancerVideoImpl::Prepare()
void AihdrEnhancerVideoImpl::InitBuffers()
{
std::lock_guard<std::mutex> lock(mutex_);
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return;
}
CHECK_AND_RETURN_LOG(outputSurface_ != nullptr, "outputSurface_ is nullptr");
flushCfg_.damage.x = 0;
flushCfg_.damage.y = 0;
@@ -317,8 +320,8 @@ int32_t AihdrEnhancerVideoImpl::Reset()
int32_t AihdrEnhancerVideoImpl::Release()
{
std::lock_guard<std::mutex> lock(mutex_);
{
std::lock_guard<std::mutex> lock(mutex_);
std::unique_lock<std::mutex> lockTask(mtxTaskDone_);
state_ = VPEAlgoState::UNINITIALIZED;
cvTaskDone_.wait(lockTask, [this]() { return isProcessing_.load() == false; });
@@ -383,6 +386,7 @@ void AihdrEnhancerVideoImpl::Process(std::shared_ptr<SurfaceBufferWrapper> input
outputBuffer->timestamp = inputBuffer->timestamp;
sptr<SurfaceBuffer> surfaceInputBuffer = inputBuffer->memory;
sptr<SurfaceBuffer> surfaceOutputBuffer = outputBuffer->memory;
surfaceInputBuffer->InvalidateCache();
bool copyRet = AlgorithmUtils::CopySurfaceBufferToSurfaceBuffer(surfaceInputBuffer, surfaceOutputBuffer);
if (!copyRet) {
requestCfg_.width = surfaceInputBuffer->GetWidth();
@@ -423,6 +427,7 @@ bool AihdrEnhancerVideoImpl::WaitProcessing()
{
std::unique_lock<std::mutex> lock(mtxTaskStart_);
cvTaskStart_.wait(lock, [this]() {
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> inQueueLock(onBqMutex_);
std::lock_guard<std::mutex> outQueueLock(renderQueMutex_);
if (initBuffer_.load()) {
@@ -587,6 +592,10 @@ GSError AihdrEnhancerVideoImpl::OnProducerBufferReleased()
GSError AihdrEnhancerVideoImpl::OnConsumerBufferAvailable()
{
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> lockInQue(onBqMutex_);
CHECK_AND_RETURN_RET_LOG(inputSurface_ != nullptr, GSERROR_OK, "inputSurface is nullptr");
@@ -16,7 +16,6 @@
#include "colorspace_converter_display_fwk.h"
#include "securec.h"
#include "extension_manager.h"
#include "vpe_parse_metadata.h"
#include "vpe_trace.h"
#include "vpe_log.h"
@@ -43,12 +42,9 @@ VPEAlgoErrCode ColorSpaceConverterDisplayFwk::Process(const std::shared_ptr<OHOS
VPE_LOGD("size of impl %{public}zu", impl_.size());
CHECK_AND_RETURN_RET_LOG(!impl_.empty(), VPE_ALGO_ERR_NOT_IMPLEMENTED, "Extension is not found");
DeserializedDisplayParameter localParameter;
DeserializeDisplayParameter(parameter, localParameter);
VPE_SYNC_TRACE;
for (const auto& impl : impl_) {
ret = impl->Process(input, output, localParameter);
ret = impl->Process(input, output, parameter);
if (ret == VPE_ALGO_ERR_OK) {
return VPE_ALGO_ERR_OK;
}
@@ -74,52 +70,6 @@ VPEAlgoErrCode ColorSpaceConverterDisplayFwk::Init()
return VPE_ALGO_ERR_OK;
}
void ColorSpaceConverterDisplayFwk::DeserializeDisplayParameter(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed)
{
deserialzed.inputColorSpace = parameter.inputColorSpace;
deserialzed.outputColorSpace = parameter.outputColorSpace;
deserialzed.sdrNits = parameter.sdrNits;
deserialzed.tmoNits = parameter.tmoNits;
deserialzed.currentDisplayNits = parameter.currentDisplayNits;
deserialzed.disableHdrFloatHeadRoom = parameter.disableHdrFloatHeadRoom;
deserialzed.linearMatrix = parameter.layerLinearMatrix;
DeserializeStaticMetadata(parameter, deserialzed);
DeserializeDynamicMetadata(parameter, deserialzed);
}
void ColorSpaceConverterDisplayFwk::DeserializeStaticMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed)
{
if (parameter.staticMetadata.size() == 0) {
deserialzed.staticMetadata = std::nullopt;
return;
}
HdrStaticMetadata data;
errno_t ret = memcpy_s(&data, sizeof(data), parameter.staticMetadata.data(), parameter.staticMetadata.size());
if (ret != EOK) {
VPE_LOGE("memcpy_s failed, err = %d\n", ret);
return;
}
deserialzed.staticMetadata = data;
}
void ColorSpaceConverterDisplayFwk::DeserializeDynamicMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed)
{
if (parameter.dynamicMetadata.size() == 0) {
deserialzed.hdrVividMetadata = std::nullopt;
return;
}
HdrVividMetadataV1 data;
HwDisplayMeta displayMeta;
(void)PraseMetadataFromArray(parameter.dynamicMetadata, data, displayMeta);
deserialzed.hdrVividMetadata = data;
deserialzed.displayMeta = displayMeta;
}
std::shared_ptr<ColorSpaceConverterDisplay> ColorSpaceConverterDisplay::Create()
{
auto p = std::make_shared<ColorSpaceConverterDisplayFwk>();
@@ -21,7 +21,6 @@
#include "nocopyable.h"
#include "effect/shader_effect.h"
#include "algorithm_common.h"
#include "deserialized_display_parameter.h"
namespace OHOS {
namespace Media {
@@ -34,7 +33,7 @@ public:
virtual ~ColorSpaceConverterDisplayBase() = default;
virtual VPEAlgoErrCode Process(const std::shared_ptr<OHOS::Rosen::Drawing::ShaderEffect>& input,
std::shared_ptr<OHOS::Rosen::Drawing::ShaderEffect>& output,
const DeserializedDisplayParameter& parameter) = 0;
const ColorSpaceConverterDisplayParameter& parameter) = 0;
};
using ColorSpaceConverterDisplayCreator = std::function<std::shared_ptr<ColorSpaceConverterDisplayBase>()>;
@@ -37,12 +37,6 @@ public:
const ColorSpaceConverterDisplayParameter& parameter) override;
private:
VPEAlgoErrCode Init();
void DeserializeDisplayParameter(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed);
void DeserializeStaticMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed);
void DeserializeDynamicMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed);
std::set<std::shared_ptr<ColorSpaceConverterDisplayBase>> impl_;
std::atomic<bool> initialized_ {false};
@@ -1,47 +0,0 @@
/*
* Copyright (c) 2025 Huawei Device 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 VPE_FRAMEWORK_ALGORITHM_COLORSPACE_CONVERTER_DISPLAY_DESERIALIZED_DISPLAY_PARAMETER_H
#define VPE_FRAMEWORK_ALGORITHM_COLORSPACE_CONVERTER_DISPLAY_DESERIALIZED_DISPLAY_PARAMETER_H
#include <optional>
#include "v1_0/hdr_static_metadata.h"
#include "algorithm_common.h"
#include "hdr_vivid_metadata_v1.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
using namespace HDI::Display::Graphic::Common::V1_0;
struct DeserializedDisplayParameter {
ColorSpaceDescription inputColorSpace; // 色彩空间信息
ColorSpaceDescription outputColorSpace; // 色彩空间信息
std::optional<HdrStaticMetadata> staticMetadata; // 静态元数据
std::optional<HdrVividMetadataV1> hdrVividMetadata; // 动态元数据
float sdrNits; // SDR亮度
float tmoNits; // TMO目标亮度
float currentDisplayNits; // 屏幕当前亮度,和tmoNits相除得到sdr亮度打折比
bool disableHdrFloatHeadRoom; // 不使用HDRfp16方案做额外提亮
HwDisplayMeta displayMeta; // 拍显协同元数据
int32_t width; // 宽度
int32_t height; // 高度
std::vector<float> linearMatrix; // 线性域转换矩阵,作用在原色域上
};
} // namespace VideoProcessingEngine
} // Media
} // OHOS
#endif // VPE_FRAMEWORK_ALGORITHM_COLORSPACE_CONVERTER_DISPLAY_DESERIALIZED_DISPLAY_PARAMETER_H
@@ -414,7 +414,10 @@ void GetFormatFromSurfaceBuffer(Format &outputFormat, sptr<SurfaceBuffer> &buffe
void ColorSpaceConverterVideoImpl::InitBuffers()
{
std::lock_guard<std::mutex> lock(mutex_);
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return;
}
CHECK_AND_RETURN_LOG(outputSurface_ != nullptr, "outputSurface_ is nullptr");
flushCfg_.damage.x = 0;
flushCfg_.damage.y = 0;
@@ -490,8 +493,8 @@ int32_t ColorSpaceConverterVideoImpl::Reset()
int32_t ColorSpaceConverterVideoImpl::Release()
{
std::lock_guard<std::mutex> lock(mutex_);
{
std::lock_guard<std::mutex> lock(mutex_);
std::unique_lock<std::mutex> lockTask(mtxTaskDone_);
state_ = VPEAlgoState::UNINITIALIZED;
cvTaskDone_.wait(lockTask, [this]() { return isProcessing_.load() == false; });
@@ -633,6 +636,7 @@ bool ColorSpaceConverterVideoImpl::WaitProcessing()
{
std::unique_lock<std::mutex> lock(mtxTaskStart_);
cvTaskStart_.wait(lock, [this]() {
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> inQueueLock(onBqMutex_);
std::lock_guard<std::mutex> outQueueLock(renderQueMutex_);
if (initBuffer_.load()) {
@@ -802,6 +806,10 @@ GSError ColorSpaceConverterVideoImpl::OnProducerBufferReleased()
GSError ColorSpaceConverterVideoImpl::OnConsumerBufferAvailable()
{
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> lockInQue(onBqMutex_);
CHECK_AND_RETURN_RET_LOG(inputSurface_ != nullptr, GSERROR_OK, "inputSurface is nullptr");
+57 -12
View File
@@ -18,9 +18,49 @@
#include <unordered_map>
#include "securec.h"
#include "vpe_log.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
const std::unordered_map<GSError, std::string> GSERROR_STR_MAP = {
{ GSERROR_OK, VPE_TO_STR(GSERROR_OK) },
{ GSERROR_MEM_OPERATION_ERROR, VPE_TO_STR(GSERROR_MEM_OPERATION_ERROR) },
{ GSERROR_INVALID_ARGUMENTS, VPE_TO_STR(GSERROR_INVALID_ARGUMENTS) },
{ GSERROR_NO_PERMISSION, VPE_TO_STR(GSERROR_NO_PERMISSION) },
{ GSERROR_CONNOT_CONNECT_SAMGR, VPE_TO_STR(GSERROR_CONNOT_CONNECT_SAMGR) },
{ GSERROR_CONNOT_CONNECT_SERVER, VPE_TO_STR(GSERROR_CONNOT_CONNECT_SERVER) },
{ GSERROR_CONNOT_CONNECT_WESTON, VPE_TO_STR(GSERROR_CONNOT_CONNECT_WESTON) },
{ GSERROR_NO_BUFFER, VPE_TO_STR(GSERROR_NO_BUFFER) },
{ GSERROR_NO_ENTRY, VPE_TO_STR(GSERROR_NO_ENTRY) },
{ GSERROR_OUT_OF_RANGE, VPE_TO_STR(GSERROR_OUT_OF_RANGE) },
{ GSERROR_NO_SCREEN, VPE_TO_STR(GSERROR_NO_SCREEN) },
{ GSERROR_NO_BUFFER_READY, VPE_TO_STR(GSERROR_NO_BUFFER_READY) },
{ GSERROR_INVALID_OPERATING, VPE_TO_STR(GSERROR_INVALID_OPERATING) },
{ GSERROR_NO_CONSUMER, VPE_TO_STR(GSERROR_NO_CONSUMER) },
{ GSERROR_NOT_INIT, VPE_TO_STR(GSERROR_NOT_INIT) },
{ GSERROR_TYPE_ERROR, VPE_TO_STR(GSERROR_TYPE_ERROR) },
{ GSERROR_DESTROYED_OBJECT, VPE_TO_STR(GSERROR_DESTROYED_OBJECT) },
{ GSERROR_CONSUMER_IS_CONNECTED, VPE_TO_STR(GSERROR_CONSUMER_IS_CONNECTED) },
{ GSERROR_BUFFER_STATE_INVALID, VPE_TO_STR(GSERROR_BUFFER_STATE_INVALID) },
{ GSERROR_BUFFER_IS_INCACHE, VPE_TO_STR(GSERROR_BUFFER_IS_INCACHE) },
{ GSERROR_BUFFER_QUEUE_FULL, VPE_TO_STR(GSERROR_BUFFER_QUEUE_FULL) },
{ GSERROR_BUFFER_NOT_INCACHE, VPE_TO_STR(GSERROR_BUFFER_NOT_INCACHE) },
{ GSERROR_CONSUMER_DISCONNECTED, VPE_TO_STR(GSERROR_CONSUMER_DISCONNECTED) },
{ GSERROR_CONSUMER_UNREGISTER_LISTENER, VPE_TO_STR(GSERROR_CONSUMER_UNREGISTER_LISTENER) },
{ GSERROR_API_FAILED, VPE_TO_STR(GSERROR_API_FAILED) },
{ GSERROR_INTERNAL, VPE_TO_STR(GSERROR_INTERNAL) },
{ GSERROR_NO_MEM, VPE_TO_STR(GSERROR_NO_MEM) },
{ GSERROR_PROXY_NOT_INCLUDE, VPE_TO_STR(GSERROR_PROXY_NOT_INCLUDE) },
{ GSERROR_SERVER_ERROR, VPE_TO_STR(GSERROR_SERVER_ERROR) },
{ GSERROR_ANIMATION_RUNNING, VPE_TO_STR(GSERROR_ANIMATION_RUNNING) },
{ GSERROR_HDI_ERROR, VPE_TO_STR(GSERROR_HDI_ERROR) },
{ GSERROR_NOT_IMPLEMENT, VPE_TO_STR(GSERROR_NOT_IMPLEMENT) },
{ GSERROR_NOT_SUPPORT, VPE_TO_STR(GSERROR_NOT_SUPPORT) },
{ GSERROR_BINDER, VPE_TO_STR(GSERROR_BINDER) },
{ GSERROR_EGL_STATE_UNKOWN, VPE_TO_STR(GSERROR_EGL_STATE_UNKOWN) },
{ GSERROR_EGL_API_FAILED, VPE_TO_STR(GSERROR_EGL_API_FAILED) },
};
const std::unordered_map<VPEAlgoErrCode, std::string> ERROR_STR_MAP = {
{ VPE_ALGO_ERR_OK, VPE_TO_STR(VPE_ALGO_ERR_OK) },
{ VPE_ALGO_ERR_NO_MEMORY, VPE_TO_STR(VPE_ALGO_ERR_NO_MEMORY) },
@@ -46,26 +86,31 @@ const std::unordered_map<VPEAlgoState, std::string> STATE_STR_MAP = {
{ VPEAlgoState::EOS, VPE_TO_STR(VPEAlgoState::EOS) },
{ VPEAlgoState::ERROR, VPE_TO_STR(VPEAlgoState::ERROR) },
};
template <typename T>
std::string CodeToString(T code, const std::unordered_map<T, std::string>& codeMap, const std::string& name)
{
auto it = codeMap.find(code);
if (it == codeMap.end()) [[unlikely]] {
return "unknown " + name + "(" + std::to_string(static_cast<int>(code)) + ")";
}
return it->second;
}
} // namespace
std::string AlgorithmUtils::ToString(GSError errorCode)
{
return CodeToString(errorCode, GSERROR_STR_MAP, "GSError");
}
std::string AlgorithmUtils::ToString(VPEAlgoErrCode errorCode)
{
auto it = ERROR_STR_MAP.find(errorCode);
if (it == ERROR_STR_MAP.end()) [[unlikely]] {
VPE_LOGE("Invalid error code:%{public}d", errorCode);
return "Unsupported error:" + std::to_string(static_cast<int>(errorCode));
}
return it->second;
return CodeToString(errorCode, ERROR_STR_MAP, "VPEAlgoErrCode");
}
std::string AlgorithmUtils::ToString(VPEAlgoState state)
{
auto it = STATE_STR_MAP.find(state);
if (it == STATE_STR_MAP.end()) [[unlikely]] {
VPE_LOGE("Invalid state:%{public}d", state);
return "Unsupported state:" + std::to_string(static_cast<int>(state));
}
return it->second;
return CodeToString(state, STATE_STR_MAP, "VPEAlgoState");
}
bool AlgorithmUtils::CopySurfaceBufferToSurfaceBuffer(const sptr<SurfaceBuffer>& srcBuffer,
@@ -16,9 +16,11 @@
#include "algorithm_video_impl.h"
#include <chrono>
#include <limits>
#include <list>
#include <sstream>
#include "vpe_log.h"
#include "algorithm_utils.h"
#include "vpe_trace.h"
using namespace OHOS;
@@ -26,6 +28,7 @@ using namespace OHOS::Media::VideoProcessingEngine;
using namespace std::chrono_literals;
namespace {
constexpr uint32_t WAIT_FOR_EVER = std::numeric_limits<uint32_t>::max();
constexpr uint32_t BUFFER_QUEUE_SIZE = 5;
std::string ToString(const sptr<SurfaceBuffer>& buffer)
@@ -34,7 +37,8 @@ std::string ToString(const sptr<SurfaceBuffer>& buffer)
return "null";
}
std::stringstream stream;
stream << "id:" << buffer->GetSeqNum() << " " << buffer->GetWidth() << "x" << buffer->GetHeight() <<
stream << "id:" << buffer->GetSeqNum() << " fd:" << buffer->GetFileDescriptor() <<
" " << buffer->GetWidth() << "x" << buffer->GetHeight() <<
" format:" << buffer->GetFormat() << " usage:0x" << std::hex << buffer->GetUsage();
return stream.str();
}
@@ -62,7 +66,7 @@ VPEAlgoErrCode VpeVideoImpl::RegisterCallback(const std::shared_ptr<VpeVideoCall
[this, callback]() {
cb_ = callback;
return VPE_ALGO_ERR_OK;
}, "Registration of callbacks during running is not allowed!");
}, "Registration of callbacks during running is not allowed!", VPE_LOG_INFO);
}
VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
@@ -77,7 +81,7 @@ VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
std::lock_guard<std::mutex> producerLock(producerLock_);
if (producer_ != nullptr) {
if (producer_->GetUniqueId() == surface->GetUniqueId()) {
VPE_LOGD("Oops! The same surface!");
VPE_LOGD("Oops! The same surface(%{public}llu)!", surface->GetUniqueId());
return VPE_ALGO_ERR_OK;
}
producer_->UnRegisterReleaseListener();
@@ -86,11 +90,12 @@ VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
surface->UnRegisterReleaseListener();
GSError err = surface->RegisterReleaseListener([this](sptr<SurfaceBuffer>&) { return OnProducerBufferReleased(); });
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN, "RegisterReleaseListener failed!");
VPE_LOGI("Set output buffer queue size to %{public}u", BUFFER_QUEUE_SIZE);
VPE_LOGI("Set output(%{public}llu) buffer queue size to %{public}u", surface->GetUniqueId(), BUFFER_QUEUE_SIZE);
surface->SetQueueSize(BUFFER_QUEUE_SIZE);
surface->Connect();
surface->CleanCache();
AttachAndRefreshProducerBuffers(surface);
CHECK_AND_RETURN_RET_LOG(AttachAndRefreshProducerBuffers(surface), VPE_ALGO_ERR_UNKNOWN,
"Failed to attach buffers to new output surface(%{public}llu)!", surface->GetUniqueId());;
if (state_.load() != VPEState::IDLE) {
cvTrigger_.notify_one();
}
@@ -111,42 +116,13 @@ VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
return ret;
}
VPEAlgoErrCode VpeVideoImpl::UpdateProducerLocked()
{
auto transform = consumer_->GetTransform();
GSError err;
if (isForceUpdateProducer_ || lastTransform_ != transform) {
err = producer_->SetTransform(transform);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetTransform(%{public}d), ret:%{public}d!", transform, err);
lastTransform_ = transform;
VPE_LOGD("producer_->SetTransform(%{public}d) success.", transform);
}
if (lastConsumerBufferId_ == 0) {
return VPE_ALGO_ERR_OK;
}
ScalingMode scaleMode;
err = consumer_->GetScalingMode(lastConsumerBufferId_, scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to GetScalingMode(%{public}u), ret:%{public}d!", lastConsumerBufferId_, err);
if (isForceUpdateProducer_ || lastScalingMode_ != scaleMode) {
err = producer_->SetScalingMode(scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetScalingMode(%{public}d), ret:%{public}d!", scaleMode, err);
lastScalingMode_ = scaleMode;
VPE_LOGD("producer_->SetScalingMode(%{public}d) success.", scaleMode);
}
isForceUpdateProducer_ = false;
return VPE_ALGO_ERR_OK;
}
sptr<Surface> VpeVideoImpl::GetInputSurface()
{
sptr<Surface> producerSurface;
if (ExecuteWhenIdle([this, &producerSurface]() {
producerSurface = CreateConsumerSurfaceLocked();
return VPE_ALGO_ERR_OK;
}, "Getting a surface during running is not allowed!") != VPE_ALGO_ERR_OK) {
}, "Getting a surface during running is not allowed!", VPE_LOG_INFO) != VPE_ALGO_ERR_OK) {
return nullptr;
}
return producerSurface;
@@ -154,6 +130,7 @@ sptr<Surface> VpeVideoImpl::GetInputSurface()
VPEAlgoErrCode VpeVideoImpl::Start()
{
VPE_LOGD("step in");
return ExecuteWhenIdle(
[this]() {
CHECK_AND_RETURN_RET_LOG(isInitialized_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "NOT initialized!");
@@ -162,16 +139,17 @@ VPEAlgoErrCode VpeVideoImpl::Start()
state_ = VPEState::RUNNING;
OnStateLocked(VPEAlgoState::RUNNING);
return VPE_ALGO_ERR_OK;
}, "Already start!");
}, "Already start!", VPE_LOG_INFO);
}
VPEAlgoErrCode VpeVideoImpl::Stop()
{
VPE_LOGD("step in");
auto err = ExecuteWhenRunning([this]() {
state_ = VPEState::STOPPING;
cvTrigger_.notify_one();
return VPE_ALGO_ERR_OK;
}, "Already stop!");
}, "Already stop!", VPE_LOG_INFO);
return err;
}
@@ -183,6 +161,7 @@ VPEAlgoErrCode VpeVideoImpl::Release()
VPEAlgoErrCode VpeVideoImpl::Flush()
{
VPE_LOGD("step in");
CHECK_AND_RETURN_RET_LOG(isRunning_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "Flush must be called during running!");
std::lock_guard<std::mutex> lock(lock_);
{
std::unique_lock<std::mutex> lockTask(taskLock_);
@@ -193,8 +172,8 @@ VPEAlgoErrCode VpeVideoImpl::Flush()
std::queue<SurfaceBufferInfo> tempQueue1;
std::queue<SurfaceBufferInfo> tempQueue2;
{
std::lock_guard<std::mutex> bufferLock(bufferLock_);
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
consumerBufferQueue_.swap(tempQueue1);
for (auto& [index, bufferInfo] : renderBufferQueue_) {
producerBufferQueue_.push(bufferInfo);
@@ -206,6 +185,7 @@ VPEAlgoErrCode VpeVideoImpl::Flush()
ClearConsumerLocked(tempQueue1);
ClearConsumerLocked(tempQueue2);
} else {
CHECK_AND_RETURN_RET_LOG(producer_ != nullptr, VPE_ALGO_ERR_INVALID_OPERATION, "output surface is null!");
producer_->CleanCache(false);
ClearBufferQueues();
}
@@ -241,25 +221,30 @@ VPEAlgoErrCode VpeVideoImpl::Disable()
CHECK_AND_RETURN_RET_LOG(isEnable_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "Already disabled!");
std::lock_guard<std::mutex> lock(lock_);
isEnable_ = false;
isEnableChange_ = true;
VPE_LOGD("requestCfg_({ %{public}s })", ToString(requestCfg_).c_str());
return VPE_ALGO_ERR_OK;
return DisableLocked();
}
VPEAlgoErrCode VpeVideoImpl::NotifyEos()
{
VPE_LOGD("step in.");
return ExecuteWhenNotIdle(
[this]() {
VPE_LOGD("Try to NotifyEos...");
{
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
if (!isBufferQueueReady_.load()) {
isBufferQueueReady_ = true;
VPE_LOGD("Use requestCfg_({ %{public}s }) to prepare buffers.", ToString(requestCfg_).c_str());
needPrepareBuffers_ = true;
}
SurfaceBufferInfo bufferInfo{};
bufferInfo.bufferFlag = VPE_BUFFER_FLAG_EOS;
consumerBufferQueue_.push(bufferInfo);
}
cvTrigger_.notify_one();
VPE_LOGD("NotifyEos done.");
return VPE_ALGO_ERR_OK;
}, "Notify EOS must be called during running!");
}, "Notify EOS must be called during running!", VPE_LOG_INFO);
}
VPEAlgoErrCode VpeVideoImpl::ReleaseOutputBuffer(uint32_t index, bool render)
@@ -283,7 +268,7 @@ bool VpeVideoImpl::IsInitialized() const
VPEAlgoErrCode VpeVideoImpl::Initialize()
{
VPE_LOGD("Start to initializing... this:%{public}p", this);
VPE_LOGD("Start to initializing... this:%p", this);
std::lock_guard<std::mutex> lock(lock_);
if (isInitialized_.load()) {
VPE_LOGD("Already initialize!");
@@ -302,33 +287,32 @@ VPEAlgoErrCode VpeVideoImpl::Initialize()
});
auto errorCode = OnInitialize();
isInitialized_ = true;
VPE_LOGD("OnInitialize() return %{public}d. this:%{public}p", errorCode, this);
VPE_LOGD("OnInitialize() return %{public}d. this:%p", errorCode, this);
return errorCode;
}
VPEAlgoErrCode VpeVideoImpl::Deinitialize()
{
VPE_LOGD("Start to deinitializing... this:%{public}p", this);
std::lock_guard<std::mutex> lock(lock_);
VPE_LOGD("Start to deinitializing... this:%p", this);
std::unique_lock<std::mutex> lock(lock_);
if (!isInitialized_.load()) {
VPE_LOGD("Already deinitialize!");
return VPE_ALGO_ERR_OK;
}
{
std::unique_lock<std::mutex> taskLock(taskLock_);
cvDone_.wait(taskLock, [this]() { return !isProcessing_.load(); });
}
isInitialized_ = false;
VPEAlgoErrCode errorCode = OnDeinitialize();
isRunning_.store(false);
isInitialized_.store(false);
if (state_.load() == VPEState::RUNNING) {
state_ = VPEState::STOPPING;
}
isRunning_ = false;
lock.unlock();
cvTrigger_.notify_one();
if (worker_.joinable()) {
VPE_LOGD("Wait for thread ending... this:%p", this);
worker_.join();
}
lock.lock();
CheckStoppingLocked();
VPEAlgoErrCode errorCode = OnDeinitialize();
cb_ = nullptr;
std::lock_guard<std::mutex> producerLock(producerLock_);
ClearBufferQueues();
@@ -341,12 +325,16 @@ VPEAlgoErrCode VpeVideoImpl::Deinitialize()
producer_->CleanCache(true);
producer_ = nullptr;
}
VPE_LOGD("OnDeinitialize() return %{public}d. this:%{public}p", errorCode, this);
VPE_LOGD("OnDeinitialize() return %{public}d. this:%p", errorCode, this);
return errorCode;
}
void VpeVideoImpl::RefreshBuffers()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
std::lock_guard<std::mutex> lock(lock_);
if (state_.load() != VPEState::RUNNING) {
VPE_LOGD("Skip refreshing during Non-Running.");
@@ -368,6 +356,10 @@ void VpeVideoImpl::RefreshBuffers()
void VpeVideoImpl::OnOutputFormatChanged(const Format& format)
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
std::lock_guard<std::mutex> lock(lock_);
if (cb_ != nullptr) {
VPE_LOGD("OnOutputFormatChanged()");
@@ -391,11 +383,26 @@ VPEAlgoErrCode VpeVideoImpl::Process([[maybe_unused]] const sptr<SurfaceBuffer>&
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode VpeVideoImpl::ResetAfterDisable()
{
return VPE_ALGO_ERR_OK;
}
bool VpeVideoImpl::IsDisableAfterProcessFail()
{
return true;
}
bool VpeVideoImpl::IsProducerSurfaceValid([[maybe_unused]] const sptr<Surface>& surface)
{
return true;
}
bool VpeVideoImpl::IsConsumerBufferValid([[maybe_unused]] const sptr<SurfaceBuffer>& buffer)
{
return true;
}
VPEAlgoErrCode VpeVideoImpl::UpdateRequestCfg([[maybe_unused]] const sptr<Surface>& surface,
[[maybe_unused]] BufferRequestConfig& requestCfg)
{
@@ -410,7 +417,7 @@ void VpeVideoImpl::UpdateRequestCfg([[maybe_unused]] const sptr<SurfaceBuffer>&
void VpeVideoImpl::OnError(VPEAlgoErrCode errorCode)
{
if (cb_ != nullptr) {
VPE_LOGD("OnError(%{public}d)", errorCode);
VPE_LOGD("OnError(%{public}s)", AlgorithmUtils::ToString(errorCode).c_str());
cb_->OnError(errorCode);
}
}
@@ -418,7 +425,7 @@ void VpeVideoImpl::OnError(VPEAlgoErrCode errorCode)
void VpeVideoImpl::OnStateLocked(VPEAlgoState state)
{
if (cb_ != nullptr) {
VPE_LOGD("OnState(%{public}d)", state);
VPE_LOGD("OnState(%{public}s)", AlgorithmUtils::ToString(state).c_str());
cb_->OnState(state);
}
}
@@ -441,6 +448,10 @@ void VpeVideoImpl::OnOutputBufferAvailable(uint32_t index, const VpeBufferInfo&
GSError VpeVideoImpl::OnConsumerBufferAvailable()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> lock(lock_);
CHECK_AND_RETURN_RET_LOG(consumer_ != nullptr, GSERROR_OK, "Input surface is null!");
if (state_.load() != VPEState::RUNNING) {
@@ -449,14 +460,22 @@ GSError VpeVideoImpl::OnConsumerBufferAvailable()
}
SurfaceBufferInfo bufferInfo{};
int releaseFence = -1;
OHOS::Rect damage;
GSError err = consumer_->AcquireBuffer(bufferInfo.buffer, releaseFence, bufferInfo.timestamp, damage);
GSError err = consumer_->AcquireBuffer(bufferInfo.buffer, bufferInfo.fence, bufferInfo.timestamp, damage);
if (err != GSERROR_OK || bufferInfo.buffer == nullptr) {
VPE_LOGE("Failed to acquire buffer!");
VPE_LOGE("Failed to acquire buffer, ret:%{public}s!", AlgorithmUtils::ToString(err).c_str());
return err;
}
if (bufferInfo.fence != nullptr) [[likely]] {
bufferInfo.fence->Wait(WAIT_FOR_EVER);
} else [[unlikely]] {
VPE_LOGW("Fence is null for { %{public}s }", ToString(bufferInfo.buffer).c_str());
}
VPE_LOGD("consumer_->AcquireBuffer({ %{public}s })", ToString(bufferInfo.buffer).c_str());
if (!IsConsumerBufferValid(bufferInfo.buffer)) {
VPE_LOGD("Invalid buffer:{ %{public}s }", ToString(bufferInfo.buffer).c_str());
DisableLocked();
}
lastConsumerBufferId_ = bufferInfo.buffer->GetSeqNum();
{
@@ -479,6 +498,10 @@ GSError VpeVideoImpl::OnConsumerBufferAvailable()
GSError VpeVideoImpl::OnProducerBufferReleased()
{
VPE_LOGD("step in");
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> producerLock(producerLock_);
CHECK_AND_RETURN_RET_LOG(producer_ != nullptr, GSERROR_OK, "Output surface is null!");
@@ -486,12 +509,12 @@ GSError VpeVideoImpl::OnProducerBufferReleased()
std::lock_guard<std::mutex> bufferLock(bufferLock_);
GSError err = GSERROR_OK;
SurfaceBufferInfo bufferInfo{};
CHECK_AND_RETURN_RET_LOG(RequestBuffer(bufferInfo, err), err, "Failed to request buffer!");
CHECK_AND_RETURN_RET_LOG(RequestBuffer(bufferInfo, err, VPE_LOG_INFO_EX), err, "Failed to request buffer!");
PopBuffer(flushBufferQueue_, bufferInfo.buffer->GetSeqNum(), bufferInfo,
[this](sptr<SurfaceBuffer>& buffer) {
VPE_LOGD("OnProducerBufferReleased: Pop flush buffer { %{public}s } flushBQ=%{public}zu",
ToString(buffer).c_str(), flushBufferQueue_.size());
});
}, VPE_LOG_INFO_EX);
}
if (state_.load() != VPEState::IDLE) {
cvTrigger_.notify_one();
@@ -500,8 +523,68 @@ GSError VpeVideoImpl::OnProducerBufferReleased()
return GSERROR_OK;
}
bool VpeVideoImpl::CheckEnableNotifyStatus(bool isEnable, const std::string& status)
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return false;
}
std::lock_guard<std::mutex> lock(lock_);
CHECK_AND_RETURN_RET_LOG(isEnableChange_.load(), false, "Oops! Keep enable:%{public}d", isEnable_.load());
if (isEnable_.load() != isEnable) {
VPE_LOGD("Try to notify '%{public}s' but enable:%{public}d", status.c_str(), isEnable_.load());
return false;
}
isEnableChange_ = false;
return true;
}
VPEAlgoErrCode VpeVideoImpl::DisableLocked()
{
CHECK_AND_RETURN_RET_LOG(isEnable_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "Already disabled!");
isEnable_ = false;
isEnableChange_ = true;
VPE_LOGD("requestCfg_({ %{public}s })", ToString(requestCfg_).c_str());
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode VpeVideoImpl::UpdateProducerLocked()
{
auto transform = consumer_->GetTransform();
GSError err;
if (isForceUpdateProducer_ || lastTransform_ != transform) {
err = producer_->SetTransform(transform);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetTransform(%{public}d), ret:%{public}s!", transform, AlgorithmUtils::ToString(err).c_str());
lastTransform_ = transform;
VPE_LOGD("producer_->SetTransform(%{public}d) success.", transform);
}
if (lastConsumerBufferId_ == 0) {
return VPE_ALGO_ERR_OK;
}
ScalingMode scaleMode;
err = consumer_->GetScalingMode(lastConsumerBufferId_, scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to GetScalingMode(%{public}u), ret:%{public}s!",
lastConsumerBufferId_, AlgorithmUtils::ToString(err).c_str());
if (isForceUpdateProducer_ || lastScalingMode_ != scaleMode) {
err = producer_->SetScalingMode(scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetScalingMode(%{public}d), ret:%{public}s!", scaleMode, AlgorithmUtils::ToString(err).c_str());
lastScalingMode_ = scaleMode;
VPE_LOGD("producer_->SetScalingMode(%{public}d) success.", scaleMode);
}
isForceUpdateProducer_ = false;
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode VpeVideoImpl::RenderOutputBuffer(uint32_t index, int64_t renderTimestamp, bool render)
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return VPE_ALGO_ERR_INVALID_OPERATION;
}
std::unique_lock<std::mutex> bufferLock(bufferLock_);
auto it = renderBufferQueue_.find(index);
CHECK_AND_RETURN_RET_LOG(it != renderBufferQueue_.end(), VPE_ALGO_ERR_INVALID_PARAM,
@@ -519,14 +602,20 @@ VPEAlgoErrCode VpeVideoImpl::RenderOutputBuffer(uint32_t index, int64_t renderTi
std::lock_guard<std::mutex> producerLock(producerLock_);
CHECK_AND_RETURN_RET_LOG(producer_ != nullptr, VPE_ALGO_ERR_INVALID_OPERATION, "Output surface is null!");
auto ret = producer_->FlushBuffer(bufferInfo.buffer, -1, flushcfg);
VPE_LOGD("producer_->FlushBuffer({ %{public}s })=%{public}d flushBQ=%{public}zu",
ToString(bufferInfo.buffer).c_str(), ret, flushBufferQueue_.size() + 1);
VPE_LOGD("producer_(%{public}llu)->FlushBuffer({ %{public}s })=%{public}s flushBQ=%{public}zu",
producer_->GetUniqueId(), ToString(bufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret).c_str(),
flushBufferQueue_.size() + 1);
if (ret != GSERROR_OK) {
return VPE_ALGO_ERR_UNKNOWN;
}
}
bufferLock.lock();
flushBufferQueue_.push(bufferInfo);
auto itCache = producerBufferCache_.find(bufferInfo.buffer->GetSeqNum());
if (itCache != producerBufferCache_.end()) {
itCache->second.isFlushed = true;
itCache->second.flushedTime = std::chrono::steady_clock::now();
}
} else {
VPE_LOGD("reback { %{public}s } producerBQ=%{public}zu",
ToString(bufferInfo.buffer).c_str(), producerBufferQueue_.size() + 1);
@@ -563,31 +652,36 @@ sptr<Surface> VpeVideoImpl::CreateConsumerSurfaceLocked()
return producerSurface;
}
bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode)
bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode,
const LogInfoEx& logInfos)
{
CHECK_AND_RETURN_RET_LOG(hasConsumer_.load(), false, "Input surface is null!");
int releaseFence = -1;
errorCode = producer_->RequestBuffer(bufferInfo.buffer, releaseFence, requestCfg_);
errorCode = producer_->RequestBuffer(bufferInfo.buffer, bufferInfo.fence, requestCfg_);
if (errorCode != GSERROR_OK || bufferInfo.buffer == nullptr) {
VPE_LOGW("Failed to producer_->RequestBuffer(requestCfg={ %{public}s })", ToString(requestCfg_).c_str());
VPE_EX_LOGW(logInfos, "Failed to producer_(%{public}llu)->RequestBuffer(requestCfg={ %{public}s }), "
"ret:%{public}s", producer_->GetUniqueId(),
ToString(requestCfg_).c_str(), AlgorithmUtils::ToString(errorCode).c_str());
return false;
}
producerBufferQueue_.push(bufferInfo);
AddBufferToCache(bufferInfo);
if (!isEnable_.load()) {
VPE_LOGD("producer_->RequestBuffer({ %{public}s }) and try to release.", ToString(bufferInfo.buffer).c_str());
VPE_EX_LOGD(logInfos, "producer_(%{public}llu)->RequestBuffer({ %{public}s }) and try to release.",
producer_->GetUniqueId(), ToString(bufferInfo.buffer).c_str());
auto it = attachBufferIDs_.find(bufferInfo.buffer->GetSeqNum());
if (it != attachBufferIDs_.end()) {
PopBuffer(attachBufferQueue_, bufferInfo.buffer->GetSeqNum(), bufferInfo,
[this](sptr<SurfaceBuffer>& buffer) {
[this, &logInfos](sptr<SurfaceBuffer>& buffer) {
CHECK_AND_RETURN_LOG(buffer != nullptr, "Attach buffer is null!");
attachBufferIDs_.erase(buffer->GetSeqNum());
auto ret = consumer_->ReleaseBuffer(buffer, -1);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}d cache=%{public}zu",
ToString(buffer).c_str(), ret, attachBufferQueue_.size());
});
VPE_EX_LOGD(logInfos, "consumer_->ReleaseBuffer({ %{public}s })=%{public}s cache=%{public}zu",
ToString(buffer).c_str(), AlgorithmUtils::ToString(ret).c_str(), attachBufferQueue_.size());
}, ADD_VPE_LOG_INFO(logInfos));
}
} else {
VPE_LOGD("producer_->RequestBuffer({ %{public}s })", ToString(bufferInfo.buffer).c_str());
VPE_EX_LOGD(logInfos, "producer_(%{public}llu)->RequestBuffer({ %{public}s })", producer_->GetUniqueId(),
ToString(bufferInfo.buffer).c_str());
if (attachBufferQueue_.empty()) {
return true;
}
@@ -596,8 +690,8 @@ bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCo
if (bufferInfo.buffer != nullptr) {
attachBufferIDs_.erase(bufferInfo.buffer->GetSeqNum());
auto ret = consumer_->ReleaseBuffer(bufferInfo.buffer, -1);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}d cache->%{public}zu",
ToString(bufferInfo.buffer).c_str(), ret, attachBufferQueue_.size());
VPE_EX_LOGD(logInfos, "consumer_->ReleaseBuffer({ %{public}s })=%{public}s cache->%{public}zu",
ToString(bufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret).c_str(), attachBufferQueue_.size());
}
}
return true;
@@ -605,41 +699,59 @@ bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCo
void VpeVideoImpl::PrepareBuffers()
{
std::lock_guard<std::mutex> lock(lock_);
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
CHECK_AND_RETURN_LOG(producer_ != nullptr, "producer is null!");
for (uint32_t i = 0; i < producer_->GetQueueSize(); i++) {
uint32_t cacheSize = producerBufferCache_.size();
VPE_LOGD("producerBufferCache_.size=%{public}u", cacheSize);
for (uint32_t i = cacheSize; i < producer_->GetQueueSize(); i++) {
GSError errorCode;
SurfaceBufferInfo bufferInfo{};
RequestBuffer(bufferInfo, errorCode);
VPE_LOGD("<%{public}u> RequestBuffer({ %{public}s })=%{public}d", i, ToString(requestCfg_).c_str(), errorCode);
RequestBuffer(bufferInfo, errorCode, VPE_LOG_INFO_EX);
VPE_LOGD("<%{public}u> RequestBuffer({ %{public}s })=%{public}s", i, ToString(requestCfg_).c_str(),
AlgorithmUtils::ToString(errorCode).c_str());
}
}
void VpeVideoImpl::AttachAndRefreshProducerBuffers(const sptr<Surface>& producer)
bool VpeVideoImpl::AttachAndRefreshProducerBuffers(const sptr<Surface>& producer)
{
std::lock_guard<std::mutex> bufferLock(bufferLock_);
needPrepareBuffersForNewProducer_ = true;
CheckAndUpdateProducerCache();
for (auto& [index, bufferInfo] : producerBufferCache_) {
auto errorCode = producer->AttachBufferToQueue(bufferInfo.buffer);
CHECK_AND_RETURN_RET_LOG(errorCode == GSERROR_OK, false,
"Failed to producer(%{public}llu)->AttachBufferToQueue({ %{public}s })=%{public}s", producer->GetUniqueId(),
ToString(bufferInfo.buffer).c_str(), AlgorithmUtils::ToString(errorCode).c_str());
VPE_LOGD("producer(%{public}llu)->AttachBufferToQueue({ %{public}s })", producer->GetUniqueId(),
ToString(bufferInfo.buffer).c_str());
}
std::set<uint32_t> producerBufferIDs{};
std::queue<SurfaceBufferInfo> tempQueue;
producerBufferQueue_.swap(tempQueue);
AttachBuffers(producer, tempQueue);
RefreshProducerBuffers(flushBufferQueue_, [](SurfaceBufferInfo&) { return true; });
AddProducerBuffers(tempQueue, producerBufferIDs);
AddProducerBuffers(flushBufferQueue_, producerBufferIDs);
if (producerBufferQueue_.size() + renderBufferQueue_.size() >= producerBufferCache_.size()) {
VPE_LOGD("producerBQ:%{public}zu renderBQ:%{public}zu flushBQ:%{public}zu attachBQ:%{public}zu "
"producerBufferCache_:%{public}zu",
producerBufferQueue_.size(), renderBufferQueue_.size(), flushBufferQueue_.size(),
attachBufferQueue_.size(), producerBufferCache_.size());
return true;
}
VPE_LOGD("Add cache buffers to producerBQ");
for (auto& [index, bufferInfo] : producerBufferCache_) {
if (producerBufferIDs.count(index) > 0) {
continue;
}
VPE_LOGD("Add { %{public}s } to producerBQ", ToString(bufferInfo.buffer).c_str());
producerBufferQueue_.push(bufferInfo);
}
return true;
}
void VpeVideoImpl::AttachBuffers(const sptr<Surface>& producer, std::queue<SurfaceBufferInfo>& bufferQueue)
{
RefreshProducerBuffers(bufferQueue,
[&producer](SurfaceBufferInfo& bufferInfo) {
auto errorCode = producer->AttachBufferToQueue(bufferInfo.buffer);
if (errorCode != GSERROR_OK) {
VPE_LOGW("AttachBuffers: Failed to producer->AttachBufferToQueue({ %{public}s })=%{public}d",
ToString(bufferInfo.buffer).c_str(), errorCode);
return false;
}
return true;
});
}
void VpeVideoImpl::RefreshProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue,
std::function<bool(SurfaceBufferInfo&)>&& refresher)
void VpeVideoImpl::AddProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue, std::set<uint32_t>& producerBufferIDs)
{
for (; !bufferQueue.empty(); bufferQueue.pop()) {
auto bufferInfo = bufferQueue.front();
@@ -647,52 +759,95 @@ void VpeVideoImpl::RefreshProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQ
VPE_LOGW("buffer is null!");
continue;
}
if (!refresher(bufferInfo)) {
producerBufferIDs.insert(bufferInfo.buffer->GetSeqNum());
producerBufferQueue_.push(bufferInfo);
}
}
void VpeVideoImpl::AddBufferToCache(const SurfaceBufferInfo& bufferInfo)
{
CHECK_AND_RETURN_LOG(bufferInfo.buffer != nullptr, "buffer is null!");
auto it = producerBufferCache_.find(bufferInfo.buffer->GetSeqNum());
if (it != producerBufferCache_.end()) {
it->second.isFlushed = false;
VPE_LOGD("Refresh { %{public}s } of producerBufferCache_.size:%{public}zu",
ToString(bufferInfo.buffer).c_str(), producerBufferCache_.size());
return;
}
uint32_t size = producerBufferCache_.size();
producerBufferCache_[bufferInfo.buffer->GetSeqNum()] = bufferInfo;
VPE_LOGD("Add { %{public}s } to producerBufferCache_.size:%{public}u->%{public}zu",
ToString(bufferInfo.buffer).c_str(), size, producerBufferCache_.size());
CheckAndUpdateProducerCache();
}
void VpeVideoImpl::DelBufferFromCache(const SurfaceBufferInfo& bufferInfo)
{
CHECK_AND_RETURN_LOG(bufferInfo.buffer != nullptr, "buffer is null!");
uint32_t size = producerBufferCache_.size();
producerBufferCache_.erase(bufferInfo.buffer->GetSeqNum());
VPE_LOGD("Del { %{public}s } from producerBufferCache_.size:%{public}u->%{public}zu",
ToString(bufferInfo.buffer).c_str(), size, producerBufferCache_.size());
}
void VpeVideoImpl::CheckAndUpdateProducerCache()
{
uint32_t size = producerBufferCache_.size();
if (size <= BUFFER_QUEUE_SIZE) {
return;
}
std::list<SurfaceBufferInfo> toBeDel;
for (auto& [index, info] : producerBufferCache_) {
if (!info.isFlushed) {
continue;
}
producerBufferQueue_.push(bufferInfo);
for (auto it = toBeDel.begin(); it != toBeDel.end(); it++) {
if (info.flushedTime < it->flushedTime) {
toBeDel.insert(it, info);
continue;
}
}
toBeDel.push_back(info);
}
for (auto it = toBeDel.begin(); it != toBeDel.end(); it++) {
size = producerBufferCache_.size();
producerBufferCache_.erase(it->buffer->GetSeqNum());
VPE_LOGD("Del { %{public}s } from producerBufferCache_.size:%{public}u->%{public}zu",
ToString(it->buffer).c_str(), size, producerBufferCache_.size());
if (producerBufferCache_.size() <= BUFFER_QUEUE_SIZE) {
break;
}
}
}
void VpeVideoImpl::ProcessBuffers()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
{
std::lock_guard<std::mutex> lock(lock_);
CHECK_AND_RETURN_LOG(consumer_ != nullptr && producer_ != nullptr, "consumer or producer is null!");
UpdateProducerLocked();
}
while (isRunning_.load()) {
std::lock_guard<std::mutex> taskLock(taskLock_);
isProcessing_ = true;
SurfaceBufferInfo srcBufferInfo;
SurfaceBufferInfo dstBufferInfo;
{
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
if (producerBufferQueue_.empty() || consumerBufferQueue_.empty()) {
break;
}
srcBufferInfo = consumerBufferQueue_.front();
if (srcBufferInfo.buffer == nullptr) {
consumerBufferQueue_.pop();
continue;
}
dstBufferInfo = producerBufferQueue_.front();
if (dstBufferInfo.buffer == nullptr) {
producerBufferQueue_.pop();
continue;
}
consumerBufferQueue_.pop();
producerBufferQueue_.pop();
if (!GetConsumerAndProducerBuffer(srcBufferInfo, dstBufferInfo)) {
break;
}
if (srcBufferInfo.bufferFlag == VPE_BUFFER_FLAG_EOS) {
VPE_LOGD("EOS frame.");
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {});
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {}, VPE_LOG_INFO);
break;
}
if (isEnable_.load()) {
if (!ProcessBuffer(srcBufferInfo, dstBufferInfo)) {
if (!ProcessBuffer(srcBufferInfo, dstBufferInfo) && IsDisableAfterProcessFail()) {
VPE_LOGD("Dsiable because failed to process !");
Disable();
continue;
}
} else {
@@ -705,12 +860,37 @@ void VpeVideoImpl::ProcessBuffers()
cvDone_.notify_all();
}
bool VpeVideoImpl::GetConsumerAndProducerBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo)
{
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
if (producerBufferQueue_.empty() || consumerBufferQueue_.empty()) {
return false;
}
srcBufferInfo = consumerBufferQueue_.front();
if (srcBufferInfo.buffer == nullptr && srcBufferInfo.bufferFlag != VPE_BUFFER_FLAG_EOS) {
consumerBufferQueue_.pop();
VPE_LOGW("input buffer is null!");
return false;
}
dstBufferInfo = producerBufferQueue_.front();
if (dstBufferInfo.buffer == nullptr) {
producerBufferQueue_.pop();
VPE_LOGW("output buffer is null!");
return false;
}
consumerBufferQueue_.pop();
producerBufferQueue_.pop();
return true;
}
bool VpeVideoImpl::ProcessBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo)
{
dstBufferInfo.timestamp = srcBufferInfo.timestamp;
auto errorCode = Process(srcBufferInfo.buffer, dstBufferInfo.buffer);
auto ret = consumer_->ReleaseBuffer(srcBufferInfo.buffer, -1);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}d", ToString(srcBufferInfo.buffer).c_str(), ret);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}s", ToString(srcBufferInfo.buffer).c_str(),
AlgorithmUtils::ToString(ret).c_str());
if (errorCode != VPE_ALGO_ERR_OK) {
OnError(errorCode);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
@@ -719,39 +899,53 @@ bool VpeVideoImpl::ProcessBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBuffer
ToString(srcBufferInfo.buffer).c_str(), ToString(dstBufferInfo.buffer).c_str(), errorCode);
return false;
}
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {});
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {}, VPE_LOG_INFO);
NotifyEnableStatus(type_, "enable");
return true;
}
void VpeVideoImpl::BypassBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo)
{
GSError ret1;
GSError ret2;
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
std::lock_guard<std::mutex> lock(lock_);
auto ret1 = producer_->DetachBufferFromQueue(dstBufferInfo.buffer);
auto ret2 = producer_->AttachBufferToQueue(srcBufferInfo.buffer);
ret1 = producer_->DetachBufferFromQueue(dstBufferInfo.buffer);
ret2 = producer_->AttachBufferToQueue(srcBufferInfo.buffer);
SetRequestCfgLocked(srcBufferInfo.buffer);
VPE_LOGD("producer_->DetachBufferFromQueue({ %{public}s })=%{public}d, "
"AttachBufferToQueue({ %{public}s })=%{public}d requestCfg:{ %{public}s }",
ToString(dstBufferInfo.buffer).c_str(), ret1,
ToString(srcBufferInfo.buffer).c_str(), ret2, ToString(requestCfg_).c_str());
VPE_LOGD("producer_(%{public}llu)->DetachBufferFromQueue({ %{public}s })=%{public}s, "
"AttachBufferToQueue({ %{public}s })=%{public}s requestCfg:{ %{public}s } ", producer_->GetUniqueId(),
ToString(dstBufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret1).c_str(),
ToString(srcBufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret2).c_str(),
ToString(requestCfg_).c_str());
}
OutputBuffer(srcBufferInfo, srcBufferInfo, [this, &srcBufferInfo] {
OutputBuffer(srcBufferInfo, srcBufferInfo, [this, &srcBufferInfo, &dstBufferInfo, &ret1, &ret2] {
attachBufferIDs_.insert(srcBufferInfo.buffer->GetSeqNum());
attachBufferQueue_.push(srcBufferInfo);
});
if (ret1 == GSERROR_OK) {
DelBufferFromCache(dstBufferInfo);
}
if (ret2 == GSERROR_OK) {
AddBufferToCache(srcBufferInfo);
}
}, VPE_LOG_INFO);
VPE_LOGD("cache(%{public}s)->%{public}zu/%{public}zu", ToString(srcBufferInfo.buffer).c_str(),
attachBufferIDs_.size(), attachBufferIDs_.size());
NotifyEnableStatus(0, "disable");
}
void VpeVideoImpl::OutputBuffer(const SurfaceBufferInfo& bufferInfo, const SurfaceBufferInfo& bufferImage,
std::function<void(void)>&& getReadyToRender)
std::function<void(void)>&& getReadyToRender, const LogInfo& logInfo)
{
{
std::lock_guard<std::mutex> bufferLock(bufferLock_);
renderBufferQueue_[bufferImage.buffer->GetSeqNum()] = bufferImage;
VPE_LOGD("renderBufferQueue_.push({ %{public}s })", ToString(bufferImage.buffer).c_str());
VPE_ORG_LOGD(logInfo, "renderBufferQueue_.push({ %{public}s }) size:%{public}zu",
ToString(bufferImage.buffer).c_str(), renderBufferQueue_.size());
getReadyToRender();
}
VpeBufferInfo info {
@@ -767,20 +961,25 @@ void VpeVideoImpl::NotifyEnableStatus(uint32_t type, const std::string& status)
VPE_LOGD("Keep %{public}s.", status.c_str());
return;
}
if (!CheckEnableNotifyStatus(type > 0, status)) {
return;
}
OnEffectChange(type);
std::lock_guard<std::mutex> lock(lock_);
isEnableChange_ = false;
if (type == 0) {
VPE_LOGD("Call ResetAfterDisable.");
ResetAfterDisable();
}
}
bool VpeVideoImpl::PopBuffer(std::queue<SurfaceBufferInfo>& bufferQueue, uint32_t index, SurfaceBufferInfo& bufferInfo,
std::function<void(sptr<SurfaceBuffer>&)>&& func)
std::function<void(sptr<SurfaceBuffer>&)>&& func, const LogInfoEx& logInfos)
{
bool isFound = false;
while (!bufferQueue.empty()) {
bufferInfo = bufferQueue.front();
bufferQueue.pop();
func(bufferInfo.buffer);
VPE_LOGD("index:%{public}u buffer:{ %{public}s }", index, ToString(bufferInfo.buffer).c_str());
VPE_EX_LOGD(logInfos, "index:%{public}u buffer:{ %{public}s }", index, ToString(bufferInfo.buffer).c_str());
if (bufferInfo.buffer != nullptr && bufferInfo.buffer->GetSeqNum() == index) {
isFound = true;
break;
@@ -811,28 +1010,36 @@ bool VpeVideoImpl::WaitTrigger()
{
uint32_t consumerSize = 0;
uint32_t producerSize = 0;
std::unique_lock<std::mutex> bufferLock(bufferLock_);
if (!cvTrigger_.wait_for(bufferLock, 200s, [this, &consumerSize, &producerSize] {
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
if (needPrepareBuffers_.load()) {
std::unique_lock<std::mutex> waitLock(waitLock_);
if (!cvTrigger_.wait_for(waitLock, 200s, [this, &consumerSize, &producerSize] {
if (!isRunning_.load()) {
VPE_LOGI("Skip WaitTrigger when died.");
return true;
}
if (needPrepareBuffers_.load() || needPrepareBuffersForNewProducer_.load()) {
std::lock_guard<std::mutex> lock(lock_);
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
PrepareBuffers();
needPrepareBuffers_ = false;
needPrepareBuffersForNewProducer_ = false;
}
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
consumerSize = consumerBufferQueue_.size();
producerSize = producerBufferQueue_.size();
VPE_LOGD("run:%d stopping:%d consumerBQ:%{public}u producerBQ:%{public}u "
VPE_LOGD("run:%{public}d stopping:%{public}d consumerBQ:%{public}u producerBQ:%{public}u "
"renderBQ:%{public}zu flushBQ:%{public}zu attachBQ:%{public}zu",
isRunning_.load(), state_.load() == VPEState::STOPPING, consumerSize, producerSize,
renderBufferQueue_.size(), flushBufferQueue_.size(), attachBufferQueue_.size());
return !isRunning_.load() || state_.load() == VPEState::STOPPING ||
(consumerSize > 0 && producerSize > 0);
return !isRunning_.load() || state_.load() == VPEState::STOPPING || (consumerSize > 0 && producerSize > 0);
})) {
VPE_LOGI("Video processing timeout.");
return false;
}
if (!isRunning_.load()) {
VPE_LOGI("Video processing clear.");
VPE_LOGI("die.");
return false;
}
if (consumerSize == 0 || producerSize == 0) {
@@ -852,6 +1059,10 @@ void VpeVideoImpl::CheckSpuriousWakeup()
bool VpeVideoImpl::CheckStopping()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return true;
}
std::lock_guard<std::mutex> lock(lock_);
return CheckStoppingLocked();
}
@@ -876,11 +1087,13 @@ void VpeVideoImpl::ClearQueue(std::queue<SurfaceBufferInfo>& bufferQueue)
void VpeVideoImpl::ClearConsumerLocked(std::queue<SurfaceBufferInfo>& bufferQueue)
{
CHECK_AND_RETURN_LOG(consumer_ != nullptr, "input surface is null!");
while (!bufferQueue.empty()) {
auto bufferInfo = bufferQueue.front();
auto err = consumer_->ReleaseBuffer(bufferInfo.buffer, -1);
if (err != GSERROR_OK) {
VPE_LOGW("Failed to ReleaseBuffer({ %{public}s }):%{public}d", ToString(bufferInfo.buffer).c_str(), err);
VPE_LOGW("Failed to ReleaseBuffer({ %{public}s }):%{public}s", ToString(bufferInfo.buffer).c_str(),
AlgorithmUtils::ToString(err).c_str());
}
bufferQueue.pop();
}
@@ -898,6 +1111,7 @@ void VpeVideoImpl::ClearBufferQueues()
ClearQueue(producerBufferQueue_);
renderBufferQueue_.clear();
ClearQueue(flushBufferQueue_);
producerBufferCache_.clear();
attachBufferQueue_.swap(tempQueue2);
attachBufferIDs_.clear();
}
@@ -906,31 +1120,34 @@ void VpeVideoImpl::ClearBufferQueues()
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWhenIdle(std::function<VPEAlgoErrCode(void)>&& operation,
const std::string& errorMessage)
const std::string& errorMessage, const LogInfo& logInfo)
{
return ExecuteWithCheck([this] { return state_.load() == VPEState::IDLE; }, std::move(operation), errorMessage);
return ExecuteWithCheck([this] { return state_.load() == VPEState::IDLE; }, std::move(operation), errorMessage,
logInfo);
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWhenNotIdle(std::function<VPEAlgoErrCode(void)>&& operation,
const std::string& errorMessage)
const std::string& errorMessage, const LogInfo& logInfo)
{
return ExecuteWithCheck([this] { return state_.load() != VPEState::IDLE; }, std::move(operation), errorMessage);
return ExecuteWithCheck([this] { return state_.load() != VPEState::IDLE; }, std::move(operation), errorMessage,
logInfo);
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWhenRunning(std::function<VPEAlgoErrCode(void)>&& operation,
const std::string& errorMessage)
const std::string& errorMessage, const LogInfo& logInfo)
{
return ExecuteWithCheck([this] { return state_.load() == VPEState::RUNNING; }, std::move(operation), errorMessage);
return ExecuteWithCheck([this] { return state_.load() == VPEState::RUNNING; }, std::move(operation), errorMessage,
logInfo);
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWithCheck(std::function<bool(void)>&& checker,
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage)
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage, const LogInfo& logInfo)
{
std::lock_guard<std::mutex> lock(lock_);
if (checker()) {
return operation();
}
VPE_LOGW("%{public}s", errorMessage.c_str());
VPE_ORG_LOGW(logInfo, "%{public}s", errorMessage.c_str());
return VPE_ALGO_ERR_INVALID_OPERATION;
}
@@ -21,6 +21,7 @@
#include "algorithm_errors.h"
#include "algorithm_video_common.h"
#include "surface_buffer.h"
#include "graphic_common_c.h"
#define VPE_TO_STR(val) (std::string(#val) + "(" + std::to_string(static_cast<int>(val)) + ")")
@@ -29,6 +30,7 @@ namespace Media {
namespace VideoProcessingEngine {
class AlgorithmUtils {
public:
static std::string ToString(GSError errorCode);
static std::string ToString(VPEAlgoErrCode errorCode);
static std::string ToString(VPEAlgoState state);
static bool CopySurfaceBufferToSurfaceBuffer(const sptr<SurfaceBuffer>& srcBuffer,
@@ -17,6 +17,7 @@
#define ALGORITHM_VIDEO_IMPL_H
#include <atomic>
#include <chrono>
#include <cinttypes>
#include <condition_variable>
#include <functional>
@@ -30,9 +31,12 @@
#include "refbase.h"
#include "surface.h"
#include "surface_buffer.h"
#include "sync_fence.h"
#include "algorithm_errors.h"
#include "algorithm_video.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
@@ -60,16 +64,23 @@ protected:
VpeVideoImpl(VpeVideoImpl&&) = delete;
VpeVideoImpl& operator=(VpeVideoImpl&&) = delete;
// These funcions may be called by derived class as necessary.
bool IsInitialized() const;
VPEAlgoErrCode Initialize();
VPEAlgoErrCode Deinitialize();
void RefreshBuffers();
void OnOutputFormatChanged(const Format& format);
// These funcions may be overried by derived class as necessary.
virtual VPEAlgoErrCode OnInitialize();
virtual VPEAlgoErrCode OnDeinitialize();
virtual VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& sourceImage, sptr<SurfaceBuffer>& destinationImage);
// This function will be called after disable, you may reset such as timeout protection status in derived class.
// if you do NOT reset the protection status, the feature may not response properly when user call Enable() again.
virtual VPEAlgoErrCode ResetAfterDisable();
virtual bool IsDisableAfterProcessFail();
virtual bool IsProducerSurfaceValid(const sptr<Surface>& surface);
virtual bool IsConsumerBufferValid(const sptr<SurfaceBuffer>& buffer);
virtual VPEAlgoErrCode UpdateRequestCfg(const sptr<Surface>& surface, BufferRequestConfig& requestCfg);
virtual void UpdateRequestCfg(const sptr<SurfaceBuffer>& consumerBuffer, BufferRequestConfig& requestCfg);
@@ -82,8 +93,11 @@ private:
struct SurfaceBufferInfo {
sptr<SurfaceBuffer> buffer{};
sptr<SyncFence> fence{};
VpeBufferFlag bufferFlag{VPE_BUFFER_FLAG_NONE};
int64_t timestamp{};
bool isFlushed{};
std::chrono::time_point<std::chrono::steady_clock> flushedTime{};
};
class ConsumerListener : public IBufferConsumerListener {
@@ -109,23 +123,27 @@ private:
GSError OnConsumerBufferAvailable();
GSError OnProducerBufferReleased();
bool CheckEnableNotifyStatus(bool isEnable, const std::string& status);
VPEAlgoErrCode DisableLocked();
VPEAlgoErrCode UpdateProducerLocked();
VPEAlgoErrCode RenderOutputBuffer(uint32_t index, int64_t renderTimestamp, bool render);
sptr<Surface> CreateConsumerSurfaceLocked();
bool RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode);
bool RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode, const LogInfoEx& logInfos);
void PrepareBuffers();
void AttachAndRefreshProducerBuffers(const sptr<Surface>& producer);
void AttachBuffers(const sptr<Surface>& producer, std::queue<SurfaceBufferInfo>& bufferQueue);
void RefreshProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue,
std::function<bool(SurfaceBufferInfo&)>&& refresher);
bool AttachAndRefreshProducerBuffers(const sptr<Surface>& producer);
void AddProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue, std::set<uint32_t>& producerBufferIDs);
void AddBufferToCache(const SurfaceBufferInfo& bufferInfo);
void DelBufferFromCache(const SurfaceBufferInfo& bufferInfo);
void CheckAndUpdateProducerCache();
void ProcessBuffers();
bool GetConsumerAndProducerBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo);
bool ProcessBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo);
void BypassBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo);
void OutputBuffer(const SurfaceBufferInfo& bufferInfo, const SurfaceBufferInfo& bufferImage,
std::function<void(void)>&& getReadyToRender);
std::function<void(void)>&& getReadyToRender, const LogInfo& logInfo);
void NotifyEnableStatus(uint32_t type, const std::string& status);
bool PopBuffer(std::queue<SurfaceBufferInfo>& bufferQueue, uint32_t index, SurfaceBufferInfo& bufferInfo,
std::function<void(sptr<SurfaceBuffer>&)>&& func);
std::function<void(sptr<SurfaceBuffer>&)>&& func, const LogInfoEx& logInfos);
void PrintBufferSize() const;
void SetRequestCfgLocked(const sptr<SurfaceBuffer>& buffer);
bool WaitTrigger();
@@ -136,11 +154,14 @@ private:
void ClearConsumerLocked(std::queue<SurfaceBufferInfo>& bufferQueue);
void ClearBufferQueues();
VPEAlgoErrCode ExecuteWhenIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
VPEAlgoErrCode ExecuteWhenNotIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
VPEAlgoErrCode ExecuteWhenRunning(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
VPEAlgoErrCode ExecuteWhenIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage,
const LogInfo& logInfo);
VPEAlgoErrCode ExecuteWhenNotIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage,
const LogInfo& logInfo);
VPEAlgoErrCode ExecuteWhenRunning(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage,
const LogInfo& logInfo);
VPEAlgoErrCode ExecuteWithCheck(std::function<bool(void)>&& checker,
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage, const LogInfo& logInfo);
// Common
uint32_t type_{};
@@ -149,6 +170,15 @@ private:
std::condition_variable cvTrigger_{};
std::condition_variable cvDone_{};
// [WARNING]
// The lock must be held in the following order:
// waitLock_
// lock_
// taskLock_
// producerLock_
// consumerBufferLock_
// bufferLock_
mutable std::mutex waitLock_{};
mutable std::mutex lock_{};
// Guarded by lock_ begin
std::atomic<bool> isInitialized_{false};
@@ -184,9 +214,11 @@ private:
mutable std::mutex bufferLock_{};
// Guarded by bufferLock_ begin
std::atomic<bool> needPrepareBuffersForNewProducer_{false};
std::queue<SurfaceBufferInfo> producerBufferQueue_{};
std::unordered_map<uint32_t, SurfaceBufferInfo> renderBufferQueue_{};
std::queue<SurfaceBufferInfo> flushBufferQueue_{};
std::unordered_map<uint32_t, SurfaceBufferInfo> producerBufferCache_{};
std::queue<SurfaceBufferInfo> attachBufferQueue_{};
std::set<uint32_t> attachBufferIDs_{};
// Guarded by bufferLock_ end
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -12,13 +12,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VIDEO_PROCESSING_SERVICE_VPE_MODEL_PATH_H
#define VIDEO_PROCESSING_SERVICE_VPE_MODEL_PATH_H
#ifndef VPE_MODEL_PATH_H
#define VPE_MODEL_PATH_H
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
enum MODEL_PATHS {
AILIGHT_NORMAL = 0,
enum VpeModelKey {
VPE_MODE_KEY_INVALID = -1,
AILIGHT_NORMAL,
AILIGHT_STRONG,
AILIGHT_CLS,
AIHDR_PIC,
@@ -78,10 +81,11 @@ enum MODEL_PATHS {
EVE_10bit_SCALE_KERNEL,
VIDEO_AIHDR_ALGO_CONFIG,
VIDEO_AIHDR_MODEL,
VPEMODEL_PATHS_LENGTH,
IMAGE_SR_10bit_CONVERT_KERNEL,
VPE_MODEL_KEY_NUM,
};
const std::array<std::string, VPEMODEL_PATHS_LENGTH> VPE_MODEL_PATHS = {
const std::array<std::string, VPE_MODEL_KEY_NUM> VPE_MODEL_PATHS = {
"/sys_prod/etc/VideoProcessingEngine/AILIGHT_normal.omc",
"/sys_prod/etc/VideoProcessingEngine/AILIGHT_strong.omc",
"/sys_prod/etc/VideoProcessingEngine/AILIGHT_cls.omc",
@@ -142,9 +146,10 @@ const std::array<std::string, VPEMODEL_PATHS_LENGTH> VPE_MODEL_PATHS = {
"/sys_prod/etc/VideoProcessingEngine/10bitProcess.bin",
"/sys_prod/etc/VideoProcessingEngine/video_aihdr_algo_config.xml",
"/sys_prod/etc/VideoProcessingEngine/GTM_AIHDR.omc",
"/sys_prod/etc/VideoProcessingEngine/10bitAisr.bin",
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_SERVICE_VPE_MODEL_PATH_H
#endif // VPE_MODEL_PATH_H
@@ -1,76 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device 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 VPE_FRAMEWORK_ALGORITHM_COMMON_PARSE_METADATA_H
#define VPE_FRAMEWORK_ALGORITHM_COMMON_PARSE_METADATA_H
#include <vector>
#include "hdr_vivid_metadata_v1.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
constexpr int METADATA_MAX_LENGTH = 512;
constexpr int AIHDR_METADATA_MAX_LENGTH = 128;
// 以下变量根据CUVA标准7.4确定了每个元数据所占用的bit数
using CuvaMetadataBitNum = enum {
SYSTEM_START_CODE_BIT = 8,
MINIMUM_MAXRGB_BIT = 12,
AVERAGE_MAXRGB_BIT = 12,
VARIANCE_MAXRGB_BIT = 12,
MAXIMUM_MAXRGB_BIT = 12,
TONE_MAPPING_MODE_BIT = 1,
TONE_MAPPING_PARAM_NUM_BIT = 1,
TARGETED_SYSTEM_DISPLAY_BIT = 12,
BASE_FLAG_BIT = 1,
BASE_PARAM_MP_BIT = 14,
BASE_PARAM_MM_BIT = 6,
BASE_PARAM_MA_BIT = 10,
BASE_PARAM_MB_BIT = 10,
BASE_PARAM_MN_BIT = 6,
BASE_PARAM_K1_BIT = 2,
BASE_PARAM_K2_BIT = 2,
BASE_PARAM_K3_BIT = 4,
BASE_PARAM_DELTA_MODE_BIT = 3,
BASE_PARAM_DELTA_BIT = 7,
P3SPLINE_FLAG_BIT = 1,
P3SPLINE_NUM_BIT = 1,
P3SPLINE_TH_MODE_BIT = 2,
P3SPLINE_TH_MB_BIT = 8,
P3SPLINE_TH_OFFSET_BIT = 2,
P3SPLINE_TH1_BIT = 12,
P3SPLINE_TH2_BIT = 10,
P3SPLINE_TH3_BIT = 10,
P3SPLINE_STRENGTH_BIT = 8,
COLOR_SATURATION_BIT = 1,
COLOR_SATURATION_NUM_BIT = 3,
COLOR_SATURATION_GAIN_BIT = 8,
CUVA_TWELVE_BIT_NUM = 4095,
CUVA_LOW_AREA_CURVE = 0,
CUVA_SPLINE_AREA_CURVE = 1,
CUVA_HIGH_AREA_CURVE = 2,
CUVA_TYPE_BIT = 4,
MARKERBIT_BIT = 1,
DISPLAY_3BIT = 3,
DISPLAY_8BIT = 8,
DISPLAY_MARKERBIT = 1,
DISPLAY_16BIT = 16
};
int PraseMetadataFromArray(const std::vector<uint8_t> &cuvaInfo, HdrVividMetadataV1 &tmoCuvaMetadata,
HwDisplayMeta &displayMeta);
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VPE_FRAMEWORK_ALGORITHM_COMMON_PARSE_METADATA_H
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -13,10 +13,11 @@
* limitations under the License.
*/
#ifndef IMAGE_PROCESSING_UTILS_IMPL_H
#define IMAGE_PROCESSING_UTILS_IMPL_H
#ifndef VIDEO_PROCESSING_ENGINE_UTILS_H
#define VIDEO_PROCESSING_ENGINE_UTILS_H
#include "pixelmap_native_impl.h"
#include "algorithm_errors.h"
#include "pixel_map.h"
#include "surface_buffer.h"
namespace OHOS {
@@ -39,9 +40,10 @@ public:
std::shared_ptr<OHOS::Media::PixelMap>& pixelmap);
static bool CopyNV12PixelmapToSurfaceBuffer(const std::shared_ptr<OHOS::Media::PixelMap>& pixelmap,
sptr<SurfaceBuffer>& buffer);
static VPEAlgoErrCode LoadModel(int modelKey, sptr<SurfaceBuffer>& modelBuffer);
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // IMAGE_PROCESSING_UTILS_IMPL_H
#endif // VIDEO_PROCESSING_ENGINE_UTILS_H
@@ -1,313 +0,0 @@
/*
* Copyright (c) 2023 Huawei Device 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 "vpe_parse_metadata.h"
#include <cstdint>
#include <vector>
#include "securec.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
// 做了字节颠倒ˇ把4个字节逆序排列
static inline uint32_t ConvertEndian(uint32_t x)
{
// 8 & 24: bit offset; 0x0000ff00 & 0x00ff0000 & 0x000000ff: bit mask
return ((x << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x >> 24) & 0x000000ff));
}
struct BsInfo {
uint8_t *head;
uint8_t *tail;
uint32_t bufA;
uint32_t bufB;
int32_t bsLen;
int32_t bufPos;
uint32_t totalPos;
};
static void InitBs(BsInfo *bs, const uint8_t *input, int32_t length)
{
uint32_t data;
uint64_t alignWord = 0x3; // 使首地址4字节对齐
bs->head = reinterpret_cast<uint8_t *>(reinterpret_cast<uintptr_t>(input) & ~alignWord);
bs->tail = bs->head + 8; // 8 :将尾地址初始化为首地址8字节之后
bs->bsLen = length;
data = *reinterpret_cast<uint32_t *>(bs->head);
bs->bufA = ConvertEndian(data);
// 4 :读取后4个字节的值传给bufBˇ当要取的元数据跨越两段4字节时会用到
data = *reinterpret_cast<uint32_t *>(bs->head + 4);
bs->bufB = ConvertEndian(data);
// 3 is bit ofsˇ记录对齐地址和实际地址的偏差量
bs->bufPos = (reinterpret_cast<uintptr_t>(input) & 0x3) << 3;
bs->totalPos = 0;
return;
}
static int32_t ShowBs(const BsInfo *bs, int32_t currentBitNum)
{
uint32_t pos = static_cast<uint32_t>(bs->bufPos);
// 0x20:4字节ˇ如果对齐后和实际地址的偏差量大于4字节ˇ或要读取的位数为0
// 或要取的位数大于4字节ˇ直接返回0
if (pos >= 0x20 || currentBitNum == 0 || currentBitNum > 0x20) {
return 0;
}
// 要读取的位数超出剩余码流的位数时,直接返回0
// 8 :一个字节占8位ˇ当前读取位小于传入数组总位数才合理
if (static_cast<uint32_t>(bs->totalPos + currentBitNum) > static_cast<uint32_t>(bs->bsLen * 8)) {
return 0;
}
// 0x20ˇ32ˇ如果要取的元数据要跨越两段4个字节ˇ则要取两次值进行拼接。
uint32_t data = 0;
int32_t abPos = currentBitNum + bs->bufPos;
if (abPos > 0x20) {
data = bs->bufA << pos;
// 0x20-pos为高四节数值和低四节数值的位偏移量ˇ移位后data1和data对齐
uint32_t data1 = (pos == 0) ? 0 : (bs->bufB >> (0x20 - pos));
data |= data1;
data >>= static_cast<uint32_t>(0x20 - currentBitNum); // 0x20:4字节
} else { // 如果要取的元数据没有跨越两个4字节ˇ则直接读取bufA移位后的值。0x20:4字节
data = (bs->bufA << pos) >> static_cast<uint32_t>(0x20 - currentBitNum);
}
return static_cast<int32_t>(data);
}
static int32_t SkipBs(BsInfo *bs, int32_t currentBitNum)
{
bs->totalPos += static_cast<uint32_t>(currentBitNum);
// 8 :一个字节占8位ˇ当前读取位小于传入数组总位数才合理
if (bs->totalPos < static_cast<uint32_t>(bs->bsLen * 8)) {
int32_t abPos = currentBitNum + bs->bufPos;
if (abPos >= 32) { // 32 :如果ˇ地址偏移量+读取位数ˇ大于4字节
bs->bufPos = abPos - 32; // 32 :则更新偏移量为(地址偏移量+读取位数)%32
bs->bufA = bs->bufB; // 前四字节的buf更新为后4字节的buf
uint32_t data = *reinterpret_cast<uint32_t *>(bs->tail);
bs->bufB = ConvertEndian(data);
bs->tail += 4; // 4 :整体ˇ后移4字节
} else {
bs->bufPos += currentBitNum;
}
}
return currentBitNum;
}
static __inline int32_t GetBs(BsInfo *bs, int32_t currentBitNum)
{
uint32_t data = static_cast<uint32_t>(ShowBs(bs, currentBitNum));
SkipBs(bs, currentBitNum);
return static_cast<int32_t>(data);
}
static uint32_t HevcUv(BsInfo *bsPtr, int32_t bitNum)
{
uint32_t code = static_cast<uint32_t>(GetBs(bsPtr, bitNum));
return code;
}
void SetThreeSpline(BsInfo *bsPtr, HdrVividMetadataV1 &tmoCuvaMetadata, int index)
{
for (unsigned int mode_i = 0; mode_i < tmoCuvaMetadata.threeSplineNum[index]; mode_i++) {
tmoCuvaMetadata.threeSplineThMode[index][mode_i] = HevcUv(bsPtr, P3SPLINE_TH_MODE_BIT);
// 对应标准7.3
if ((tmoCuvaMetadata.threeSplineThMode[index][mode_i] == 0) ||
(tmoCuvaMetadata.threeSplineThMode[index][mode_i] == 2)) { // 2:
tmoCuvaMetadata.threeSplineThMb[index][mode_i] = HevcUv(bsPtr, P3SPLINE_TH_MB_BIT);
}
tmoCuvaMetadata.threeSplineTh[index][mode_i][0] = HevcUv(bsPtr, P3SPLINE_TH1_BIT);
tmoCuvaMetadata.threeSplineTh[index][mode_i][1] = HevcUv(bsPtr, P3SPLINE_TH2_BIT);
tmoCuvaMetadata.threeSplineTh[index][mode_i][2] = HevcUv(bsPtr, P3SPLINE_TH3_BIT); // 2:
tmoCuvaMetadata.threeSplineStrength[index][mode_i] = HevcUv(bsPtr, P3SPLINE_STRENGTH_BIT);
}
}
int SetToneMappingMode(BsInfo *bsPtr, HdrVividMetadataV1 &tmoCuvaMetadata)
{
if (!tmoCuvaMetadata.toneMappingMode) {
return 0;
}
tmoCuvaMetadata.toneMappingParamNum = HevcUv(bsPtr, TONE_MAPPING_PARAM_NUM_BIT);
// test
tmoCuvaMetadata.toneMappingParamNum++;
// For Memory Safety
// tone_mapping_param_num占用1bitˇ最大为1ˇ加1后最大为2
if (tmoCuvaMetadata.toneMappingParamNum > 2) {
VPE_LOGE("ToneMappingParamNum Out Of Range, value: %i", tmoCuvaMetadata.toneMappingParamNum);
return 1;
}
for (unsigned int j = 0; j < tmoCuvaMetadata.toneMappingParamNum; j++) {
tmoCuvaMetadata.targetedSystemDisplayMaximumLuminance[j] = HevcUv(bsPtr, TARGETED_SYSTEM_DISPLAY_BIT);
tmoCuvaMetadata.baseFlag[j] = HevcUv(bsPtr, BASE_FLAG_BIT);
if (tmoCuvaMetadata.baseFlag[j]) {
tmoCuvaMetadata.baseParamMp[j] = HevcUv(bsPtr, BASE_PARAM_MP_BIT);
tmoCuvaMetadata.baseParamMm[j] = HevcUv(bsPtr, BASE_PARAM_MM_BIT);
tmoCuvaMetadata.baseParamMa[j] = HevcUv(bsPtr, BASE_PARAM_MA_BIT);
tmoCuvaMetadata.baseParamMb[j] = HevcUv(bsPtr, BASE_PARAM_MB_BIT);
tmoCuvaMetadata.baseParamMn[j] = HevcUv(bsPtr, BASE_PARAM_MN_BIT);
tmoCuvaMetadata.baseParamK1[j] = HevcUv(bsPtr, BASE_PARAM_K1_BIT);
tmoCuvaMetadata.baseParamK2[j] = HevcUv(bsPtr, BASE_PARAM_K2_BIT);
tmoCuvaMetadata.baseParamK3[j] = HevcUv(bsPtr, BASE_PARAM_K3_BIT);
tmoCuvaMetadata.baseParamDeltaMode[j] = HevcUv(bsPtr, BASE_PARAM_DELTA_MODE_BIT);
tmoCuvaMetadata.baseParamDelta[j] = HevcUv(bsPtr, BASE_PARAM_DELTA_BIT);
}
tmoCuvaMetadata.threeSplineFlag[j] = HevcUv(bsPtr, P3SPLINE_FLAG_BIT);
if (tmoCuvaMetadata.threeSplineFlag[j]) {
tmoCuvaMetadata.threeSplineNum[j] = HevcUv(bsPtr, P3SPLINE_NUM_BIT);
tmoCuvaMetadata.threeSplineNum[j]++;
// For Memory Safety
// p3SplineNum占用1bitˇ最大为1ˇ加1后最大为2
if (tmoCuvaMetadata.threeSplineNum[j] > 2) {
VPE_LOGE("ThreeSplineNum Out Of Range, value: %i", tmoCuvaMetadata.threeSplineNum[j]);
return 1;
}
SetThreeSpline(bsPtr, tmoCuvaMetadata, j);
}
}
return 0;
}
int SetcolorSaturationMapping(BsInfo *bsPtr, HdrVividMetadataV1 &tmoCuvaMetadata)
{
if (tmoCuvaMetadata.colorSaturationMappingFlag) {
tmoCuvaMetadata.colorSaturationNum = HevcUv(bsPtr, COLOR_SATURATION_NUM_BIT);
// For Memory Safety
if (tmoCuvaMetadata.colorSaturationNum > 8) { // 8:
VPE_LOGE("ColorSaturationNum Out Of Range, value: %i", tmoCuvaMetadata.colorSaturationNum);
return 1;
}
for (unsigned int mode_i = 0; mode_i < tmoCuvaMetadata.colorSaturationNum; mode_i++) {
tmoCuvaMetadata.colorSaturationGain[mode_i] = HevcUv(bsPtr, COLOR_SATURATION_GAIN_BIT);
}
}
return 0;
}
void PraseDisplayMetadataFromArray(BsInfo *bsPtr, HwDisplayMeta &displayMeta)
{
// HwDisplayMeta displayMeta;
displayMeta.type = HevcUv(bsPtr, DISPLAY_3BIT);
VPE_LOGD("displayMeta type = %{public}d", displayMeta.type);
if (displayMeta.type > 0) {
displayMeta.size = HevcUv(bsPtr, DISPLAY_16BIT);
auto markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.startX = HevcUv(bsPtr, DISPLAY_16BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.startY = HevcUv(bsPtr, DISPLAY_16BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.endX = HevcUv(bsPtr, DISPLAY_16BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.endY = HevcUv(bsPtr, DISPLAY_16BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
for (int i = 0; i < 17; i++) { // 17
displayMeta.lutMap[i] = HevcUv(bsPtr, DISPLAY_8BIT);
if (i % 2 == 1) { // 2
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
}
}
displayMeta.averageLuma = HevcUv(bsPtr, DISPLAY_16BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.scene = HevcUv(bsPtr, DISPLAY_8BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.expo = HevcUv(bsPtr, DISPLAY_16BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.iso = HevcUv(bsPtr, DISPLAY_16BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.flash = HevcUv(bsPtr, DISPLAY_8BIT);
for (int i = 0; i < 32; i++) { // 32
displayMeta.hdrHistgram[i] = HevcUv(bsPtr, DISPLAY_8BIT);
if (i % 2 == 0) { // 2
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
}
}
displayMeta.noiseLevel = HevcUv(bsPtr, DISPLAY_8BIT);
markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.apetureValue = HevcUv(bsPtr, DISPLAY_8BIT);
displayMeta.aelv = HevcUv(bsPtr, DISPLAY_8BIT);
displayMeta.maxHeadroom = 5115; // 5115 = 5 * 1023;
VPE_LOGD("CLink displayMeta.markerbit = %{public}d\n", markerbit);
}
if (displayMeta.type > 1) {
auto markerbit = HevcUv(bsPtr, DISPLAY_MARKERBIT);
displayMeta.maxHeadroom = HevcUv(bsPtr, DISPLAY_16BIT);
VPE_LOGD("CLink displayMeta.markerbit = %{public}d\n", markerbit);
VPE_LOGD("CLink displayMeta.maxHeadroom = %{public}d\n", displayMeta.maxHeadroom);
}
return;
}
uint32_t PraseMatadataType(BsInfo *bsPtr)
{
HevcUv(bsPtr, MARKERBIT_BIT);
uint32_t type = HevcUv(bsPtr, CUVA_TYPE_BIT);
VPE_LOGD("HDR: extension metadata type = %{public}d", type);
return type;
}
int PraseMetadataFromArray(const std::vector<uint8_t> &cuvaInfo, HdrVividMetadataV1 &tmoCuvaMetadata,
HwDisplayMeta &displayMeta)
{
BsInfo bs {};
BsInfo *bsPtr = &bs;
int cuvaInfoSize = static_cast<int>(cuvaInfo.size());
if (cuvaInfoSize == AIHDR_METADATA_MAX_LENGTH) {
tmoCuvaMetadata.gtmLut = cuvaInfo;
}
VPE_LOGD("cuvaInfoSize = %{public}d\n", cuvaInfoSize);
std::vector<uint8_t> cuvaInfoCopy;
if (cuvaInfoSize > METADATA_MAX_LENGTH) { // 最大metadata长度512
cuvaInfoSize = METADATA_MAX_LENGTH;
}
cuvaInfoCopy.resize(METADATA_MAX_LENGTH); // 最大metadata长度512
errno_t res = memcpy_s(cuvaInfoCopy.data(), cuvaInfoCopy.size(), cuvaInfo.data(), cuvaInfo.size());
CHECK_AND_RETURN_RET_LOG(res == EOK, res, "memcpy_s failed");
InitBs(bsPtr, &cuvaInfoCopy[0], cuvaInfoSize);
tmoCuvaMetadata.systemStartCode = HevcUv(bsPtr, SYSTEM_START_CODE_BIT);
int numWindows = 0;
if (tmoCuvaMetadata.systemStartCode == 1) {
numWindows = 1;
}
for (int i = 0; i < numWindows; i++) {
tmoCuvaMetadata.minimumMaxRgbPq = HevcUv(bsPtr, MINIMUM_MAXRGB_BIT);
tmoCuvaMetadata.averageMaxRgbPq = HevcUv(bsPtr, AVERAGE_MAXRGB_BIT);
tmoCuvaMetadata.varianceMaxRgbPq = HevcUv(bsPtr, VARIANCE_MAXRGB_BIT);
tmoCuvaMetadata.maximumMaxRgbPq = HevcUv(bsPtr, MAXIMUM_MAXRGB_BIT);
tmoCuvaMetadata.toneMappingMode = HevcUv(bsPtr, TONE_MAPPING_MODE_BIT);
int ret = SetToneMappingMode(bsPtr, tmoCuvaMetadata);
if (ret != 0) { return ret; }
tmoCuvaMetadata.colorSaturationMappingFlag = HevcUv(bsPtr, COLOR_SATURATION_BIT);
ret = SetcolorSaturationMapping(bsPtr, tmoCuvaMetadata);
if (ret != 0) { return ret; }
}
// 8 :一个字节占8位ˇ当前读取位小于传入数组总位数才合理
while (bsPtr->totalPos + 8 < static_cast<uint32_t>(bsPtr->bsLen * 8)) { // 存在后续元数据内容
uint32_t metadataType = PraseMatadataType(bsPtr);
if ((metadataType & 0x3) == 1) {
// ToDo: Prase LocalToneMapping Metadata
VPE_LOGD("LTM Metadata Prase!");
} else if ((metadataType & 0x3) == 3) { // 3 拍显元数据标志位
VPE_LOGD("CLink Metadata Prase!");
PraseDisplayMetadataFromArray(bsPtr, displayMeta);
} else {
VPE_LOGD("Unknown Extension Metadata type!");
break;
}
}
return 0;
}
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -15,18 +15,25 @@
#include "vpe_utils_common.h"
#include <fstream>
#include <memory>
#include <string>
#include <unordered_map>
#include "securec.h"
#include "algorithm_errors.h"
#include "algorithm_utils.h"
#include "image_type.h"
#include "surface_buffer_impl.h"
#include "surface_type.h"
#include "vpe_log.h"
#include "vpe_model_path.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
const std::map<OHOS::Media::PixelFormat, GraphicPixelFormat> FORMAT_MAP = {
constexpr int VPE_MODEL_FILE_MAX_SIZE = 20485760;
const std::unordered_map<OHOS::Media::PixelFormat, GraphicPixelFormat> FORMAT_MAP = {
{ OHOS::Media::PixelFormat::RGBA_8888, GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888 },
{ OHOS::Media::PixelFormat::BGRA_8888, GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BGRA_8888 },
{ OHOS::Media::PixelFormat::NV21, GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCRCB_420_SP },
@@ -263,3 +270,35 @@ bool VpeUtils::SetSurfaceBufferToPixelMap(const sptr<SurfaceBuffer>& buffer,
}
return ConvertSurfaceBufferToPixelmap(buffer, pixelmap);
}
VPEAlgoErrCode VpeUtils::LoadModel(int modelKey, sptr<SurfaceBuffer>& modelBuffer)
{
CHECK_AND_RETURN_RET_LOG(modelKey >= 0 && modelKey < VPE_MODEL_KEY_NUM, VPE_ALGO_ERR_INVALID_VAL,
"Invalid input: modelKey is %{public}d(Expected:[0,%{public}d)!", modelKey, VPE_MODEL_KEY_NUM);
std::string path = VPE_MODEL_PATHS[modelKey];
std::unique_ptr<std::ifstream> fileStream = std::make_unique<std::ifstream>(path, std::ios::binary);
CHECK_AND_RETURN_RET_LOG(fileStream->is_open(), VPE_ALGO_ERR_NO_MEMORY, "Failed to open %{public}s!", path.c_str());
fileStream->seekg(0, std::ios::end);
int fileSize = fileStream->tellg();
fileStream->seekg(0, std::ios::beg);
CHECK_AND_RETURN_RET_LOG(fileSize > 0 && fileSize <= VPE_MODEL_FILE_MAX_SIZE, VPE_ALGO_ERR_INVALID_VAL,
"Invalid input: '%{public}s' size is %{public}d(Expected:(0,%{public}d]!", path.c_str(), fileSize,
VPE_MODEL_FILE_MAX_SIZE);
modelBuffer = SurfaceBuffer::Create();
CHECK_AND_RETURN_RET_LOG(modelBuffer != nullptr, VPE_ALGO_ERR_NO_MEMORY,
"Failed to create surface buffer for '%{public}s'!", path.c_str());
BufferRequestConfig requestCfg;
requestCfg.width = fileSize;
requestCfg.height = 1;
requestCfg.strideAlignment = fileSize;
requestCfg.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
requestCfg.format = GRAPHIC_PIXEL_FMT_YCBCR_420_SP;
requestCfg.timeout = 0;
CHECK_AND_RETURN_RET_LOG(modelBuffer->Alloc(requestCfg) == GSERROR_OK, VPE_ALGO_ERR_NO_MEMORY,
"Failed to alloc surface buffer size:%{public}d for '%{public}s'!", fileSize, path.c_str());
fileStream->read(reinterpret_cast<char*>(modelBuffer->GetVirAddr()), fileSize);
fileStream->close();
VPE_LOGD("Load model '%{public}s' size:%{public}d", path.c_str(), fileSize);
return VPE_ALGO_ERR_OK;
}
@@ -0,0 +1,166 @@
/*
* Copyright (C) 2024 Huawei Device 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 "contrast_enhancer_image_fwk.h"
#include <dlfcn.h>
#include "contrast_enhancer_common.h"
#include "extension_manager.h"
#include "native_buffer.h"
#include "surface_buffer.h"
#include "video_processing_client.h"
#include "vpe_log.h"
#include "vpe_trace.h"
#include "frame_info.h"
#include "v2_1/buffer_handle_meta_key_type.h"
namespace {
const int MAX_URL_LENGTH = 100;
const int SUPPORTED_MIN_WIDTH = 720; // consistent with napi
const int SUPPORTED_MIN_HEIGHT = 720; // consistent with napi
const int SUPPORTED_MAX_WIDTH = 20000; // consistent with napi
const int SUPPORTED_MAX_HEIGHT = 20000; // consistent with napi
const std::unordered_set<int32_t> SUPPORTED_FORMATS = {
OHOS::GRAPHIC_PIXEL_FMT_RGBA_1010102, // RGBA_1010102
OHOS::GRAPHIC_PIXEL_FMT_YCBCR_P010,
};
constexpr int MAX_FAILURE_NUM = 5;
}
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
ContrastEnhancerImageFwk::ContrastEnhancerImageFwk()
{
Extension::ExtensionManager::GetInstance().IncreaseInstance();
}
ContrastEnhancerImageFwk::~ContrastEnhancerImageFwk()
{
{
std::lock_guard<std::mutex> lock(lock_);
algorithms_.clear();
}
Extension::ExtensionManager::GetInstance().DecreaseInstance();
}
std::shared_ptr<ContrastEnhancerImage> ContrastEnhancerImage::Create()
{
std::shared_ptr<ContrastEnhancerImage> impl = std::make_shared<ContrastEnhancerImageFwk>();
CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to init ContrastEnhancerImage");
return impl;
}
std::shared_ptr<ContrastEnhancerBase> ContrastEnhancerImageFwk::GetAlgorithm(ContrastEnhancerType level)
{
if (!getAlgoLock_.try_lock()) {
VPE_LOGI("get algo lock failed");
return nullptr;
}
std::lock_guard<std::mutex> lock(lock_);
auto createdImpl = algorithms_.find(level);
if (createdImpl != algorithms_.end()) [[likely]] {
getAlgoLock_.unlock();
return createdImpl->second;
}
if (failureCount_.load() > MAX_FAILURE_NUM) {
VPE_LOGW("has failed many times");
getAlgoLock_.unlock();
return nullptr;
}
std::shared_ptr<ContrastEnhancerBase> algo = CreateAlgorithm(level);
if (algo.get() == nullptr) {
failureCount_++;
VPE_LOGE("create algo failed");
getAlgoLock_.unlock();
return nullptr;
}
algorithms_[level] = algo;
getAlgoLock_.unlock();
return algorithms_[level];
}
std::shared_ptr<ContrastEnhancerBase> ContrastEnhancerImageFwk::CreateAlgorithm(ContrastEnhancerType type)
{
auto& manager = Extension::ExtensionManager::GetInstance();
VPE_SYNC_TRACE;
std::shared_ptr<ContrastEnhancerBase> algoImpl = manager.CreateContrastEnhancer(type);
if (algoImpl == nullptr) {
VPE_LOGE("Extension create failed, get a empty impl, type: %{public}d", type);
return nullptr;
}
if (algoImpl->Init() != VPE_ALGO_ERR_OK) {
VPE_LOGE("Init failed, extension type: %{public}d", type);
return nullptr;
}
return algoImpl;
}
VPEAlgoErrCode ContrastEnhancerImageFwk::SetParameter(const ContrastEnhancerParameters& parameter)
{
CHECK_AND_RETURN_RET_LOG(parameter.uri.length() < MAX_URL_LENGTH, VPE_ALGO_ERR_INVALID_VAL, "Invalid parameter");
std::lock_guard<std::mutex> lock(lock_);
parameter_ = parameter;
VPE_LOGI("ContrastEnhancerImageFwk SetParameter Succeed");
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode ContrastEnhancerImageFwk::GetParameter(ContrastEnhancerParameters& parameter) const
{
std::lock_guard<std::mutex> lock(lock_);
parameter = parameter_;
VPE_LOGI("ContrastEnhancerImageFwk GetParameter Succeed");
return VPE_ALGO_ERR_OK;
}
bool ContrastEnhancerImageFwk::IsValidProcessedObject(const sptr<SurfaceBuffer>& buffer)
{
CHECK_AND_RETURN_RET_LOG(buffer != nullptr, false, "buffer is nullptr!!");
return SUPPORTED_FORMATS.find(buffer->GetFormat()) != SUPPORTED_FORMATS.end() &&
buffer->GetWidth() > SUPPORTED_MIN_WIDTH && buffer->GetHeight() > SUPPORTED_MIN_HEIGHT &&
buffer->GetWidth() <= SUPPORTED_MAX_WIDTH && buffer->GetHeight() <= SUPPORTED_MAX_HEIGHT;
}
VPEAlgoErrCode ContrastEnhancerImageFwk::GetRegionHist(const sptr<SurfaceBuffer>& input)
{
auto algoImpl = GetAlgorithm(parameter_.type);
CHECK_AND_RETURN_RET_LOG(algoImpl != nullptr, VPE_ALGO_ERR_UNKNOWN, "set parameter failed!");
return algoImpl->GetRegionHist(input);
}
VPEAlgoErrCode ContrastEnhancerImageFwk::UpdateMetadataBasedOnHist(OHOS::Rect rect, sptr<SurfaceBuffer> surfaceBuffer,
std::tuple<int, int, double, double, double, int> pixelmapInfo)
{
VPETrace vpeTrace("VpeFwk::ContrastProcess");
CHECK_AND_RETURN_RET_LOG(IsValidProcessedObject(surfaceBuffer), VPE_ALGO_ERR_UNKNOWN, "Invalid input");
auto algoImpl = GetAlgorithm(parameter_.type);
CHECK_AND_RETURN_RET_LOG(algoImpl != nullptr, VPE_ALGO_ERR_UNKNOWN, "set parameter failed!");
return algoImpl->UpdateMetadataBasedOnHist(rect, surfaceBuffer, pixelmapInfo);
}
VPEAlgoErrCode ContrastEnhancerImageFwk::UpdateMetadataBasedOnPixel(OHOS::Rect displayArea, OHOS::Rect curPixelmapArea,
OHOS::Rect completePixelmapArea, sptr<SurfaceBuffer> surfaceBuffer, float fullRatio)
{
CHECK_AND_RETURN_RET_LOG(IsValidProcessedObject(surfaceBuffer), VPE_ALGO_ERR_UNKNOWN, "Invalid input");
auto algoImpl = GetAlgorithm(parameter_.type);
CHECK_AND_RETURN_RET_LOG(algoImpl != nullptr, VPE_ALGO_ERR_UNKNOWN, "set parameter failed!");
return algoImpl->UpdateMetadataBasedOnPixel(displayArea, curPixelmapArea, completePixelmapArea,
surfaceBuffer, fullRatio);
}
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
@@ -25,7 +25,6 @@
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class ContrastEnhancerBase {
public:
ContrastEnhancerBase() = default;
@@ -37,12 +36,12 @@ public:
virtual VPEAlgoErrCode Init() = 0;
virtual VPEAlgoErrCode Deinit() = 0;
virtual VPEAlgoErrCode SetParameter(const ContrastEnhancerParameters& parameter, int type, bool flag) = 0;
virtual VPEAlgoErrCode SetParameter(const ContrastEnhancerParameters& parameter) = 0;
virtual VPEAlgoErrCode GetRegionHist(const sptr<SurfaceBuffer>& input) = 0;
virtual bool UpdateMetadataBasedOnLcd(OHOS::Rect rect, int lcdWidth, int lcdHeight,
sptr<SurfaceBuffer> surfaceBuffer) = 0;
virtual bool UpdateMetadataBasedOnDetail(OHOS::Rect displayArea, OHOS::Rect curPixelmapArea,
virtual VPEAlgoErrCode UpdateMetadataBasedOnHist(OHOS::Rect rect, sptr<SurfaceBuffer> surfaceBuffer,
std::tuple<int, int, double, double, double, int> pixelmapInfo) = 0;
virtual VPEAlgoErrCode UpdateMetadataBasedOnPixel(OHOS::Rect displayArea, OHOS::Rect curPixelmapArea,
OHOS::Rect completePixelmapArea, sptr<SurfaceBuffer> surfaceBuffer, float fullRatio) = 0;
};
@@ -20,13 +20,14 @@
#include <vector>
#include "algorithm_common.h"
#include "contrast_enhancer_base.h"
#include "extension_base.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
struct ContrastEnhancerCapability {
std::vector<uint32_t> levels;
std::vector<ContrastEnhancerType> types;
Extension::Rank rank;
int32_t version;
};
@@ -36,19 +36,20 @@ public:
VPEAlgoErrCode SetParameter(const ContrastEnhancerParameters& parameter) override;
VPEAlgoErrCode GetParameter(ContrastEnhancerParameters& parameter) const override;
VPEAlgoErrCode GetRegionHist(const sptr<SurfaceBuffer>& input) override;
VPEAlgoErrCode UpdateMetadataBasedOnLcd(OHOS::Rect displayArea, int lcdWidth, int lcdHeight,
sptr<SurfaceBuffer> surfaceBuffer) override;
VPEAlgoErrCode UpdateMetadataBasedOnDetail(OHOS::Rect displayArea, OHOS::Rect curPixelmapArea,
VPEAlgoErrCode UpdateMetadataBasedOnHist(OHOS::Rect displayArea, sptr<SurfaceBuffer> surfaceBuffer,
std::tuple<int, int, double, double, double, int> pixelmapInfo) override;
VPEAlgoErrCode UpdateMetadataBasedOnPixel(OHOS::Rect displayArea, OHOS::Rect curPixelmapArea,
OHOS::Rect completePixelmapArea, sptr<SurfaceBuffer> surfaceBuffer, float fullRatio) override;
private:
std::shared_ptr<ContrastEnhancerBase> GetAlgorithm(int feature);
std::shared_ptr<ContrastEnhancerBase> CreateAlgorithm(int feature);
std::shared_ptr<ContrastEnhancerBase> GetAlgorithm(ContrastEnhancerType feature);
std::shared_ptr<ContrastEnhancerBase> CreateAlgorithm(ContrastEnhancerType feature);
bool IsValidProcessedObject(const sptr<SurfaceBuffer>& buffer);
ContrastEnhancerParameters parameter_{};
mutable std::mutex lock_{};
std::mutex getAlgoLock_{};
std::unordered_map<int, std::shared_ptr<ContrastEnhancerBase>> algorithms_{};
std::unordered_map<ContrastEnhancerType, std::shared_ptr<ContrastEnhancerBase>> algorithms_{};
std::atomic<int> failureCount_{};
};
} // namespace VideoProcessingEngine
} // namespace Media
@@ -24,6 +24,7 @@
#include "video_processing_client.h"
#include "securec.h"
#include "vpe_log.h"
#include "vpe_sa_constants.h"
#include "vpe_trace.h"
namespace {
@@ -40,8 +41,8 @@ constexpr float EPSILON = 1e-6; // extremely small value
const int MAX_URL_LENGTH = 100;
const int SUPPORTED_MIN_WIDTH = 32;
const int SUPPORTED_MIN_HEIGHT = 32;
const int SUPPORTED_MAX_WIDTH = 8192;
const int SUPPORTED_MAX_HEIGHT = 8192;
const int SUPPORTED_MAX_WIDTH = 20000; // 20000 max support width
const int SUPPORTED_MAX_HEIGHT = 20000; // 20000 max support height
const int TIMEOUT_THRESHOLD = 10; // 10 millisecond
const std::unordered_set<int32_t> SUPPORTED_FORMATS = {
OHOS::GRAPHIC_PIXEL_FMT_BGRA_8888, // BGRA
@@ -82,7 +83,7 @@ DetailEnhancerImageFwk::DetailEnhancerImageFwk(int type)
DetailEnhancerImageFwk::~DetailEnhancerImageFwk()
{
algorithms_.clear();
Clear();
Extension::ExtensionManager::GetInstance().DecreaseInstance();
}
@@ -105,7 +106,15 @@ std::shared_ptr<DetailEnhancerBase> DetailEnhancerImageFwk::GetAlgorithm(int lev
if (createdImpl != algorithms_.end()) [[likely]] {
return createdImpl->second;
}
algorithms_[level] = CreateAlgorithm(level);
auto algo = CreateAlgorithm(level);
if (algo.get() == nullptr) {
return nullptr;
}
VPE_LOGD("level:%d enable:%d", level, enableProtection_);
auto ret = algo->EnableProtection(enableProtection_);
CHECK_AND_RETURN_RET_LOG(ret == VPE_ALGO_ERR_OK, nullptr,
"Failed to EnableProtection(%{public}d) for level:%{pubcli}d ret:%{pubcli}d", enableProtection_, level, ret);
algorithms_[level] = algo;
return algorithms_[level];
}
@@ -114,6 +123,7 @@ std::shared_ptr<DetailEnhancerBase> DetailEnhancerImageFwk::CreateAlgorithm(int
auto& manager = Extension::ExtensionManager::GetInstance();
VPE_SYNC_TRACE;
std::shared_ptr<DetailEnhancerBase> algoImpl = manager.CreateDetailEnhancer(level);
VPE_LOGE("level:%{public}d", level);
if (algoImpl == nullptr) {
VPE_LOGE("Extension create failed, get a empty impl, level: %{public}d", level);
return nullptr;
@@ -132,6 +142,7 @@ VPEAlgoErrCode DetailEnhancerImageFwk::SetParameter(const DetailEnhancerParamete
std::lock_guard<std::mutex> lock(lock_);
parameter_ = parameter;
parameterUpdated = true;
hasParameter_ = true;
VPE_LOGI("DetailEnhancerImageFwk SetParameter Succeed");
return VPE_ALGO_ERR_OK;
}
@@ -176,40 +187,51 @@ int DetailEnhancerImageFwk::EvaluateTargetLevel(const sptr<SurfaceBuffer>& input
}
VPEAlgoErrCode DetailEnhancerImageFwk::ProcessVideo(const sptr<SurfaceBuffer>& input,
const sptr<SurfaceBuffer>& output, bool flag)
const sptr<SurfaceBuffer>& output)
{
auto algoImpl = GetAlgorithm(DETAIL_ENH_LEVEL_VIDEO);
if (algoImpl == nullptr) {
VPE_LOGE("Get Algorithm impl for video failed!");
return VPE_ALGO_ERR_UNKNOWN;
}
if (parameterUpdated.load() && (algoImpl->SetParameter(parameter_, type_, flag) != VPE_ALGO_ERR_OK)) {
if (parameterUpdated.load() && (algoImpl->SetParameter(parameter_) != VPE_ALGO_ERR_OK)) {
VPE_LOGE("set parameter failed!");
return VPE_ALGO_ERR_UNKNOWN;
} else {
parameterUpdated = false;
}
if (algoImpl->Process(input, output) != VPE_ALGO_ERR_OK) {
UpdateLastAlgorithm(algoImpl);
if (ProcessAlgorithm(algoImpl, input, output) != VPE_ALGO_ERR_OK) {
VPE_LOGE("process video failed");
return VPE_ALGO_ERR_UNKNOWN;
}
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode DetailEnhancerImageFwk::Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output,
bool flag)
VPEAlgoErrCode DetailEnhancerImageFwk::Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output)
{
CHECK_AND_RETURN_RET_LOG(IsValidProcessedObject(input, output), VPE_ALGO_ERR_INVALID_VAL,
"Invalid processd object");
VPE_SYNC_TRACE;
if (parameter_.forceEve) {
auto algoImpl = GetAlgorithm(DETAIL_ENH_LEVEL_HIGH);
CHECK_AND_RETURN_RET_LOG(algoImpl != nullptr && algoImpl->SetParameter(parameter_, type_, flag) ==
VPE_ALGO_ERR_OK, VPE_ALGO_ERR_UNKNOWN, "set parameter failed!");
return algoImpl->Process(input, output);
auto err = DoProcess(input, output);
if (err != VPE_ALGO_ERR_OK) {
std::lock_guard<std::mutex> lock(restoreLock_);
if (!needRestore_) {
return err;
}
VPE_LOGD("Clear status to restore algorithms.");
Clear();
needRestore_ = false;
VPE_LOGD("Try to process again.");
err = DoProcess(input, output);
VPE_LOGD("process return %{public}d", err);
}
return err;
}
VPEAlgoErrCode DetailEnhancerImageFwk::DoProcess(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output)
{
CHECK_AND_RETURN_RET_LOG(IsValidProcessedObject(input, output), VPE_ALGO_ERR_INVALID_VAL, "Invalid input!");
VPE_SYNC_TRACE;
if (type_ == VIDEO) {
return ProcessVideo(input, output, flag);
return ProcessVideo(input, output);
}
float widthRatio = static_cast<float>(output->GetWidth()) / static_cast<float>(input->GetWidth());
float heightRatio = static_cast<float>(output->GetHeight()) / static_cast<float>(input->GetHeight());
@@ -229,11 +251,12 @@ VPEAlgoErrCode DetailEnhancerImageFwk::Process(const sptr<SurfaceBuffer>& input,
}
parameter_.level = static_cast<DetailEnhancerLevel>((level == DETAIL_ENH_LEVEL_HIGH_AISR) ?
DETAIL_ENH_LEVEL_HIGH : level); // map level
if (algoImpl->SetParameter(parameter_, type_, flag) != VPE_ALGO_ERR_OK) {
if (algoImpl->SetParameter(parameter_) != VPE_ALGO_ERR_OK) {
VPE_LOGE("set parameter failed!");
return VPE_ALGO_ERR_UNKNOWN;
}
if (algoImpl->Process(input, output) == VPE_ALGO_ERR_OK) {
UpdateLastAlgorithm(algoImpl);
if (ProcessAlgorithm(algoImpl, input, output) == VPE_ALGO_ERR_OK) {
processSuccessfully = true;
break;
} else if (level == DETAIL_ENH_LEVEL_HIGH_AISR) {
@@ -248,6 +271,63 @@ VPEAlgoErrCode DetailEnhancerImageFwk::Process(const sptr<SurfaceBuffer>& input,
return processSuccessfully ? VPE_ALGO_ERR_OK : VPE_ALGO_ERR_INVALID_VAL;
}
VPEAlgoErrCode DetailEnhancerImageFwk::EnableProtection(bool enable)
{
std::lock_guard<std::mutex> lock(lock_);
VPEAlgoErrCode ret = VPE_ALGO_ERR_OK;
for (auto& [level, algo] : algorithms_) {
if (algo == nullptr) {
VPE_LOGW("Algorithm for level:%{pubcli}d is null!", level);
continue;
}
VPE_LOGD("level:%d enable:%d", level, enable);
ret = algo->EnableProtection(enable);
if (ret != VPE_ALGO_ERR_OK) {
VPE_LOGW("Failed to EnableProtection(%{public}d) for level:%{pubcli}d ret:%{pubcli}d", enable, level, ret);
}
}
enableProtection_ = enable;
return ret;
}
VPEAlgoErrCode DetailEnhancerImageFwk::ResetProtectionStatus()
{
std::lock_guard<std::mutex> lock(lock_);
if (lastAlgorithm_ == nullptr) {
return VPE_ALGO_ERR_OK;
}
return lastAlgorithm_->ResetProtectionStatus();
}
void DetailEnhancerImageFwk::UpdateLastAlgorithm(const std::shared_ptr<DetailEnhancerBase>& algorithm)
{
std::lock_guard<std::mutex> lock(lock_);
lastAlgorithm_ = algorithm;
}
void DetailEnhancerImageFwk::Clear()
{
std::lock_guard<std::mutex> lock(lock_);
lastAlgorithm_ = nullptr;
algorithms_.clear();
if (hasParameter_) {
parameterUpdated = true;
}
}
VPEAlgoErrCode DetailEnhancerImageFwk::ProcessAlgorithm(const std::shared_ptr<DetailEnhancerBase>& algo,
const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output)
{
CHECK_AND_RETURN_RET_LOG(algo != nullptr, VPE_ALGO_ERR_INVALID_VAL, "Invalid input: algorithm is null!");
auto err = algo->Process(input, output);
if (static_cast<VPEAlgoErrExCode>(err) == VPE_ALGO_ERR_INVALID_CLIENT_ID) {
VPE_LOGD("needRestore_ = true");
std::lock_guard<std::mutex> lock(restoreLock_);
needRestore_ = true;
}
return err;
}
int32_t DetailEnhancerCreate(int32_t* instance)
{
CHECK_AND_RETURN_RET_LOG(g_externLock.try_lock_for(std::chrono::milliseconds(TIMEOUT_THRESHOLD)),
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (C) 2025 Huawei Device 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
@@ -38,7 +38,7 @@ public:
DETAIL_ENH_TYPE_IMAGE = 0,
DETAIL_ENH_TYPE_VIDEO,
};
DetailEnhancerBase() = default;
virtual ~DetailEnhancerBase() = default;
DetailEnhancerBase(const DetailEnhancerBase&) = delete;
@@ -48,8 +48,10 @@ public:
virtual VPEAlgoErrCode Init() = 0;
virtual VPEAlgoErrCode Deinit() = 0;
virtual VPEAlgoErrCode SetParameter(const DetailEnhancerParameters& parameter, int type, bool flag) = 0;
virtual VPEAlgoErrCode SetParameter(const DetailEnhancerParameters& parameter) = 0;
virtual VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output) = 0;
virtual VPEAlgoErrCode EnableProtection(bool enable) = 0;
virtual VPEAlgoErrCode ResetProtectionStatus() = 0;
};
using DetailEnhancerCreator = std::function<std::shared_ptr<DetailEnhancerBase>()>;
@@ -35,7 +35,9 @@ public:
VPEAlgoErrCode SetParameter(const DetailEnhancerParameters& parameter) override;
VPEAlgoErrCode GetParameter(DetailEnhancerParameters& parameter) const override;
VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output, bool flag) override;
VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output) override;
VPEAlgoErrCode EnableProtection(bool enable) final;
VPEAlgoErrCode ResetProtectionStatus() final;
private:
std::shared_ptr<DetailEnhancerBase> GetAlgorithm(int feature);
@@ -43,13 +45,23 @@ private:
bool IsValidProcessedObject(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output);
int EvaluateTargetLevel(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output,
float widthRatio, float heightRatio) const;
VPEAlgoErrCode ProcessVideo(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output, bool flag);
VPEAlgoErrCode DoProcess(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output);
VPEAlgoErrCode ProcessVideo(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output);
void UpdateLastAlgorithm(const std::shared_ptr<DetailEnhancerBase>& algorithm);
void Clear();
VPEAlgoErrCode ProcessAlgorithm(const std::shared_ptr<DetailEnhancerBase>& algo, const sptr<SurfaceBuffer>& input,
const sptr<SurfaceBuffer>& output);
DetailEnhancerParameters parameter_{};
mutable std::mutex lock_{};
std::unordered_map<int, std::shared_ptr<DetailEnhancerBase>> algorithms_{};
std::shared_ptr<DetailEnhancerBase> lastAlgorithm_{};
int type_;
std::atomic<bool> parameterUpdated{};
bool hasParameter_{};
bool enableProtection_{};
mutable std::mutex restoreLock_{};
bool needRestore_{}; // Guarded by restoreLock_
};
} // namespace VideoProcessingEngine
} // namespace Media
@@ -27,11 +27,18 @@ using namespace std::chrono_literals;
namespace {
constexpr int MAX_TARGET_WIDTH = 2000;
constexpr int MAX_TARGET_HEIGHT = 2000;
constexpr int MIN_SOURCE_WIDTH = 320;
constexpr int MIN_SOURCE_HEIGHT = 320;
} // namespace
std::shared_ptr<VpeVideoImpl> DetailEnhancerVideoFwk::Create()
{
auto obj = std::make_shared<DetailEnhancerVideoFwk>(VIDEO_TYPE_DETAIL_ENHANCER);
return CreateEx(true);
}
std::shared_ptr<VpeVideoImpl> DetailEnhancerVideoFwk::CreateEx(bool disable)
{
auto obj = std::make_shared<DetailEnhancerVideoFwk>(VIDEO_TYPE_DETAIL_ENHANCER, disable);
CHECK_AND_RETURN_RET_LOG(obj != nullptr, nullptr, "Failed to create detail enhancer!");
CHECK_AND_RETURN_RET_LOG(obj->Initialize() == VPE_ALGO_ERR_OK, nullptr, "Failed to initialize detail enhancer!");
return obj;
@@ -69,7 +76,7 @@ VPEAlgoErrCode DetailEnhancerVideoFwk::OnInitialize()
{
detailEnh_ = DetailEnhancerImage::Create(VIDEO);
CHECK_AND_RETURN_RET_LOG(detailEnh_ != nullptr, VPE_ALGO_ERR_UNKNOWN, "Failed to create DetailEnhancer!");
return VPE_ALGO_ERR_OK;
return detailEnh_->EnableProtection(isAutoDisable_);
}
VPEAlgoErrCode DetailEnhancerVideoFwk::OnDeinitialize()
@@ -107,12 +114,31 @@ VPEAlgoErrCode DetailEnhancerVideoFwk::Process(const sptr<SurfaceBuffer>& source
return ret;
}
VPEAlgoErrCode DetailEnhancerVideoFwk::ResetAfterDisable()
{
CHECK_AND_RETURN_RET_LOG(IsInitialized(), VPE_ALGO_ERR_INVALID_OPERATION, "NOT initialized!");
return detailEnh_->ResetProtectionStatus();
}
bool DetailEnhancerVideoFwk::IsDisableAfterProcessFail()
{
return isAutoDisable_;
}
bool DetailEnhancerVideoFwk::IsProducerSurfaceValid([[maybe_unused]] const sptr<Surface>& surface)
{
// Check resolution for detail enhancer is valid or not
return true;
}
bool DetailEnhancerVideoFwk::IsConsumerBufferValid(const sptr<SurfaceBuffer>& buffer)
{
CHECK_AND_RETURN_RET_LOG(buffer != nullptr, false, "buffer is null!");
CHECK_AND_RETURN_RET_LOG(buffer->GetWidth() > MIN_SOURCE_WIDTH && buffer->GetHeight() > MIN_SOURCE_HEIGHT, false,
"Invalid input: %{public}dx%{public}d!", buffer->GetWidth(), buffer->GetHeight());
return true;
}
VPEAlgoErrCode DetailEnhancerVideoFwk::UpdateRequestCfg(const sptr<Surface>& surface, BufferRequestConfig& requestCfg)
{
CHECK_AND_RETURN_RET_LOG(surface != nullptr, VPE_ALGO_ERR_INVALID_VAL, "surface is null!");
@@ -144,8 +170,10 @@ void DetailEnhancerVideoFwk::UpdateRequestCfg(const sptr<SurfaceBuffer>& consume
requestCfg.width = size_.width;
requestCfg.height = size_.height;
} else {
requestCfg.width = consumerBuffer->GetWidth();
requestCfg.height = consumerBuffer->GetHeight();
if (requestCfg.width == 0 || requestCfg.height == 0) {
requestCfg.width = consumerBuffer->GetWidth();
requestCfg.height = consumerBuffer->GetHeight();
}
}
requestCfg.format = consumerBuffer->GetFormat();
}
@@ -90,7 +90,7 @@ int32_t DetailEnhancerVideoImpl::Init()
{
std::lock_guard<std::mutex> lock(lock_);
CHECK_AND_RETURN_RET_LOG(!isInitialized_.load(), VPE_ALGO_ERR_INVALID_STATE, "Already initialized!");
detailEnhancerVideo_ = DetailEnhancerVideoFwk::Create();
detailEnhancerVideo_ = DetailEnhancerVideoFwk::CreateEx(false);
CHECK_AND_RETURN_RET_LOG(detailEnhancerVideo_ != nullptr, VPE_ALGO_ERR_UNKNOWN,
"Failed to create video detail enhancer!");
isInitialized_ = true;
@@ -28,8 +28,9 @@ namespace VideoProcessingEngine {
class DetailEnhancerVideoFwk : public VpeVideoImpl {
public:
static std::shared_ptr<VpeVideoImpl> Create();
static std::shared_ptr<VpeVideoImpl> CreateEx(bool disable);
explicit DetailEnhancerVideoFwk(uint32_t type) : VpeVideoImpl(type) {}
explicit DetailEnhancerVideoFwk(uint32_t type, bool disable) : VpeVideoImpl(type), isAutoDisable_(disable) {}
~DetailEnhancerVideoFwk() = default;
DetailEnhancerVideoFwk(const DetailEnhancerVideoFwk&) = delete;
DetailEnhancerVideoFwk& operator=(const DetailEnhancerVideoFwk&) = delete;
@@ -43,7 +44,10 @@ protected:
VPEAlgoErrCode OnInitialize() final;
VPEAlgoErrCode OnDeinitialize() final;
VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& sourceImage, sptr<SurfaceBuffer>& destinationImage) final;
VPEAlgoErrCode ResetAfterDisable() final;
bool IsDisableAfterProcessFail() final;
bool IsProducerSurfaceValid(const sptr<Surface>& surface) final;
bool IsConsumerBufferValid(const sptr<SurfaceBuffer>& buffer) final;
VPEAlgoErrCode UpdateRequestCfg(const sptr<Surface>& surface, BufferRequestConfig& requestCfg) final;
void UpdateRequestCfg(const sptr<SurfaceBuffer>& consumerBuffer, BufferRequestConfig& requestCfg) final;
@@ -68,6 +72,7 @@ private:
// Guarded by lock_ end
std::shared_ptr<DetailEnhancerImage> detailEnh_{};
bool isAutoDisable_{};
};
} // namespace VideoProcessingEngine
} // namespace Media
@@ -49,6 +49,9 @@ ExtensionManager::ExtensionManager()
{
(void)Init();
g_algoHandle = dlopen("libvideoprocessingengine_ext.z.so", RTLD_NOW);
if (g_algoHandle == nullptr) {
VPE_LOGE("dlopen libvideoprocessingengine_ext failed %{public}s", dlerror());
}
}
ExtensionManager::~ExtensionManager()
@@ -213,6 +216,19 @@ std::shared_ptr<DetailEnhancerBase> ExtensionManager::CreateDetailEnhancer(uint3
return impl;
}
std::shared_ptr<ContrastEnhancerBase> ExtensionManager::CreateContrastEnhancer(ContrastEnhancerType type) const
{
CHECK_AND_RETURN_RET_LOG(initialized_ == true, nullptr, "Not initialized");
auto extension = FindContrastEnhancerExtension(type);
CHECK_AND_RETURN_RET_LOG(extension != nullptr, nullptr,
"Create failed, get an empty extension. type: %{public}d", type);
auto impl = extension->creator();
CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr,
"Call extension creator failed, return a empty impl, extension: %{public}s, type: %{public}d",
extension->info.name.c_str(), type);
return impl;
}
ExtensionList ExtensionManager::LoadExtensions() const
{
ExtensionList extensionList {};
@@ -487,7 +503,13 @@ T ExtensionManager::BuildCaps(const ExtensionList& extensionList) const
CHECK_AND_LOG(err == VPE_ALGO_ERR_OK, "Build caps failed, extension: %{public}s",
extension->info.name.c_str());
}
} else if constexpr (std::is_same_v<T, AihdrEnhancerCapabilityMap>) {
} else if constexpr (std::is_same_v<T, ContrastEnhancerCapabilityMap>) {
if (extension->info.type == ExtensionType::CONTRAST_ENHANCER) {
err = BuildContrastEnhancerCaps(extension, idx, capMap);
CHECK_AND_LOG(err == VPE_ALGO_ERR_OK, "Build caps failed, extension: %{public}s",
extension->info.name.c_str());
}
} else if constexpr (std::is_same_v<T, AihdrEnhancerCapabilityMap>) {
if (extension->info.type == ExtensionType::AIHDR_ENHANCER) {
err = BuildAihdrEnhancerCaps(extension, idx, capMap);
CHECK_AND_LOG(err == VPE_ALGO_ERR_OK, "Build caps failed, extension: %{public}s",
@@ -498,7 +520,6 @@ T ExtensionManager::BuildCaps(const ExtensionList& extensionList) const
return {};
}
}
return capMap;
}
@@ -526,7 +547,7 @@ std::shared_ptr<ColorSpaceConverterExtension> ExtensionManager::FindColorSpaceCo
(CSDesc).range, outputInfo.pixelFormat, outputInfo.colorSpace.metadataType);
return nullptr;
}
size_t idx = std::get<2>(*(iter->second.cbegin())); // 2
size_t idx = std::get<2>(*(iter->second.cbegin()));
for (const auto &cap : iter->second) {
if (std::get<0>(cap) == Rank::RANK_HIGH) {
idx = std::get<2>(cap); // 2
@@ -563,7 +584,7 @@ std::shared_ptr<MetadataGeneratorExtension> ExtensionManager::FindMetadataGenera
const auto iter = metadataGeneratorCapabilityMap.find(key);
CHECK_AND_RETURN_RET_LOG(iter != metadataGeneratorCapabilityMap.cend() && !iter->second.empty(), nullptr,
"CSC metadata generator extension is not found");
size_t idx = std::get<2>(*(iter->second.cbegin())); // 2
size_t idx = std::get<2>(*(iter->second.cbegin()));
for (const auto &cap : iter->second) {
if (std::get<0>(cap) == Rank::RANK_HIGH) {
idx = std::get<2>(cap); // 2
@@ -608,7 +629,7 @@ std::shared_ptr<AihdrEnhancerExtension> ExtensionManager::FindAihdrEnhancerExten
const auto iter = aihdrEnhancerCapabilityMap.find(key);
CHECK_AND_RETURN_RET_LOG(iter != aihdrEnhancerCapabilityMap.cend() && !iter->second.empty(), nullptr,
"Aihdr enhancer extension is not found");
size_t idx = std::get<2>(*(iter->second.cbegin())); // 2
size_t idx = std::get<2>(*(iter->second.cbegin()));
for (const auto &cap : iter->second) {
if (std::get<0>(cap) == Rank::RANK_HIGH) {
idx = std::get<2>(cap); // 2
@@ -618,6 +639,20 @@ std::shared_ptr<AihdrEnhancerExtension> ExtensionManager::FindAihdrEnhancerExten
return std::static_pointer_cast<AihdrEnhancerExtension>(extensionList[idx]);
}
std::shared_ptr<ContrastEnhancerExtension> ExtensionManager::FindContrastEnhancerExtension(
ContrastEnhancerType type) const
{
auto extensionList = LoadExtensions();
CHECK_AND_RETURN_RET_LOG(!extensionList.empty(), nullptr, "No extension found");
auto contrastEnhancerCapabilityMap = BuildCaps<ContrastEnhancerCapabilityMap>(extensionList);
CHECK_AND_RETURN_RET_LOG(!contrastEnhancerCapabilityMap.empty(), nullptr, "No extension available");
const auto iter = contrastEnhancerCapabilityMap.find(type);
CHECK_AND_RETURN_RET_LOG(iter != contrastEnhancerCapabilityMap.cend(), nullptr,
"Contrast enhancer Extension is not found");
size_t idx = iter->second;
return std::static_pointer_cast<ContrastEnhancerExtension>(extensionList[idx]);
}
VPEAlgoErrCode ExtensionManager::ExtractColorSpaceConverterCap(const ColorSpaceConverterCapability& cap, size_t idx,
ColorSpaceConverterCapabilityMap& colorSpaceConverterCapabilityMap) const
{
@@ -720,6 +755,16 @@ VPEAlgoErrCode ExtensionManager::BuildAihdrEnhancerCaps(const std::shared_ptr<Ex
}
return err;
}
VPEAlgoErrCode ExtensionManager::BuildContrastEnhancerCaps(const std::shared_ptr<ExtensionBase>& ext, size_t idx,
ContrastEnhancerCapabilityMap& contrastEnhancerCapabilityMap) const
{
auto realExtension = std::static_pointer_cast<ContrastEnhancerExtension>(ext);
auto capabilities = realExtension->capabilitiesBuilder();
for (const auto &level : capabilities.types) {
contrastEnhancerCapabilityMap.emplace(level, idx);
}
return VPE_ALGO_ERR_OK;
}
} // namespace Extension
} // namespace VideoProcessingEngine
} // namespace Media
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2024 Huawei Device 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 FRAMEWORK_ALGORITHM_EXTENSION_MANAGER_CONTRAST_ENHANCER_EXTENSION_H
#define FRAMEWORK_ALGORITHM_EXTENSION_MANAGER_CONTRAST_ENHANCER_EXTENSION_H
#include <vector>
#include "contrast_enhancer_base.h"
#include "contrast_enhancer_capability.h"
#include "extension_base.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
namespace Extension {
struct ContrastEnhancerExtension : public ExtensionBase {
ContrastEnhancerCreator creator;
ContrastEnhancerCapabilitiesBuilder capabilitiesBuilder;
};
} // namespace Extension
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // FRAMEWORK_ALGORITHM_EXTENSION_MANAGER_CONTRAST_ENHANCER_EXTENSION_H
@@ -28,7 +28,8 @@ enum class ExtensionType {
METADATA_GENERATOR,
DETAIL_ENHANCER,
VIDEO_REFRESHRATE_PREDICTION,
AIHDR_ENHANCER
AIHDR_ENHANCER,
CONTRAST_ENHANCER,
};
enum class Rank : uint32_t {
@@ -43,6 +43,7 @@
#include "colorspace_converter_display_extension.h"
#include "metadata_generator_extension.h"
#include "detail_enhancer_extension.h"
#include "contrast_enhancer_extension.h"
#include "video_refreshrate_prediction_extension.h"
#include "utils.h"
@@ -82,6 +83,7 @@ using AihdrEnhancerCapabilityMap =
std::map<
std::tuple<ColorSpaceDescription, GraphicPixelFormat>,
std::vector<std::tuple<Rank, int32_t, size_t>>>;
using ContrastEnhancerCapabilityMap = std::map<ContrastEnhancerType, size_t>;
using ColorSpaceConverterDisplaySet = std::set<std::shared_ptr<ColorSpaceConverterDisplayBase>>;
using ColorSpaceConverterDisplayExtensionSet = std::set<std::shared_ptr<ColorSpaceConverterDisplayExtension>>;
@@ -101,6 +103,7 @@ public:
Extension::ExtensionInfo &extensionInfo) const;
std::shared_ptr<DetailEnhancerBase> CreateDetailEnhancer(uint32_t level) const;
std::shared_ptr<VideoRefreshRatePredictionBase> CreateVideoRefreshRatePredictor() const;
std::shared_ptr<ContrastEnhancerBase> CreateContrastEnhancer(ContrastEnhancerType type) const;
using InstanceVariableType = std::variant<std::shared_ptr<ColorSpaceConverter>,
std::shared_ptr<MetadataGenerator>,
@@ -129,6 +132,7 @@ private:
MetadataGeneratorAlgoType algoType) const;
std::shared_ptr<AihdrEnhancerExtension> FindAihdrEnhancerExtension(const FrameInfo &inputInfo) const;
std::shared_ptr<DetailEnhancerExtension> FindDetailEnhancerExtension(uint32_t level) const;
std::shared_ptr<ContrastEnhancerExtension> FindContrastEnhancerExtension(ContrastEnhancerType type) const;
ExtensionList LoadExtensions() const;
VPEAlgoErrCode LoadStaticExtensions(ExtensionList& extensionList) const;
ExtensionList LoadStaticImageExtensions(
@@ -148,6 +152,8 @@ private:
AihdrEnhancerCapabilityMap& aihdrEnhancerCapabilityMap) const;
VPEAlgoErrCode BuildDetailEnhancerCaps(const std::shared_ptr<ExtensionBase>& ext, size_t idx,
DetailEnhancerCapabilityMap& detailEnhancerCapabilityMap) const;
VPEAlgoErrCode BuildContrastEnhancerCaps(const std::shared_ptr<ExtensionBase>& ext, size_t idx,
ContrastEnhancerCapabilityMap& contrastEnhancerCapabilityMap) const;
VPEAlgoErrCode ExtractColorSpaceConverterCap(const ColorSpaceConverterCapability& cap, size_t idx,
ColorSpaceConverterCapabilityMap& colorSpaceConverterCapabilityMap) const;
VPEAlgoErrCode ExtractMetadataGeneratorCap(const MetadataGeneratorCapability &cap, size_t idx,
@@ -19,7 +19,7 @@
namespace OHOS::Media::VideoProcessingEngine::Extension {
using RegisterExtensionFunc = void (*)(uintptr_t extensionListAddr);
const std::unordered_map<std::string, RegisterExtensionFunc> staticExtensionsRegisterMap = {
{ "Skia", RegisterSkiaExtensions },
{"Skia", RegisterSkiaExtensions},
};
} // namespace OHOS::Media::VideoProcessingEngine::Extension
@@ -39,8 +39,10 @@ public:
static DetailEnhancerCapability BuildCapabilities();
VPEAlgoErrCode Init() override;
VPEAlgoErrCode Deinit() override;
VPEAlgoErrCode SetParameter(const DetailEnhancerParameters& parameter, int type, bool flag) override;
VPEAlgoErrCode SetParameter(const DetailEnhancerParameters& parameter) override;
VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output) override;
VPEAlgoErrCode EnableProtection(bool enable) override;
VPEAlgoErrCode ResetProtectionStatus() override;
};
void RegisterSkiaExtensions(uintptr_t extensionListAddr);
@@ -188,6 +188,7 @@ int CreateYUVPixmap(const sptr<SurfaceBuffer>& buffer, std::array<SkPixmap, SkYU
for (int i = 0; i < SkYUVAInfo::kMaxPlanes; i++) {
rowbyte[i] = static_cast<size_t>(buffer->GetStride());
}
return 0;
}
rowbyte[CHANNEL_Y] = planesInfo->planes[CHANNEL_Y].columnStride;
@@ -256,8 +257,17 @@ VPEAlgoErrCode Skia::Deinit()
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode Skia::SetParameter([[maybe_unused]] const DetailEnhancerParameters& parameter,
[[maybe_unused]] int type, [[maybe_unused]] bool flag)
VPEAlgoErrCode Skia::SetParameter([[maybe_unused]] const DetailEnhancerParameters& parameter)
{
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode Skia::EnableProtection([[maybe_unused]] bool enable)
{
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode Skia::ResetProtectionStatus()
{
return VPE_ALGO_ERR_OK;
}
@@ -283,7 +293,7 @@ static std::vector<std::shared_ptr<Extension::ExtensionBase>> RegisterExtensions
auto extension = std::make_shared<Extension::DetailEnhancerExtension>();
CHECK_AND_RETURN_RET_LOG(extension != nullptr, extensions, "null pointer");
extension->info = { Extension::ExtensionType::DETAIL_ENHANCER, "SKIA", "0.0.1" };
extension->info = { Extension::ExtensionType::DETAIL_ENHANCER, "AISR", "0.0.1" };
extension->creator = Skia::Create;
extension->capabilitiesBuilder = Skia::BuildCapabilities;
extensions.push_back(std::static_pointer_cast<Extension::ExtensionBase>(extension));
@@ -291,10 +301,12 @@ static std::vector<std::shared_ptr<Extension::ExtensionBase>> RegisterExtensions
return extensions;
}
void RegisterSkiaExtensions(uintptr_t extensionListAddr)
{
Extension::DoRegisterExtensions(extensionListAddr, RegisterExtensions);
}
} // VideoProcessingEngine
} // Media
} // OHOS
@@ -222,7 +222,7 @@ sptr<Surface> MetadataGeneratorVideoImpl::CreateInputSurface()
sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
CHECK_AND_RETURN_RET_LOG(producerSurface != nullptr, nullptr, "CreateSurfaceAsProducer fail");
producerSurface->SetDefaultUsage(BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_HW_RENDER |
BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE);
BUFFER_USAGE_MEM_DMA);
inputSurface_->SetQueueSize(inBufferCnt_);
state_ = VPEAlgoState::CONFIGURING;
@@ -259,7 +259,10 @@ int32_t MetadataGeneratorVideoImpl::Prepare()
void MetadataGeneratorVideoImpl::InitBuffers()
{
std::lock_guard<std::mutex> lock(mutex_);
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return;
}
CHECK_AND_RETURN_LOG(outputSurface_ != nullptr, "outputSurface_ is nullptr");
flushCfg_.damage.x = 0;
flushCfg_.damage.y = 0;
@@ -327,8 +330,8 @@ int32_t MetadataGeneratorVideoImpl::Reset()
int32_t MetadataGeneratorVideoImpl::Release()
{
std::lock_guard<std::mutex> lock(mutex_);
{
std::lock_guard<std::mutex> lock(mutex_);
std::unique_lock<std::mutex> lockTask(mtxTaskDone_);
state_ = VPEAlgoState::UNINITIALIZED;
cvTaskDone_.wait(lockTask, [this]() { return isProcessing_.load() == false; });
@@ -393,6 +396,7 @@ void MetadataGeneratorVideoImpl::Process(std::shared_ptr<SurfaceBufferWrapper> i
outputBuffer->timestamp = inputBuffer->timestamp;
sptr<SurfaceBuffer> surfaceInputBuffer = inputBuffer->memory;
sptr<SurfaceBuffer> surfaceOutputBuffer = outputBuffer->memory;
surfaceInputBuffer->InvalidateCache();
bool copyRet = AlgorithmUtils::CopySurfaceBufferToSurfaceBuffer(surfaceInputBuffer, surfaceOutputBuffer);
if (!copyRet) {
requestCfg_.width = surfaceInputBuffer->GetWidth();
@@ -433,6 +437,7 @@ bool MetadataGeneratorVideoImpl::WaitProcessing()
{
std::unique_lock<std::mutex> lock(mtxTaskStart_);
cvTaskStart_.wait(lock, [this]() {
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> inQueueLock(onBqMutex_);
std::lock_guard<std::mutex> outQueueLock(renderQueMutex_);
if (initBuffer_.load()) {
@@ -597,6 +602,10 @@ GSError MetadataGeneratorVideoImpl::OnProducerBufferReleased()
GSError MetadataGeneratorVideoImpl::OnConsumerBufferAvailable()
{
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> lockInQue(onBqMutex_);
CHECK_AND_RETURN_RET_LOG(inputSurface_ != nullptr, GSERROR_OK, "inputSurface is nullptr");
@@ -608,6 +617,10 @@ GSError MetadataGeneratorVideoImpl::OnConsumerBufferAvailable()
VPE_LOGW("AcquireBuffer failed, GSError=%{public}d", err);
return err;
}
constexpr uint32_t waitForEver = -1; // wait fence -1
if (buffer->fence != nullptr) {
(void)buffer->fence->Wait(waitForEver);
}
inputBufferAvilQue_.push(buffer);
if (!getUsage_) {
@@ -27,7 +27,6 @@
#include "log_tags.h"
#include "media_errors.h"
#include "memory_manager.h"
#include "native_avformat.h"
#include "pixelmap_native_impl.h"
#include "pixelmap_native.h"
#include "vpe_utils.h"
@@ -106,7 +105,6 @@ napi_value DetailEnhanceNapi::Init(napi_env env, napi_callback_info info)
DetailEnhancerParameters param {
.uri = "",
.level = static_cast<DetailEnhancerLevel>(DETAIL_ENH_LEVEL_HIGH),
.forceEve = 1,
};
if (mDetailEnh->SetParameter(param)!= VPE_ALGO_ERR_OK) {
printf("Init failed!");
@@ -22,7 +22,6 @@
#include <algorithm>
#include "image_processing_types.h"
#include "image_napi_utils.h"
#include "media_errors.h"
#include "memory_manager.h"
@@ -43,16 +42,25 @@ constexpr uint32_t NUM_3 = 3;
constexpr uint32_t NUM_4 = 4;
constexpr uint32_t NUM_5 = 5;
constexpr uint32_t NUM_6 = 6;
constexpr uint32_t NUM_7 = 7;
constexpr uint32_t NUM_8 = 8;
constexpr uint32_t NUM_9 = 9;
constexpr int32_t NEW_INSTANCE_ARGC = 1;
constexpr int32_t MIN_WIDTH_CONTRAST = 720; // min support width 720, consistent with fwk
constexpr int32_t MIN_HEIGHT_CONTRAST = 720; // min support height 720, consistent with fwk
constexpr int32_t MAX_RESOLUTION_CONTRAST = 20000; // max support resolution 20000, consistent with fwk
constexpr int32_t MIN_RESOLUTION_DETAIL = 32; // min support resolution 32, consistent with fwk
constexpr int32_t MAX_RESOLUTION_DETAIL = 8192; // max support resolution 8192, consistent with fwk
constexpr float ROUNDING_OPERATOR = 0.5;
const std::string CLASS_NAME = "ImageProcessor";
static std::mutex g_imageProcessorMutex{std::mutex()};
static std::mutex g_detailLock{std::mutex()};
static std::mutex g_contrastLock{std::mutex()};
}
namespace OHOS {
namespace Media {
using namespace VideoProcessingEngine;
using namespace std::chrono;
thread_local napi_ref VpeNapi::constructor_ = nullptr;
thread_local napi_ref VpeNapi::qualityLevelTypeRef_ = nullptr;
thread_local std::shared_ptr<VpeNapi::DetailEnhanceContext> VpeNapi::detailContext_ = nullptr;
@@ -102,6 +110,7 @@ ImageType VpeNapi::ParserImageType(napi_env env, napi_value argv)
ret = napi_get_named_property(env, global, "PixelMap", &constructor);
if (ret != napi_ok) {
VPE_LOGI("Get VpeNapi property failed!");
return ImageType::TYPE_UNKNOWN;
}
bool isInstance = false;
ret = napi_instanceof(env, argv, constructor, &isInstance);
@@ -142,7 +151,6 @@ bool VpeNapi::ConfigResolution(napi_env env, napi_value& width, napi_value& heig
bool VpeNapi::ParseDetailEnhanceParameter(napi_env env, napi_callback_info info)
{
VPETrace vpeTrace("VpeNapi::DetailEnhanceParseParameter");
std::lock_guard<std::mutex> lock(g_detailLock);
CHECK_AND_RETURN_RET_LOG(detailContext_ != nullptr, false, "detailContext_ == nullptr");
NapiValues nVal;
nVal.argc = NUM_4; // Use the maximum value to initialize argc before executing PrepareNapiEnv
@@ -182,8 +190,8 @@ bool VpeNapi::ParseDetailEnhanceParameter(napi_env env, napi_callback_info info)
if (nVal.argc == NUM_4) { // 4 parameter: pixelmap x y level
CHECK_AND_RETURN_RET_LOG(ConfigResolution(env, nVal.argv[NUM_1], nVal.argv[NUM_2], detailContext_),
false, "ConfigResolution failed");
CHECK_AND_RETURN_RET_LOG(napi_ok == napi_get_value_int32(env, nVal.argv[NUM_3],
&(detailContext_->qualityLevel)), false, "Arg 3 type mismatch");
CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, nVal.argv[NUM_3],
&(detailContext_->qualityLevel)) == napi_ok, false, "Arg 3 type mismatch");
}
return true;
}
@@ -198,7 +206,6 @@ napi_value VpeNapi::InitializeEnvironment(napi_env env, napi_callback_info info)
napi_value VpeNapi::DeinitializeEnvironment(napi_env env, napi_callback_info info)
{
VPETrace vpeTrace("VpeNapi::DetailEnhanceDeinitializeEnvironment");
std::lock_guard<std::mutex> lock(g_detailLock);
napi_value result;
napi_get_boolean(env, true, &result);
return result;
@@ -216,10 +223,22 @@ void VpeNapi::SetDstPixelMapInfo(PixelMap& source, void* dstPixels, uint32_t dst
VPE_LOGW("Invalid memory");
return;
}
if (memory->extend.data == nullptr) {
VPE_LOGE("memory->extend.data == nullptr");
return;
}
dstPixelMap.SetPixelsAddr(dstPixels, memory->extend.data, memory->data.size, sourceType, nullptr);
if (source.GetAllocatorType() == AllocatorType::DMA_ALLOC && source.IsHdr()) {
sptr<SurfaceBuffer> sourceSurfaceBuffer(reinterpret_cast<SurfaceBuffer*> (source.GetFd()));
sptr<SurfaceBuffer> dstSurfaceBuffer(reinterpret_cast<SurfaceBuffer*> (dstPixelMap.GetFd()));
if (sourceSurfaceBuffer == nullptr) {
VPE_LOGE("sourceSurfaceBuffer == nullptr");
return;
}
if (dstSurfaceBuffer == nullptr) {
VPE_LOGE("dstSurfaceBuffer == nullptr");
return;
}
VpeUtils::CopySurfaceBufferInfo(sourceSurfaceBuffer, dstSurfaceBuffer);
}
OHOS::ColorManager::ColorSpace colorspace = source.InnerGetGrColorSpace();
@@ -277,6 +296,7 @@ std::unique_ptr<PixelMap> VpeNapi::CreateDstPixelMap(PixelMap& source, const Ini
return nullptr;
}
if (!AllocMemory(source, *dstPixelMap.get(), opts)) {
VPE_LOGE("alloc memory failed");
return nullptr;
}
return dstPixelMap;
@@ -329,25 +349,27 @@ napi_value VpeNapi::Create(napi_env env, napi_callback_info info)
ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_CREATE_FAILED, "create instance failed");
return nullptr;
}
VPE_LOGE("create done");
VPE_LOGI("create done");
return result;
}
std::shared_ptr<PixelMap> VpeNapi::PrepareDstPixelMap(napi_env env, DetailEnhanceContext* context)
{
CHECK_AND_RETURN_RET_LOG(context->inputPixelMap->GetWidth() != 0 && context->inputPixelMap->GetHeight() != 0,
CHECK_AND_RETURN_RET_LOG(context->inputPixelMap->GetWidth() >= MIN_RESOLUTION_DETAIL &&
context->inputPixelMap->GetHeight() >= MIN_RESOLUTION_DETAIL &&
context->inputPixelMap->GetWidth() <= MAX_RESOLUTION_DETAIL &&
context->inputPixelMap->GetHeight() <= MAX_RESOLUTION_DETAIL,
nullptr, "invalid resolution");
float ratio = std::min(static_cast<float>(context->xArg) / static_cast<float>(context->inputPixelMap->GetWidth()),
static_cast<float>(context->yArg) / static_cast<float>(context->inputPixelMap->GetHeight()));
InitializationOptions opts {
.size = {
.width = ratio < 1.0 ? static_cast<int>(context->xArg) :
static_cast<int>(context->inputPixelMap->GetWidth()),
.height = ratio < 1.0 ? static_cast<int>(context->yArg) :
static_cast<int>(context->inputPixelMap->GetHeight()),
.width = static_cast<int>(context->xArg),
.height = static_cast<int>(context->yArg),
},
};
std::unique_ptr<PixelMap> outputPtr = CreateDstPixelMap(*context->inputPixelMap, opts);
VPE_LOGD("res:w %{public}d, h %{public}d, -> w %{public}d, h %{public}d",
context->inputPixelMap->GetWidth(), context->inputPixelMap->GetHeight(),
static_cast<int>(context->xArg), static_cast<int>(context->yArg));
std::unique_ptr<PixelMap> outputPtr = context->inputPixelMap->Create(*context->inputPixelMap, opts);
if (outputPtr == nullptr) {
ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_INVALID_VALUE, "create failed");
return nullptr;
@@ -356,12 +378,20 @@ std::shared_ptr<PixelMap> VpeNapi::PrepareDstPixelMap(napi_env env, DetailEnhanc
return dstPixelMap;
}
bool VpeNapi::InitDetailAlgo(napi_env env, int level)
bool VpeNapi::InitDetailAlgo(napi_env env)
{
VPETrace vpeTrace("VpeNapi::DetailEnhanceInitAlgo");
CHECK_AND_RETURN_RET_LOG(g_detailEnh == nullptr, true, "DetailEnhancerImage handle has created");
if (g_detailEnh != nullptr) {
VPE_LOGW("DetailEnhancerImage handle has created");
return true;
}
g_detailEnh = DetailEnhancerImage::Create();
CHECK_AND_RETURN_RET_LOG(g_detailEnh != nullptr, false, "create DetailEnhancerImage failed");
return true;
}
bool VpeNapi::SetDetailAlgoParam(napi_env env, int level)
{
DetailEnhancerParameters param {
.uri = "",
.level = static_cast<DetailEnhancerLevel>(level),
@@ -380,11 +410,20 @@ std::shared_ptr<PixelMap> VpeNapi::DetailEnhanceImpl(napi_env env, DetailEnhance
VPE_LOGE("context == nullptr");
return nullptr;
}
if (!InitDetailAlgo(env, context->qualityLevel)) {
if (context->inputPixelMap->GetPixelFormat() == PixelFormat::YCBCR_P010 ||
context->inputPixelMap->GetPixelFormat() == PixelFormat::YCRCB_P010) {
VPE_LOGI("not support P010");
return context->inputPixelMap;
}
if (!InitDetailAlgo(env)) {
VPE_LOGE("init algo failed");
ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_CREATE_FAILED, "init algo failed");
return nullptr;
}
if (!SetDetailAlgoParam(env, context->qualityLevel)) {
VPE_LOGE("set detail param failed");
return nullptr;
}
if (context->inputPixelMap == nullptr) {
VPE_LOGE("*context->inputPixelMap == nullptr");
return nullptr;
@@ -398,10 +437,48 @@ std::shared_ptr<PixelMap> VpeNapi::DetailEnhanceImpl(napi_env env, DetailEnhance
auto input = GetSurfaceBufferFromDMAPixelMap(context->inputPixelMap);
CHECK_AND_RETURN_RET_LOG((g_detailEnh != nullptr && g_detailEnh->Process(input, output) == VPE_ALGO_ERR_OK),
nullptr, "process failed");
VPE_LOGI("process done");
return dstPixelMap;
}
void VpeNapi::EnhanceDetailWork(napi_env env, void* data)
{
DetailEnhanceContext* innerAsyncContext = reinterpret_cast<DetailEnhanceContext*>(data);
if (innerAsyncContext == nullptr) {
std::string errCodeStr = std::to_string(IMAGE_PROCESSING_ERROR_PROCESS_FAILED);
std::string errMsg = "innerAsyncContext is nullptr";
napi_throw_error(env, errCodeStr.c_str(), errMsg.c_str());
return;
}
innerAsyncContext->outputPixelMap = DetailEnhanceImpl(env, innerAsyncContext);
};
void VpeNapi::EnhanceDetailCallBackWork(napi_env env, napi_status status, void* data)
{
DetailEnhanceContext* innerAsyncContext = reinterpret_cast<DetailEnhanceContext*>(data);
if (innerAsyncContext == nullptr) {
std::string errCodeStr = std::to_string(IMAGE_PROCESSING_ERROR_PROCESS_FAILED);
std::string errMsg = "innerAsyncContext is nullptr";
napi_throw_error(env, errCodeStr.c_str(), errMsg.c_str());
return;
}
napi_value outputPixelMapNapi = (innerAsyncContext->outputPixelMap == nullptr) ?
nullptr : PixelMapNapi::CreatePixelMap(env, innerAsyncContext->outputPixelMap);
if (outputPixelMapNapi == nullptr) {
return;
}
if (innerAsyncContext->deferred) {
napi_resolve_deferred(env, innerAsyncContext->deferred, outputPixelMapNapi);
} else {
napi_value callback = nullptr;
napi_get_reference_value(env, innerAsyncContext->callbackRef, &callback);
napi_call_function(env, nullptr, callback, 1, &(outputPixelMapNapi), nullptr);
napi_delete_reference(env, innerAsyncContext->callbackRef);
innerAsyncContext->callbackRef = nullptr;
}
napi_delete_async_work(env, innerAsyncContext->asyncWork);
delete innerAsyncContext;
};
napi_value VpeNapi::EnhanceDetail(napi_env env, napi_callback_info info)
{
VPETrace vpeTrace("VpeNapi::DetailEnhanceProcess");
@@ -412,44 +489,19 @@ napi_value VpeNapi::EnhanceDetail(napi_env env, napi_callback_info info)
napi_deferred deferred;
napi_value promise;
NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
CHECK_AND_RETURN_RET_LOG(ParseDetailEnhanceParameter(env, info), nullptr, "parse parameter failed");
if (!ParseDetailEnhanceParameter(env, info)) {
VPE_LOGE("parse parameter failed");
return nullptr;
}
detailContext_->deferred = deferred;
napi_value resourceName;
napi_create_string_latin1(env, "Asynchronous processing", NAPI_AUTO_LENGTH, &resourceName);
napi_status status = napi_create_async_work(env, nullptr, resourceName,
[](napi_env env, void* data) {
DetailEnhanceContext* innerAsyncContext = reinterpret_cast<DetailEnhanceContext*>(data);
if (innerAsyncContext == nullptr) {
ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_PROCESS_FAILED, "innerAsyncContext is nullptr");
return;
}
innerAsyncContext->outputPixelMap = DetailEnhanceImpl(env, innerAsyncContext);
},
[](napi_env env, napi_status status, void* data) {
DetailEnhanceContext* innerAsyncContext = reinterpret_cast<DetailEnhanceContext*>(data);
if (innerAsyncContext == nullptr) {
ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_PROCESS_FAILED, "innerAsyncContext is nullptr");
return;
}
napi_value outputPixelMapNapi = (innerAsyncContext->outputPixelMap == nullptr) ?
nullptr : PixelMapNapi::CreatePixelMap(env, innerAsyncContext->outputPixelMap);
if (outputPixelMapNapi == nullptr) {
VPE_LOGI("outputPixelMap is nullptr");
return;
}
if (innerAsyncContext->deferred) {
napi_resolve_deferred(env, innerAsyncContext->deferred, outputPixelMapNapi);
} else {
napi_value callback = nullptr;
napi_get_reference_value(env, innerAsyncContext->callbackRef, &callback);
napi_call_function(env, nullptr, callback, 1, &(outputPixelMapNapi), nullptr);
napi_delete_reference(env, innerAsyncContext->callbackRef);
innerAsyncContext->callbackRef = nullptr;
}
napi_delete_async_work(env, innerAsyncContext->asyncWork);
delete innerAsyncContext;
}, reinterpret_cast<void*>(detailContext_.get()), &detailContext_->asyncWork);
CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "create aysnc failed");
napi_status status = napi_create_async_work(env, nullptr, resourceName, EnhanceDetailWork,
EnhanceDetailCallBackWork, reinterpret_cast<void*>(detailContext_.get()), &detailContext_->asyncWork);
if (status != napi_ok) {
VPE_LOGE("create aysnc failed");
return nullptr;
}
napi_queue_async_work(env, detailContext_->asyncWork);
return promise;
}
@@ -471,15 +523,42 @@ napi_value VpeNapi::EnhanceDetailSync(napi_env env, napi_callback_info info)
return outputPixelMapNapi;
}
bool VpeNapi::UpdateMetadataBasedOnLcd(ContrastEnhanceContext* context)
OHOS::Rect VpeNapi::PrepareRect(std::shared_ptr<PixelMap> input, OHOS::Rect& displayArea, float ratio)
{
sptr<SurfaceBuffer> surfaceBuffer = GetSurfaceBufferFromDMAPixelMap(context->inputPixelMap);
return g_contrastEnh->UpdateMetadataBasedOnLcd(context->displayArea, context->lcdWidth, context->lcdHeight,
surfaceBuffer);
OHOS::Rect rect;
rect.x = static_cast<int>(displayArea.x * ratio + ROUNDING_OPERATOR);
rect.y = static_cast<int>(displayArea.y * ratio + ROUNDING_OPERATOR);
rect.w = std::min(input->GetWidth() - 1 - rect.x,
static_cast<int>(displayArea.w * ratio + ROUNDING_OPERATOR));
rect.h = std::min(input->GetHeight() - 1 - rect.y,
static_cast<int>(displayArea.h * ratio + ROUNDING_OPERATOR));
return rect;
}
bool VpeNapi::UpdateMetadataBasedOnDetail(ContrastEnhanceContext* context)
bool VpeNapi::UpdateMetadataBasedOnHist(ContrastEnhanceContext* context)
{
CHECK_AND_RETURN_RET_LOG(context->inputPixelMap != nullptr && context->oriWidth >= MIN_WIDTH_CONTRAST &&
context->oriHeight >= MIN_HEIGHT_CONTRAST && context->oriHeight < MAX_RESOLUTION_CONTRAST &&
context->oriWidth < MAX_RESOLUTION_CONTRAST, false, "unsupport resolution");
CHECK_AND_RETURN_RET_LOG(context->inputPixelMap->IsHdr(), false, "It's not hdr pixelmap");
sptr<SurfaceBuffer> surfaceBuffer = GetSurfaceBufferFromDMAPixelMap(context->inputPixelMap);
OHOS::Rect rect = PrepareRect(context->inputPixelMap, context->displayArea, context->fullRatio);
VPE_LOGI("area x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d",
context->displayArea.x, context->displayArea.y, context->displayArea.w, context->displayArea.h);
VPE_LOGI("cur pixelmap:w:%{public}d, h:%{public}d, ori pixelmap:w:%{public}d, h:%{public}d",
context->inputPixelMap->GetWidth(), context->inputPixelMap->GetHeight(), context->oriWidth, context->oriHeight);
std::tuple<int, int, double, double, double, int> pixelmapInfo =
std::make_tuple(context->inputPixelMap->GetUniqueId(), context->contentId,
context->curRatio, context->maxRatio, context->defaultRatio, context->animationDuration);
return g_contrastEnh->UpdateMetadataBasedOnHist(rect, surfaceBuffer, pixelmapInfo);
}
bool VpeNapi::UpdateMetadataBasedOnPixel(ContrastEnhanceContext* context)
{
CHECK_AND_RETURN_RET_LOG(context->inputPixelMap != nullptr &&
context->inputPixelMap->GetWidth() >= MIN_WIDTH_CONTRAST &&
context->inputPixelMap->GetHeight() >= MIN_HEIGHT_CONTRAST && context->oriHeight < MAX_RESOLUTION_CONTRAST &&
context->oriWidth < MAX_RESOLUTION_CONTRAST, false, "unsupport resolution");
OHOS::Rect completePixelmapArea = {
.x = 0,
.y = 0,
@@ -487,13 +566,15 @@ bool VpeNapi::UpdateMetadataBasedOnDetail(ContrastEnhanceContext* context)
.h = context->oriHeight,
};
sptr<SurfaceBuffer> surfaceBuffer = GetSurfaceBufferFromDMAPixelMap(context->inputPixelMap);
return g_contrastEnh->UpdateMetadataBasedOnDetail(context->displayArea, context->curPixelmapArea,
VPE_LOGI("area x:%{public}d, y:%{public}d, w:%{public}d, h:%{public}d",
context->displayArea.x, context->displayArea.y, context->displayArea.w, context->displayArea.h);
return g_contrastEnh->UpdateMetadataBasedOnPixel(context->displayArea, context->curPixelmapArea,
completePixelmapArea, surfaceBuffer, context->fullRatio);
}
napi_value VpeNapi::SetDetailImage(napi_env env, napi_callback_info info)
{
VPETrace vpeTrace("VpeNapi::DetailEnhanceProcess");
VPETrace vpeTrace("VpeNapi::ContrastProcess");
if (contrastContext_ == nullptr) {
contrastContext_ = std::make_shared<ContrastEnhanceContext>();
VPE_LOGI("create new contrast context");
@@ -501,11 +582,10 @@ napi_value VpeNapi::SetDetailImage(napi_env env, napi_callback_info info)
CHECK_AND_RETURN_RET_LOG(contrastContext_ != nullptr, nullptr, "context == nullptr");
NapiValues nVal;
CHECK_AND_RETURN_RET_LOG(ParseDetailImageParameter(env, info, nVal), nullptr, "parse parameter failed");
CHECK_AND_RETURN_RET_LOG(InitContrastAlgo(env), nullptr, "init contrast algo failed");
// 不管是不是区域解码,都先使用直方图的结果进行展示,之后再转变成bitmap的结果
UpdateMetadataBasedOnLcd(contrastContext_.get());
CallCallback(env, contrastContext_.get());
// 如果在计算完成前坐标位置已经发生了变化,则不需要继续进行计算
CHECK_AND_RETURN_RET_LOG(!contrastContext_->genFinalEffect, nullptr, "It's still moving. Stop processing");
if (contrastContext_->callbackRef == nullptr) {
napi_create_promise(env, &(contrastContext_->deferred), &(nVal.result));
}
@@ -519,7 +599,7 @@ napi_value VpeNapi::SetDetailImage(napi_env env, napi_callback_info info)
ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_PROCESS_FAILED, "innerAsyncContext == nullptr");
return;
}
UpdateMetadataBasedOnDetail(innerAsyncContext);
UpdateMetadataBasedOnHist(innerAsyncContext);
},
[](napi_env env, napi_status status, void* data) {
ContrastEnhanceContext* innerAsyncContext = reinterpret_cast<ContrastEnhanceContext*>(data);
@@ -527,7 +607,7 @@ napi_value VpeNapi::SetDetailImage(napi_env env, napi_callback_info info)
if (status != napi_ok) {
VPE_LOGE("process failed");
}
VPE_LOGI("process detail image done");
VPE_LOGD("process detail image done");
},
(void*)(contrastContext_.get()), &contrastContext_->asyncWork);
CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "create aysnc failed");
@@ -538,6 +618,7 @@ napi_value VpeNapi::SetDetailImage(napi_env env, napi_callback_info info)
bool VpeNapi::GenerateRegionHist(napi_env env, ContrastEnhanceContext* context)
{
CHECK_AND_RETURN_RET_LOG(InitContrastAlgo(env), false, "init contrast algo failed");
CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context == nullptr");
CHECK_AND_RETURN_RET_LOG(context->lcdPixelMap != nullptr, false, "lcdPixelMap == nullptr");
auto input = GetSurfaceBufferFromDMAPixelMap(context->lcdPixelMap);
@@ -553,11 +634,15 @@ bool VpeNapi::GenerateRegionHist(napi_env env, ContrastEnhanceContext* context)
bool VpeNapi::InitContrastAlgo(napi_env env)
{
VPETrace vpeTrace("VpeNapi::DetailEnhanceInitAlgo");
CHECK_AND_RETURN_RET_LOG(g_contrastEnh == nullptr, true, "ContrastEnhancerImage handle has created");
if (g_contrastEnh != nullptr) {
VPE_LOGD("ContrastEnhancerImage handle has created");
return true;
}
g_contrastEnh = ContrastEnhancerImage::Create();
CHECK_AND_RETURN_RET_LOG(g_contrastEnh != nullptr, false, "create ContrastEnhancerImage failed");
ContrastEnhancerParameters param {
.uri = "",
.type = ADAPTIVE_FOV,
};
if (g_contrastEnh->SetParameter(param)!= VPE_ALGO_ERR_OK) {
ThrowExceptionError(env, IMAGE_PROCESSING_ERROR_CREATE_FAILED, "set parameter failed");
@@ -592,13 +677,13 @@ bool VpeNapi::ParseDetailImageParameter(napi_env env, napi_callback_info info, N
{
VPETrace vpeTrace("VpeNapi::DetailEnhance");
std::lock_guard<std::mutex> lock(g_contrastLock);
nVal.argc = NUM_6;
napi_value argValue[NUM_6] = {0};
nVal.argc = NUM_9;
napi_value argValue[NUM_9] = {0};
nVal.argv = argValue;
if (!PrepareNapiEnv(env, info, &nVal)) {
return false;
}
if (nVal.argc != NUM_6) {
if (nVal.argc != NUM_9) {
VPE_LOGE("Invalid args count %{public}zu", nVal.argc);
return false;
} else {
@@ -616,12 +701,23 @@ bool VpeNapi::ParseDetailImageParameter(napi_env env, napi_callback_info info, N
CHECK_AND_RETURN_RET_LOG(ParseSize(env, argValue[NUM_4]), false, "parse resolution of original image failed");
CHECK_AND_RETURN_RET_LOG(napi_get_value_bool(env, nVal.argv[NUM_5],
&(contrastContext_->genFinalEffect)) == napi_ok, false, "Arg 5 type mismatch");
CHECK_AND_RETURN_RET_LOG(napi_get_value_double(env, nVal.argv[NUM_6],
&(contrastContext_->maxRatio)) == napi_ok, false, "Arg 6 type mismatch");
CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, nVal.argv[NUM_7],
&(contrastContext_->animationDuration)) == napi_ok, false, "Arg 7 type mismatch");
CHECK_AND_RETURN_RET_LOG(napi_get_value_double(env, nVal.argv[NUM_8],
&(contrastContext_->curRatio)) == napi_ok, false, "Arg 8 type mismatch");
}
contrastContext_->fullRatio = std::min(
static_cast<float>(contrastContext_->inputPixelMap->GetWidth()) /
static_cast<float>(contrastContext_->curPixelmapArea.w),
static_cast<float>(contrastContext_->inputPixelMap->GetHeight()) /
static_cast<float>(contrastContext_->curPixelmapArea.h));
VPE_LOGI("res: %{public}d x %{public}d, curArea: %{public}d x %{public}d, ratio:%{puiblic}f, maxRatio:%{public}f",
contrastContext_->inputPixelMap->GetWidth(), contrastContext_->inputPixelMap->GetHeight(),
contrastContext_->curPixelmapArea.w, contrastContext_->curPixelmapArea.h,
contrastContext_->curRatio, contrastContext_->maxRatio);
return true;
}
@@ -642,12 +738,15 @@ bool VpeNapi::ParseLCDParameter(napi_env env, napi_callback_info info, NapiValue
CHECK_AND_RETURN_RET_LOG(ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP,
false, "Arg 0 type is not pixelmap");
contrastContext_->lcdPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_0]);
CHECK_AND_RETURN_RET_LOG(contrastContext_->lcdPixelMap != nullptr, false, "pixelmap is nullptr");
CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, nVal.argv[NUM_1],
&(contrastContext_->contentId)) == napi_ok, false, "Failed to parse lcd param. Arg 1 type mismatch");
CHECK_AND_RETURN_RET_LOG(napi_get_value_double(env, nVal.argv[NUM_2],
&(contrastContext_->defaultRatio)) == napi_ok, false, "Failed to parse lcd param. Arg 2 type mismatch");
contrastContext_->lcdWidth = contrastContext_->lcdPixelMap->GetWidth();
contrastContext_->lcdHeight = contrastContext_->lcdPixelMap->GetHeight();
CHECK_AND_RETURN_RET_LOG(contrastContext_->lcdPixelMap->GetWidth() > 0 &&
contrastContext_->lcdPixelMap->GetHeight() > 0, false, "invalid resolution");
contrastContext_->lcdWidth = static_cast<unsigned int>(contrastContext_->lcdPixelMap->GetWidth());
contrastContext_->lcdHeight = static_cast<unsigned int>(contrastContext_->lcdPixelMap->GetHeight());
}
VPE_LOGI("update content info: lcdWidth:%{public}d, lcdHeight:%{public}d",
contrastContext_->lcdWidth, contrastContext_->lcdHeight);
@@ -834,9 +933,10 @@ napi_value VpeNapi::Init(napi_env env, napi_value exports)
CHECK_AND_RETURN_RET_LOG(napi_create_reference(env, constructor, 1, &constructor_) == napi_ok,
nullptr, "create reference fail");
static napi_property_descriptor desc[] = {
DECLARE_NAPI_PROPERTY("QualityLevel",
CreateEnumTypeObject(env, napi_number, &qualityLevelTypeRef_, g_qualityLevels)),
napi_value qualityLevel = CreateEnumTypeObject(env, napi_number, &qualityLevelTypeRef_, g_qualityLevels);
CHECK_AND_RETURN_RET_LOG(qualityLevel != nullptr, nullptr, "CreateEnumTypeObject failed");
napi_property_descriptor desc[] = {
DECLARE_NAPI_PROPERTY("QualityLevel", qualityLevel),
DECLARE_NAPI_FUNCTION("create", VpeNapi::Create),
DECLARE_NAPI_FUNCTION("initializeEnvironment", VpeNapi::InitializeEnvironment),
DECLARE_NAPI_FUNCTION("deinitializeEnvironment", VpeNapi::DeinitializeEnvironment),
@@ -113,7 +113,7 @@ ImageProcessing_ErrorCode DetailEnhancerImageNative::Process(const std::shared_p
auto ret = CheckParameter();
CHECK_AND_RETURN_RET_LOG(ret == IMAGE_PROCESSING_SUCCESS, ret, "check parameter failed!");
ret = ImageProcessingUtils::InnerErrorToCAPI(
detailEnhancer_->Process(sourceImageSurfaceBuffer, destinationImageSurfaceBuffer, true));
detailEnhancer_->Process(sourceImageSurfaceBuffer, destinationImageSurfaceBuffer));
CHECK_AND_RETURN_RET_LOG(ret == IMAGE_PROCESSING_SUCCESS, ret, "process failed!");
ret = ImageProcessingUtils::SetSurfaceBufferToPixelMap(destinationImageSurfaceBuffer, destinationImage);
CHECK_AND_RETURN_RET_LOG(ret == IMAGE_PROCESSING_SUCCESS, ret, "convert to pixelmap failed!");
+65 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -17,6 +17,10 @@
#define FRAMEWORK_DFX_LOG_H
#include <cinttypes>
#include <sstream>
#include <type_traits>
#include <vector>
#include "hilog/log.h"
namespace OHOS {
@@ -39,6 +43,66 @@ extern const bool VERBOSE_LOG;
#define VPE_LOGW(fmt, ...) HILOG_WARN(LOG_CORE, LOG_FMT fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define VPE_LOGI(fmt, ...) HILOG_INFO(LOG_CORE, LOG_FMT fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define VPE_LOGD(fmt, ...) HILOG_DEBUG(LOG_CORE, LOG_FMT fmt, __FILE_NAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
struct LogInfo {
const char* function;
uint32_t line;
};
using LogInfoEx = std::vector<LogInfo>;
inline LogInfoEx GetLogInfoEx(const LogInfo& info)
{
return std::vector<LogInfo>(1, info);
}
inline LogInfoEx AddLogInfoEx(const LogInfoEx& infos, const LogInfo& info)
{
std::vector<LogInfo> newInfos(infos);
newInfos.push_back(info);
return newInfos;
}
inline std::string GetLogStack(const LogInfoEx& infos, const LogInfo& info)
{
std::stringstream stream;
for (auto& item : infos) {
stream << "[" << item.function << " " << item.line << "]";
}
stream << "[" << info.function << " " << info.line << "]";
return stream.str();
}
#define VPE_LOG_INFO LogInfo{ __FUNCTION__, __LINE__ }
#define VPE_LOG_INFO_EX GetLogInfoEx(VPE_LOG_INFO)
#define ADD_VPE_LOG_INFO(vec) AddLogInfoEx(vec, VPE_LOG_INFO)
#define VPE_ORG_LOG(type, info, fmt, ...) \
do { \
static_assert(std::is_same<decltype(info), const LogInfo&>::value, "Type mismatch!"); \
HiLogPrint(LOG_CORE, type, LOG_DOMAIN, LOG_TAG, LOG_FMT fmt, __FILE_NAME__, info.function, info.line, \
##__VA_ARGS__); \
} while (0)
#define VPE_EX_LOG(type, infos, info, fmt, ...) \
do { \
static_assert(std::is_same<decltype(infos), const LogInfoEx&>::value, "Type mismatch!"); \
HiLogPrint(LOG_CORE, type, LOG_DOMAIN, LOG_TAG, "[%{public}s]%{public}s" fmt, __FILE_NAME__, \
GetLogStack(infos, info).c_str(), ##__VA_ARGS__); \
} while (0)
#define VPE_ORG_LOGF(info, fmt, ...) VPE_ORG_LOG(LOG_FATAL, info, fmt, ##__VA_ARGS__)
#define VPE_ORG_LOGE(info, fmt, ...) VPE_ORG_LOG(LOG_ERROR, info, fmt, ##__VA_ARGS__)
#define VPE_ORG_LOGW(info, fmt, ...) VPE_ORG_LOG(LOG_WARN, info, fmt, ##__VA_ARGS__)
#define VPE_ORG_LOGI(info, fmt, ...) VPE_ORG_LOG(LOG_INFO, info, fmt, ##__VA_ARGS__)
#define VPE_ORG_LOGD(info, fmt, ...) VPE_ORG_LOG(LOG_DEBUG, info, fmt, ##__VA_ARGS__)
#define VPE_EX_LOGF(infos, fmt, ...) VPE_EX_LOG(LOG_FATAL, infos, VPE_LOG_INFO, fmt, ##__VA_ARGS__)
#define VPE_EX_LOGE(infos, fmt, ...) VPE_EX_LOG(LOG_ERROR, infos, VPE_LOG_INFO, fmt, ##__VA_ARGS__)
#define VPE_EX_LOGW(infos, fmt, ...) VPE_EX_LOG(LOG_WARN, infos, VPE_LOG_INFO, fmt, ##__VA_ARGS__)
#define VPE_EX_LOGI(infos, fmt, ...) VPE_EX_LOG(LOG_INFO, infos, VPE_LOG_INFO, fmt, ##__VA_ARGS__)
#define VPE_EX_LOGD(infos, fmt, ...) VPE_EX_LOG(LOG_DEBUG, infos, VPE_LOG_INFO, fmt, ##__VA_ARGS__)
#define VPE_LOGD_LIMIT(frequency, fmt, ...) \
do { \
thread_local uint64_t currentTimes = 0; \
@@ -21,12 +21,14 @@
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
enum ContrastEnhancerLevel {
CONTRAST_ENHANCER = 0,
enum ContrastEnhancerType {
ADAPTIVE_FOV,
INVALID_CONTRAST_ENHANCER_TYPE,
};
struct ContrastEnhancerParameters {
std::string uri{};
ContrastEnhancerType type{INVALID_CONTRAST_ENHANCER_TYPE};
};
} // namespace VideoProcessingEngine
} // namespace Media
@@ -85,7 +85,7 @@ public:
* @return 返回错误码VPEAlgoErrCode
* @since 16
*/
virtual VPEAlgoErrCode UpdateMetadataBasedOnDetail(OHOS::Rect displayArea, OHOS::Rect curPixelmapArea,
virtual VPEAlgoErrCode UpdateMetadataBasedOnPixel(OHOS::Rect displayArea, OHOS::Rect curPixelmapArea,
OHOS::Rect completePixelmapArea, sptr<SurfaceBuffer> surfaceBuffer, float fullRatio) = 0;
/**
@@ -98,8 +98,8 @@ public:
* @return 返回错误码VPEAlgoErrCode
* @since 16
*/
virtual VPEAlgoErrCode UpdateMetadataBasedOnLcd(OHOS::Rect displayArea, int lcdWidth, int lcdHeight,
sptr<SurfaceBuffer> surfaceBuffer) = 0;
virtual VPEAlgoErrCode UpdateMetadataBasedOnHist(OHOS::Rect displayArea, sptr<SurfaceBuffer> surfaceBuffer,
std::tuple<int, int, double, double, double, int> pixelmapInfo) = 0;
protected:
ContrastEnhancerImage() = default;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -28,17 +28,20 @@ enum DetailEnhancerLevel {
// High gear is the highest gear. If you need to add a higher gear, you should
// pay attention to the level configuration of the high gear in impl.
DETAIL_ENH_LEVEL_HIGH,
DETAIL_ENH_LEVEL_NUM
};
enum SourceType {
IMAGE = 0,
SOURCE_TYPE_INVALID = -1,
IMAGE,
VIDEO,
SOURCE_TYPE_NUM
};
struct DetailEnhancerParameters {
std::string uri{};
DetailEnhancerLevel level{DETAIL_ENH_LEVEL_LOW};
int forceEve{};
int contentId;
};
} // namespace VideoProcessingEngine
} // namespace Media
+4 -2
View File
@@ -73,8 +73,10 @@ public:
* @return 返回错误码VPEAlgoErrCode
* @since 12
*/
virtual VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output,
bool flag = false) = 0;
virtual VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& input, const sptr<SurfaceBuffer>& output) = 0;
virtual VPEAlgoErrCode EnableProtection(bool enable) = 0;
virtual VPEAlgoErrCode ResetProtectionStatus() = 0;
protected:
DetailEnhancerImage() = default;
@@ -19,6 +19,7 @@
#include "detail_enhancer_image.h"
#include "contrast_enhancer_image.h"
#include "image_type.h"
#include "image_processing_types.h"
#include "pixel_map_napi.h"
namespace OHOS {
@@ -56,9 +57,7 @@ private:
napi_deferred deferred;
napi_ref callbackRef;
std::shared_ptr<PixelMap> inputPixelMap{};
std::shared_ptr<PixelMap> scaledPixelMap{};
std::shared_ptr<PixelMap> lcdPixelMap{};
sptr<SurfaceBuffer> pazzleBuffer{};
OHOS::Rect curPixelmapArea;
OHOS::Rect displayArea;
int pixelmapId = -1;
@@ -75,6 +74,9 @@ private:
bool isLCDLutFinished{};
bool isCanceled{};
bool genFinalEffect{};
double maxRatio{};
int animationDuration{};
double curRatio{};
};
struct NapiValues {
@@ -110,22 +112,26 @@ private:
napi_valuetype type, napi_ref* ref, std::vector<struct QualityLevelEnum>& imageEnumMap);
// detail enhancer
static bool InitDetailAlgo(napi_env env, int level);
static bool InitDetailAlgo(napi_env env);
static bool ConfigResolutionBasedOnRatio(napi_env env, napi_value& nVal,
std::shared_ptr<VpeNapi::DetailEnhanceContext> context);
static bool ConfigResolution(napi_env env, napi_value& width, napi_value& height,
std::shared_ptr<VpeNapi::DetailEnhanceContext> context);
static bool ParseDetailEnhanceParameter(napi_env env, napi_callback_info info);
static std::shared_ptr<PixelMap> DetailEnhanceImpl(napi_env env, VpeNapi::DetailEnhanceContext* context);
static bool SetDetailAlgoParam(napi_env env, int level);
static void EnhanceDetailWork(napi_env env, void* data);
static void EnhanceDetailCallBackWork(napi_env env, napi_status status, void* data);
// contrast enhancer
static bool InitContrastAlgo(napi_env env);
static bool ParseLCDParameter(napi_env env, napi_callback_info info, NapiValues& nVal);
static bool ParseDetailImageParameter(napi_env env, napi_callback_info info, NapiValues& nVal);
static bool GenerateRegionHist(napi_env env, ContrastEnhanceContext* context);
static bool UpdateMetadataBasedOnLcd(ContrastEnhanceContext* context);
static bool UpdateMetadataBasedOnDetail(ContrastEnhanceContext* context);
static bool UpdateMetadataBasedOnHist(ContrastEnhanceContext* context);
static bool UpdateMetadataBasedOnPixel(ContrastEnhanceContext* context);
static napi_value CallCallback(napi_env env, ContrastEnhanceContext* context);
static OHOS::Rect PrepareRect(std::shared_ptr<PixelMap> input, OHOS::Rect& displayArea, float ratio);
static napi_value Constructor(napi_env env, napi_callback_info info);
static void Destructor(napi_env env, void* nativeObject, void* finalize);
-19
View File
@@ -1,19 +0,0 @@
{
"patches": [
{
"project":"multimedia_media_foundation",
"path":"foundation/multimedia/media_foundation",
"pr_url":"https://gitee.com/openharmony/multimedia_media_foundation/pulls/1930"
},
{
"project":"vendor_hihope",
"path":"vendor/hihope",
"pr_url":"https://gitee.com/openharmony/vendor_hihope/pulls/1420"
},
{
"project":"graphic_graphic_2d",
"path":"foundation/graphic/graphic_2d",
"pr_url":"https://gitee.com/openharmony/graphic_graphic_2d/pulls/20476"
}
]
}
+76 -13
View File
@@ -19,6 +19,7 @@ import("//foundation/multimedia/video_processing_engine/config.gni")
group("video_processing_service_group") {
deps = [
":videoprocessingservice",
":videoprocessingserviceimpl",
"sa_profile:video_processing_service",
"sa_profile:video_processing_service_etc"
]
@@ -48,9 +49,21 @@ config("videoprocessingservice_config") {
}
}
ohos_shared_library("videoprocessingservice") {
config("videoprocessingservice_export_config") {
include_dirs = [
"$ALGORITHM_COMMON_DIR/include",
"$ALGORITHM_EXTENSION_MANAGER_DIR/include",
"$DFX_DIR/include",
"$INTERFACES_INNER_API_DIR",
"$SERVICES_DIR/algorithm/include/",
"$SERVICES_DIR/utils/include/",
"${target_gen_dir}",
]
}
ohos_shared_library("videoprocessingserviceimpl") {
install_enable = true
sanitize = {
boundary_sanitize = true
cfi = true
@@ -61,40 +74,90 @@ ohos_shared_library("videoprocessingservice") {
}
configs = [ ":videoprocessingservice_config" ]
public_configs = [ ":videoprocessingservice_export_config" ]
sources = [
# common for VPE
"$ALGORITHM_COMMON_DIR/vpe_utils_common.cpp",
"$DFX_DIR/vpe_trace.cpp",
# Only for service
"algorithm/video_processing_algorithm_base.cpp",
"algorithm/video_processing_algorithm_factory.cpp",
"algorithm/video_processing_algorithm_without_data.cpp",
"utils/configuration_helper.cpp",
"utils/surface_buffer_info.cpp",
"utils/vpe_sa_utils.cpp",
]
defines = [ "AMS_LOG_TAG = \"VideoProcessingService\"" ]
include_dirs = [
"include",
"${target_gen_dir}",
]
external_deps = [
"c_utils:utils",
"graphic_2d:2d_graphics",
"graphic_surface:surface",
"hilog:libhilog",
"hitrace:hitrace_meter",
"image_framework:image_native",
"image_framework:pixelmap",
"libxml2:libxml2",
"media_foundation:media_foundation",
]
subsystem_name = "multimedia"
part_name = "video_processing_engine"
}
ohos_shared_library("videoprocessingservice") {
install_enable = true
sanitize = {
boundary_sanitize = true
cfi = true
cfi_cross_dso = true
integer_overflow = true
ubsan = true
debug = false
}
shlib_type = "sa"
configs = [ ":videoprocessingservice_config" ]
public_configs = [ ":videoprocessingservice_export_config" ]
output_values = get_target_outputs(":videoprocessingservice_interface")
sources = [
"src/surface_buffer_info.cpp",
"src/video_processing_server.cpp",
"src/event_handler_factory.cpp",
]
sources += filter_include(output_values, [ "*.cpp" ])
defines = [ "AMS_LOG_TAG = \"VideoProcessingService\"" ]
include_dirs = [
"include",
"${target_gen_dir}",
"//foundation/multimedia/video_processing_engine/framework/dfx/include"
"${target_gen_dir}"
]
deps = [
":videoprocessingservice_interface",
":videoprocessingserviceimpl",
]
external_deps = [
"c_utils:utils",
"eventhandler:libeventhandler",
"graphic_2d:2d_graphics",
"graphic_surface:surface",
"hilog:libhilog",
"hitrace:hitrace_meter",
"image_framework:image_native",
"image_framework:pixelmap",
"ipc:ipc_single",
"graphic_surface:surface",
"media_foundation:media_foundation",
"safwk:system_ability_fwk",
"samgr:samgr_proxy",
"eventhandler:libeventhandler",
]
subsystem_name = "multimedia"
part_name = "video_processing_engine"
}
group("videoprocessingservice_idl_headers") {
public_configs = [ ":videoprocessingservice_config" ]
deps = [ ":videoprocessingservice_interface" ]
}
+14 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -14,6 +14,18 @@
*/
sequenceable SurfaceBufferInfo..OHOS.SurfaceBufferInfo;
interface OHOS.IVideoProcessingServiceManager {
void LoadInfo([in] int key, [out] SurfaceBufferInfo bufferInfo);
}
void Create([in] String feature, [in] String clientName, [out] int clientID);
void Destroy([in] int clientID);
void SetParameter([in] int clientID, [in] int tag, [in] unsigned char[] parameter);
void GetParameter([in] int clientID, [in] int tag, [inout] unsigned char[] parameter);
void UpdateMetadata([in] int clientID, [inout] SurfaceBufferInfo image);
void Process([in] int clientID, [in] SurfaceBufferInfo input, [inout] SurfaceBufferInfo output);
void ComposeImage([in] int clientID, [in] SurfaceBufferInfo inputSdrImage, [in] SurfaceBufferInfo inputGainmap,
[inout] SurfaceBufferInfo outputHdrImage, [in] boolean legacy);
void DecomposeImage([in] int clientID, [in] SurfaceBufferInfo inputImage, [inout] SurfaceBufferInfo outputSdrImage,
[inout] SurfaceBufferInfo outputGainmap);
}
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2025 Huawei Device 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 IVIDEO_PROCESSING_ALGORITHM_H
#define IVIDEO_PROCESSING_ALGORITHM_H
#include <cinttypes>
#include <string>
#include <vector>
#include "surface_buffer_info.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class IVideoProcessingAlgorithm {
public:
virtual int Initialize() = 0;
virtual int Deinitialize() = 0;
virtual bool HasClient() const = 0;
virtual int Add(const std::string& clientName, uint32_t& clientID) = 0;
virtual int Del(uint32_t clientID) = 0;
virtual int SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter) = 0;
virtual int GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter) = 0;
virtual int UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) = 0;
virtual int Process(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) = 0;
virtual int ComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy) = 0;
virtual int DecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap) = 0;
protected:
IVideoProcessingAlgorithm() = default;
virtual ~IVideoProcessingAlgorithm() = default;
IVideoProcessingAlgorithm(const IVideoProcessingAlgorithm&) = delete;
IVideoProcessingAlgorithm& operator=(const IVideoProcessingAlgorithm&) = delete;
IVideoProcessingAlgorithm(IVideoProcessingAlgorithm&&) = delete;
IVideoProcessingAlgorithm& operator=(IVideoProcessingAlgorithm&&) = delete;
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // IVIDEO_PROCESSING_ALGORITHM_H
@@ -0,0 +1,117 @@
/*
* Copyright (c) 2025 Huawei Device 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 VIDEO_PROCESSING_ALGORITHM_BASE_H
#define VIDEO_PROCESSING_ALGORITHM_BASE_H
#include <atomic>
#include <functional>
#include <mutex>
#include <string>
#include "algorithm_errors.h"
#include "ivideo_processing_algorithm.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VideoProcessingAlgorithmBase : public IVideoProcessingAlgorithm {
public:
int Initialize() final;
int Deinitialize() final;
bool HasClient() const final;
int Add(const std::string& clientName, uint32_t& clientID) final;
int Del(uint32_t clientID) final;
int UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) final;
int Process(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) final;
int ComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy) final;
int DecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap) final;
protected:
VideoProcessingAlgorithmBase(const std::string& feature, uint32_t id) : feature_(feature), featureID_(id) {}
virtual ~VideoProcessingAlgorithmBase() = default;
VideoProcessingAlgorithmBase(const VideoProcessingAlgorithmBase&) = delete;
VideoProcessingAlgorithmBase& operator=(const VideoProcessingAlgorithmBase&) = delete;
VideoProcessingAlgorithmBase(VideoProcessingAlgorithmBase&&) = delete;
VideoProcessingAlgorithmBase& operator=(VideoProcessingAlgorithmBase&&) = delete;
// Note: called by algorithm derived classes
virtual inline bool IsValid(const SurfaceBufferInfo& info) const // Derived classes can modify the checker if needed
{
return info.surfacebuffer != nullptr;
}
template <typename T>
static inline int CallSetParameter(std::function<int(const T&)>&& setter, const std::vector<uint8_t>& parameter,
const LogInfo& logInfo)
{
if (parameter.size() != sizeof(T)) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: size=%{public}zu(Expected:%{public}zu)!",
parameter.size(), sizeof(T));
return VPE_ALGO_ERR_INVALID_VAL;
}
return setter(*reinterpret_cast<const T*>(parameter.data()));
}
template <typename T>
static inline int CallGetParameter(std::function<int(T&)>&& getter, std::vector<uint8_t>& parameter)
{
parameter.resize(sizeof(T));
return getter(*reinterpret_cast<T*>(parameter.data()));
}
// Note: implement by algorithm derived classes
virtual int OnInitializeLocked();
virtual int OnDeinitializeLocked();
virtual int AddClientIDLocked(const std::string& clientName, uint32_t& clientID);
virtual int DelClientIDLocked(uint32_t clientID, bool& isEmpty);
virtual size_t GetClientSizeLocked() const;
virtual void ClearClientsLocked();
virtual int DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image);
virtual int DoProcess(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output);
virtual int DoComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy);
virtual int DoDecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap);
int ReturnNotSupport(const LogInfo& logInfo) const;
bool GenerateClientID(std::function<bool(uint32_t)>&& isDuplicate, uint32_t& clientID);
// Note: Data members to be accessed by algorithm derived classes
const std::string feature_{};
uint32_t featureID_{};
mutable std::mutex lock_{};
// Guarded by lock_ begin
bool isInitialized_{};
// Guarded by lock_ end
private:
uint32_t GenerateClientID();
// Guarded by lock_ begin
std::atomic<bool> hasClient_{};
uint32_t clientIdBase_{};
// Guarded by lock_ end
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_BASE_H
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2025 Huawei Device 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 VIDEO_PROCESSING_ALGORITHM_FACTORY_H
#define VIDEO_PROCESSING_ALGORITHM_FACTORY_H
#include <memory>
#include <string>
#include "ivideo_processing_algorithm.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VideoProcessingAlgorithmFactory {
public:
VideoProcessingAlgorithmFactory();
~VideoProcessingAlgorithmFactory();
VideoProcessingAlgorithmFactory(const VideoProcessingAlgorithmFactory&) = delete;
VideoProcessingAlgorithmFactory& operator=(const VideoProcessingAlgorithmFactory&) = delete;
VideoProcessingAlgorithmFactory(VideoProcessingAlgorithmFactory&&) = delete;
VideoProcessingAlgorithmFactory& operator=(VideoProcessingAlgorithmFactory&&) = delete;
std::shared_ptr<IVideoProcessingAlgorithm> Create(const std::string& feature) const;
private:
bool LoadDynamicAlgorithm(const std::string& path);
void UnloadDynamicAlgorithm();
void GenerateFeatureIDs();
void* handle_{};
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_FACTORY_H
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2025 Huawei Device 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 VIDEO_PROCESSING_ALGORITHM_FACTORY_COMMON_H
#define VIDEO_PROCESSING_ALGORITHM_FACTORY_COMMON_H
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include "ivideo_processing_algorithm.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
using VpeAlgorithmCreator = std::function<std::shared_ptr<IVideoProcessingAlgorithm>(const std::string&, uint32_t)>;
struct VpeAlgorithmCreatorInfo {
uint32_t id;
VpeAlgorithmCreator creator;
};
using VpeAlgorithmCreatorMap = std::unordered_map<std::string, VpeAlgorithmCreatorInfo>;
// NOTE:
// All algorithms MUST be derived from VideoProcessingAlgorithmWithData or VideoProcessingAlgorithmWithoutData.
// And algorithms MUST keep the input parameters of constructor like (const std::string& feature, uint32_t id).
template <typename T>
std::shared_ptr<IVideoProcessingAlgorithm> CreateVpeAlgorithm(const std::string& feature, uint32_t id)
{
return std::make_shared<T>(feature, id);
}
template <typename T>
VpeAlgorithmCreatorInfo MakeCreator()
{
VpeAlgorithmCreatorInfo info {
.id = 0,
.creator = CreateVpeAlgorithm<T>,
};
return info;
}
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_FACTORY_COMMON_H
@@ -0,0 +1,233 @@
/*
* Copyright (c) 2025 Huawei Device 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 VIDEO_PROCESSING_ALGORITHM_WITH_DATA_H
#define VIDEO_PROCESSING_ALGORITHM_WITH_DATA_H
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include "algorithm_errors.h"
#include "video_processing_algorithm_base.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
template <typename T>
class VideoProcessingAlgorithmWithData : public VideoProcessingAlgorithmBase {
public:
int SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter) final
{
auto set = &VideoProcessingAlgorithmWithData::OnSetParameter;
return Execute(clientID, std::bind(set, this, std::placeholders::_1, tag, parameter), VPE_LOG_INFO);
}
int GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter) final
{
auto get = &VideoProcessingAlgorithmWithData::OnGetParameter;
return Execute(clientID, std::bind(get, this, std::placeholders::_1, tag, parameter), VPE_LOG_INFO);
}
int DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) final
{
auto update = &VideoProcessingAlgorithmWithData::OnUpdateMetadata;
return Execute(clientID, std::bind(update, this, std::placeholders::_1, image), VPE_LOG_INFO);
}
int DoProcess(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) final
{
auto process = &VideoProcessingAlgorithmWithData::OnProcess;
return Execute(clientID, std::bind(process, this, std::placeholders::_1, input, output), VPE_LOG_INFO);
}
int DoComposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap,
SurfaceBufferInfo& outputHdrImage, bool legacy) final
{
auto compose = &VideoProcessingAlgorithmWithData::OnComposeImage;
return Execute(clientID,
std::bind(compose, this, std::placeholders::_1, inputSdrImage, inputGainmap, outputHdrImage, legacy),
VPE_LOG_INFO);
}
int DoDecomposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage,
SurfaceBufferInfo& outputGainmap) final
{
auto decompose = &VideoProcessingAlgorithmWithData::OnDecomposeImage;
return Execute(clientID,
std::bind(decompose, this, std::placeholders::_1, inputImage, outputSdrImage, outputGainmap), VPE_LOG_INFO);
}
protected:
using ClientInfo = std::pair<std::string, std::shared_ptr<T>>;
VideoProcessingAlgorithmWithData(const std::string& feature, uint32_t id)
: VideoProcessingAlgorithmBase(feature, id) {}
virtual ~VideoProcessingAlgorithmWithData() = default;
VideoProcessingAlgorithmWithData(const VideoProcessingAlgorithmWithData&) = delete;
VideoProcessingAlgorithmWithData& operator=(const VideoProcessingAlgorithmWithData&) = delete;
VideoProcessingAlgorithmWithData(VideoProcessingAlgorithmWithData&&) = delete;
VideoProcessingAlgorithmWithData& operator=(VideoProcessingAlgorithmWithData&&) = delete;
// NOTE: Would be override by the actual algorithm when necessary.
// The input ClientInfo& clientInfo is already checked for all OnXXX functions.
// It's NOT necessary to check clientInfo.second whether is nullptr.
// Actual methods begin
// int OnInitializeLocked() - declared by VideoProcessingAlgorithmBase
// int OnDeinitializeLocked() - declared by VideoProcessingAlgorithmBase
virtual int OnContextInitializeLocked([[maybe_unused]] ClientInfo& clientInfo)
{
return VPE_ALGO_ERR_OK;
}
virtual int OnContextDeinitializeLocked([[maybe_unused]] ClientInfo& clientInfo)
{
return VPE_ALGO_ERR_OK;
}
virtual int OnSetParameter([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] int tag, [[maybe_unused]] const std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnGetParameter([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] int tag, [[maybe_unused]] std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnUpdateMetadata([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] SurfaceBufferInfo& image)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnProcess([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] const SurfaceBufferInfo& input,
[[maybe_unused]] SurfaceBufferInfo& output)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnComposeImage([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] const SurfaceBufferInfo& inputSdrImage,
[[maybe_unused]] const SurfaceBufferInfo& inputGainmap,
[[maybe_unused]] SurfaceBufferInfo& outputHdrImage, [[maybe_unused]] bool legacy)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnDecomposeImage([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] const SurfaceBufferInfo& inputImage,
[[maybe_unused]] SurfaceBufferInfo& outputSdrImage,
[[maybe_unused]] SurfaceBufferInfo& outputGainmap)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
// Actual methods end
// Utils methods would be called by the derived algorithm class
ClientInfo GetContext(uint32_t clientID)
{
std::lock_guard<std::mutex>lock(lock_);
return GetContextLocked(clientID);
}
ClientInfo GetContextLocked(uint32_t clientID)
{
auto it = contexts_.find(clientID);
if (it == contexts_.end()) [[unlikely]] {
return std::make_pair("", nullptr);
}
return it->second;
}
private:
int AddClientIDLocked(const std::string& clientName, uint32_t& clientID) final
{
uint32_t id;
if (!GenerateClientID([this](uint32_t id) { return contexts_.find(id) != contexts_.end(); }, id)) {
return VPE_ALGO_ERR_INVALID_STATE;
}
auto context = std::make_shared<T>();
CHECK_AND_RETURN_RET_LOG(context != nullptr, VPE_ALGO_ERR_NO_MEMORY, "Failed to create context for %{public}s!",
clientName.c_str());
contexts_[id] = std::make_pair(clientName, context);
clientID = id;
return OnContextInitializeLocked(contexts_[id]);
}
int DelClientIDLocked(uint32_t clientID, bool& isEmpty) final
{
auto it = contexts_.find(clientID);
CHECK_AND_RETURN_RET_LOG(it != contexts_.end(), VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: clientID:%{public}u!", clientID);
int ret = OnContextDeinitializeLocked(it->second);
contexts_.erase(it);
isEmpty = contexts_.empty();
return ret;
}
size_t GetClientSizeLocked() const final
{
return contexts_.size();
}
void ClearClientsLocked() final
{
for (auto& [id, info] : contexts_) {
CHECK_AND_LOG(OnContextDeinitializeLocked(info) == VPE_ALGO_ERR_OK,
"Failed to deinitialize(id:%{public}d, client:%{public}s)", id, info.first.c_str());
}
contexts_.clear();
}
int Execute(uint32_t clientID, std::function<int(ClientInfo&)>&& operation,
const LogInfo& logInfo)
{
ClientInfo ctxt;
{
std::lock_guard<std::mutex>lock(lock_);
if (!isInitialized_) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Oops! Not initialized!");
return VPE_ALGO_ERR_INVALID_STATE;
}
ctxt = GetContextLocked(clientID);
if (ctxt.first.empty() || ctxt.second == nullptr) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: client(%{public}u) for '%{public}s'!",
clientID, ctxt.first.c_str());
return VPE_ALGO_ERR_INVALID_PARAM;
}
}
return operation(ctxt);
}
// Guarded by lock_ begin
std::unordered_map<uint32_t, ClientInfo> contexts_{};
// Guarded by lock_ end
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_WITH_DATA_H
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2025 Huawei Device 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 VIDEO_PROCESSING_ALGORITHM_WITHOUT_DATA_H
#define VIDEO_PROCESSING_ALGORITHM_WITHOUT_DATA_H
#include <functional>
#include <string>
#include <unordered_map>
#include "video_processing_algorithm_base.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VideoProcessingAlgorithmWithoutData : public VideoProcessingAlgorithmBase {
public:
int SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter) final;
int GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter) final;
int DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) final;
int DoProcess(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) final;
int DoComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy) final;
int DoDecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap) final;
protected:
VideoProcessingAlgorithmWithoutData(const std::string& feature, uint32_t id)
: VideoProcessingAlgorithmBase(feature, id) {}
virtual ~VideoProcessingAlgorithmWithoutData() = default;
VideoProcessingAlgorithmWithoutData(const VideoProcessingAlgorithmWithoutData&) = delete;
VideoProcessingAlgorithmWithoutData& operator=(const VideoProcessingAlgorithmWithoutData&) = delete;
VideoProcessingAlgorithmWithoutData(VideoProcessingAlgorithmWithoutData&&) = delete;
VideoProcessingAlgorithmWithoutData& operator=(VideoProcessingAlgorithmWithoutData&&) = delete;
// NOTE: Would be override by the actual algorithm when necessary
// Actual methods begin
// int OnInitializeLocked() - declared by VideoProcessingAlgorithmBase
// int OnDeinitializeLocked() - declared by VideoProcessingAlgorithmBase
virtual int OnSetParameter(const std::string& clientName, int tag, const std::vector<uint8_t>& parameter);
virtual int OnGetParameter(const std::string& clientName, int tag, std::vector<uint8_t>& parameter);
virtual int OnUpdateMetadata(const std::string& clientName, SurfaceBufferInfo& image);
virtual int OnProcess(const std::string& clientName, const SurfaceBufferInfo& input, SurfaceBufferInfo& output);
virtual int OnComposeImage(const std::string& clientName, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy);
virtual int OnDecomposeImage(const std::string& clientName, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap);
// Actual methods end
private:
int AddClientIDLocked(const std::string& clientName, uint32_t& clientID) final;
int DelClientIDLocked(uint32_t clientID, bool& isEmpty) final;
void ClearClientsLocked() final;
int Execute(uint32_t clientID, std::function<int(const std::string&)>&& operation, const LogInfo& logInfo);
// Guarded by lock_ begin
std::unordered_map<uint32_t, std::string> clients_{};
// Guarded by lock_ end
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_WITHOUT_DATA_H
@@ -0,0 +1,225 @@
/*
* Copyright (c) 2025 Huawei Device 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 "video_processing_algorithm_base.h"
#include "algorithm_errors.h"
#include "video_processing_algorithm_factory.h"
#include "vpe_sa_types.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
constexpr uint32_t MAX_CLIENT_GEN_COUNT = 500;
}
int VideoProcessingAlgorithmBase::Initialize()
{
std::lock_guard<std::mutex> lock(lock_);
if (isInitialized_) {
VPE_LOGW("Already initialized!");
return VPE_ALGO_ERR_OK;
}
int ret = OnInitializeLocked();
if (ret != VPE_ALGO_ERR_OK) {
VPE_LOGE("Failed to initialize!");
return ret;
}
isInitialized_ = true;
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::Deinitialize()
{
std::lock_guard<std::mutex> lock(lock_);
if (!isInitialized_) {
VPE_LOGW("Already deinitialized!");
return VPE_ALGO_ERR_OK;
}
ClearClientsLocked();
int ret = OnDeinitializeLocked();
if (ret != VPE_ALGO_ERR_OK) {
VPE_LOGE("Failed to deinitialize!");
return ret;
}
isInitialized_ = false;
return VPE_ALGO_ERR_OK;
}
bool VideoProcessingAlgorithmBase::HasClient() const
{
return hasClient_.load();
}
int VideoProcessingAlgorithmBase::Add(const std::string& clientName, uint32_t& clientID)
{
CHECK_AND_RETURN_RET_LOG(!clientName.empty(), VPE_ALGO_ERR_INVALID_PARAM, "Invalid input: clientName is empty!");
std::lock_guard<std::mutex> lock(lock_);
int ret = AddClientIDLocked(clientName, clientID);
CHECK_AND_RETURN_RET_LOG(ret == VPE_ALGO_ERR_OK, ret, "Failed to add client for %{public}s!", clientName.c_str());
hasClient_ = true;
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::Del(uint32_t clientID)
{
std::lock_guard<std::mutex> lock(lock_);
bool isEmpty;
int ret = DelClientIDLocked(clientID, isEmpty);
CHECK_AND_RETURN_RET_LOG(ret == VPE_ALGO_ERR_OK, ret, "Failed to del client(%{public}u)!", clientID);
if (isEmpty) {
hasClient_ = false;
}
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image)
{
CHECK_AND_RETURN_RET_LOG(IsValid(image), VPE_ALGO_ERR_INVALID_PARAM, "Invalid input: %{public}s!",
image.str().c_str());
return DoUpdateMetadata(clientID, image);
}
int VideoProcessingAlgorithmBase::Process(uint32_t clientID,
const SurfaceBufferInfo& input, SurfaceBufferInfo& output)
{
CHECK_AND_RETURN_RET_LOG(IsValid(input) && IsValid(output), VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: input={%{public}s} output={%{public}s}!", input.str().c_str(), output.str().c_str());
return DoProcess(clientID, input, output);
}
int VideoProcessingAlgorithmBase::ComposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap,
SurfaceBufferInfo& outputHdrImage, bool legacy)
{
CHECK_AND_RETURN_RET_LOG(IsValid(inputSdrImage) && IsValid(inputGainmap) && IsValid(outputHdrImage),
VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: inputSdrImage={%{public}s} inputGainmap={%{public}s} outputHdrImage={%{public}s}!",
inputSdrImage.str().c_str(), inputGainmap.str().c_str(), outputHdrImage.str().c_str());
return DoComposeImage(clientID, inputSdrImage, inputGainmap, outputHdrImage, legacy);
}
int VideoProcessingAlgorithmBase::DecomposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage,
SurfaceBufferInfo& outputGainmap)
{
CHECK_AND_RETURN_RET_LOG(IsValid(inputImage) && IsValid(outputSdrImage) && IsValid(outputGainmap),
VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: inputImage={%{public}s} outputSdrImage={%{public}s} outputGainmap={%{public}s}!",
inputImage.str().c_str(), outputSdrImage.str().c_str(), outputGainmap.str().c_str());
return DoDecomposeImage(clientID, inputImage, outputSdrImage, outputGainmap);
}
int VideoProcessingAlgorithmBase::OnInitializeLocked()
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::OnDeinitializeLocked()
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::AddClientIDLocked([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] uint32_t& clientID)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DelClientIDLocked([[maybe_unused]] uint32_t clientID, [[maybe_unused]] bool& isEmpty)
{
return VPE_ALGO_ERR_OK;
}
size_t VideoProcessingAlgorithmBase::GetClientSizeLocked() const
{
return 0;
}
void VideoProcessingAlgorithmBase::ClearClientsLocked()
{
}
int VideoProcessingAlgorithmBase::DoUpdateMetadata([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] SurfaceBufferInfo& image)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DoProcess([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] const SurfaceBufferInfo& input, [[maybe_unused]] SurfaceBufferInfo& output)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DoComposeImage([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] const SurfaceBufferInfo& inputSdrImage,
[[maybe_unused]] const SurfaceBufferInfo& inputGainmap,
[[maybe_unused]] SurfaceBufferInfo& outputHdrImage, [[maybe_unused]] bool legacy)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DoDecomposeImage([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] const SurfaceBufferInfo& inputImage,
[[maybe_unused]] SurfaceBufferInfo& outputSdrImage,
[[maybe_unused]] SurfaceBufferInfo& outputGainmap)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::ReturnNotSupport(const LogInfo& logInfo) const
{
VPE_ORG_LOGE(logInfo, "Not support this operation!");
return VPE_ALGO_ERR_OPERATION_NOT_SUPPORTED;
}
bool VideoProcessingAlgorithmBase::GenerateClientID(std::function<bool(uint32_t)>&& isDuplicate, uint32_t& clientID)
{
uint32_t id;
uint32_t i = 0;
do {
// MAX_CLIENT_GEN_COUNT will control the ID generation times,
// it will avoid an infinite loop during ID generation.
if (i++ > MAX_CLIENT_GEN_COUNT) {
VPE_LOGE("Failed to generate new client ID, maybe too many clients(size:%{public}zu).",
GetClientSizeLocked());
return false;
}
id = GenerateClientID();
} while (isDuplicate(id));
clientID = id;
return true;
}
uint32_t VideoProcessingAlgorithmBase::GenerateClientID()
{
// clientIdBase_ CAN overflow after self-adding, because the ID value maybe reused.
// And MAX_CLIENT_GEN_COUNT will control the ID generation times,
// it will avoid an infinite loop during ID generation.
// +---------------------------------------+
// | High <----------------------> Low |
// +---------+-----------------------------+
// | 1 Byte | 3 Bytes |
// +---------+---------+---------+---------+
// |FeatureID| ClientID |
// +---------+---------+---------+---------+
return (featureID_ << 24) | (clientIdBase_++ & 0xFFFFFF);
}
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2025 Huawei Device 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 "video_processing_algorithm_factory.h"
#include <dlfcn.h>
#include "algorithm_errors.h"
#include "video_processing_algorithm_factory_common.h"
#include "vpe_log.h"
// NOTE: Add header file of static algorithm which would be called by VPE SA below:
// algorithm begin
// algorithm end
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
const std::string DYNAMIC_ALGORITHM_LIBRARY_PATH = "libvideoprocessingengineservice_ext.z.so";
VpeAlgorithmCreatorMap g_creators = {
// NOTE: Add static algorithm which would be called by VPE SA below:
// algorithm begin
// algorithm end
};
}
VideoProcessingAlgorithmFactory::VideoProcessingAlgorithmFactory()
{
VPE_LOGD("step in");
if (!LoadDynamicAlgorithm(DYNAMIC_ALGORITHM_LIBRARY_PATH)) {
UnloadDynamicAlgorithm();
}
GenerateFeatureIDs();
}
VideoProcessingAlgorithmFactory::~VideoProcessingAlgorithmFactory()
{
UnloadDynamicAlgorithm();
}
std::shared_ptr<IVideoProcessingAlgorithm> VideoProcessingAlgorithmFactory::Create(const std::string& feature) const
{
auto it = g_creators.find(feature);
if (it == g_creators.end()) {
return nullptr;
}
return it->second.creator(feature, it->second.id);
}
bool VideoProcessingAlgorithmFactory::LoadDynamicAlgorithm(const std::string& path)
{
handle_ = dlopen(path.c_str(), RTLD_NOW);
if (handle_ == nullptr) {
VPE_LOGD("Can't open library '%{public}s' - %{public}s", path.c_str(), dlerror());
return false;
}
using GetCreator = VpeAlgorithmCreatorMap* (*)();
auto getCreator = reinterpret_cast<GetCreator>(dlsym(handle_, "GetDynamicAlgorithmCreator"));
if (getCreator == nullptr) {
VPE_LOGD("Failed to locate GetDynamicAlgorithmCreator in '%{public}s' - %{public}s", path.c_str(), dlerror());
return false;
}
auto dynamicAlgorithms = getCreator();
if (dynamicAlgorithms == nullptr) {
VPE_LOGD("Failed to GetDynamicAlgorithmCreator() from '%{public}s'", path.c_str());
return false;
}
auto staticSize = g_creators.size();
auto dynamicSize = dynamicAlgorithms->size();
g_creators.merge(*dynamicAlgorithms);
VPE_LOGI("Algorithms: { static:%{public}zu + dynamic:%{public}zu -> total:%{public}zu }",
staticSize, dynamicSize, g_creators.size());
return true;
}
void VideoProcessingAlgorithmFactory::UnloadDynamicAlgorithm()
{
if (handle_ != nullptr) {
dlclose(handle_);
handle_ = nullptr;
}
}
void VideoProcessingAlgorithmFactory::GenerateFeatureIDs()
{
// When GenerateFeatureIDs be called, the g_creators size is fixed.
// And we fill algorithm feature ID here from 1 to N.
uint32_t id = 0;
for (auto& creatorInfo : g_creators) {
creatorInfo.second.id = ++id;
}
}
@@ -0,0 +1,159 @@
/*
* Copyright (c) 2025 Huawei Device 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 "video_processing_algorithm_without_data.h"
#include "algorithm_errors.h"
#include "vpe_log.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
using namespace std::placeholders;
int VideoProcessingAlgorithmWithoutData::SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnSetParameter, this, _1, tag, parameter),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnGetParameter, this, _1, tag, parameter),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnUpdateMetadata, this, _1, image),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoProcess(uint32_t clientID,
const SurfaceBufferInfo& input, SurfaceBufferInfo& output)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnProcess, this, _1, input, output),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoComposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap,
SurfaceBufferInfo& outputHdrImage, bool legacy)
{
auto compose = &VideoProcessingAlgorithmWithoutData::OnComposeImage;
return Execute(clientID, std::bind(compose, this, _1, inputSdrImage, inputGainmap, outputHdrImage, legacy),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoDecomposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage,
SurfaceBufferInfo& outputGainmap)
{
auto decompose = &VideoProcessingAlgorithmWithoutData::OnDecomposeImage;
return Execute(clientID, std::bind(decompose, this, _1, inputImage, outputSdrImage, outputGainmap),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnSetParameter([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] int tag, [[maybe_unused]] const std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnGetParameter([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] int tag, [[maybe_unused]] std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnUpdateMetadata([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] SurfaceBufferInfo& image)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnProcess([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] const SurfaceBufferInfo& input,
[[maybe_unused]] SurfaceBufferInfo& output)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnComposeImage([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] const SurfaceBufferInfo& inputSdrImage,
[[maybe_unused]] const SurfaceBufferInfo& inputGainmap,
[[maybe_unused]] SurfaceBufferInfo& outputHdrImage, [[maybe_unused]] bool legacy)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnDecomposeImage([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] const SurfaceBufferInfo& inputImage,
[[maybe_unused]] SurfaceBufferInfo& outputSdrImage,
[[maybe_unused]] SurfaceBufferInfo& outputGainmap)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::AddClientIDLocked(const std::string& clientName, uint32_t& clientID)
{
uint32_t id;
if (!GenerateClientID([this](uint32_t id) { return clients_.find(id) != clients_.end(); }, id)) {
return VPE_ALGO_ERR_INVALID_STATE;
}
clients_[id] = clientName;
clientID = id;
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmWithoutData::DelClientIDLocked(uint32_t clientID, bool& isEmpty)
{
auto it = clients_.find(clientID);
CHECK_AND_RETURN_RET_LOG(it != clients_.end(), VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: clientID:%{public}u!", clientID);
clients_.erase(it);
isEmpty = clients_.empty();
return VPE_ALGO_ERR_OK;
}
void VideoProcessingAlgorithmWithoutData::ClearClientsLocked()
{
clients_.clear();
}
int VideoProcessingAlgorithmWithoutData::Execute(uint32_t clientID, std::function<int(const std::string&)>&& operation,
const LogInfo& logInfo)
{
std::string clientName;
{
std::lock_guard<std::mutex> lock(lock_);
if (!isInitialized_) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Oops! Not initialized!");
return VPE_ALGO_ERR_INVALID_STATE;
}
auto it = clients_.find(clientID);
if (it == clients_.end()) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: client(%{public}u)!", clientID);
return VPE_ALGO_ERR_INVALID_PARAM;
}
clientName = it->second;
if (clientName.empty()) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: client(%{public}u) for ''!", clientID);
return VPE_ALGO_ERR_INVALID_PARAM;
}
}
return operation(clientName);
}
-50
View File
@@ -1,50 +0,0 @@
/*
* Copyright (c) 2024 Huawei Device 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 OHOS_VPE_EVENT_HANDLER_FACTORY_H
#define OHOS_VPE_EVENT_HANDLER_FACTORY_H
#include <map>
#include <memory>
#include <mutex>
#include "event_handler.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class EventHandlerFactory {
public:
static EventHandlerFactory& GetInstance();
private:
EventHandlerFactory(const EventHandlerFactory&) = delete;
EventHandlerFactory& operator= (const EventHandlerFactory&) = delete;
EventHandlerFactory(EventHandlerFactory&&) = delete;
EventHandlerFactory& operator= (EventHandlerFactory&&) = delete;
public:
int32_t Init();
int32_t UnInit();
std::shared_ptr<AppExecFwk::EventHandler> CreateEventHandler(const std::string& handlerName);
private:
EventHandlerFactory() = default;
virtual ~EventHandlerFactory() = default;
std::mutex eventHandlerMutex_;
std::map<std::string, std::shared_ptr<AppExecFwk::EventHandler>> eventHandlerMap_;
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // OHOS_VPE_EVENT_HANDLER_FACTORY_H
+190 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -16,23 +16,29 @@
#ifndef VPE_VIDEO_PROCESSING_CLENT_H
#define VPE_VIDEO_PROCESSING_CLENT_H
#include <atomic>
#include <cinttypes>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <string>
#include <vector>
#include "ipc_types.h"
#include "iremote_object.h"
#include "refbase.h"
#include "system_ability_load_callback_stub.h"
#include "algorithm_errors.h"
#include "surface_buffer_info.h"
#include "video_processing_service_manager_proxy.h"
#include "ipc_types.h"
#include "refbase.h"
#include "iremote_object.h"
#include "vpe_model_path.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VideoProcessingManager {
public:
VideoProcessingManager(const VideoProcessingManager&) = delete;
VideoProcessingManager& operator=(const VideoProcessingManager&) = delete;
VideoProcessingManager(VideoProcessingManager&&) = delete;
VideoProcessingManager& operator=(VideoProcessingManager&&) = delete;
static VideoProcessingManager& GetInstance();
/*
@@ -56,13 +62,182 @@ public:
void LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject);
void LoadSystemAbilityFail();
/*
* @brief Create a new client to access feature algorithm such as HDR2SDR, SDR2HDR, AISR and etc.
* @param feature The name of feature algorithm such as "AisrImage".
* @param clientName The name of caller process.
* @param clientID The unique client ID generated by feature algorithms is used for other algorithm methods.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode Create(const std::string& feature, const std::string& clientName, uint32_t& clientID);
/*
* @brief Destroy the specified client.
* @param clientID The unique client ID generated by {@linke Create}.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode Destroy(uint32_t clientID);
/*
* @brief Set parameters to feature algorithm.
* @param clientID The unique client ID generated by {@linke Create}.
* @param tag A int value that is used to specify the parameter.
* @param parameter The variable-length buffer is used to transfer the actual parameter.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode SetParameter(uint32_t clientID, int32_t tag, const std::vector<uint8_t>& parameter);
/*
* @brief Set parameters to feature algorithm.
* @param clientID The unique client ID generated by {@linke Create}.
* @param tag A int value that is used to specify the parameter.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode SetParameter(uint32_t clientID, int32_t tag);
/*
* @brief Set parameters to feature algorithm.
* @param clientID The unique client ID generated by {@linke Create}.
* @param tag A int value that is used to specify the parameter.
* @param parameter The parameter for the tag.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
template <typename T>
VPEAlgoErrCode SetParameter(uint32_t clientID, int32_t tag, const T& parameter)
{
std::vector<uint8_t> param;
param.resize(sizeof(parameter));
*reinterpret_cast<T*>(param.data()) = parameter;
return SetParameter(clientID, tag, param);
}
/*
* @brief Get parameters from feature algorithm.
* @param clientID The unique client ID generated by {@linke Create}.
* @param tag A int value that is used to specify the parameter.
* @param parameter The variable-length buffer is used to transfer the actual parameter.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode GetParameter(uint32_t clientID, int32_t tag, std::vector<uint8_t>& parameter);
/*
* @brief Get parameters from feature algorithm.
* @param clientID The unique client ID generated by {@linke Create}.
* @param tag A int value that is used to specify the parameter.
* @param parameter The parameter for the tag.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
template <typename T>
VPEAlgoErrCode GetParameter(uint32_t clientID, int32_t tag, T& parameter)
{
std::vector<uint8_t> param;
param.resize(sizeof(parameter));
*reinterpret_cast<T*>(param.data()) = parameter;
auto ret = GetParameter(clientID, tag, param);
parameter = *reinterpret_cast<T*>(param.data());
return ret;
}
/*
* @brief Update metadata of the surface buffer.
* @param clientID The unique client ID generated by {@linke Create}.
* @param image The surface buffer that contain the image content.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image);
/*
* @brief Process the image buffer.
* @param clientID The unique client ID generated by {@linke Create}.
* @param input Input surface buffer of image.
* @param output Output surface buffer of image.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode Process(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output);
/*
* @brief Composition from dual-layer HDR images to single-layer HDR images.
* @param clientID The unique client ID generated by {@linke Create}.
* @param inputSdrImage Input surface buffer of SDR image.
* @param inputGainmap Input surface buffer of gainmap.
* @param outputHdrImage Output surface buffer of HDR image.
* @param legacy A bool value that indicates weather the format of dual-layer HDR image is old format.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode ComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy);
/*
* @brief Decomposition from single-layer HDR images to dual-layer HDR images.
* @param clientID The unique client ID generated by {@linke Create}.
* @param inputImage Input surface buffer of HDR image.
* @param outputSdrImage Output surface buffer of SDR image.
* @param outputGainmap Output surface buffer of gainmap.
* @return VPE_ALGO_ERR_OK if creation is successful. Other values if failed. See algorithm_errors.h.
*/
VPEAlgoErrCode DecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap);
private:
// Inner callback class for SA loading
class LoadCallback : public SystemAbilityLoadCallbackStub {
public:
LoadCallback(std::function<void(const sptr<IRemoteObject>&)>&& onSuccess, std::function<void(void)>&& onFail)
: onSuccess_(onSuccess), onFail_(onFail) {}
virtual ~LoadCallback() = default;
LoadCallback(const LoadCallback&) = delete;
LoadCallback& operator=(const LoadCallback&) = delete;
LoadCallback(LoadCallback&&) = delete;
LoadCallback& operator=(LoadCallback&&) = delete;
void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject>& remoteObject) final;
void OnLoadSystemAbilityFail(int32_t systemAbilityId) final;
private:
std::function<void(const sptr<IRemoteObject>&)> onSuccess_;
std::function<void(void)> onFail_;
};
class DeathObserver : public IPCObjectProxy::DeathRecipient {
public:
DeathObserver(std::function<void(const wptr<IRemoteObject>&)>&& onRemoteDied) : onRemoteDied_(onRemoteDied) {}
virtual ~DeathObserver() = default;
DeathObserver(const DeathObserver&) = delete;
DeathObserver& operator=(const DeathObserver&) = delete;
DeathObserver(DeathObserver&&) = delete;
DeathObserver& operator=(DeathObserver&&) = delete;
void OnRemoteDied(const wptr<IRemoteObject>& remoteObject) final;
private:
std::function<void(const wptr<IRemoteObject>&)> onRemoteDied_;
};
VideoProcessingManager() = default;
virtual ~VideoProcessingManager() = default;
sptr<IVideoProcessingServiceManager> g_proxy = nullptr;
std::condition_variable g_proxyConVar;
VideoProcessingManager(const VideoProcessingManager&) = delete;
VideoProcessingManager& operator=(const VideoProcessingManager&) = delete;
VideoProcessingManager(VideoProcessingManager&&) = delete;
VideoProcessingManager& operator=(VideoProcessingManager&&) = delete;
sptr<IVideoProcessingServiceManager> GetService();
void OnSaLoad(const sptr<IRemoteObject>& remoteObject);
void OnSaDied(const wptr<IRemoteObject>& remoteObject);
VPEAlgoErrCode Execute(std::function<ErrCode(sptr<IVideoProcessingServiceManager>&)>&& operation,
const LogInfo& logInfo);
void ClearSa();
void ClearSaLocked();
std::condition_variable cvProxy_{};
std::mutex lock_{};
// Guarded by lock_ begin
std::atomic<bool> isLoading_{};
sptr<IVideoProcessingServiceManager> proxy_{};
// Guarded by lock_ end
std::atomic<int> deadRetryCount_{};
};
}
}
}
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VPE_VIDEO_PROCESSING_CLENT_H
+51 -18
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -16,17 +16,23 @@
#ifndef VPE_VIDEO_PROCESSING_SERVER_H
#define VPE_VIDEO_PROCESSING_SERVER_H
#include <atomic>
#include <cinttypes>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <refbase.h>
#include <system_ability.h>
#include "video_processing_service_manager_stub.h"
#include "ipc_types.h"
#include "event_handler.h"
#include "event_runner.h"
#include "ipc_types.h"
#include "video_processing_algorithm_factory.h"
#include "video_processing_service_manager_stub.h"
#include "vpe_log.h"
#include "vpe_model_path.h"
namespace OHOS {
namespace Media {
@@ -37,28 +43,55 @@ class VideoProcessingServer : public SystemAbility, public VideoProcessingServic
public:
VideoProcessingServer(int32_t saId, bool runOnCreate);
~VideoProcessingServer();
VideoProcessingServer(const VideoProcessingServer&) = delete;
VideoProcessingServer& operator=(const VideoProcessingServer&) = delete;
VideoProcessingServer(VideoProcessingServer&&) = delete;
VideoProcessingServer& operator=(VideoProcessingServer&&) = delete;
int32_t Init();
int32_t UnInit();
ErrCode LoadInfo(int32_t key, SurfaceBufferInfo& bufferInfo) override;
bool IsInited();
protected:
void OnStart() override;
void OnStop() override;
// For optimized SA
ErrCode Create(const std::string& feature, const std::string& clientName, int32_t& clientID) final;
ErrCode Destroy(int32_t clientID) final;
ErrCode SetParameter(int32_t clientID, int32_t tag, const std::vector<uint8_t>& parameter) final;
ErrCode GetParameter(int32_t clientID, int32_t tag, std::vector<uint8_t>& parameter) final;
ErrCode UpdateMetadata(int32_t clientID, SurfaceBufferInfo& image) final;
ErrCode Process(int32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) final;
ErrCode ComposeImage(int32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy) final;
ErrCode DecomposeImage(int32_t clientID, const SurfaceBufferInfo& inputImage, SurfaceBufferInfo& outputSdrImage,
SurfaceBufferInfo& outputGainmap) final;
private:
int32_t CreateUnloadHandler();
int32_t DestroyUnloadHandler();
void DelayUnloadTask();
using AlgoPtr = std::shared_ptr<IVideoProcessingAlgorithm>;
void OnStart(const SystemAbilityOnDemandReason& startReason) final;
void OnStop(const SystemAbilityOnDemandReason& stopReason) final;
void UnloadVideoProcessingSA();
private:
std::shared_ptr<AppExecFwk::EventHandler> unloadHandler_;
std::mutex unloadMutex_;
std::atomic<bool> isInited_{false};
// For optimized SA
ErrCode CreateLocked(const std::string& feature, const std::string& clientName, uint32_t& id);
ErrCode DestroyLocked(uint32_t id);
bool CreateUnloadHandler();
bool CreateUnloadHandlerLocked();
void DestroyUnloadHandler();
void DelayUnloadTask();
void DelayUnloadTaskLocked();
void ClearAlgorithms();
ErrCode Execute(int clientID, std::function<int(AlgoPtr&, uint32_t)>&& operation, const LogInfo& logInfo);
VideoProcessingAlgorithmFactory factory_{};
mutable std::mutex lock_{};
// Guarded by lock_ begin
std::atomic<bool> isWorking_{false};
std::shared_ptr<AppExecFwk::EventHandler> unloadHandler_{};
std::unordered_map<uint32_t, std::string> clients_{};
std::unordered_map<std::string, AlgoPtr> algorithms_{};
// Guarded by lock_ end
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VPE_VIDEO_PROCESSING_SERVER_H
#endif // VPE_VIDEO_PROCESSING_SERVER_H
-59
View File
@@ -1,59 +0,0 @@
/*
* Copyright (c) 2023-2024 Huawei Device 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 "event_handler_factory.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
const int HANDLER_NAME_MAX_LANEGTH = 4096;
EventHandlerFactory& EventHandlerFactory::GetInstance()
{
static EventHandlerFactory instance;
return instance;
}
int32_t EventHandlerFactory::Init()
{
VPE_LOGI("EventHandlerFactory Init!");
auto unloadRunner = AppExecFwk::EventRunner::Create("unload_vpe_sa_handler");
std::lock_guard<std::mutex> lock(eventHandlerMutex_);
eventHandlerMap_["unload_vpe_sa_handler"] = std::make_shared<AppExecFwk::EventHandler>(unloadRunner);
return ERR_OK;
}
int32_t EventHandlerFactory::UnInit()
{
VPE_LOGI("EventHandlerFactory UnInit");
std::lock_guard<std::mutex> lock(eventHandlerMutex_);
eventHandlerMap_.clear();
return ERR_OK;
}
std::shared_ptr<AppExecFwk::EventHandler> EventHandlerFactory::CreateEventHandler(const std::string& handlerName)
{
if (handlerName.empty() || handlerName.size() > HANDLER_NAME_MAX_LANEGTH) {
VPE_LOGE("handlerName is invalid!");
return nullptr;
}
VPE_LOGI("createEventHandler, handlerName: %{public}s", handlerName.c_str());
std::lock_guard<std::mutex> lock(eventHandlerMutex_);
return eventHandlerMap_[handlerName];
}
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
-63
View File
@@ -1,63 +0,0 @@
/*
* Copyright (c) 2022-2024 Huawei Device 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 "surface_buffer_info.h"
#include "message_parcel.h"
#include "vpe_log.h"
namespace OHOS {
bool SurfaceBufferInfo::ReadFromParcel(Parcel &parcel)
{
auto messageParcel = static_cast<MessageParcel*>(&parcel);
if (surfacebuffer == nullptr) {
VPE_LOGE("surfacebuffer is null!");
return false;
}
auto status = surfacebuffer->ReadFromMessageParcel(*messageParcel);
if (status != GSERROR_OK) {
return false;
}
if (surfacebuffer == nullptr) {
return false;
}
return true;
}
bool SurfaceBufferInfo::Marshalling(Parcel &parcel) const
{
auto messageParcel = static_cast<MessageParcel*>(&parcel);
auto status = surfacebuffer->WriteToMessageParcel(*messageParcel);
if (status != GSERROR_OK) {
return false;
}
return true;
}
SurfaceBufferInfo *SurfaceBufferInfo::Unmarshalling(Parcel &parcel)
{
SurfaceBufferInfo *info = new (std::nothrow) SurfaceBufferInfo();
if (info == nullptr) {
return nullptr;
}
info->surfacebuffer = SurfaceBuffer::Create();
if (!info->ReadFromParcel(parcel)) {
delete info;
return nullptr;
}
return info;
}
} // namespace OHOS
+201 -47
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -15,24 +15,21 @@
#include "video_processing_client.h"
#include <mutex>
#include "video_processing_service_manager_proxy.h"
#include "iservice_registry.h"
#include "surface_buffer.h"
#include "event_handler.h"
#include "event_runner.h"
#include "video_processing_load_callback.h"
#include "vpe_log.h"
#include "vpe_sa_constants.h"
using namespace OHOS::Media::VideoProcessingEngine;
using namespace OHOS;
using namespace std::chrono_literals;
using namespace std::placeholders;
using VpeSa = IVideoProcessingServiceManager;
namespace OHOS { class IRemoteObject; }
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
namespace {
std::mutex g_proxyLock;
const int32_t VIDEO_PROCESSING_SERVER_SA_ID = 0x00010256;
const int LOADSA_TIMEOUT_MS = 1000;
constexpr int ERROR_DEAD_REPLY = 29189;
constexpr int DEAD_RETRY_COUNT = 5;
}
VideoProcessingManager& VideoProcessingManager::GetInstance()
@@ -43,34 +40,8 @@ VideoProcessingManager& VideoProcessingManager::GetInstance()
void VideoProcessingManager::Connect()
{
std::unique_lock<std::mutex> lock(g_proxyLock);
g_proxy = nullptr;
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
CHECK_AND_RETURN_LOG(samgr != nullptr, "GetSystemAbilityManager return null");
VPE_LOGD("GetSystemAbilityManager return is not null, success");
auto object = samgr->CheckSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID);
if (object != nullptr) {
VPE_LOGD("object is not null, get service succeed");
g_proxy = iface_cast<IVideoProcessingServiceManager>(object);
return;
}
VPE_LOGD("object is null, Start load SA");
sptr<VideoProcessingLoadCallback> loadCallback = new VideoProcessingLoadCallback();
CHECK_AND_RETURN_LOG(loadCallback != nullptr, "New VideoProcessingLoadCallback fail!");
int32_t ret = samgr->LoadSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID, loadCallback);
CHECK_AND_RETURN_LOG(ret == ERR_OK, "LoadSystemAbility %{public}d failed!", VIDEO_PROCESSING_SERVER_SA_ID);
VPE_LOGD("VideoProcessingService SA load start!");
auto waitStatus = g_proxyConVar.wait_for(lock, std::chrono::milliseconds(LOADSA_TIMEOUT_MS),
[this]() { return g_proxy != nullptr; });
VPE_LOGD("VideoProcessingService SA load end!");
if (!waitStatus) {
VPE_LOGE("VideoProcessingService SA load timeout!");
return;
}
if (waitStatus && g_proxy != nullptr) {
VPE_LOGI("Load VideoProcessingService success");
}
return;
VPE_LOGD("call GetService");
GetService();
}
void VideoProcessingManager::Disconnect()
@@ -82,8 +53,7 @@ void VideoProcessingManager::Disconnect()
ErrCode VideoProcessingManager::LoadInfo(int32_t key, SurfaceBufferInfo& bufferInfo)
{
std::lock_guard<std::mutex> lock(g_proxyLock);
CHECK_AND_RETURN_RET_LOG(g_proxy != nullptr, ERR_NULL_OBJECT, "LoadInfo: g_proxy is nullptr!");
return g_proxy->LoadInfo(key, bufferInfo);
return Execute([&key, &bufferInfo](sptr<VpeSa>& proxy) { return proxy->LoadInfo(key, bufferInfo); }, VPE_LOG_INFO);
}
void VideoProcessingManager::LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
@@ -92,8 +62,8 @@ void VideoProcessingManager::LoadSystemAbilitySuccess(const sptr<IRemoteObject>
std::unique_lock<std::mutex> lock(g_proxyLock);
if (remoteObject != nullptr) {
VPE_LOGD("remoteObject is not null.");
g_proxy = iface_cast<IVideoProcessingServiceManager>(remoteObject);
g_proxyConVar.notify_one();
proxy_ = iface_cast<IVideoProcessingServiceManager>(remoteObject);
cvProxy_.notify_one();
}
}
@@ -101,8 +71,192 @@ void VideoProcessingManager::LoadSystemAbilityFail()
{
VPE_LOGE("Get VideoProcessingService SA failed!");
std::unique_lock<std::mutex> lock(g_proxyLock);
g_proxy = nullptr;
proxy_ = nullptr;
}
VPEAlgoErrCode VideoProcessingManager::Create(const std::string& feature, const std::string& clientName,
uint32_t& clientID)
{
int id;
auto ret = Execute(std::bind(&VpeSa::Create, _1, feature, clientName, std::ref(id)), VPE_LOG_INFO);
if (ret == ERR_NONE) {
clientID = static_cast<uint32_t>(id);
VPE_LOGD("feature:%{public}s client:%{public}s -> ID:%{public}d", feature.c_str(), clientName.c_str(), id);
} else {
VPE_LOGE("feature:%{public}s client:%{public}s failed! ret:%{public}d", feature.c_str(), clientName.c_str(),
ret);
}
return ret;
}
VPEAlgoErrCode VideoProcessingManager::Destroy(uint32_t clientID)
{
return Execute(std::bind(&VpeSa::Destroy, _1, clientID), VPE_LOG_INFO);
}
VPEAlgoErrCode VideoProcessingManager::SetParameter(uint32_t clientID, int32_t tag,
const std::vector<uint8_t>& parameter)
{
return Execute(std::bind(&VpeSa::SetParameter, _1, clientID, tag, parameter), VPE_LOG_INFO);
}
VPEAlgoErrCode VideoProcessingManager::SetParameter(uint32_t clientID, int32_t tag)
{
std::vector<uint8_t> param;
return SetParameter(clientID, tag, param);
}
VPEAlgoErrCode VideoProcessingManager::GetParameter(uint32_t clientID, int32_t tag, std::vector<uint8_t>& parameter)
{
return Execute(std::bind(&VpeSa::GetParameter, _1, clientID, tag, parameter), VPE_LOG_INFO);
}
VPEAlgoErrCode VideoProcessingManager::UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image)
{
return Execute(std::bind(&VpeSa::UpdateMetadata, _1, clientID, image), VPE_LOG_INFO);
}
VPEAlgoErrCode VideoProcessingManager::Process(uint32_t clientID, const SurfaceBufferInfo& input,
SurfaceBufferInfo& output)
{
return Execute(std::bind(&VpeSa::Process, _1, clientID, input, output), VPE_LOG_INFO);
}
VPEAlgoErrCode VideoProcessingManager::ComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy)
{
return Execute(std::bind(&VpeSa::ComposeImage, _1, clientID, inputSdrImage, inputGainmap, outputHdrImage, legacy),
VPE_LOG_INFO);
}
VPEAlgoErrCode VideoProcessingManager::DecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap)
{
return Execute(std::bind(&VpeSa::DecomposeImage, _1, clientID, inputImage, outputSdrImage, outputGainmap),
VPE_LOG_INFO);
}
sptr<IVideoProcessingServiceManager> VideoProcessingManager::GetService()
{
do {
std::lock_guard<std::mutex> lock(lock_);
if (proxy_ != nullptr) {
if (proxy_->AsObject() != nullptr && !proxy_->AsObject()->IsObjectDead()) [[likely]] {
return proxy_;
}
VPE_LOGD("SA remote died.");
ClearSaLocked();
}
if (isLoading_.load()) {
VPE_LOGD("SA is loading, so wait for the result directly .");
break;
}
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "Failed to GetSystemAbilityManager!");
VPE_LOGD("Try to check VPE SA.");
auto object = samgr->CheckSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID);
if (object != nullptr) {
proxy_ = iface_cast<IVideoProcessingServiceManager>(object);
VPE_LOGD("SA is already start");
return proxy_;
}
sptr<LoadCallback> loadCallback = new(std::nothrow) LoadCallback(
std::bind(&VideoProcessingManager::OnSaLoad, this, _1),
std::bind(&VideoProcessingManager::OnSaLoad, this, nullptr));
CHECK_AND_RETURN_RET_LOG(loadCallback != nullptr, nullptr, "Failed to create LoadCallback!");
VPE_LOGD("Loading VPE SA...");
CHECK_AND_RETURN_RET_LOG(samgr->LoadSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID, loadCallback) == ERR_OK,
nullptr, "Failed to load VPE SA!");
isLoading_ = true;
} while (false);
std::unique_lock lock(lock_);
CHECK_AND_RETURN_RET_LOG(cvProxy_.wait_for(lock, 1s, [this] { return !isLoading_.load(); }), nullptr,
"load SA timeout!");
if (proxy_ != nullptr) {
VPE_LOGD("Finish loading VPE SA success.");
} else {
VPE_LOGE("Finish loading VPE SA fail!");
}
return proxy_;
}
void VideoProcessingManager::OnSaLoad(const sptr<IRemoteObject>& remoteObject)
{
{
std::lock_guard<std::mutex> lock(lock_);
if (remoteObject != nullptr) {
sptr<DeathObserver> observer = new(std::nothrow) DeathObserver(
std::bind(&VideoProcessingManager::OnSaDied, this, _1));
CHECK_AND_RETURN_LOG(observer != nullptr, "Failed to create DeathObserver!");
CHECK_AND_RETURN_LOG(remoteObject->AddDeathRecipient(observer), "Failed to AddDeathRecipient!");
VPE_LOGD("AddDeathRecipient success.");
proxy_ = iface_cast<IVideoProcessingServiceManager>(remoteObject);
VPE_LOGI("SA load success.");
} else {
proxy_ = nullptr;
VPE_LOGE("SA load fail!");
}
isLoading_ = false;
}
cvProxy_.notify_all();
}
void VideoProcessingManager::OnSaDied([[maybe_unused]] const wptr<IRemoteObject>& remoteObject)
{
std::lock_guard<std::mutex> lock(lock_);
proxy_ = nullptr;
}
VPEAlgoErrCode VideoProcessingManager::Execute(
std::function<ErrCode(sptr<IVideoProcessingServiceManager>&)>&& operation, const LogInfo& logInfo)
{
auto proxy = GetService();
if (proxy == nullptr) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "proxy is null!");
return VPE_ALGO_ERR_INVALID_STATE;
}
auto err = static_cast<VPEAlgoErrCode>(operation(proxy));
if (err == ERROR_DEAD_REPLY) {
ClearSa();
if (deadRetryCount_.load() < DEAD_RETRY_COUNT) {
deadRetryCount_++;
VPE_ORG_LOGD(logInfo, "<%{public}d> Retry to check SA again for dead reply.", deadRetryCount_.load());
return Execute(std::move(operation), logInfo);
}
} else {
deadRetryCount_.store(0);
}
return err;
}
void VideoProcessingManager::ClearSa()
{
std::lock_guard<std::mutex> lock(lock_);
ClearSaLocked();
}
void VideoProcessingManager::ClearSaLocked()
{
proxy_ = nullptr;
isLoading_ = false;
}
void VideoProcessingManager::LoadCallback::OnLoadSystemAbilitySuccess([[maybe_unused]] int32_t systemAbilityId,
const sptr<IRemoteObject>& remoteObject)
{
onSuccess_(remoteObject);
}
void VideoProcessingManager::LoadCallback::OnLoadSystemAbilityFail([[maybe_unused]] int32_t systemAbilityId)
{
onFail_();
}
void VideoProcessingManager::DeathObserver::OnRemoteDied(const wptr<IRemoteObject>& remoteObject)
{
onRemoteDied_(remoteObject);
}
+239 -95
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -18,90 +18,42 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <iremote_object.h>
#include <iservice_registry.h>
#include <system_ability_definition.h>
#include "algorithm_errors.h"
#include "surface_buffer.h"
#include "event_handler_factory.h"
#include "vpe_log.h"
#include "vpe_model_path.h"
#include "vpe_sa_constants.h"
using namespace OHOS::Media::VideoProcessingEngine;
using namespace OHOS;
using namespace std::placeholders;
using VpeAlgo = IVideoProcessingAlgorithm;
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
namespace {
const int VPE_INFO_FILE_MAX_LENGTH = 20485760;
const int32_t VIDEO_PROCESSING_SERVER_SA_ID = 0x00010256;
const std::string UNLOAD_TASK_ID = "unload_vpe_svr";
constexpr int32_t DELAY_TIME = 180000;
REGISTER_SYSTEM_ABILITY_BY_ID(VideoProcessingServer, VIDEO_PROCESSING_SERVER_SA_ID, false);
const int VPE_INFO_FILE_MAX_LENGTH = 20485760;
const std::string UNLOAD_HANLDER = "unload_vpe_sa_handler";
const std::string UNLOAD_TASK_ID = "unload_vpe_sa";
constexpr int32_t DELAY_TIME = 180000;
REGISTER_SYSTEM_ABILITY_BY_ID(VideoProcessingServer, VIDEO_PROCESSING_SERVER_SA_ID, false);
}
VideoProcessingServer::VideoProcessingServer(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate)
{
VPE_LOGD("VideoProcessingServer construct!");
}
VideoProcessingServer::~VideoProcessingServer()
{
VPE_LOGD("VideoProcessingServer destruction!");
UnInit();
}
int32_t VideoProcessingServer::Init()
{
VPE_LOGD("VideoProcessingServer init begin");
if (EventHandlerFactory::GetInstance().Init() != ERR_NONE) {
VPE_LOGE("EventHandlerFactory init failed");
return ERR_NULL_OBJECT;
}
VPE_LOGD("VideoProcessingServer init finish");
return ERR_NONE;
}
bool VideoProcessingServer::IsInited()
{
return isInited_;
}
int32_t VideoProcessingServer::UnInit()
{
isInited_ = false;
if (EventHandlerFactory::GetInstance().UnInit() != ERR_NONE) {
VPE_LOGE("EventHandlerFactory UnInit failed");
return ERR_NULL_OBJECT;
}
VPE_LOGD("VideoProcessingServer uninit succeeded");
return ERR_NONE;
}
int32_t VideoProcessingServer::CreateUnloadHandler()
{
std::lock_guard<std::mutex> lock(unloadMutex_);
if (unloadHandler_ == nullptr) {
unloadHandler_ = EventHandlerFactory::GetInstance().CreateEventHandler("unload_vpe_sa_handler");
}
if (unloadHandler_ == nullptr) {
VPE_LOGE("UnloadHandler is nullptr!");
return ERR_NULL_OBJECT;
}
return ERR_NONE;
}
int32_t VideoProcessingServer::DestroyUnloadHandler()
{
std::lock_guard<std::mutex> lock(unloadMutex_);
if (unloadHandler_ == nullptr) {
VPE_LOGE("UnloadHandler is nullptr!");
return ERR_NULL_OBJECT;
}
unloadHandler_->RemoveTask(UNLOAD_TASK_ID);
unloadHandler_ = nullptr;
return ERR_NONE;
}
ErrCode VideoProcessingServer::LoadInfo(int32_t key, SurfaceBufferInfo& bufferInfo)
{
if (key < 0 || key >= VPEMODEL_PATHS_LENGTH) {
if (key < 0 || key >= VPE_MODEL_KEY_NUM) {
VPE_LOGE("Input key %{public}d is invalid!", key);
UnloadVideoProcessingSA();
return ERR_INVALID_DATA;
@@ -149,9 +101,75 @@ ErrCode VideoProcessingServer::LoadInfo(int32_t key, SurfaceBufferInfo& bufferIn
return ERR_NONE;
}
// For optimized SA
ErrCode VideoProcessingServer::Create(const std::string& feature, const std::string& clientName, int32_t& clientID)
{
VPE_LOGD(">>> feature:%{public}s client:%{public}s", feature.c_str(), clientName.c_str());
uint32_t id;
std::lock_guard<std::mutex> lock(lock_);
auto ret = CreateLocked(feature, clientName, id);
if (ret == VPE_ALGO_ERR_OK) {
clientID = static_cast<int>(id);
VPE_LOGD("<<< feature:%{public}s client:%{public}s isWorking_:%{public}d {new ID:%{public}u}",
feature.c_str(), clientName.c_str(), isWorking_.load(), id);
}
DelayUnloadTaskLocked();
return ret;
}
ErrCode VideoProcessingServer::Destroy(int32_t clientID)
{
std::lock_guard<std::mutex> lock(lock_);
auto ret = DestroyLocked(static_cast<uint32_t>(clientID));
DelayUnloadTaskLocked();
return ret;
}
ErrCode VideoProcessingServer::SetParameter(int32_t clientID, int32_t tag, const std::vector<uint8_t>& parameter)
{
return Execute(clientID, std::bind(&VpeAlgo::SetParameter, _1, _2, tag, parameter), VPE_LOG_INFO);
}
ErrCode VideoProcessingServer::GetParameter(int32_t clientID, int32_t tag, std::vector<uint8_t>& parameter)
{
return Execute(clientID, std::bind(&VpeAlgo::GetParameter, _1, _2, tag, parameter), VPE_LOG_INFO);
}
ErrCode VideoProcessingServer::UpdateMetadata(int32_t clientID, SurfaceBufferInfo& image)
{
CHECK_AND_RETURN_RET_LOG(image.surfacebuffer != nullptr, VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: image is null!");
return Execute(clientID, std::bind(&VpeAlgo::UpdateMetadata, _1, _2, image), VPE_LOG_INFO);
}
ErrCode VideoProcessingServer::Process(int32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output)
{
CHECK_AND_RETURN_RET_LOG(input.surfacebuffer != nullptr && output.surfacebuffer != nullptr,
VPE_ALGO_ERR_INVALID_PARAM, "Invalid input: input or output is null!");
return Execute(clientID, std::bind(&VpeAlgo::Process, _1, _2, input, output), VPE_LOG_INFO);
}
ErrCode VideoProcessingServer::ComposeImage(int32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy)
{
CHECK_AND_RETURN_RET_LOG(inputSdrImage.surfacebuffer != nullptr && inputGainmap.surfacebuffer != nullptr &&
outputHdrImage.surfacebuffer != nullptr, VPE_ALGO_ERR_INVALID_PARAM, "Invalid input: input or output is null!");
return Execute(clientID,
std::bind(&VpeAlgo::ComposeImage, _1, _2, inputSdrImage, inputGainmap, outputHdrImage, legacy), VPE_LOG_INFO);
}
ErrCode VideoProcessingServer::DecomposeImage(int32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap)
{
CHECK_AND_RETURN_RET_LOG(inputImage.surfacebuffer != nullptr && outputSdrImage.surfacebuffer != nullptr &&
outputGainmap.surfacebuffer != nullptr, VPE_ALGO_ERR_INVALID_PARAM, "Invalid input: input or output is null!");
return Execute(clientID,
std::bind(&VpeAlgo::DecomposeImage, _1, _2, inputImage, outputSdrImage, outputGainmap), VPE_LOG_INFO);
}
void VideoProcessingServer::UnloadVideoProcessingSA()
{
if (CreateUnloadHandler() == ERR_NONE) {
if (CreateUnloadHandler()) {
VPE_LOGI("CreateUnloadHandler success!");
DelayUnloadTask();
} else {
@@ -161,44 +179,170 @@ void VideoProcessingServer::UnloadVideoProcessingSA()
return;
}
void VideoProcessingServer::OnStart(const SystemAbilityOnDemandReason& startReason)
{
VPE_LOGD("Start VPE SA because %{public}s.", startReason.GetName().c_str());
if (CreateUnloadHandler()) {
VPE_LOGI("CreateUnloadHandler success!");
DelayUnloadTask();
}
CHECK_AND_RETURN_LOG(Publish(this), "Failed to publish SA!");
}
void VideoProcessingServer::OnStop(const SystemAbilityOnDemandReason& stopReason)
{
VPE_LOGD("Stop VPE SA because %{public}s.", stopReason.GetName().c_str());
DestroyUnloadHandler();
ClearAlgorithms();
}
ErrCode VideoProcessingServer::CreateLocked(const std::string& feature, const std::string& clientName, uint32_t& id)
{
AlgoPtr algo = nullptr;
bool isNew = false;
auto it = algorithms_.find(feature);
if (it == algorithms_.end() || it->second == nullptr) {
algo = factory_.Create(feature);
CHECK_AND_RETURN_RET_LOG(algo != nullptr, VPE_ALGO_ERR_NO_MEMORY,
"Failed to create '%{public}s' for '%{public}s'!", feature.c_str(), clientName.c_str());
CHECK_AND_RETURN_RET_LOG(algo->Initialize() == VPE_ALGO_ERR_OK, ERR_INVALID_STATE,
"Failed to initialize '%{public}s' for '%{public}s'!", feature.c_str(), clientName.c_str());
isNew = true;
} else {
algo = it->second;
}
CHECK_AND_RETURN_RET_LOG(algo->Add(clientName, id) == VPE_ALGO_ERR_OK, ERR_INVALID_DATA,
"Failed to add client to '%{public}s' for '%{public}s'!", feature.c_str(), clientName.c_str());
clients_[id] = feature;
if (isNew) {
algorithms_[feature] = algo;
}
isWorking_ = true;
return VPE_ALGO_ERR_OK;
}
ErrCode VideoProcessingServer::DestroyLocked(uint32_t id)
{
auto it = clients_.find(id);
if (it == clients_.end()) [[unlikely]] {
VPE_LOGE("Invalid input: no client for ID=%{public}d", id);
return VPE_ALGO_ERR_INVALID_CLIENT_ID;
}
std::string feature = it->second;
clients_.erase(it);
isWorking_ = !clients_.empty();
VPE_LOGD("isWorking_:%{public}d", isWorking_.load());
auto itAlgo = algorithms_.find(feature);
if (itAlgo == algorithms_.end()) [[unlikely]] {
VPE_LOGE("Invalid input: no '%{public}s' for ID=%{public}d", feature.c_str(), id);
return VPE_ALGO_ERR_INVALID_VAL;
}
if (itAlgo->second == nullptr) [[unlikely]] {
VPE_LOGE("Invalid input: null '%{public}s' for ID=%{public}d", feature.c_str(), id);
algorithms_.erase(itAlgo);
return VPE_ALGO_ERR_INVALID_VAL;
}
auto algo = itAlgo->second;
auto ret = algo->Del(id);
CHECK_AND_LOG(ret == VPE_ALGO_ERR_OK, "Failed to del(ID=%{public}d) of '%{public}s'", id, feature.c_str());
if (!algo->HasClient()) {
ret = algo->Deinitialize();
CHECK_AND_LOG(ret == VPE_ALGO_ERR_OK, "Failed to deinitialize of '%{public}s' for ID=%{public}d",
feature.c_str(), id);
algorithms_.erase(itAlgo);
}
return ret;
}
bool VideoProcessingServer::CreateUnloadHandler()
{
std::lock_guard<std::mutex> lock(lock_);
return CreateUnloadHandlerLocked();
}
bool VideoProcessingServer::CreateUnloadHandlerLocked()
{
if (unloadHandler_ != nullptr) {
return true;
}
unloadHandler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::Create(UNLOAD_HANLDER));
return unloadHandler_ != nullptr;
}
void VideoProcessingServer::DestroyUnloadHandler()
{
std::lock_guard<std::mutex> lock(lock_);
if (unloadHandler_ != nullptr) {
unloadHandler_->RemoveAllEvents();
unloadHandler_->RemoveTask(UNLOAD_TASK_ID);
unloadHandler_ = nullptr;
}
}
void VideoProcessingServer::DelayUnloadTask()
{
VPE_LOGD("delay unload task begin");
auto task = []() {
VPE_LOGD("do unload task");
auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (samgrProxy == nullptr) {
VPE_LOGE("get samgr failed");
return;
}
int32_t unloadResult = samgrProxy->UnloadSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID);
if (unloadResult != ERR_OK) {
VPE_LOGE("remove system ability failed");
return;
}
std::lock_guard<std::mutex> lock(lock_);
DelayUnloadTaskLocked();
}
void VideoProcessingServer::DelayUnloadTaskLocked()
{
VPE_LOGD("delay unload task begin, isWorking_:%{public}d", isWorking_.load());
CHECK_AND_RETURN_LOG(CreateUnloadHandlerLocked(), "unloadHandler_ is NOT created!");
unloadHandler_->RemoveTask(UNLOAD_TASK_ID);
VPE_LOGD("delay unload task post task(wait %{public}dms)", DELAY_TIME);
auto task = [this]() {
VPE_LOGD("do unload task, isWorking_:%{public}d", isWorking_.load());
auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
CHECK_AND_RETURN_LOG(samgr != nullptr, "Failed to GetSystemAbilityManager!");
CHECK_AND_RETURN_LOG(samgr->UnloadSystemAbility(VIDEO_PROCESSING_SERVER_SA_ID) == ERR_OK,
"Failed to unload VPE SA!");
VPE_LOGI("kill VPE service success!");
};
unloadHandler_->RemoveTask(UNLOAD_TASK_ID);
VPE_LOGD("delay unload task post task");
unloadHandler_->PostTask(task, UNLOAD_TASK_ID, DELAY_TIME);
}
void VideoProcessingServer::OnStart()
void VideoProcessingServer::ClearAlgorithms()
{
VPE_LOGD("VPE SA Onstart!");
Init();
Publish(this);
std::lock_guard<std::mutex> lock(lock_);
for (auto& [feature, algo] : algorithms_) {
if (algo == nullptr) [[unlikely]] {
VPE_LOGE("algorithm is null of '%{public}s'!", feature.c_str());
continue;
}
if (algo->Deinitialize() != VPE_ALGO_ERR_OK) [[unlikely]] {
VPE_LOGE("Failed to deinitialize of '%{public}s'!", feature.c_str());
continue;
}
}
algorithms_.clear();
clients_.clear();
isWorking_ = false;
VPE_LOGD("isWorking_:%{public}d", isWorking_.load());
}
void VideoProcessingServer::OnStop()
ErrCode VideoProcessingServer::Execute(int clientID, std::function<int(AlgoPtr&, uint32_t)>&& operation,
const LogInfo& logInfo)
{
VPE_LOGD("VPE SA Onstop!");
DestroyUnloadHandler();
if (UnInit() != ERR_NONE) {
VPE_LOGE("Uninit failed");
return;
uint32_t id = static_cast<uint32_t>(clientID);
AlgoPtr algorithm;
{
std::lock_guard<std::mutex> lock(lock_);
auto it = clients_.find(id);
if (it == clients_.end()) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: no client for ID=%{public}d!", id);
DelayUnloadTaskLocked();
return VPE_ALGO_ERR_INVALID_CLIENT_ID;
}
auto itAlgo = algorithms_.find(it->second);
if (itAlgo == algorithms_.end() || itAlgo->second == nullptr) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: no '%{public}s' for ID=%{public}d!", it->second.c_str(), id);
DelayUnloadTaskLocked();
return VPE_ALGO_ERR_INVALID_VAL;
}
algorithm = itAlgo->second;
}
auto err = operation(algorithm, id);
DelayUnloadTask();
return err;
}
}
}
}
+190
View File
@@ -0,0 +1,190 @@
/*
* Copyright (c) 2025 Huawei Device 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 "configuration_helper.h"
#include <functional>
#include <securec.h>
#include <unistd.h>
#include "vpe_log.h"
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
inline const std::string GetElementInfo(const xmlNode& parent, const std::string& tag,
std::function<const std::string(const xmlNode&)>&& getter)
{
const xmlNode* node = parent.children;
CHECK_AND_RETURN_RET_LOG(node != nullptr, "", "No children when finding <%{public}s>!", tag.c_str());
CHECK_AND_RETURN_RET_LOG(xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>(tag.c_str())) == 0, "",
"Element <%{public}s> is not found!", tag.c_str());
return getter(*node);
}
inline const xmlNode* GetElement(const xmlNode& parent, const std::string& tag,
std::function<bool(const xmlNode&)>&& checker, const std::string& notFoundLog)
{
for (const xmlNode* node = parent.children; node != nullptr; node = node->next) {
if (xmlStrcmp(node->name, reinterpret_cast<const xmlChar*>(tag.c_str())) != 0) {
continue;
}
if (checker(*node)) {
return node;
}
}
VPE_LOGW("%{public}s is NOT found!", notFoundLog.c_str());
return nullptr;
}
}
bool ConfigurationHelper::LoadConfigurationFromXml(const std::string& xmlFilePath)
{
if (access(xmlFilePath.c_str(), R_OK) != 0) [[unlikely]] {
VPE_LOGW("Invalid input: %{public}s is NOT exist!", xmlFilePath.c_str());
return false;
}
xmlDocPtr doc = xmlParseFile(xmlFilePath.c_str());
if (doc == nullptr) [[unlikely]] {
VPE_LOGW("Failed to parse %{public}s!", xmlFilePath.c_str());
return false;
}
xmlNode* root = xmlDocGetRootElement(doc);
if (root == nullptr) [[unlikely]] {
VPE_LOGW("Failed to parse %{public}s: there is no root element!", xmlFilePath.c_str());
xmlFreeDoc(doc);
return false;
}
auto ret = ParseXml(*root);
if (!ret) {
VPE_LOGW("Failed to parse %{public}s: Content is invalid!", xmlFilePath.c_str());
}
xmlFreeDoc(doc);
return ret;
}
bool ConfigurationHelper::ParseXml([[maybe_unused]] const xmlNode& root)
{
return true;
}
const xmlNode* ConfigurationHelper::GetElement(const xmlNode& parent, const std::string& tag) const
{
return ::GetElement(parent, tag, [](const xmlNode&) { return true; }, "<" + tag + ">");
}
const xmlNode* ConfigurationHelper::GetElementByName(const xmlNode& parent,
const std::string& tag, const std::string& name) const
{
return ::GetElement(parent, tag, [&tag, &name](const xmlNode& node) {
const xmlChar* nameText = xmlGetProp(&node, reinterpret_cast<const xmlChar*>("name"));
if (nameText == nullptr) {
VPE_LOGD("name of <%{public}s> is null!", tag.c_str());
return false;
}
return name.compare(reinterpret_cast<const char*>(nameText)) == 0;
}, "<" + tag + " name=\"" + name + "\">");
}
const std::string ConfigurationHelper::GetElementName(const xmlNode& parent, const std::string& tag) const
{
return GetElementInfo(parent, tag, [this](const xmlNode& node) { return GetElementName(node); });
}
const std::string ConfigurationHelper::GetElementName(const xmlNode& myself) const
{
const char* nameText = reinterpret_cast<char*>(xmlGetProp(&myself, reinterpret_cast<const xmlChar*>("name")));
CHECK_AND_RETURN_RET_LOG(nameText != nullptr, "", "name of <%{public}s> is null!", myself.name);
return std::string(nameText);
}
const std::string ConfigurationHelper::GetElementText(const xmlNode& parent, const std::string& tag) const
{
return GetElementInfo(parent, tag, [this](const xmlNode& node) { return GetElementText(node); });
}
const std::string ConfigurationHelper::GetElementText(const xmlNode& myself) const
{
const char* text = reinterpret_cast<char*>(xmlNodeGetContent(&myself));
CHECK_AND_RETURN_RET_LOG(text != nullptr, "", "Element <%{public}s> is empty!", myself.name);
return std::string(text);
}
bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, uint32_t& value) const
{
value = 0;
const std::string& text = GetElementText(parent, tag);
if (text.empty()) {
return false;
}
return sscanf_s(text.c_str(), "%u", &value) == 1;
}
bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, int& value) const
{
value = 0;
const std::string& text = GetElementText(parent, tag);
if (text.empty()) {
return false;
}
return sscanf_s(text.c_str(), "%d", &value) == 1;
}
bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, uint64_t& value) const
{
value = 0;
const std::string& text = GetElementText(parent, tag);
if (text.empty()) {
return false;
}
return sscanf_s(text.c_str(), "%lu", &value) == 1;
}
bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, bool& value) const
{
const std::string& text = GetElementText(parent, tag);
if (text.empty()) {
value = false;
return false;
}
value = (text.compare("true") == 0);
return true;
}
bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, float& value) const
{
value = 0;
const std::string& text = GetElementText(parent, tag);
if (text.empty()) {
return false;
}
return sscanf_s(text.c_str(), "%f", &value) == 1;
}
bool ConfigurationHelper::GetElementValue(const xmlNode& parent, const std::string& tag, std::string& value) const
{
value = GetElementText(parent, tag);
return !value.empty();
}
bool ConfigurationHelper::GetElementValue(const xmlNode& myself, std::string& value) const
{
value = GetElementText(myself);
return !value.empty();
}
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2025 Huawei Device 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 CONFIGURATION_HELPER_H
#define CONFIGURATION_HELPER_H
#include <cinttypes>
#include <string>
#include <libxml/parser.h>
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class ConfigurationHelper {
protected:
ConfigurationHelper() = default;
virtual ~ConfigurationHelper() = default;
ConfigurationHelper(const ConfigurationHelper&) = delete;
ConfigurationHelper& operator=(const ConfigurationHelper&) = delete;
ConfigurationHelper(ConfigurationHelper&&) = delete;
ConfigurationHelper& operator=(ConfigurationHelper&&) = delete;
bool LoadConfigurationFromXml(const std::string& xmlFilePath);
virtual bool ParseXml(const xmlNode& root);
const xmlNode* GetElement(const xmlNode& parent, const std::string& tag) const;
const xmlNode* GetElementByName(const xmlNode& parent, const std::string& tag, const std::string& name) const;
const std::string GetElementName(const xmlNode& parent, const std::string& tag) const;
const std::string GetElementName(const xmlNode& myself) const;
const std::string GetElementText(const xmlNode& parent, const std::string& tag) const;
const std::string GetElementText(const xmlNode& myself) const;
bool GetElementValue(const xmlNode& parent, const std::string& tag, uint32_t& value) const;
bool GetElementValue(const xmlNode& parent, const std::string& tag, int& value) const;
bool GetElementValue(const xmlNode& parent, const std::string& tag, uint64_t& value) const;
bool GetElementValue(const xmlNode& parent, const std::string& tag, bool& value) const;
bool GetElementValue(const xmlNode& parent, const std::string& tag, float& value) const;
bool GetElementValue(const xmlNode& parent, const std::string& tag, std::string& value) const;
bool GetElementValue(const xmlNode& myself, std::string& value) const;
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif /* CONFIGURATION_HELPER_H */
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -16,16 +16,31 @@
#ifndef SURFACE_BUFFER_INFO_H
#define SURFACE_BUFFER_INFO_H
#include <string>
#include "parcel.h"
#include "surface_buffer.h"
#include "vpe_sa_types.h"
namespace OHOS {
struct SurfaceBufferInfo : public Parcelable {
// Data
Media::VideoProcessingEngine::VideoInfo videoInfo;
sptr<SurfaceBuffer> surfacebuffer;
// Get rectangle string of the surface buffer
std::string rectStr() const;
// Get rectangle and id, index string of the surface buffer
std::string str() const;
// Copy all information except surface buffer
void CopyInfo(const SurfaceBufferInfo& input);
// For IPC transfer
bool ReadFromParcel(Parcel &parcel);
virtual bool Marshalling(Parcel &parcel) const override;
static SurfaceBufferInfo *Unmarshalling(Parcel &parcel);
};
} // namespace OHOS
#endif // SURFACE_BUFFER_INFO_H
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -13,27 +13,22 @@
* limitations under the License.
*/
#ifndef ALGORITHM_TYPES_H
#define ALGORITHM_TYPES_H
#ifndef VPE_SA_CONSTANTS_H
#define VPE_SA_CONSTANTS_H
#include <cstdint>
#include "algorithm_errors.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
enum AlgoErrorCode {
ALGO_SUCCESS,
ALGO_ERROR_INVALID_PARAMETER,
ALGO_ERROR_UNKNOWN,
ALGO_ERROR_INITIALIZE_FAILED,
ALGO_ERROR_CREATE_FAILED,
ALGO_ERROR_PROCESS_FAILED,
ALGO_ERROR_UNSUPPORTED_PROCESSING,
ALGO_ERROR_OPERATION_NOT_PERMITTED,
ALGO_ERROR_NO_MEMORY,
ALGO_ERROR_INVALID_INSTANCE,
ALGO_ERROR_INVALID_VALUE
constexpr int32_t VIDEO_PROCESSING_SERVER_SA_ID = 0x00010256;
enum VPEAlgoErrExCode : ErrCode {
VPE_ALGO_ERR_INVALID_CLIENT_ID = VPE_ALGO_ERR_EXTEND_START,
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // ALGORITHM_TYPES_H
#endif // VPE_SA_CONSTANTS_H
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2025 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -12,4 +12,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
FUZZ
#ifndef VPE_SA_TYPES_H
#define VPE_SA_TYPES_H
#include <cstdint>
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
struct VideoInfo {
uint64_t videoIndex;
uint64_t frameIndex;
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VPE_SA_TYPES_H
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 Huawei Device Co., Ltd.
* Copyright (c) 2025 Huawei Device 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
@@ -13,21 +13,20 @@
* limitations under the License.
*/
#ifndef VPE_TEST_YUV_VIEWER_H
#define VPE_TEST_YUV_VIEWER_H
#include "wm/window.h"
#include "surface/native_image.h"
#include "surface/native_buffer.h"
namespace OHOS {
class YuvViewer {
public:
~YuvViewer();
OHNativeWindow *CreateWindow(uint32_t width, uint32_t height,
OH_NativeBuffer_Format pix_fmt, OH_NativeBuffer_ColorSpace color_space, bool isHDRVivid);
#ifndef VPE_SA_UTILS_H
#define VPE_SA_UTILS_H
private:
sptr<Rosen::Window> rosenWindow_;
OHNativeWindow *window_ = nullptr;
#include <string>
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VpeSaUtils {
public:
static std::string GetProcessName();
};
}
#endif // VPE_TEST_YUV_VIEWER_H
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif /* VPE_SA_UTILS_H */
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2022-2025 Huawei Device 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 "surface_buffer_info.h"
#include "message_parcel.h"
#include "vpe_log.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
std::string SurfaceBufferInfo::rectStr() const
{
return surfacebuffer == nullptr ? "image=null" :
std::to_string(surfacebuffer->GetWidth()) + "(" + std::to_string(surfacebuffer->GetStride()) + ")x" +
std::to_string(surfacebuffer->GetHeight());
}
std::string SurfaceBufferInfo::str() const
{
return "buffer:{ id=" + std::to_string(videoInfo.videoIndex) + " idx=" + std::to_string(videoInfo.frameIndex) +
" " + rectStr() + " }";
}
void SurfaceBufferInfo::CopyInfo(const SurfaceBufferInfo& input)
{
// Copy information from input except SurfaceBuffer
videoInfo = input.videoInfo;
}
bool SurfaceBufferInfo::ReadFromParcel(Parcel &parcel)
{
CHECK_AND_RETURN_RET_LOG(surfacebuffer != nullptr, false, "surfacebuffer is null!");
return parcel.ReadUint64(videoInfo.videoIndex) && parcel.ReadUint64(videoInfo.frameIndex) &&
surfacebuffer->ReadFromMessageParcel(*static_cast<MessageParcel*>(&parcel)) == GSERROR_OK;
}
bool SurfaceBufferInfo::Marshalling(Parcel &parcel) const
{
CHECK_AND_RETURN_RET_LOG(surfacebuffer != nullptr, false, "surfacebuffer is null!");
return parcel.WriteUint64(videoInfo.videoIndex) && parcel.WriteUint64(videoInfo.frameIndex) &&
surfacebuffer->WriteToMessageParcel(*static_cast<MessageParcel*>(&parcel)) == GSERROR_OK;
}
SurfaceBufferInfo *SurfaceBufferInfo::Unmarshalling(Parcel &parcel)
{
SurfaceBufferInfo *info = new (std::nothrow) SurfaceBufferInfo();
if (info == nullptr) [[unlikely]] {
return nullptr;
}
info->surfacebuffer = SurfaceBuffer::Create();
if (!info->ReadFromParcel(parcel)) [[unlikely]] {
delete info;
return nullptr;
}
return info;
}
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2025 Huawei Device 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 "vpe_sa_utils.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "vpe_log.h"
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
constexpr uint32_t DEV_VALUE_SIZE = 256;
}
std::string VpeSaUtils::GetProcessName()
{
std::string pid = std::to_string(getpid());
std::string devPath = "/proc/" + pid + "/cmdline";
pid = "pid:" + pid;
int fd = open(devPath.c_str(), O_RDONLY);
if (fd < 0) [[unlikely]] {
VPE_LOGW("Failed to open %{public}s! %{public}s", devPath.c_str(), strerror(errno));
return pid;
}
std::string name;
char text[DEV_VALUE_SIZE]{};
if (read(fd, text, sizeof(text) - 1) <= 0) [[unlikely]] {
VPE_LOGW("Failed to read %{public}s! %{public}s", devPath.c_str(), strerror(errno));
name = pid;
} else [[likely]] {
// Video app may have several process like below, and we use "tv.danmaku.bili" as the app name,
// and trim the suffix after ":" such as ":ijkservice" and etc.
// tv.danmaku.bili
// tv.danmaku.bili:pushservice
// tv.danmaku.bili:ijkservice
// tv.danmaku.bili:download
name = text;
auto pos = name.find_first_of(':');
if (pos != std::string::npos) {
name = name.substr(0, pos);
}
}
close(fd);
return name;
}
+18
View File
@@ -28,6 +28,7 @@ declare_args() {
metadata_gen_video_ndk_unit_test = true
video_variable_refreshrate_unit_test = true
aihdr_enhancer_video_unit_test = true
service_unit_test = true
aihdr_enhancer_unit_test = true
}
@@ -48,6 +49,7 @@ if (defined(global_parts_info) &&
video_variable_refreshrate_unit_test = false
aihdr_enhancer_video_unit_test = false
aihdr_enhancer_unit_test = false
service_unit_test = false
}
group("demo_test") {
@@ -94,9 +96,15 @@ group("unit_test") {
if (aihdr_enhancer_video_unit_test) {
deps += [ "unittest/aihdr_enhancer_video:aihdr_enhancer_video_unit_test" ]
}
if (service_unit_test) {
deps += [ "unittest/service:services_test" ]
}
if (aihdr_enhancer_unit_test) {
deps += [ "unittest/aihdr_enhancer_video:aihdr_enhancer_video_unit_test" ]
}
if (contrast_enhancer_unit_test) {
deps += [ "unittest/contrast_enhancer:contrast_enhancer_unit_test" ]
}
}
group("module_test") {
@@ -111,3 +119,13 @@ group("module_test") {
]
}
}
group("fuzz_test") {
testonly = true
deps = []
if (services_fuzzer_test) {
deps += [
"fuzztest/services_fuzzer:ServicesFuzzTest",
]
}
}
@@ -1,52 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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.
*/
#####################hydra_fuzz######################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "video_processing_engine/fuzztest"
############################fuzztest#############################
ohos_fuzztest("ImagecomposeFuzzTest") {
module_output_path = module_output_path
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/iamgecompose_fuzzer"
include_dirs = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/../media_foundation/video_processing_engine/interface/kits/c"
]
include_dirs += [
"./"
]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"iamgecompose_fuzzer.cpp"
]
external_deps = [
"graphic_2d:libnative_color_space_manager",
"image_framework:pixelmap",
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_single",
"media_foundation:native_media_core",
"media_foundation:media_foundation",
"window_manager:libwm",
]
deps = [
"$FRAMEWORK_DIR:image_processing"
]
}
@@ -1,74 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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 "iamgecompose_fuzzer.h"
#include "image_processing.h"
#include "image/pixelmap_native.h"
#include "native_color_space_manager.h"
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
constexpr uint32_t DEFAULT_WIDTH = 3840;
constexpr uint32_t DEFAULT_HEIGHT = 2160;
static void CreatePixelmap(OH_PixelmapNative **pixelmap, int32_t width, int32_t height, int format,
OH_NativeColorSpaceManager *colorSpaceNative)
{
OH_Pixelmap_InintializationOptions *options = nullptr;
(void)OH_Pixelmap_InintializationOptions_Create(&options);
(void)OH_Pixelmap_InintializationOptions_SetWidth(options, width);
(void)OH_Pixelmap_InintializationOptions_SetHeight(options, height);
(void)OH_Pixelmap_InintializationOptions_SetPixelFormat(options, format);
(void)OH_PixelmapNative_CreateEmptyPixelmap(options, pixelmap);
(void)OH_PixelmapNative_SetColorSpaceNative(*pixelmap, colorSpaceNative);
}
bool DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)
{
OH_ImageProcessing* imageProcessor = nullptr;
OH_ImageProcessing_Create(&imageProcessor, IMAGE_PROCESSING_TYPE_COMPOSITION);
OH_NativeColorSpaceManager *srcColorSpace = OH_NativeColorSpaceManager_CreateForName(SRGB);
OH_NativeColorSpaceManager *dstColorSpace = OH_NativeColorSpaceManager_CreateForName(BT2020_PQ);
OH_PixelmapNative *srcPic = nullptr;
OH_PixelmapNative *srcGainmap = nullptr;
OH_PixelmapNative *dst = nullptr;
CreatePixelmap(&srcPic, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888, dstColorSpace);
CreatePixelmap(&srcGainmap, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888, srcColorSpace);
CreatePixelmap(&dst, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_1010102, dstColorSpace);
OH_PixelmapNative_WritePixels(srcPic, const_cast<unit8_t *>(data), size);
OH_PixelmapNative_WritePixels(srcGainmap, const_cast<unit8_t *>(data), size);
bool ret = OH_ImageProcessing_Compose(imageProcessor, srcPic, srcGainmap, dst);
OH_PixelmapNative_Release(srcPic);
OH_PixelmapNative_Release(srcGainmap);
OH_PixelmapNative_Release(dst);
OH_NativeColorSpaceManager_Destroy(srcColorSpace);
OH_NativeColorSpaceManager_Destroy(dstColorSpace);
OH_ImageProcessing_Destroy(imageProcessor);
return ret;
}
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::DoSomethingInterestingWithMyAPI(data, size);
return 0;
}
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2025 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>300</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>
@@ -1,48 +0,0 @@
# Copyright (c) 2025 Huawei Device 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.
#####################hydra-fuzz###################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "video_processing_engine/fuzztest"
##############################fuzztest##########################################
ohos_fuzztest("Imagesdr2hdrFuzzTest") {
module_out_path = module_output_path
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/imagesdr2hdr_fuzzer"
include_dirs = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/../media_foundation/video_processing_engine/interface/kits/c"
]
include_dirs += [ "./" ]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"imagesdr2hdr_fuzzer.cpp",
]
external_deps = [
"graphic_2d:libnative_color_space_manager",
"image_framework:pixcelmap",
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_single",
"media_foundation:native_media_core",
"media_foundation:media_foundation",
"window_manager:libwm",
]
deps = [
"$FRAMEWORK_DIR:image_processing"
]
}
@@ -1,202 +0,0 @@
/*
* Copyright (c) 2024 Huawei Device 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 "imagesdr2hdr_fuzzer.h"
#include "image_processing.h"
#include "image/pixelmap_native.h"
#include "native_color_space_manager.h"
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
using namespace OHOS;
using namespace OHOS::Media;
using namespace OHOS::MediaAVCodec;
using namespace OHOS::MediaAVCodec::Codec;
using namespace std;
namespace {
} // namespace
void VDecServerSample::CallBack::OnError(AVCodecErrorType errorType, int32_t errorCode)
{
cout << "--OnError--" << endl;
tester->isRunning_.store(false);
tester->signal_->inCond_.notify_all();
}
void VDecServerSample::CallBack::OnOutputFormatChanged(const Format &format)
{
tester->GetOutputFormat();
}
void VDecServerSample::CallBack::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
{
unique_lock<mutex> lock(tester->signal_->inMutex_);
tester->signal_->inIdxQueue_.push(index);
tester->signal_->inBufferQueue_.push(buffer);
tester->signal_->inCond_.notify_all();
}
void VDecServerSample::CallBack::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
{
tester->codec_->ReleaseOutputBuffer(index);
}
VDecServerSample::~VDecServerSample()
{
if (codec_ != nullptr) {
codec_->Stop();
codec_->Release();
}
if (signal_ != nullptr) {
delete signal_;
signal_ = nullptr;
}
}
int32_t VDecServerSample::ConfigServerDecoder()
{
Format fmt;
fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width);
fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height);
fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, 1);
fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate);
fmt.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, 0);
return codec_->Configure(fmt);
}
int32_t VDecServerSample::SetCallback()
{
shared_ptr<CallBack> cb = make_shared<CallBack>(this);
return codec_->SetCallback(cb);
}
void VDecServerSample::RunVideoServerDecoder()
{
codec_ = make_shared<FCodec>("OH.Media.Codec.Decoder.Video.AVC");
if (codec_ == nullptr) {
cout << "Create failed" << endl;
return;
}
int32_t err = ConfigServerDecoder();
if (err != AVCS_ERR_OK) {
cout << "ConfigServerDecoder failed" << endl;
return;
}
signal_ = new VDecSignal();
if (signal_ == nullptr) {
cout << "Failed to new VDecSignal" << endl;
return;
}
err = SetCallback();
if (err != AVCS_ERR_OK) {
cout << "SetCallback failed" << endl;
return;
}
err = codec_->Start();
if (err != AVCS_ERR_OK) {
cout << "Start failed" << endl;
return;
}
isRunning_.store(true);
inputLoop_ = make_unique<thread>(&VDecServerSample::InputFunc, this);
if (inputLoop_ == nullptr) {
cout << "Failed to create input loop" << endl;
isRunning_.store(false);
}
}
void VDecServerSample::InputFunc()
{
int32_t time = 1000;
while (sendFrameIndex < frameIndex) {
if (!isRunning_.load()) {
break;
}
unique_lock<mutex> lock(signal_->inMutex_);
signal_->inCond_.wait_for(lock, std::chrono::milliseconds(time), [this]() {
if (!isRunning_.load()) {
cout << "quit signal" << endl;
return true;
}
return signal_->inIdxQueue_.size() > 0;
});
if (!isRunning_.load() || signal_->inIdxQueue_.size() == 0) {
break;
}
uint32_t index = signal_->inIdxQueue_.front();
auto buffer = signal_->inBufferQueue_.front();
signal_->inIdxQueue_.pop();
signal_->inBufferQueue_.pop();
lock.unlock();
if (buffer->memory_ == nullptr) {
isRunning_.store(false);
break;
}
uint8_t *bufferAddr = buffer->memory_->GetAddr();
if (memcpy_s(bufferAddr, buffer->memory_->GetCapacity(), fuzzData, fuzzSize) != EOK) {
break;
}
int32_t err = codec_->QueueInputBuffer(index);
if (err != AVCS_ERR_OK) {
cout << "QueueInputBuffer fail" << endl;
break;
}
sendFrameIndex++;
}
}
void VDecServerSample::WaitForEos()
{
if (inputLoop_ && inputLoop_->joinable()) {
inputLoop_->join();
}
}
void VDecServerSample::GetOutputFormat()
{
Format fmt;
int32_t err = codec_->GetOutputFormat(fmt);
if (err != AVCS_ERR_OK) {
cout << "GetOutputFormat fail" << endl;
isRunning_.store(false);
signal_->inCond_.notify_all();
}
}
void VDecServerSample::Flush()
{
int32_t err = codec_->Flush();
if (err != AVCS_ERR_OK) {
cout << "Flush fail" << endl;
isRunning_.store(false);
signal_->inCond_.notify_all();
}
}
void VDecServerSample::Reset()
{
int32_t err = codec_->Reset();
if (err != AVCS_ERR_OK) {
cout << "Reset fail" << endl;
isRunning_.store(false);
signal_->inCond_.notify_all();
}
}
@@ -1,50 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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.
*/
#####################hydra_fuzz######################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "video_processing_engine/fuzztest"
############################fuzztest#############################
ohos_fuzztest("ImagedecomposeFuzzTest") {
module_output_path = module_output_path
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/imagedecompose_fuzzer"
include_dirs = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/../media_foundation/video_processing_engine/interface/kits/c"
]
include_dirs += [ "./" ]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"imagedecompose_fuzzer.cpp"
]
external_deps = [
"graphic_2d:libnative_color_space_manager",
"image_framework:pixelmap",
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_single",
"media_foundation:native_media_core",
"media_foundation:media_foundation",
"window_manager:libwm",
]
deps = [
"$FRAMEWORK_DIR:image_processing"
]
}
@@ -1,72 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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 "iamgedecompose_fuzzer.h"
#include "image_processing.h"
#include "image/pixelmap_native.h"
#include "native_color_space_manager.h"
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
constexpr uint32_t DEFAULT_WIDTH = 3840;
constexpr uint32_t DEFAULT_HEIGHT = 2160;
static void CreatePixelmap(OH_PixelmapNative **pixelmap, int32_t width, int32_t height, int format,
OH_NativeColorSpaceManager *colorSpaceNative)
{
OH_Pixelmap_InintializationOptions *options = nullptr;
(void)OH_Pixelmap_InintializationOptions_Create(&options);
(void)OH_Pixelmap_InintializationOptions_SetWidth(options, width);
(void)OH_Pixelmap_InintializationOptions_SetHeight(options, height);
(void)OH_Pixelmap_InintializationOptions_SetPixelFormat(options, format);
(void)OH_PixelmapNative_CreateEmptyPixelmap(options, pixelmap);
(void)OH_PixelmapNative_SetColorSpaceNative(*pixelmap, colorSpaceNative);
}
bool DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)
{
OH_ImageProcessing* imageProcessor = nullptr;
OH_ImageProcessing_Create(&imageProcessor, IMAGE_PROCESSING_TYPE_DECOMPOSITION);
OH_NativeColorSpaceManager *srcColorSpace = OH_NativeColorSpaceManager_CreateForName(BT2020_PQ);
OH_NativeColorSpaceManager *dstColorSpace = OH_NativeColorSpaceManager_CreateForName(SRGB);
OH_PixelmapNative *src = nullptr;
OH_PixelmapNative *dstPic = nullptr;
OH_PixelmapNative *dstGainmap = nullptr;
CreatePixelmap(&src, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_1010102, srcColorSpace);
CreatePixelmap(&dstPic, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888, dstColorSpace);
CreatePixelmap(&dstGainmap, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888, dstColorSpace);
OH_PixelmapNative_WritePixels(src, const_cast<unit8_t *>(data), size);
bool ret = OH_ImageProcessing_Decompose(imageProcessor, src, dstPic, dstGainmap);
OH_PixelmapNative_Release(src);
OH_PixelmapNative_Release(dstPic);
OH_PixelmapNative_Release(dstGainmap);
OH_NativeColorSpaceManager_Destroy(srcColorSpace);
OH_NativeColorSpaceManager_Destroy(dstColorSpace);
OH_ImageProcessing_Destroy(imageProcessor);
return ret;
}
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::DoSomethingInterestingWithMyAPI(data, size);
return 0;
}
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2025 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>300</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>
@@ -1,50 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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.
*/
#####################hydra_fuzz######################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "video_processing_engine/fuzztest"
############################fuzztest#############################
ohos_fuzztest("Imagehdr2sdrFuzzTest") {
module_output_path = module_output_path
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/imagehdr2sdr_fuzzer"
include_dirs = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/../media_foundation/video_processing_engine/interface/kits/c"
]
include_dirs += [ "./" ]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"imagehdr2sdr_fuzzer.cpp"
]
external_deps = [
"graphic_2d:libnative_color_space_manager",
"image_framework:pixelmap",
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_single",
"media_foundation:native_media_core",
"media_foundation:media_foundation",
"window_manager:libwm",
]
deps = [
"$FRAMEWORK_DIR:image_processing"
]
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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 "imagehdr2sdr_fuzzer.h"
#include "image_processing.h"
#include "image/pixelmap_native.h"
#include "native_color_space_manager.h"
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
constexpr uint32_t DEFAULT_WIDTH = 3840;
constexpr uint32_t DEFAULT_HEIGHT = 2160;
OH_ImageProcessing *imageProcessor = nullptr;
static void CreatePixelmap(OH_PixelmapNative **pixelmap, int32_t width, int32_t height, int format,
OH_NativeColorSpaceManager *colorSpaceNative)
{
OH_Pixelmap_InintializationOptions *options = nullptr;
(void)OH_Pixelmap_InintializationOptions_Create(&options);
(void)OH_Pixelmap_InintializationOptions_SetWidth(options, width);
(void)OH_Pixelmap_InintializationOptions_SetHeight(options, height);
(void)OH_Pixelmap_InintializationOptions_SetPixelFormat(options, format);
(void)OH_PixelmapNative_CreateEmptyPixelmap(options, pixelmap);
(void)OH_PixelmapNative_SetColorSpaceNative(*pixelmap, colorSpaceNative);
}
bool DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)
{
if (imageProcessor == nullptr) {
OH_ImageProcessing_Create(&imageProcessor, IMAGE_PROCESSING_TYPE_COLOR_SPACE_CONVERSION);
}
OH_NativeColorSpaceManager *srcColorSpace = OH_NativeColorSpaceManager_CreateForName(BT2020_PQ);
OH_NativeColorSpaceManager *dstColorSpace = OH_NativeColorSpaceManager_CreateForName(SRGB);
OH_PixelmapNative *src = nullptr;
OH_PixelmapNative *dst = nullptr;
CreatePixelmap(&src, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_1010102, srcColorSpace);
CreatePixelmap(&dst, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888, dstColorSpace);
OH_PixelmapNative_WritePixels(src, const_cast<unit8_t *>(data), size);
bool ret = OH_ImageProcessing_ConvertColorSpace(imageProcessor, src, dst);
OH_PixelmapNative_Release(src);
OH_PixelmapNative_Release(dst);
OH_NativeColorSpaceManager_Destroy(srcColorSpace);
OH_NativeColorSpaceManager_Destroy(dstColorSpace);
return ret;
}
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::DoSomethingInterestingWithMyAPI(data, size);
return 0;
}
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2025 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>300</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>
@@ -1,50 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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.
*/
#####################hydra_fuzz######################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "video_processing_engine/fuzztest"
############################fuzztest#############################
ohos_fuzztest("ImagemetadatagenFuzzTest") {
module_output_path = module_output_path
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/imagemetadatagen_fuzzer"
include_dirs = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/../media_foundation/video_processing_engine/interface/kits/c"
]
include_dirs += [ "./" ]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"imagemetadatagen_fuzzer.cpp"
]
external_deps = [
"graphic_2d:libnative_color_space_manager",
"image_framework:pixelmap",
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_single",
"media_foundation:native_media_core",
"media_foundation:media_foundation",
"window_manager:libwm",
]
deps = [
"$FRAMEWORK_DIR:image_processing"
]
}
@@ -1,65 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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 "imagehdr2sdr_fuzzer.h"
#include "image_processing.h"
#include "image/pixelmap_native.h"
#include "native_color_space_manager.h"
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
constexpr uint32_t DEFAULT_WIDTH = 3840;
constexpr uint32_t DEFAULT_HEIGHT = 2160;
OH_ImageProcessing *imageProcessor = nullptr;
static void CreatePixelmap(OH_PixelmapNative **pixelmap, int32_t width, int32_t height, int format,
OH_NativeColorSpaceManager *colorSpaceNative)
{
OH_Pixelmap_InintializationOptions *options = nullptr;
(void)OH_Pixelmap_InintializationOptions_Create(&options);
(void)OH_Pixelmap_InintializationOptions_SetWidth(options, width);
(void)OH_Pixelmap_InintializationOptions_SetHeight(options, height);
(void)OH_Pixelmap_InintializationOptions_SetPixelFormat(options, format);
(void)OH_PixelmapNative_CreateEmptyPixelmap(options, pixelmap);
(void)OH_PixelmapNative_SetColorSpaceNative(*pixelmap, colorSpaceNative);
}
bool DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)
{
if (imageProcessor == nullptr) {
OH_ImageProcessing_Create(&imageProcessor, IMAGE_PROCESSING_TYPE_METADATA_GENERATION);
}
OH_NativeColorSpaceManager *srcColorSpace = OH_NativeColorSpaceManager_CreateForName(BT2020_PQ);
OH_PixelmapNative *src = nullptr;
CreatePixelmap(&src, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_1010102, srcColorSpace);
OH_PixelmapNative_WritePixels(src, const_cast<unit8_t *>(data), size);
bool ret = OH_ImageProcessing_GenerateMetadata(imageProcessor, src);
OH_PixelmapNative_Release(src);
OH_NativeColorSpaceManager_Destroy(srcColorSpace);
return ret;
}
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::DoSomethingInterestingWithMyAPI(data, size);
return 0;
}
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2025 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>300</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>
@@ -1,51 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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.
*/
#####################hydra_fuzz######################
import("//build/config/features.gni")
import("//build/test.gni")
module_output_path = "video_processing_engine/fuzztest"
############################fuzztest#############################
ohos_fuzztest("Imagesdr2sdrFuzzTest") {
module_output_path = module_output_path
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/imagesdr2sdr_fuzzer"
include_dirs = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/../media_foundation/video_processing_engine/interface/kits/c"
]
include_dirs += [ "./" ]
cflags = [
"-g",
"-O0",
"-Wno-unused-variable",
"-fno-omit-frame-pointer",
]
sources = [
"imagesdr2sdr_fuzzer.cpp"
]
external_deps = [
"c_utils:utils",
"graphic_2d:libnative_color_space_manager",
"hilog:libhilog",
"ipc:ipc_single",
"media_foundation:native_media_core",
"media_foundation:media_foundation",
"image_framework:pixelmap",
"image_framework:pixelmap_ndk",
"window_manager:libwm",
]
deps = [
"$FRAMEWORK_DIR:image_processing"
]
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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 "imagesdr2sdr_fuzzer.h"
#include "image_processing.h"
#include "image/pixelmap_native.h"
#include "native_color_space_manager.h"
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
constexpr uint32_t DEFAULT_WIDTH = 3840;
constexpr uint32_t DEFAULT_HEIGHT = 2160;
OH_ImageProcessing *imageProcessor = nullptr;
static void CreatePixelmap(OH_PixelmapNative **pixelmap, int32_t width, int32_t height,
int format, OH_NativeColorSpaceManager *colorSpaceNative)
{
OH_Pixelmap_InintializationOptions *options = nullptr;
(void)OH_Pixelmap_InintializationOptions_Create(&options);
(void)OH_Pixelmap_InintializationOptions_SetWidth(options, width);
(void)OH_Pixelmap_InintializationOptions_SetHeight(options, height);
(void)OH_Pixelmap_InintializationOptions_SetPixelFormat(options, format);
(void)OH_PixelmapNative_CreateEmptyPixelmap(options, pixelmap);
(void)OH_PixelmapNative_SetColorSpaceNative(*pixelmap, colorSpaceNative);
}
bool DoSomethingInterestingWithMyAPI(const uint8_t *data, size_t size)
{
if (imageProcessor == nullptr) {
OH_ImageProcessing_Create(&imageProcessor, IMAGE_PROCESSING_TYPE_COLOR_SPACE_CONVERSION);
}
OH_NativeColorSpaceManager *srcColorSpace = OH_NativeColorSpaceManager_CreateForName(SRGB);
OH_NativeColorSpaceManager *dstColorSpace = OH_NativeColorSpaceManager_CreateForName(DISPLAY_P3);
OH_PixelmapNative *src = nullptr;
OH_PixelmapNative *dst = nullptr;
CreatePixelmap(&src, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888, srcColorSpace);
CreatePixelmap(&dst, DEFAULT_WIDTH, DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888, dstColorSpace);
OH_PixelmapNative_WritePixels(src, const_cast<unit8_t *>(data), size);
bool ret = OH_ImageProcessing_ConvertColorSpace(imageProcessor, src, dst);
OH_PixelmapNative_Release(src);
OH_PixelmapNative_Release(dst);
OH_NativeColorSpaceManager_Destroy(srcColorSpace);
OH_NativeColorSpaceManager_Destroy(dstColorSpace);
return ret;
}
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
/* Run your code on data */
OHOS::DoSomethingInterestingWithMyAPI(data, size);
return 0;
}
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2025 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>300</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>
-25
View File
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2025 Huawei Device 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.
-->
<configuration ver="2.0">
<target name="demuxer_native_module_test">
<preparer>
<option name="shell" value="mkdir -p /data/test/media"/>
<option name="push" value="demuxer/. -> /data/test/media" src="res"/>
<option name="shell" value="restorecon /data/test/media"/>
</preparer>
</target>
</configuration>
@@ -1,4 +1,4 @@
# Copyright (c) 2024 Huawei Device Co., Ltd.
# Copyright (c) 2023 Huawei Device 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
@@ -16,12 +16,14 @@ import("//build/config/features.gni")
import("//build/test.gni")
import("//foundation/multimedia/video_processing_engine/config.gni")
module_output_path = "video_processing_engine/fuzztest"
##############################fuzztest##########################################
ohos_fuzztest("VideohdrtohdrFuzzTest") {
ohos_fuzztest("ServicesFuzzTest") {
module_out_path = module_output_path
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/videohdrtohdr_fuzzer"
fuzz_config_file = "$VIDEO_PROCESSING_ENGINE_ROOT_DIR/test/fuzztest/services_fuzzer"
include_dirs = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/interfaces/kits"
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services/include/",
]
cflags = [
"-g",
@@ -30,23 +32,19 @@ ohos_fuzztest("VideohdrtohdrFuzzTest") {
"-fno-omit-frame-pointer",
]
sources = [
"videohdrtohdr_fuzzer.cpp",
"videodec_sample.cpp",
"services_fuzzer.cpp"
]
deps = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/framework:videoprocessingengine",
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services:videoprocessingservice",
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/services:videoprocessingserviceimpl",
]
external_deps = [
"c_utils:utils",
"graphic_2d:libgraphic_utils",
"graphic_2d:librender_service_client",
"graphic_surface:surface",
"graphic_surface:sync_fence",
"hilog:libhilog",
"ipc:ipc_single",
"media_foundation:media_foundation",
"media_foundation:native_media_core",
"window_manager:libwm",
"c_utils:utils",
"graphic_surface:surface",
"hilog:libhilog",
"ipc:ipc_single",
]
deps = [
"$VIDEO_PROCESSING_ENGINE_ROOT_DIR/framework:video_processing"
]
}
}
@@ -0,0 +1 @@
FUZZ
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2025 Huawei Device Co., Ltd.
<!-- Copyright (c) 2023 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2025 Huawei Device 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 <cstdint>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <fuzzer/FuzzedDataProvider.h>
#include "video_processing_client.h"
#include "services_fuzzer.h"
#include "securec.h"
using namespace std;
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
#define ATTRKEY_END 8192
namespace {
uint32_t LoadInfoFuzzerTest(int32_t key)
{
VPE_LOGI("LoadInfoFuzzerTest begin!");
SurfaceBufferInfo bufferInfo;
auto &manager = VideoProcessingManager::GetInstance();
manager.LoadInfo(key, bufferInfo);
VPE_LOGI("LoadInfoFuzzerTest end!");
return ERR_NONE;
}
uint32_t CreateFuzzerTest(std::string feature, std::string clientName, uint32_t clientID)
{
VPE_LOGI("CreateFuzzerTest begin!");
auto &manager = VideoProcessingManager::GetInstance();
manager.Create(feature, clientName, clientID);
VPE_LOGI("CreateFuzzerTest end!");
return ERR_NONE;
}
uint32_t DestroyFuzzerTest(uint32_t clientID)
{
VPE_LOGI("DestroyFuzzerTest begin!");
auto &manager = VideoProcessingManager::GetInstance();
manager.Destroy(clientID);
VPE_LOGI("DestroyFuzzerTest end!");
return ERR_NONE;
}
uint32_t SetParameterFuzzerTest(uint32_t clientID, int32_t tag, const std::vector<uint8_t>& parameter)
{
VPE_LOGI("SetParameterFuzzerTest begin!");
auto &manager = VideoProcessingManager::GetInstance();
manager.SetParameter(clientID, tag, parameter);
VPE_LOGI("SetParameterFuzzerTest end!");
return ERR_NONE;
}
uint32_t GetParameterFuzzerTest(uint32_t clientID, int32_t tag)
{
VPE_LOGI("GetParameterFuzzerTest begin!");
std::vector<uint8_t> param;
auto &manager = VideoProcessingManager::GetInstance();
manager.GetParameter(clientID, tag, param);
VPE_LOGI("GetParameterFuzzerTest end!");
return ERR_NONE;
}
uint32_t UpdateMetadataFuzzerTest(uint32_t clientID, SurfaceBufferInfo& image)
{
VPE_LOGI("UpdateMetadataFuzzerTest begin!");
auto &manager = VideoProcessingManager::GetInstance();
manager.UpdateMetadata(clientID, image);
VPE_LOGI("UpdateMetadataFuzzerTest end!");
return ERR_NONE;
}
uint32_t ProcessFuzzerTest(uint32_t clientID, const SurfaceBufferInfo& input)
{
VPE_LOGI("ProcessFuzzerTest begin!");
SurfaceBufferInfo output;
auto &manager = VideoProcessingManager::GetInstance();
manager.Process(clientID, input, output);
VPE_LOGI("ProcessFuzzerTest end!");
return ERR_NONE;
}
uint32_t ComposeImageFuzzerTest(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, bool legacy)
{
VPE_LOGI("ComposeImageFuzzerTest begin!");
auto &manager = VideoProcessingManager::GetInstance();
SurfaceBufferInfo outputHdrImage;
manager.ComposeImage(clientID, inputSdrImage, inputGainmap, outputHdrImage, legacy);
VPE_LOGI("ComposeImageFuzzerTest end!");
return ERR_NONE;
}
uint32_t DecomposeImageTest(uint32_t clientID, const SurfaceBufferInfo& inputImage)
{
VPE_LOGI("DecomposeImageTest begin!");
SurfaceBufferInfo outputSdrImage;
SurfaceBufferInfo outputGainmap;
auto &manager = VideoProcessingManager::GetInstance();
manager.DecomposeImage(clientID, inputImage, outputSdrImage, outputGainmap);
VPE_LOGI("DecomposeImageTest end!");
return ERR_NONE;
}
}
/* Fuzzer entry point */
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
FuzzedDataProvider data_provider(data, size);
SurfaceBufferInfo buffer;
buffer.videoInfo.videoIndex = data_provider.ConsumeIntegral<uint64_t>();
buffer.videoInfo.frameIndex = data_provider.ConsumeIntegral<uint64_t>();
if (data != nullptr) {
std::vector<uint8_t> vec;
vec.resize(size);
if (memcpy_s(vec.data(), vec.size(), data, size) != 0) {
VPE_LOGE("memcpy_s err");
return 0;
}
uint32_t key = data_provider.ConsumeIntegralInRange <uint32_t>(0, ATTRKEY_END);
buffer.surfacebuffer = SurfaceBuffer::Create();
if (buffer.surfacebuffer == nullptr) {
VPE_LOGI("buffer.surfacebuffer is nullptr");
return 0;
}
buffer.surfacebuffer->SetMetadata(key, vec);
}
LoadInfoFuzzerTest(data_provider.ConsumeIntegral<uint32_t>());
CreateFuzzerTest(data_provider.ConsumeRandomLengthString(), data_provider.ConsumeRandomLengthString(),
data_provider.ConsumeIntegral<uint32_t>());
DestroyFuzzerTest(data_provider.ConsumeIntegral<uint32_t>());
SetParameterFuzzerTest(data_provider.ConsumeIntegral<uint32_t>(), data_provider.ConsumeIntegral<int32_t>(),
data_provider.ConsumeRemainingBytes<uint8_t>());
ProcessFuzzerTest(data_provider.ConsumeIntegral<uint32_t>(), buffer);
GetParameterFuzzerTest(data_provider.ConsumeIntegral<uint32_t>(), data_provider.ConsumeIntegral<int32_t>());
UpdateMetadataFuzzerTest(data_provider.ConsumeIntegral<uint32_t>(), buffer);
ComposeImageFuzzerTest(data_provider.ConsumeIntegral<uint32_t>(), buffer, buffer, data_provider.ConsumeBool());
DecomposeImageTest(data_provider.ConsumeIntegral<uint32_t>(), buffer);
return 0;
}
@@ -0,0 +1,10 @@
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
*/
#ifndef TEST_FUZZTEST_IDAL_CLIENT_FUZZER_H
#define TEST_FUZZTEST_IDAL_CLIENT_FUZZER_H
#define FUZZ_PROJECT_NAME "videoProcessingEngineServices_fuzzer"
#endif // TEST_FUZZTEST_FLASHLIGHT_SERVICE_FUZZER_H
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2021 Huawei Device 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.
-->
<fuzz_config>
<fuzztest>
<!-- maximum length of a test input -->
<max_len>1000</max_len>
<!-- maximum total time in seconds to run the fuzzer -->
<max_total_time>300</max_total_time>
<!-- memory usage limit in Mb -->
<rss_limit_mb>4096</rss_limit_mb>
</fuzztest>
</fuzz_config>
@@ -1,181 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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 <fstream>
#include <vector>
#include <string>
#include <sstream>
#include "video_sample.h"
#include "securec.h"
#include "sync_fence.h"
using namespace OHOS;
using namespace std;
constexpr int64_t NANOS_IN_SECOND = 1000000000L;
constexpr int64_t NANOS_IN_MICRO = 1000L;
constexpr int64_t SLEEP_MICROSECONDS = 33333L;
constexpr int THREE = 3;
namespace OHOS {
int64_t GetSystemTimeUs()
{
struct timespec now;
(void)clock_gettime(CLOCK_BOOTTIME, &now);
int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
return nanoTime / NANOS_IN_MICRO;
}
void OnError(OH_VideoProcessing* videoProcessor, VideoProcessing_ErrorCode error, void* userData)
{
(void)videoProcessor;
(void)error;
(void)userData;
}
void OnState(OH_VideoProcessing* videoProcessor, VideoProcessing_State state, void* userData)
{
g_state = state;
if (state == VIDEO_PROCESSING_STATE_STOPPED) {
g_Cond.notify_all();
}
std::cout << "OnState callback called, new state is "<< state << std::endl;
}
void OnNewOutputBuffer(OH_VideoProcessing* videoProcessor, uint32_t index, void* userData)
{
OH_VideoProcessing_RenderOutputBuffer(videoProcessor, index);
}
}
class VPEConsumerListener : public IBufferConsumerListener {
public:
explicit VPEConsumerListener(sptr<Surface> cs) : cs(cs) {};
~VPEConsumerListener() {}
void OnBufferAvailable() override
{
sptr<SurfaceBuffer> buffer;
Rect damage = {};
cs->AcquireBuffer(buffer, fence, timestamp, damage);
cs->ReleaseBuffer(buffer, -1);
}
private:
int64_t timestamp = 0;
int32_t fence = -1;
sptr<Surface> cs {nullptr};
};
VideoSample::~VideoSample()
{
if (callback) {
OH_VideoProcessingCallback_Destroy(callback);
callback = nullptr;
}
if (rect) {
delete rect;
rect = nullptr;
}
OH_VideoProcessing_Destroy(videoProcessor);
OH_NativeWindow_DestroyNativeWindow(outWindow);
OH_NativeWindow_DestroyNativeWindow(inWindow);
if (cs) {
cs->UnregisterConsumerListener();
}
}
int32_t VideoSample::InitVideoSample(int32_t width, int32_t height, VideoProcessParam param)
{
width_ = width;
height_ = height;
isRunning = true;
param_ = param;
int32_t ret = OH_VideoProcessing_Create(&videoProcessor, VIDEO_PROCESSING_TYPE_COLOR_SPACE_CONVERSION);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_Create failed.");
cs = Surface::CreateSurfaceAsConsumer();
sptr<IBufferConsumerListener> listener = new VPEConsumerListener(cs);
cs->RegisterConsumerListener(listener);
auto p = cs->GetProducer();
sptr<Surface> ps = Surface::CreateSurfaceAsProducer(p);
outWindow = CreateNativeWindowFromSurface(&ps);
(void)OH_NativeWindow_NativeWindowHandleOpt(outWindow, SET_FORMAT, param_.outFmt);
ret = OH_NativeWindow_SetColorSpace(outWindow, param_.outColorSpace);
ret = OH_VideoProcessing_SetSurface(videoProcessor, outWindow);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_SetSurface failed.");
ret = OH_VideoProcessing_GetSurface(videoProcessor, &inWindow);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_GetSurface failed.");
SetInputWindowParam();
ret = OH_VideoProcessingCallback_Create(&callback);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessingCallback_Create failed.");
OH_VideoProcessingCallback_BindOnError(callback, OnError);
OH_VideoProcessingCallback_BindOnState(callback, OnState);
OH_VideoProcessingCallback_BindOnNewOutputBuffer(callback, OnNewOutputBuffer);
ret = OH_VideoProcessing_RegisterCallback(videoProcessor, callback, this);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_RegisterCallback failed.");
return VIDEO_PROCESSING_SUCCESS;
}
void VideoSample::SetInputWindowParam()
{
(void)OH_NativeWindow_NativeWindowHandleOpt(inWindow, SET_BUFFER_GEOMETRY, width_, height_);
(void)OH_NativeWindow_NativeWindowHandleOpt(inWindow, SET_USAGE,
NATIVEBUFFER_USAGE_CPU_READ | NATIVEBUFFER_USAGE_CPU_WRITE |
NATIVEBUFFER_USAGE_MEM_DMA | NATIVEBUFFER_USAGE_HW_RENDER);
(void)OH_NativeWindow_NativeWindowHandleOpt(inWindow, SET_FORMAT, param_.inFmt);
OH_NativeWindow_SetColorSpace(inWindow, param_.inColorSpace);
rect = new Region::Rect();
rect->x = 0;
rect->y = 0;
rect->w = width_;
rect->h = height_;
region.rects = rect;
}
int32_t VideoSample::InputFunc(const uint8_t *data, size_t size)
{
int fenceFd = -1;
OHNativeWindowBuffer *ohNativeWindowBuffer;
int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(inWindow, &ohNativeWindowBuffer, &fenceFd);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeWindow_NativeWindowRequestBuffer failed.");
if (fenceFd > 0) {
close(fenceFd);
}
OH_NativeBuffer *nativeBuffer = nullptr;
err = OH_NativeBuffer_FromNativeWindowBuffer(ohNativeWindowBuffer, &nativeBuffer);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeBuffer_FromNativeWindowBuffer failed.");
void *virAddr = nullptr;
OH_NativeBuffer_Config config;
OH_NativeBuffer_GetConfig(nativeBuffer, &config);
err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeBuffer_Map failed.");
uint8_t *addr = reinterpret_cast<uint8_t *>(virAddr);
memcpy_s(addr, config.stride * config.height * THREE, data, size);
NativeWindowHandleOpt(inWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
err = OH_NativeBuffer_Unmap(nativeBuffer);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeBuffer_Unmap failed.");
err = OH_NativeWindow_NativeWindowFlushBuffer(inWindow, ohNativeWindowBuffer, -1, region);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeWindow_NativeWindowFlushBuffer failed.");
err = OH_NativeWindow_SetColorSpace(inWindow, param_.inColorSpace);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeWindow_SetColorSpace failed.");
usleep(SLEEP_MICROSECONDS);
return err;
}
int32_t VideoSample::StartProcess()
{
int32_t ret = OH_VideoProcessing_Start(videoProcessor);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_Start failed.");
return VIDEO_PROCESSING_SUCCESS;
}
@@ -1,181 +0,0 @@
/*
* Copyright (C) 2025 Huawei Device 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 VIDEO_SAMPLE_H
#define VIDEO_SAMPLE_H
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include "securec.h"
#include "sync_fence.h"
#include "video_sample.h"
using namespace OHOS;
using namespace std;
constexpr int64_t NANOS_IN_SECOND = 1000000000L;
constexpr int64_t NANOS_IN_MICRO = 1000L;
constexpr int64_t SLEEP_MICROSECONDS = 33333L;
constexpr int THREE = 3;
namespace OHOS {
int64_t GetSystemTimeUs()
{
struct timespec now;
(void)clock_gettime(CLOCK_BOOTTIME, &now);
int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
return nanoTime / NANOS_IN_MICRO;
}
void OnError(OH_VideoProcessing* videoProcessor, VideoProcessing_ErrorCode error, void* userData)
{
(void)videoProcessor;
(void)error;
(void)userData;
}
void OnState(OH_VideoProcessing* videoProcessor, VideoProcessing_State state, void* userData)
{
(void)videoProcessor;
(void)state;
(void)userData;
}
void OnNewOutputBuffer(OH_VideoProcessing* videoProcessor, uint32_t index, void* userData)
{
OH_VideoProcessing_RenderOutputBuffer(videoProcessor, index);
}
}
class VPEConsumerListener : public IBufferConsumerListener {
public:
explicit VPEConsumerListener(sptr<Surface> cs) : cs(cs){};
~VPEConsumerListener() {};
void OnBufferAvailable() override
{
sptr<SurfaceBuffer> buffer;
Rect damage = {};
cs->AcquireBuffer(buffer, fence, timestamp, damage);
cs->ReleaseBuffer(buffer, -1);
}
private:
int32_t fence = -1;
int64_t timestamp = 0;
sptr<Surface> cs {nullptr};
}
VideoSample::~VideoSample()
{
if (callback) {
OH_VideoProcessingCallback_Destroy(callback);
callback = nullptr;
}
if (rect) {
delete rect;
rect = nullptr;
}
OH_VideoProcessing_Destroy(videoProcessor);
OH_NativeWindow_DestroyNativeWindow(outWindow);
OH_NativeWindow_DestroyNativeWindow(inWindow);
if (cs) {
cs->UnregisterConsumerListener();
}
}
int32_t VideoSample::InitVideoSample(int32_t width, int32_t height, VideoProcessParam param)
{
width_ = width;
height_ = height;
isRunning = true;
param_ = param;
int32_t ret = OH_VideoProcessing_Create(&videoProcessor, VIDEO_PROCESSING_TYPE_COLOR_SPACE_CONVERSION);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_Create failed.");
cs = Surface::CreateSurfaceAsConsumer();
sptr<IBufferConsumerListener> listener = new VPEConsumerListener(cs);
cs->RegisterConsumerListener(listener);
auto p = cs->GetProducer();
sptr<Surface> ps = Surface::CreateSurfaceAsProducer(p);
outWindow = CreateNativeWindowFromSurface(&ps);
(void)OH_NativeWindow_NativeWindowHandleOpt(outWindow, SET_FORMAT, param_.outFmt);
ret = OH_NativeWindow_SetColorSpace(outWindow, param_.outColorSpace);
ret = OH_VideoProcessing_SetSurface(videoProcessor, outWindow);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_SetSurface failed.");
ret = OH_VideoProcessing_GetSurface(videoProcessor, &inWindow);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_GetSurface failed.");
SetInputWindowParam();
ret = OH_VideoProcessingCallback_Create(&callback);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessingCallback_Create failed.");
OH_VideoProcessingCallback_BindOnError(callback, OnError);
OH_VideoProcessingCallback_BindOnState(callback, OnState);
OH_VideoProcessingCallback_BindOnNewOutputBuffer(callback, OnNewOutputBuffer);
ret = OH_VideoProcessing_RegisterCallback(videoProcessor, callback, this);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_RegisterCallback failed.");
return VIDEO_PROCESSING_SUCCESS;
}
void VideoSample::SetInputWindowParam()
{
(void)OH_NativeWindow_NativeWindowHandleOpt(inWindow, SET_BUFFER_GEOMETRY, width_, height_);
(void)OH_NativeWindow_NativeWindowHandleOpt(inWindow, SET_USAGE,
NATIVEBUFFER_USAGE_CPU_READ | NATIVEBUFFER_USAGE_CPU_WRITE |
NATIVEBUFFER_USAGE_MEM_DMA | NATIVEBUFFER_USAGE_HW_RENDER);
(void)OH_NativeWindow_NativeWindowHandleOpt(inWindow, SET_FORMAT, param_.inFmt);
OH_NativeWindow_SetColorSpace(inWindow, param_.inColorSpace);
rect = new Region::Rect();
rect->x = 0;
rect->y = 0;
rect->w = width_;
rect->h = height_;
region.rects = rect;
}
int32_t VideoSample::InputFunc(const uint8_t *data, size_t size)
{
int fenceFd = -1;
OHNativeWindowBuffer *ohNativeWindowBuffer;
int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(inWindow, &ohNativeWindowBuffer, &fenceFd);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeWindow_NativeWindowRequestBuffer failed.");
if (fenceFd > 0) {
close(fenceFd);
}
OH_NativeBuffer *nativeBuffer = nullptr;
err = OH_NativeBuffer_FromNativeWindowBuffer(ohNativeWindowBuffer, &nativeBuffer);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeBuffer_FromNativeWindowBuffer failed.");
void *virAddr = nullptr;
OH_NativeBuffer_Config config;
OH_NativeBuffer_GetConfig(nativeBuffer, &config);
err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeBuffer_Map failed.");
uint8_t *addr = reinterpret_cast<uint8_t *>(virAddr);
memcpy_s(addr, config.stride * config.height * THREE, data, size);
NativeWindowHandleOpt(inWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
err = OH_NativeBuffer_Unmap(nativeBuffer);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeBuffer_Unmap failed.");
err = OH_NativeWindow_NativeWindowFlushBuffer(inWindow, ohNativeWindowBuffer, -1, region);
CHECK_AND_RETURN_RET(err == 0, err, "OH_NativeWindow_NativeWindowFlushBuffer failed.");
usleep(SLEEP_MICROSECONDS);
return err;
}
int32_t VideoSample::StartProcess()
{
int32_t ret = OH_VideoProcessing_Start(videoProcessor);
CHECK_AND_RETURN_RET(ret == VIDEO_PROCESSING_SUCCESS, ret, "OH_VideoProcessing_Start failed.");
return VIDEO_PROCESSING_SUCCESS;
}
#endif

Some files were not shown because too many files have changed in this diff Show More