mirror of
https://github.com/openharmony/multimedia_video_processing_engine.git
synced 2026-07-20 22:47:20 -04:00
@@ -18,5 +18,6 @@ group("video_processing_engine_packages") {
|
||||
public_deps = [
|
||||
"framework:videoprocessingengine",
|
||||
"services:videoprocessingservice"
|
||||
"services:videoprocessingserviceimpl"
|
||||
]
|
||||
}
|
||||
|
||||
+20
-7
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
+1
-51
@@ -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>();
|
||||
|
||||
+1
-2
@@ -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>()>;
|
||||
|
||||
-6
@@ -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};
|
||||
|
||||
-47
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
+14
-9
@@ -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!");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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" ]
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 */
|
||||
+16
-1
@@ -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
|
||||
+11
-16
@@ -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
|
||||
+19
-2
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
+18
-20
@@ -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
-1
@@ -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
Reference in New Issue
Block a user