update vpe

Signed-off-by: liushang <liushang2@huawei.com>
This commit is contained in:
liushang
2025-04-07 18:31:00 +08:00
parent 9b6ea3f2e3
commit f39f0643a7
201 changed files with 8110 additions and 11372 deletions
@@ -204,7 +204,7 @@ sptr<Surface> AihdrEnhancerVideoImpl::CreateInputSurface()
sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
CHECK_AND_RETURN_RET_LOG(producerSurface != nullptr, nullptr, "CreateSurfaceAsProducer fail");
producerSurface->SetDefaultUsage(BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_HW_RENDER |
BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE);
BUFFER_USAGE_MEM_DMA);
inputSurface_->SetQueueSize(inBufferCnt_);
state_ = VPEAlgoState::CONFIGURING;
@@ -249,7 +249,10 @@ int32_t AihdrEnhancerVideoImpl::Prepare()
void AihdrEnhancerVideoImpl::InitBuffers()
{
std::lock_guard<std::mutex> lock(mutex_);
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return;
}
CHECK_AND_RETURN_LOG(outputSurface_ != nullptr, "outputSurface_ is nullptr");
flushCfg_.damage.x = 0;
flushCfg_.damage.y = 0;
@@ -317,8 +320,8 @@ int32_t AihdrEnhancerVideoImpl::Reset()
int32_t AihdrEnhancerVideoImpl::Release()
{
std::lock_guard<std::mutex> lock(mutex_);
{
std::lock_guard<std::mutex> lock(mutex_);
std::unique_lock<std::mutex> lockTask(mtxTaskDone_);
state_ = VPEAlgoState::UNINITIALIZED;
cvTaskDone_.wait(lockTask, [this]() { return isProcessing_.load() == false; });
@@ -383,6 +386,7 @@ void AihdrEnhancerVideoImpl::Process(std::shared_ptr<SurfaceBufferWrapper> input
outputBuffer->timestamp = inputBuffer->timestamp;
sptr<SurfaceBuffer> surfaceInputBuffer = inputBuffer->memory;
sptr<SurfaceBuffer> surfaceOutputBuffer = outputBuffer->memory;
surfaceInputBuffer->InvalidateCache();
bool copyRet = AlgorithmUtils::CopySurfaceBufferToSurfaceBuffer(surfaceInputBuffer, surfaceOutputBuffer);
if (!copyRet) {
requestCfg_.width = surfaceInputBuffer->GetWidth();
@@ -423,6 +427,7 @@ bool AihdrEnhancerVideoImpl::WaitProcessing()
{
std::unique_lock<std::mutex> lock(mtxTaskStart_);
cvTaskStart_.wait(lock, [this]() {
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> inQueueLock(onBqMutex_);
std::lock_guard<std::mutex> outQueueLock(renderQueMutex_);
if (initBuffer_.load()) {
@@ -587,6 +592,10 @@ GSError AihdrEnhancerVideoImpl::OnProducerBufferReleased()
GSError AihdrEnhancerVideoImpl::OnConsumerBufferAvailable()
{
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> lockInQue(onBqMutex_);
CHECK_AND_RETURN_RET_LOG(inputSurface_ != nullptr, GSERROR_OK, "inputSurface is nullptr");
@@ -16,7 +16,6 @@
#include "colorspace_converter_display_fwk.h"
#include "securec.h"
#include "extension_manager.h"
#include "vpe_parse_metadata.h"
#include "vpe_trace.h"
#include "vpe_log.h"
@@ -43,12 +42,9 @@ VPEAlgoErrCode ColorSpaceConverterDisplayFwk::Process(const std::shared_ptr<OHOS
VPE_LOGD("size of impl %{public}zu", impl_.size());
CHECK_AND_RETURN_RET_LOG(!impl_.empty(), VPE_ALGO_ERR_NOT_IMPLEMENTED, "Extension is not found");
DeserializedDisplayParameter localParameter;
DeserializeDisplayParameter(parameter, localParameter);
VPE_SYNC_TRACE;
for (const auto& impl : impl_) {
ret = impl->Process(input, output, localParameter);
ret = impl->Process(input, output, parameter);
if (ret == VPE_ALGO_ERR_OK) {
return VPE_ALGO_ERR_OK;
}
@@ -74,52 +70,6 @@ VPEAlgoErrCode ColorSpaceConverterDisplayFwk::Init()
return VPE_ALGO_ERR_OK;
}
void ColorSpaceConverterDisplayFwk::DeserializeDisplayParameter(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed)
{
deserialzed.inputColorSpace = parameter.inputColorSpace;
deserialzed.outputColorSpace = parameter.outputColorSpace;
deserialzed.sdrNits = parameter.sdrNits;
deserialzed.tmoNits = parameter.tmoNits;
deserialzed.currentDisplayNits = parameter.currentDisplayNits;
deserialzed.disableHdrFloatHeadRoom = parameter.disableHdrFloatHeadRoom;
deserialzed.linearMatrix = parameter.layerLinearMatrix;
DeserializeStaticMetadata(parameter, deserialzed);
DeserializeDynamicMetadata(parameter, deserialzed);
}
void ColorSpaceConverterDisplayFwk::DeserializeStaticMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed)
{
if (parameter.staticMetadata.size() == 0) {
deserialzed.staticMetadata = std::nullopt;
return;
}
HdrStaticMetadata data;
errno_t ret = memcpy_s(&data, sizeof(data), parameter.staticMetadata.data(), parameter.staticMetadata.size());
if (ret != EOK) {
VPE_LOGE("memcpy_s failed, err = %d\n", ret);
return;
}
deserialzed.staticMetadata = data;
}
void ColorSpaceConverterDisplayFwk::DeserializeDynamicMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed)
{
if (parameter.dynamicMetadata.size() == 0) {
deserialzed.hdrVividMetadata = std::nullopt;
return;
}
HdrVividMetadataV1 data;
HwDisplayMeta displayMeta;
(void)PraseMetadataFromArray(parameter.dynamicMetadata, data, displayMeta);
deserialzed.hdrVividMetadata = data;
deserialzed.displayMeta = displayMeta;
}
std::shared_ptr<ColorSpaceConverterDisplay> ColorSpaceConverterDisplay::Create()
{
auto p = std::make_shared<ColorSpaceConverterDisplayFwk>();
@@ -21,7 +21,6 @@
#include "nocopyable.h"
#include "effect/shader_effect.h"
#include "algorithm_common.h"
#include "deserialized_display_parameter.h"
namespace OHOS {
namespace Media {
@@ -34,7 +33,7 @@ public:
virtual ~ColorSpaceConverterDisplayBase() = default;
virtual VPEAlgoErrCode Process(const std::shared_ptr<OHOS::Rosen::Drawing::ShaderEffect>& input,
std::shared_ptr<OHOS::Rosen::Drawing::ShaderEffect>& output,
const DeserializedDisplayParameter& parameter) = 0;
const ColorSpaceConverterDisplayParameter& parameter) = 0;
};
using ColorSpaceConverterDisplayCreator = std::function<std::shared_ptr<ColorSpaceConverterDisplayBase>()>;
@@ -37,12 +37,6 @@ public:
const ColorSpaceConverterDisplayParameter& parameter) override;
private:
VPEAlgoErrCode Init();
void DeserializeDisplayParameter(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed);
void DeserializeStaticMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed);
void DeserializeDynamicMetadata(const ColorSpaceConverterDisplayParameter& parameter,
DeserializedDisplayParameter& deserialzed);
std::set<std::shared_ptr<ColorSpaceConverterDisplayBase>> impl_;
std::atomic<bool> initialized_ {false};
@@ -1,47 +0,0 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VPE_FRAMEWORK_ALGORITHM_COLORSPACE_CONVERTER_DISPLAY_DESERIALIZED_DISPLAY_PARAMETER_H
#define VPE_FRAMEWORK_ALGORITHM_COLORSPACE_CONVERTER_DISPLAY_DESERIALIZED_DISPLAY_PARAMETER_H
#include <optional>
#include "v1_0/hdr_static_metadata.h"
#include "algorithm_common.h"
#include "hdr_vivid_metadata_v1.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
using namespace HDI::Display::Graphic::Common::V1_0;
struct DeserializedDisplayParameter {
ColorSpaceDescription inputColorSpace; // 色彩空间信息
ColorSpaceDescription outputColorSpace; // 色彩空间信息
std::optional<HdrStaticMetadata> staticMetadata; // 静态元数据
std::optional<HdrVividMetadataV1> hdrVividMetadata; // 动态元数据
float sdrNits; // SDR亮度
float tmoNits; // TMO目标亮度
float currentDisplayNits; // 屏幕当前亮度,和tmoNits相除得到sdr亮度打折比
bool disableHdrFloatHeadRoom; // 不使用HDRfp16方案做额外提亮
HwDisplayMeta displayMeta; // 拍显协同元数据
int32_t width; // 宽度
int32_t height; // 高度
std::vector<float> linearMatrix; // 线性域转换矩阵,作用在原色域上
};
} // namespace VideoProcessingEngine
} // Media
} // OHOS
#endif // VPE_FRAMEWORK_ALGORITHM_COLORSPACE_CONVERTER_DISPLAY_DESERIALIZED_DISPLAY_PARAMETER_H
@@ -414,7 +414,10 @@ void GetFormatFromSurfaceBuffer(Format &outputFormat, sptr<SurfaceBuffer> &buffe
void ColorSpaceConverterVideoImpl::InitBuffers()
{
std::lock_guard<std::mutex> lock(mutex_);
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return;
}
CHECK_AND_RETURN_LOG(outputSurface_ != nullptr, "outputSurface_ is nullptr");
flushCfg_.damage.x = 0;
flushCfg_.damage.y = 0;
@@ -490,8 +493,8 @@ int32_t ColorSpaceConverterVideoImpl::Reset()
int32_t ColorSpaceConverterVideoImpl::Release()
{
std::lock_guard<std::mutex> lock(mutex_);
{
std::lock_guard<std::mutex> lock(mutex_);
std::unique_lock<std::mutex> lockTask(mtxTaskDone_);
state_ = VPEAlgoState::UNINITIALIZED;
cvTaskDone_.wait(lockTask, [this]() { return isProcessing_.load() == false; });
@@ -633,6 +636,7 @@ bool ColorSpaceConverterVideoImpl::WaitProcessing()
{
std::unique_lock<std::mutex> lock(mtxTaskStart_);
cvTaskStart_.wait(lock, [this]() {
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> inQueueLock(onBqMutex_);
std::lock_guard<std::mutex> outQueueLock(renderQueMutex_);
if (initBuffer_.load()) {
@@ -802,6 +806,10 @@ GSError ColorSpaceConverterVideoImpl::OnProducerBufferReleased()
GSError ColorSpaceConverterVideoImpl::OnConsumerBufferAvailable()
{
if (!isRunning_.load()) {
VPE_LOGD("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> lockInQue(onBqMutex_);
CHECK_AND_RETURN_RET_LOG(inputSurface_ != nullptr, GSERROR_OK, "inputSurface is nullptr");
+57 -12
View File
@@ -18,9 +18,49 @@
#include <unordered_map>
#include "securec.h"
#include "vpe_log.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
const std::unordered_map<GSError, std::string> GSERROR_STR_MAP = {
{ GSERROR_OK, VPE_TO_STR(GSERROR_OK) },
{ GSERROR_MEM_OPERATION_ERROR, VPE_TO_STR(GSERROR_MEM_OPERATION_ERROR) },
{ GSERROR_INVALID_ARGUMENTS, VPE_TO_STR(GSERROR_INVALID_ARGUMENTS) },
{ GSERROR_NO_PERMISSION, VPE_TO_STR(GSERROR_NO_PERMISSION) },
{ GSERROR_CONNOT_CONNECT_SAMGR, VPE_TO_STR(GSERROR_CONNOT_CONNECT_SAMGR) },
{ GSERROR_CONNOT_CONNECT_SERVER, VPE_TO_STR(GSERROR_CONNOT_CONNECT_SERVER) },
{ GSERROR_CONNOT_CONNECT_WESTON, VPE_TO_STR(GSERROR_CONNOT_CONNECT_WESTON) },
{ GSERROR_NO_BUFFER, VPE_TO_STR(GSERROR_NO_BUFFER) },
{ GSERROR_NO_ENTRY, VPE_TO_STR(GSERROR_NO_ENTRY) },
{ GSERROR_OUT_OF_RANGE, VPE_TO_STR(GSERROR_OUT_OF_RANGE) },
{ GSERROR_NO_SCREEN, VPE_TO_STR(GSERROR_NO_SCREEN) },
{ GSERROR_NO_BUFFER_READY, VPE_TO_STR(GSERROR_NO_BUFFER_READY) },
{ GSERROR_INVALID_OPERATING, VPE_TO_STR(GSERROR_INVALID_OPERATING) },
{ GSERROR_NO_CONSUMER, VPE_TO_STR(GSERROR_NO_CONSUMER) },
{ GSERROR_NOT_INIT, VPE_TO_STR(GSERROR_NOT_INIT) },
{ GSERROR_TYPE_ERROR, VPE_TO_STR(GSERROR_TYPE_ERROR) },
{ GSERROR_DESTROYED_OBJECT, VPE_TO_STR(GSERROR_DESTROYED_OBJECT) },
{ GSERROR_CONSUMER_IS_CONNECTED, VPE_TO_STR(GSERROR_CONSUMER_IS_CONNECTED) },
{ GSERROR_BUFFER_STATE_INVALID, VPE_TO_STR(GSERROR_BUFFER_STATE_INVALID) },
{ GSERROR_BUFFER_IS_INCACHE, VPE_TO_STR(GSERROR_BUFFER_IS_INCACHE) },
{ GSERROR_BUFFER_QUEUE_FULL, VPE_TO_STR(GSERROR_BUFFER_QUEUE_FULL) },
{ GSERROR_BUFFER_NOT_INCACHE, VPE_TO_STR(GSERROR_BUFFER_NOT_INCACHE) },
{ GSERROR_CONSUMER_DISCONNECTED, VPE_TO_STR(GSERROR_CONSUMER_DISCONNECTED) },
{ GSERROR_CONSUMER_UNREGISTER_LISTENER, VPE_TO_STR(GSERROR_CONSUMER_UNREGISTER_LISTENER) },
{ GSERROR_API_FAILED, VPE_TO_STR(GSERROR_API_FAILED) },
{ GSERROR_INTERNAL, VPE_TO_STR(GSERROR_INTERNAL) },
{ GSERROR_NO_MEM, VPE_TO_STR(GSERROR_NO_MEM) },
{ GSERROR_PROXY_NOT_INCLUDE, VPE_TO_STR(GSERROR_PROXY_NOT_INCLUDE) },
{ GSERROR_SERVER_ERROR, VPE_TO_STR(GSERROR_SERVER_ERROR) },
{ GSERROR_ANIMATION_RUNNING, VPE_TO_STR(GSERROR_ANIMATION_RUNNING) },
{ GSERROR_HDI_ERROR, VPE_TO_STR(GSERROR_HDI_ERROR) },
{ GSERROR_NOT_IMPLEMENT, VPE_TO_STR(GSERROR_NOT_IMPLEMENT) },
{ GSERROR_NOT_SUPPORT, VPE_TO_STR(GSERROR_NOT_SUPPORT) },
{ GSERROR_BINDER, VPE_TO_STR(GSERROR_BINDER) },
{ GSERROR_EGL_STATE_UNKOWN, VPE_TO_STR(GSERROR_EGL_STATE_UNKOWN) },
{ GSERROR_EGL_API_FAILED, VPE_TO_STR(GSERROR_EGL_API_FAILED) },
};
const std::unordered_map<VPEAlgoErrCode, std::string> ERROR_STR_MAP = {
{ VPE_ALGO_ERR_OK, VPE_TO_STR(VPE_ALGO_ERR_OK) },
{ VPE_ALGO_ERR_NO_MEMORY, VPE_TO_STR(VPE_ALGO_ERR_NO_MEMORY) },
@@ -46,26 +86,31 @@ const std::unordered_map<VPEAlgoState, std::string> STATE_STR_MAP = {
{ VPEAlgoState::EOS, VPE_TO_STR(VPEAlgoState::EOS) },
{ VPEAlgoState::ERROR, VPE_TO_STR(VPEAlgoState::ERROR) },
};
template <typename T>
std::string CodeToString(T code, const std::unordered_map<T, std::string>& codeMap, const std::string& name)
{
auto it = codeMap.find(code);
if (it == codeMap.end()) [[unlikely]] {
return "unknown " + name + "(" + std::to_string(static_cast<int>(code)) + ")";
}
return it->second;
}
} // namespace
std::string AlgorithmUtils::ToString(GSError errorCode)
{
return CodeToString(errorCode, GSERROR_STR_MAP, "GSError");
}
std::string AlgorithmUtils::ToString(VPEAlgoErrCode errorCode)
{
auto it = ERROR_STR_MAP.find(errorCode);
if (it == ERROR_STR_MAP.end()) [[unlikely]] {
VPE_LOGE("Invalid error code:%{public}d", errorCode);
return "Unsupported error:" + std::to_string(static_cast<int>(errorCode));
}
return it->second;
return CodeToString(errorCode, ERROR_STR_MAP, "VPEAlgoErrCode");
}
std::string AlgorithmUtils::ToString(VPEAlgoState state)
{
auto it = STATE_STR_MAP.find(state);
if (it == STATE_STR_MAP.end()) [[unlikely]] {
VPE_LOGE("Invalid state:%{public}d", state);
return "Unsupported state:" + std::to_string(static_cast<int>(state));
}
return it->second;
return CodeToString(state, STATE_STR_MAP, "VPEAlgoState");
}
bool AlgorithmUtils::CopySurfaceBufferToSurfaceBuffer(const sptr<SurfaceBuffer>& srcBuffer,
@@ -16,9 +16,11 @@
#include "algorithm_video_impl.h"
#include <chrono>
#include <limits>
#include <list>
#include <sstream>
#include "vpe_log.h"
#include "algorithm_utils.h"
#include "vpe_trace.h"
using namespace OHOS;
@@ -26,6 +28,7 @@ using namespace OHOS::Media::VideoProcessingEngine;
using namespace std::chrono_literals;
namespace {
constexpr uint32_t WAIT_FOR_EVER = std::numeric_limits<uint32_t>::max();
constexpr uint32_t BUFFER_QUEUE_SIZE = 5;
std::string ToString(const sptr<SurfaceBuffer>& buffer)
@@ -34,7 +37,8 @@ std::string ToString(const sptr<SurfaceBuffer>& buffer)
return "null";
}
std::stringstream stream;
stream << "id:" << buffer->GetSeqNum() << " " << buffer->GetWidth() << "x" << buffer->GetHeight() <<
stream << "id:" << buffer->GetSeqNum() << " fd:" << buffer->GetFileDescriptor() <<
" " << buffer->GetWidth() << "x" << buffer->GetHeight() <<
" format:" << buffer->GetFormat() << " usage:0x" << std::hex << buffer->GetUsage();
return stream.str();
}
@@ -62,7 +66,7 @@ VPEAlgoErrCode VpeVideoImpl::RegisterCallback(const std::shared_ptr<VpeVideoCall
[this, callback]() {
cb_ = callback;
return VPE_ALGO_ERR_OK;
}, "Registration of callbacks during running is not allowed!");
}, "Registration of callbacks during running is not allowed!", VPE_LOG_INFO);
}
VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
@@ -77,7 +81,7 @@ VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
std::lock_guard<std::mutex> producerLock(producerLock_);
if (producer_ != nullptr) {
if (producer_->GetUniqueId() == surface->GetUniqueId()) {
VPE_LOGD("Oops! The same surface!");
VPE_LOGD("Oops! The same surface(%{public}llu)!", surface->GetUniqueId());
return VPE_ALGO_ERR_OK;
}
producer_->UnRegisterReleaseListener();
@@ -86,11 +90,12 @@ VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
surface->UnRegisterReleaseListener();
GSError err = surface->RegisterReleaseListener([this](sptr<SurfaceBuffer>&) { return OnProducerBufferReleased(); });
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN, "RegisterReleaseListener failed!");
VPE_LOGI("Set output buffer queue size to %{public}u", BUFFER_QUEUE_SIZE);
VPE_LOGI("Set output(%{public}llu) buffer queue size to %{public}u", surface->GetUniqueId(), BUFFER_QUEUE_SIZE);
surface->SetQueueSize(BUFFER_QUEUE_SIZE);
surface->Connect();
surface->CleanCache();
AttachAndRefreshProducerBuffers(surface);
CHECK_AND_RETURN_RET_LOG(AttachAndRefreshProducerBuffers(surface), VPE_ALGO_ERR_UNKNOWN,
"Failed to attach buffers to new output surface(%{public}llu)!", surface->GetUniqueId());;
if (state_.load() != VPEState::IDLE) {
cvTrigger_.notify_one();
}
@@ -111,42 +116,13 @@ VPEAlgoErrCode VpeVideoImpl::SetOutputSurface(const sptr<Surface>& surface)
return ret;
}
VPEAlgoErrCode VpeVideoImpl::UpdateProducerLocked()
{
auto transform = consumer_->GetTransform();
GSError err;
if (isForceUpdateProducer_ || lastTransform_ != transform) {
err = producer_->SetTransform(transform);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetTransform(%{public}d), ret:%{public}d!", transform, err);
lastTransform_ = transform;
VPE_LOGD("producer_->SetTransform(%{public}d) success.", transform);
}
if (lastConsumerBufferId_ == 0) {
return VPE_ALGO_ERR_OK;
}
ScalingMode scaleMode;
err = consumer_->GetScalingMode(lastConsumerBufferId_, scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to GetScalingMode(%{public}u), ret:%{public}d!", lastConsumerBufferId_, err);
if (isForceUpdateProducer_ || lastScalingMode_ != scaleMode) {
err = producer_->SetScalingMode(scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetScalingMode(%{public}d), ret:%{public}d!", scaleMode, err);
lastScalingMode_ = scaleMode;
VPE_LOGD("producer_->SetScalingMode(%{public}d) success.", scaleMode);
}
isForceUpdateProducer_ = false;
return VPE_ALGO_ERR_OK;
}
sptr<Surface> VpeVideoImpl::GetInputSurface()
{
sptr<Surface> producerSurface;
if (ExecuteWhenIdle([this, &producerSurface]() {
producerSurface = CreateConsumerSurfaceLocked();
return VPE_ALGO_ERR_OK;
}, "Getting a surface during running is not allowed!") != VPE_ALGO_ERR_OK) {
}, "Getting a surface during running is not allowed!", VPE_LOG_INFO) != VPE_ALGO_ERR_OK) {
return nullptr;
}
return producerSurface;
@@ -154,6 +130,7 @@ sptr<Surface> VpeVideoImpl::GetInputSurface()
VPEAlgoErrCode VpeVideoImpl::Start()
{
VPE_LOGD("step in");
return ExecuteWhenIdle(
[this]() {
CHECK_AND_RETURN_RET_LOG(isInitialized_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "NOT initialized!");
@@ -162,16 +139,17 @@ VPEAlgoErrCode VpeVideoImpl::Start()
state_ = VPEState::RUNNING;
OnStateLocked(VPEAlgoState::RUNNING);
return VPE_ALGO_ERR_OK;
}, "Already start!");
}, "Already start!", VPE_LOG_INFO);
}
VPEAlgoErrCode VpeVideoImpl::Stop()
{
VPE_LOGD("step in");
auto err = ExecuteWhenRunning([this]() {
state_ = VPEState::STOPPING;
cvTrigger_.notify_one();
return VPE_ALGO_ERR_OK;
}, "Already stop!");
}, "Already stop!", VPE_LOG_INFO);
return err;
}
@@ -183,6 +161,7 @@ VPEAlgoErrCode VpeVideoImpl::Release()
VPEAlgoErrCode VpeVideoImpl::Flush()
{
VPE_LOGD("step in");
CHECK_AND_RETURN_RET_LOG(isRunning_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "Flush must be called during running!");
std::lock_guard<std::mutex> lock(lock_);
{
std::unique_lock<std::mutex> lockTask(taskLock_);
@@ -193,8 +172,8 @@ VPEAlgoErrCode VpeVideoImpl::Flush()
std::queue<SurfaceBufferInfo> tempQueue1;
std::queue<SurfaceBufferInfo> tempQueue2;
{
std::lock_guard<std::mutex> bufferLock(bufferLock_);
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
consumerBufferQueue_.swap(tempQueue1);
for (auto& [index, bufferInfo] : renderBufferQueue_) {
producerBufferQueue_.push(bufferInfo);
@@ -206,6 +185,7 @@ VPEAlgoErrCode VpeVideoImpl::Flush()
ClearConsumerLocked(tempQueue1);
ClearConsumerLocked(tempQueue2);
} else {
CHECK_AND_RETURN_RET_LOG(producer_ != nullptr, VPE_ALGO_ERR_INVALID_OPERATION, "output surface is null!");
producer_->CleanCache(false);
ClearBufferQueues();
}
@@ -241,25 +221,30 @@ VPEAlgoErrCode VpeVideoImpl::Disable()
CHECK_AND_RETURN_RET_LOG(isEnable_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "Already disabled!");
std::lock_guard<std::mutex> lock(lock_);
isEnable_ = false;
isEnableChange_ = true;
VPE_LOGD("requestCfg_({ %{public}s })", ToString(requestCfg_).c_str());
return VPE_ALGO_ERR_OK;
return DisableLocked();
}
VPEAlgoErrCode VpeVideoImpl::NotifyEos()
{
VPE_LOGD("step in.");
return ExecuteWhenNotIdle(
[this]() {
VPE_LOGD("Try to NotifyEos...");
{
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
if (!isBufferQueueReady_.load()) {
isBufferQueueReady_ = true;
VPE_LOGD("Use requestCfg_({ %{public}s }) to prepare buffers.", ToString(requestCfg_).c_str());
needPrepareBuffers_ = true;
}
SurfaceBufferInfo bufferInfo{};
bufferInfo.bufferFlag = VPE_BUFFER_FLAG_EOS;
consumerBufferQueue_.push(bufferInfo);
}
cvTrigger_.notify_one();
VPE_LOGD("NotifyEos done.");
return VPE_ALGO_ERR_OK;
}, "Notify EOS must be called during running!");
}, "Notify EOS must be called during running!", VPE_LOG_INFO);
}
VPEAlgoErrCode VpeVideoImpl::ReleaseOutputBuffer(uint32_t index, bool render)
@@ -283,7 +268,7 @@ bool VpeVideoImpl::IsInitialized() const
VPEAlgoErrCode VpeVideoImpl::Initialize()
{
VPE_LOGD("Start to initializing... this:%{public}p", this);
VPE_LOGD("Start to initializing... this:%p", this);
std::lock_guard<std::mutex> lock(lock_);
if (isInitialized_.load()) {
VPE_LOGD("Already initialize!");
@@ -302,33 +287,32 @@ VPEAlgoErrCode VpeVideoImpl::Initialize()
});
auto errorCode = OnInitialize();
isInitialized_ = true;
VPE_LOGD("OnInitialize() return %{public}d. this:%{public}p", errorCode, this);
VPE_LOGD("OnInitialize() return %{public}d. this:%p", errorCode, this);
return errorCode;
}
VPEAlgoErrCode VpeVideoImpl::Deinitialize()
{
VPE_LOGD("Start to deinitializing... this:%{public}p", this);
std::lock_guard<std::mutex> lock(lock_);
VPE_LOGD("Start to deinitializing... this:%p", this);
std::unique_lock<std::mutex> lock(lock_);
if (!isInitialized_.load()) {
VPE_LOGD("Already deinitialize!");
return VPE_ALGO_ERR_OK;
}
{
std::unique_lock<std::mutex> taskLock(taskLock_);
cvDone_.wait(taskLock, [this]() { return !isProcessing_.load(); });
}
isInitialized_ = false;
VPEAlgoErrCode errorCode = OnDeinitialize();
isRunning_.store(false);
isInitialized_.store(false);
if (state_.load() == VPEState::RUNNING) {
state_ = VPEState::STOPPING;
}
isRunning_ = false;
lock.unlock();
cvTrigger_.notify_one();
if (worker_.joinable()) {
VPE_LOGD("Wait for thread ending... this:%p", this);
worker_.join();
}
lock.lock();
CheckStoppingLocked();
VPEAlgoErrCode errorCode = OnDeinitialize();
cb_ = nullptr;
std::lock_guard<std::mutex> producerLock(producerLock_);
ClearBufferQueues();
@@ -341,12 +325,16 @@ VPEAlgoErrCode VpeVideoImpl::Deinitialize()
producer_->CleanCache(true);
producer_ = nullptr;
}
VPE_LOGD("OnDeinitialize() return %{public}d. this:%{public}p", errorCode, this);
VPE_LOGD("OnDeinitialize() return %{public}d. this:%p", errorCode, this);
return errorCode;
}
void VpeVideoImpl::RefreshBuffers()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
std::lock_guard<std::mutex> lock(lock_);
if (state_.load() != VPEState::RUNNING) {
VPE_LOGD("Skip refreshing during Non-Running.");
@@ -368,6 +356,10 @@ void VpeVideoImpl::RefreshBuffers()
void VpeVideoImpl::OnOutputFormatChanged(const Format& format)
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
std::lock_guard<std::mutex> lock(lock_);
if (cb_ != nullptr) {
VPE_LOGD("OnOutputFormatChanged()");
@@ -391,11 +383,26 @@ VPEAlgoErrCode VpeVideoImpl::Process([[maybe_unused]] const sptr<SurfaceBuffer>&
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode VpeVideoImpl::ResetAfterDisable()
{
return VPE_ALGO_ERR_OK;
}
bool VpeVideoImpl::IsDisableAfterProcessFail()
{
return true;
}
bool VpeVideoImpl::IsProducerSurfaceValid([[maybe_unused]] const sptr<Surface>& surface)
{
return true;
}
bool VpeVideoImpl::IsConsumerBufferValid([[maybe_unused]] const sptr<SurfaceBuffer>& buffer)
{
return true;
}
VPEAlgoErrCode VpeVideoImpl::UpdateRequestCfg([[maybe_unused]] const sptr<Surface>& surface,
[[maybe_unused]] BufferRequestConfig& requestCfg)
{
@@ -410,7 +417,7 @@ void VpeVideoImpl::UpdateRequestCfg([[maybe_unused]] const sptr<SurfaceBuffer>&
void VpeVideoImpl::OnError(VPEAlgoErrCode errorCode)
{
if (cb_ != nullptr) {
VPE_LOGD("OnError(%{public}d)", errorCode);
VPE_LOGD("OnError(%{public}s)", AlgorithmUtils::ToString(errorCode).c_str());
cb_->OnError(errorCode);
}
}
@@ -418,7 +425,7 @@ void VpeVideoImpl::OnError(VPEAlgoErrCode errorCode)
void VpeVideoImpl::OnStateLocked(VPEAlgoState state)
{
if (cb_ != nullptr) {
VPE_LOGD("OnState(%{public}d)", state);
VPE_LOGD("OnState(%{public}s)", AlgorithmUtils::ToString(state).c_str());
cb_->OnState(state);
}
}
@@ -441,6 +448,10 @@ void VpeVideoImpl::OnOutputBufferAvailable(uint32_t index, const VpeBufferInfo&
GSError VpeVideoImpl::OnConsumerBufferAvailable()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> lock(lock_);
CHECK_AND_RETURN_RET_LOG(consumer_ != nullptr, GSERROR_OK, "Input surface is null!");
if (state_.load() != VPEState::RUNNING) {
@@ -449,14 +460,22 @@ GSError VpeVideoImpl::OnConsumerBufferAvailable()
}
SurfaceBufferInfo bufferInfo{};
int releaseFence = -1;
OHOS::Rect damage;
GSError err = consumer_->AcquireBuffer(bufferInfo.buffer, releaseFence, bufferInfo.timestamp, damage);
GSError err = consumer_->AcquireBuffer(bufferInfo.buffer, bufferInfo.fence, bufferInfo.timestamp, damage);
if (err != GSERROR_OK || bufferInfo.buffer == nullptr) {
VPE_LOGE("Failed to acquire buffer!");
VPE_LOGE("Failed to acquire buffer, ret:%{public}s!", AlgorithmUtils::ToString(err).c_str());
return err;
}
if (bufferInfo.fence != nullptr) [[likely]] {
bufferInfo.fence->Wait(WAIT_FOR_EVER);
} else [[unlikely]] {
VPE_LOGW("Fence is null for { %{public}s }", ToString(bufferInfo.buffer).c_str());
}
VPE_LOGD("consumer_->AcquireBuffer({ %{public}s })", ToString(bufferInfo.buffer).c_str());
if (!IsConsumerBufferValid(bufferInfo.buffer)) {
VPE_LOGD("Invalid buffer:{ %{public}s }", ToString(bufferInfo.buffer).c_str());
DisableLocked();
}
lastConsumerBufferId_ = bufferInfo.buffer->GetSeqNum();
{
@@ -479,6 +498,10 @@ GSError VpeVideoImpl::OnConsumerBufferAvailable()
GSError VpeVideoImpl::OnProducerBufferReleased()
{
VPE_LOGD("step in");
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return GSERROR_OK;
}
std::lock_guard<std::mutex> producerLock(producerLock_);
CHECK_AND_RETURN_RET_LOG(producer_ != nullptr, GSERROR_OK, "Output surface is null!");
@@ -486,12 +509,12 @@ GSError VpeVideoImpl::OnProducerBufferReleased()
std::lock_guard<std::mutex> bufferLock(bufferLock_);
GSError err = GSERROR_OK;
SurfaceBufferInfo bufferInfo{};
CHECK_AND_RETURN_RET_LOG(RequestBuffer(bufferInfo, err), err, "Failed to request buffer!");
CHECK_AND_RETURN_RET_LOG(RequestBuffer(bufferInfo, err, VPE_LOG_INFO_EX), err, "Failed to request buffer!");
PopBuffer(flushBufferQueue_, bufferInfo.buffer->GetSeqNum(), bufferInfo,
[this](sptr<SurfaceBuffer>& buffer) {
VPE_LOGD("OnProducerBufferReleased: Pop flush buffer { %{public}s } flushBQ=%{public}zu",
ToString(buffer).c_str(), flushBufferQueue_.size());
});
}, VPE_LOG_INFO_EX);
}
if (state_.load() != VPEState::IDLE) {
cvTrigger_.notify_one();
@@ -500,8 +523,68 @@ GSError VpeVideoImpl::OnProducerBufferReleased()
return GSERROR_OK;
}
bool VpeVideoImpl::CheckEnableNotifyStatus(bool isEnable, const std::string& status)
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return false;
}
std::lock_guard<std::mutex> lock(lock_);
CHECK_AND_RETURN_RET_LOG(isEnableChange_.load(), false, "Oops! Keep enable:%{public}d", isEnable_.load());
if (isEnable_.load() != isEnable) {
VPE_LOGD("Try to notify '%{public}s' but enable:%{public}d", status.c_str(), isEnable_.load());
return false;
}
isEnableChange_ = false;
return true;
}
VPEAlgoErrCode VpeVideoImpl::DisableLocked()
{
CHECK_AND_RETURN_RET_LOG(isEnable_.load(), VPE_ALGO_ERR_INVALID_OPERATION, "Already disabled!");
isEnable_ = false;
isEnableChange_ = true;
VPE_LOGD("requestCfg_({ %{public}s })", ToString(requestCfg_).c_str());
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode VpeVideoImpl::UpdateProducerLocked()
{
auto transform = consumer_->GetTransform();
GSError err;
if (isForceUpdateProducer_ || lastTransform_ != transform) {
err = producer_->SetTransform(transform);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetTransform(%{public}d), ret:%{public}s!", transform, AlgorithmUtils::ToString(err).c_str());
lastTransform_ = transform;
VPE_LOGD("producer_->SetTransform(%{public}d) success.", transform);
}
if (lastConsumerBufferId_ == 0) {
return VPE_ALGO_ERR_OK;
}
ScalingMode scaleMode;
err = consumer_->GetScalingMode(lastConsumerBufferId_, scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to GetScalingMode(%{public}u), ret:%{public}s!",
lastConsumerBufferId_, AlgorithmUtils::ToString(err).c_str());
if (isForceUpdateProducer_ || lastScalingMode_ != scaleMode) {
err = producer_->SetScalingMode(scaleMode);
CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, VPE_ALGO_ERR_UNKNOWN,
"Failed to SetScalingMode(%{public}d), ret:%{public}s!", scaleMode, AlgorithmUtils::ToString(err).c_str());
lastScalingMode_ = scaleMode;
VPE_LOGD("producer_->SetScalingMode(%{public}d) success.", scaleMode);
}
isForceUpdateProducer_ = false;
return VPE_ALGO_ERR_OK;
}
VPEAlgoErrCode VpeVideoImpl::RenderOutputBuffer(uint32_t index, int64_t renderTimestamp, bool render)
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return VPE_ALGO_ERR_INVALID_OPERATION;
}
std::unique_lock<std::mutex> bufferLock(bufferLock_);
auto it = renderBufferQueue_.find(index);
CHECK_AND_RETURN_RET_LOG(it != renderBufferQueue_.end(), VPE_ALGO_ERR_INVALID_PARAM,
@@ -519,14 +602,20 @@ VPEAlgoErrCode VpeVideoImpl::RenderOutputBuffer(uint32_t index, int64_t renderTi
std::lock_guard<std::mutex> producerLock(producerLock_);
CHECK_AND_RETURN_RET_LOG(producer_ != nullptr, VPE_ALGO_ERR_INVALID_OPERATION, "Output surface is null!");
auto ret = producer_->FlushBuffer(bufferInfo.buffer, -1, flushcfg);
VPE_LOGD("producer_->FlushBuffer({ %{public}s })=%{public}d flushBQ=%{public}zu",
ToString(bufferInfo.buffer).c_str(), ret, flushBufferQueue_.size() + 1);
VPE_LOGD("producer_(%{public}llu)->FlushBuffer({ %{public}s })=%{public}s flushBQ=%{public}zu",
producer_->GetUniqueId(), ToString(bufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret).c_str(),
flushBufferQueue_.size() + 1);
if (ret != GSERROR_OK) {
return VPE_ALGO_ERR_UNKNOWN;
}
}
bufferLock.lock();
flushBufferQueue_.push(bufferInfo);
auto itCache = producerBufferCache_.find(bufferInfo.buffer->GetSeqNum());
if (itCache != producerBufferCache_.end()) {
itCache->second.isFlushed = true;
itCache->second.flushedTime = std::chrono::steady_clock::now();
}
} else {
VPE_LOGD("reback { %{public}s } producerBQ=%{public}zu",
ToString(bufferInfo.buffer).c_str(), producerBufferQueue_.size() + 1);
@@ -563,31 +652,36 @@ sptr<Surface> VpeVideoImpl::CreateConsumerSurfaceLocked()
return producerSurface;
}
bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode)
bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode,
const LogInfoEx& logInfos)
{
CHECK_AND_RETURN_RET_LOG(hasConsumer_.load(), false, "Input surface is null!");
int releaseFence = -1;
errorCode = producer_->RequestBuffer(bufferInfo.buffer, releaseFence, requestCfg_);
errorCode = producer_->RequestBuffer(bufferInfo.buffer, bufferInfo.fence, requestCfg_);
if (errorCode != GSERROR_OK || bufferInfo.buffer == nullptr) {
VPE_LOGW("Failed to producer_->RequestBuffer(requestCfg={ %{public}s })", ToString(requestCfg_).c_str());
VPE_EX_LOGW(logInfos, "Failed to producer_(%{public}llu)->RequestBuffer(requestCfg={ %{public}s }), "
"ret:%{public}s", producer_->GetUniqueId(),
ToString(requestCfg_).c_str(), AlgorithmUtils::ToString(errorCode).c_str());
return false;
}
producerBufferQueue_.push(bufferInfo);
AddBufferToCache(bufferInfo);
if (!isEnable_.load()) {
VPE_LOGD("producer_->RequestBuffer({ %{public}s }) and try to release.", ToString(bufferInfo.buffer).c_str());
VPE_EX_LOGD(logInfos, "producer_(%{public}llu)->RequestBuffer({ %{public}s }) and try to release.",
producer_->GetUniqueId(), ToString(bufferInfo.buffer).c_str());
auto it = attachBufferIDs_.find(bufferInfo.buffer->GetSeqNum());
if (it != attachBufferIDs_.end()) {
PopBuffer(attachBufferQueue_, bufferInfo.buffer->GetSeqNum(), bufferInfo,
[this](sptr<SurfaceBuffer>& buffer) {
[this, &logInfos](sptr<SurfaceBuffer>& buffer) {
CHECK_AND_RETURN_LOG(buffer != nullptr, "Attach buffer is null!");
attachBufferIDs_.erase(buffer->GetSeqNum());
auto ret = consumer_->ReleaseBuffer(buffer, -1);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}d cache=%{public}zu",
ToString(buffer).c_str(), ret, attachBufferQueue_.size());
});
VPE_EX_LOGD(logInfos, "consumer_->ReleaseBuffer({ %{public}s })=%{public}s cache=%{public}zu",
ToString(buffer).c_str(), AlgorithmUtils::ToString(ret).c_str(), attachBufferQueue_.size());
}, ADD_VPE_LOG_INFO(logInfos));
}
} else {
VPE_LOGD("producer_->RequestBuffer({ %{public}s })", ToString(bufferInfo.buffer).c_str());
VPE_EX_LOGD(logInfos, "producer_(%{public}llu)->RequestBuffer({ %{public}s })", producer_->GetUniqueId(),
ToString(bufferInfo.buffer).c_str());
if (attachBufferQueue_.empty()) {
return true;
}
@@ -596,8 +690,8 @@ bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCo
if (bufferInfo.buffer != nullptr) {
attachBufferIDs_.erase(bufferInfo.buffer->GetSeqNum());
auto ret = consumer_->ReleaseBuffer(bufferInfo.buffer, -1);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}d cache->%{public}zu",
ToString(bufferInfo.buffer).c_str(), ret, attachBufferQueue_.size());
VPE_EX_LOGD(logInfos, "consumer_->ReleaseBuffer({ %{public}s })=%{public}s cache->%{public}zu",
ToString(bufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret).c_str(), attachBufferQueue_.size());
}
}
return true;
@@ -605,41 +699,59 @@ bool VpeVideoImpl::RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCo
void VpeVideoImpl::PrepareBuffers()
{
std::lock_guard<std::mutex> lock(lock_);
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
CHECK_AND_RETURN_LOG(producer_ != nullptr, "producer is null!");
for (uint32_t i = 0; i < producer_->GetQueueSize(); i++) {
uint32_t cacheSize = producerBufferCache_.size();
VPE_LOGD("producerBufferCache_.size=%{public}u", cacheSize);
for (uint32_t i = cacheSize; i < producer_->GetQueueSize(); i++) {
GSError errorCode;
SurfaceBufferInfo bufferInfo{};
RequestBuffer(bufferInfo, errorCode);
VPE_LOGD("<%{public}u> RequestBuffer({ %{public}s })=%{public}d", i, ToString(requestCfg_).c_str(), errorCode);
RequestBuffer(bufferInfo, errorCode, VPE_LOG_INFO_EX);
VPE_LOGD("<%{public}u> RequestBuffer({ %{public}s })=%{public}s", i, ToString(requestCfg_).c_str(),
AlgorithmUtils::ToString(errorCode).c_str());
}
}
void VpeVideoImpl::AttachAndRefreshProducerBuffers(const sptr<Surface>& producer)
bool VpeVideoImpl::AttachAndRefreshProducerBuffers(const sptr<Surface>& producer)
{
std::lock_guard<std::mutex> bufferLock(bufferLock_);
needPrepareBuffersForNewProducer_ = true;
CheckAndUpdateProducerCache();
for (auto& [index, bufferInfo] : producerBufferCache_) {
auto errorCode = producer->AttachBufferToQueue(bufferInfo.buffer);
CHECK_AND_RETURN_RET_LOG(errorCode == GSERROR_OK, false,
"Failed to producer(%{public}llu)->AttachBufferToQueue({ %{public}s })=%{public}s", producer->GetUniqueId(),
ToString(bufferInfo.buffer).c_str(), AlgorithmUtils::ToString(errorCode).c_str());
VPE_LOGD("producer(%{public}llu)->AttachBufferToQueue({ %{public}s })", producer->GetUniqueId(),
ToString(bufferInfo.buffer).c_str());
}
std::set<uint32_t> producerBufferIDs{};
std::queue<SurfaceBufferInfo> tempQueue;
producerBufferQueue_.swap(tempQueue);
AttachBuffers(producer, tempQueue);
RefreshProducerBuffers(flushBufferQueue_, [](SurfaceBufferInfo&) { return true; });
AddProducerBuffers(tempQueue, producerBufferIDs);
AddProducerBuffers(flushBufferQueue_, producerBufferIDs);
if (producerBufferQueue_.size() + renderBufferQueue_.size() >= producerBufferCache_.size()) {
VPE_LOGD("producerBQ:%{public}zu renderBQ:%{public}zu flushBQ:%{public}zu attachBQ:%{public}zu "
"producerBufferCache_:%{public}zu",
producerBufferQueue_.size(), renderBufferQueue_.size(), flushBufferQueue_.size(),
attachBufferQueue_.size(), producerBufferCache_.size());
return true;
}
VPE_LOGD("Add cache buffers to producerBQ");
for (auto& [index, bufferInfo] : producerBufferCache_) {
if (producerBufferIDs.count(index) > 0) {
continue;
}
VPE_LOGD("Add { %{public}s } to producerBQ", ToString(bufferInfo.buffer).c_str());
producerBufferQueue_.push(bufferInfo);
}
return true;
}
void VpeVideoImpl::AttachBuffers(const sptr<Surface>& producer, std::queue<SurfaceBufferInfo>& bufferQueue)
{
RefreshProducerBuffers(bufferQueue,
[&producer](SurfaceBufferInfo& bufferInfo) {
auto errorCode = producer->AttachBufferToQueue(bufferInfo.buffer);
if (errorCode != GSERROR_OK) {
VPE_LOGW("AttachBuffers: Failed to producer->AttachBufferToQueue({ %{public}s })=%{public}d",
ToString(bufferInfo.buffer).c_str(), errorCode);
return false;
}
return true;
});
}
void VpeVideoImpl::RefreshProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue,
std::function<bool(SurfaceBufferInfo&)>&& refresher)
void VpeVideoImpl::AddProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue, std::set<uint32_t>& producerBufferIDs)
{
for (; !bufferQueue.empty(); bufferQueue.pop()) {
auto bufferInfo = bufferQueue.front();
@@ -647,52 +759,95 @@ void VpeVideoImpl::RefreshProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQ
VPE_LOGW("buffer is null!");
continue;
}
if (!refresher(bufferInfo)) {
producerBufferIDs.insert(bufferInfo.buffer->GetSeqNum());
producerBufferQueue_.push(bufferInfo);
}
}
void VpeVideoImpl::AddBufferToCache(const SurfaceBufferInfo& bufferInfo)
{
CHECK_AND_RETURN_LOG(bufferInfo.buffer != nullptr, "buffer is null!");
auto it = producerBufferCache_.find(bufferInfo.buffer->GetSeqNum());
if (it != producerBufferCache_.end()) {
it->second.isFlushed = false;
VPE_LOGD("Refresh { %{public}s } of producerBufferCache_.size:%{public}zu",
ToString(bufferInfo.buffer).c_str(), producerBufferCache_.size());
return;
}
uint32_t size = producerBufferCache_.size();
producerBufferCache_[bufferInfo.buffer->GetSeqNum()] = bufferInfo;
VPE_LOGD("Add { %{public}s } to producerBufferCache_.size:%{public}u->%{public}zu",
ToString(bufferInfo.buffer).c_str(), size, producerBufferCache_.size());
CheckAndUpdateProducerCache();
}
void VpeVideoImpl::DelBufferFromCache(const SurfaceBufferInfo& bufferInfo)
{
CHECK_AND_RETURN_LOG(bufferInfo.buffer != nullptr, "buffer is null!");
uint32_t size = producerBufferCache_.size();
producerBufferCache_.erase(bufferInfo.buffer->GetSeqNum());
VPE_LOGD("Del { %{public}s } from producerBufferCache_.size:%{public}u->%{public}zu",
ToString(bufferInfo.buffer).c_str(), size, producerBufferCache_.size());
}
void VpeVideoImpl::CheckAndUpdateProducerCache()
{
uint32_t size = producerBufferCache_.size();
if (size <= BUFFER_QUEUE_SIZE) {
return;
}
std::list<SurfaceBufferInfo> toBeDel;
for (auto& [index, info] : producerBufferCache_) {
if (!info.isFlushed) {
continue;
}
producerBufferQueue_.push(bufferInfo);
for (auto it = toBeDel.begin(); it != toBeDel.end(); it++) {
if (info.flushedTime < it->flushedTime) {
toBeDel.insert(it, info);
continue;
}
}
toBeDel.push_back(info);
}
for (auto it = toBeDel.begin(); it != toBeDel.end(); it++) {
size = producerBufferCache_.size();
producerBufferCache_.erase(it->buffer->GetSeqNum());
VPE_LOGD("Del { %{public}s } from producerBufferCache_.size:%{public}u->%{public}zu",
ToString(it->buffer).c_str(), size, producerBufferCache_.size());
if (producerBufferCache_.size() <= BUFFER_QUEUE_SIZE) {
break;
}
}
}
void VpeVideoImpl::ProcessBuffers()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
{
std::lock_guard<std::mutex> lock(lock_);
CHECK_AND_RETURN_LOG(consumer_ != nullptr && producer_ != nullptr, "consumer or producer is null!");
UpdateProducerLocked();
}
while (isRunning_.load()) {
std::lock_guard<std::mutex> taskLock(taskLock_);
isProcessing_ = true;
SurfaceBufferInfo srcBufferInfo;
SurfaceBufferInfo dstBufferInfo;
{
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
if (producerBufferQueue_.empty() || consumerBufferQueue_.empty()) {
break;
}
srcBufferInfo = consumerBufferQueue_.front();
if (srcBufferInfo.buffer == nullptr) {
consumerBufferQueue_.pop();
continue;
}
dstBufferInfo = producerBufferQueue_.front();
if (dstBufferInfo.buffer == nullptr) {
producerBufferQueue_.pop();
continue;
}
consumerBufferQueue_.pop();
producerBufferQueue_.pop();
if (!GetConsumerAndProducerBuffer(srcBufferInfo, dstBufferInfo)) {
break;
}
if (srcBufferInfo.bufferFlag == VPE_BUFFER_FLAG_EOS) {
VPE_LOGD("EOS frame.");
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {});
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {}, VPE_LOG_INFO);
break;
}
if (isEnable_.load()) {
if (!ProcessBuffer(srcBufferInfo, dstBufferInfo)) {
if (!ProcessBuffer(srcBufferInfo, dstBufferInfo) && IsDisableAfterProcessFail()) {
VPE_LOGD("Dsiable because failed to process !");
Disable();
continue;
}
} else {
@@ -705,12 +860,37 @@ void VpeVideoImpl::ProcessBuffers()
cvDone_.notify_all();
}
bool VpeVideoImpl::GetConsumerAndProducerBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo)
{
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
if (producerBufferQueue_.empty() || consumerBufferQueue_.empty()) {
return false;
}
srcBufferInfo = consumerBufferQueue_.front();
if (srcBufferInfo.buffer == nullptr && srcBufferInfo.bufferFlag != VPE_BUFFER_FLAG_EOS) {
consumerBufferQueue_.pop();
VPE_LOGW("input buffer is null!");
return false;
}
dstBufferInfo = producerBufferQueue_.front();
if (dstBufferInfo.buffer == nullptr) {
producerBufferQueue_.pop();
VPE_LOGW("output buffer is null!");
return false;
}
consumerBufferQueue_.pop();
producerBufferQueue_.pop();
return true;
}
bool VpeVideoImpl::ProcessBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo)
{
dstBufferInfo.timestamp = srcBufferInfo.timestamp;
auto errorCode = Process(srcBufferInfo.buffer, dstBufferInfo.buffer);
auto ret = consumer_->ReleaseBuffer(srcBufferInfo.buffer, -1);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}d", ToString(srcBufferInfo.buffer).c_str(), ret);
VPE_LOGD("consumer_->ReleaseBuffer({ %{public}s })=%{public}s", ToString(srcBufferInfo.buffer).c_str(),
AlgorithmUtils::ToString(ret).c_str());
if (errorCode != VPE_ALGO_ERR_OK) {
OnError(errorCode);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
@@ -719,39 +899,53 @@ bool VpeVideoImpl::ProcessBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBuffer
ToString(srcBufferInfo.buffer).c_str(), ToString(dstBufferInfo.buffer).c_str(), errorCode);
return false;
}
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {});
OutputBuffer(srcBufferInfo, dstBufferInfo, [] {}, VPE_LOG_INFO);
NotifyEnableStatus(type_, "enable");
return true;
}
void VpeVideoImpl::BypassBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo)
{
GSError ret1;
GSError ret2;
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return;
}
std::lock_guard<std::mutex> lock(lock_);
auto ret1 = producer_->DetachBufferFromQueue(dstBufferInfo.buffer);
auto ret2 = producer_->AttachBufferToQueue(srcBufferInfo.buffer);
ret1 = producer_->DetachBufferFromQueue(dstBufferInfo.buffer);
ret2 = producer_->AttachBufferToQueue(srcBufferInfo.buffer);
SetRequestCfgLocked(srcBufferInfo.buffer);
VPE_LOGD("producer_->DetachBufferFromQueue({ %{public}s })=%{public}d, "
"AttachBufferToQueue({ %{public}s })=%{public}d requestCfg:{ %{public}s }",
ToString(dstBufferInfo.buffer).c_str(), ret1,
ToString(srcBufferInfo.buffer).c_str(), ret2, ToString(requestCfg_).c_str());
VPE_LOGD("producer_(%{public}llu)->DetachBufferFromQueue({ %{public}s })=%{public}s, "
"AttachBufferToQueue({ %{public}s })=%{public}s requestCfg:{ %{public}s } ", producer_->GetUniqueId(),
ToString(dstBufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret1).c_str(),
ToString(srcBufferInfo.buffer).c_str(), AlgorithmUtils::ToString(ret2).c_str(),
ToString(requestCfg_).c_str());
}
OutputBuffer(srcBufferInfo, srcBufferInfo, [this, &srcBufferInfo] {
OutputBuffer(srcBufferInfo, srcBufferInfo, [this, &srcBufferInfo, &dstBufferInfo, &ret1, &ret2] {
attachBufferIDs_.insert(srcBufferInfo.buffer->GetSeqNum());
attachBufferQueue_.push(srcBufferInfo);
});
if (ret1 == GSERROR_OK) {
DelBufferFromCache(dstBufferInfo);
}
if (ret2 == GSERROR_OK) {
AddBufferToCache(srcBufferInfo);
}
}, VPE_LOG_INFO);
VPE_LOGD("cache(%{public}s)->%{public}zu/%{public}zu", ToString(srcBufferInfo.buffer).c_str(),
attachBufferIDs_.size(), attachBufferIDs_.size());
NotifyEnableStatus(0, "disable");
}
void VpeVideoImpl::OutputBuffer(const SurfaceBufferInfo& bufferInfo, const SurfaceBufferInfo& bufferImage,
std::function<void(void)>&& getReadyToRender)
std::function<void(void)>&& getReadyToRender, const LogInfo& logInfo)
{
{
std::lock_guard<std::mutex> bufferLock(bufferLock_);
renderBufferQueue_[bufferImage.buffer->GetSeqNum()] = bufferImage;
VPE_LOGD("renderBufferQueue_.push({ %{public}s })", ToString(bufferImage.buffer).c_str());
VPE_ORG_LOGD(logInfo, "renderBufferQueue_.push({ %{public}s }) size:%{public}zu",
ToString(bufferImage.buffer).c_str(), renderBufferQueue_.size());
getReadyToRender();
}
VpeBufferInfo info {
@@ -767,20 +961,25 @@ void VpeVideoImpl::NotifyEnableStatus(uint32_t type, const std::string& status)
VPE_LOGD("Keep %{public}s.", status.c_str());
return;
}
if (!CheckEnableNotifyStatus(type > 0, status)) {
return;
}
OnEffectChange(type);
std::lock_guard<std::mutex> lock(lock_);
isEnableChange_ = false;
if (type == 0) {
VPE_LOGD("Call ResetAfterDisable.");
ResetAfterDisable();
}
}
bool VpeVideoImpl::PopBuffer(std::queue<SurfaceBufferInfo>& bufferQueue, uint32_t index, SurfaceBufferInfo& bufferInfo,
std::function<void(sptr<SurfaceBuffer>&)>&& func)
std::function<void(sptr<SurfaceBuffer>&)>&& func, const LogInfoEx& logInfos)
{
bool isFound = false;
while (!bufferQueue.empty()) {
bufferInfo = bufferQueue.front();
bufferQueue.pop();
func(bufferInfo.buffer);
VPE_LOGD("index:%{public}u buffer:{ %{public}s }", index, ToString(bufferInfo.buffer).c_str());
VPE_EX_LOGD(logInfos, "index:%{public}u buffer:{ %{public}s }", index, ToString(bufferInfo.buffer).c_str());
if (bufferInfo.buffer != nullptr && bufferInfo.buffer->GetSeqNum() == index) {
isFound = true;
break;
@@ -811,28 +1010,36 @@ bool VpeVideoImpl::WaitTrigger()
{
uint32_t consumerSize = 0;
uint32_t producerSize = 0;
std::unique_lock<std::mutex> bufferLock(bufferLock_);
if (!cvTrigger_.wait_for(bufferLock, 200s, [this, &consumerSize, &producerSize] {
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
if (needPrepareBuffers_.load()) {
std::unique_lock<std::mutex> waitLock(waitLock_);
if (!cvTrigger_.wait_for(waitLock, 200s, [this, &consumerSize, &producerSize] {
if (!isRunning_.load()) {
VPE_LOGI("Skip WaitTrigger when died.");
return true;
}
if (needPrepareBuffers_.load() || needPrepareBuffersForNewProducer_.load()) {
std::lock_guard<std::mutex> lock(lock_);
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
PrepareBuffers();
needPrepareBuffers_ = false;
needPrepareBuffersForNewProducer_ = false;
}
std::lock_guard<std::mutex> consumerBufferLock(consumerBufferLock_);
std::lock_guard<std::mutex> bufferLock(bufferLock_);
consumerSize = consumerBufferQueue_.size();
producerSize = producerBufferQueue_.size();
VPE_LOGD("run:%d stopping:%d consumerBQ:%{public}u producerBQ:%{public}u "
VPE_LOGD("run:%{public}d stopping:%{public}d consumerBQ:%{public}u producerBQ:%{public}u "
"renderBQ:%{public}zu flushBQ:%{public}zu attachBQ:%{public}zu",
isRunning_.load(), state_.load() == VPEState::STOPPING, consumerSize, producerSize,
renderBufferQueue_.size(), flushBufferQueue_.size(), attachBufferQueue_.size());
return !isRunning_.load() || state_.load() == VPEState::STOPPING ||
(consumerSize > 0 && producerSize > 0);
return !isRunning_.load() || state_.load() == VPEState::STOPPING || (consumerSize > 0 && producerSize > 0);
})) {
VPE_LOGI("Video processing timeout.");
return false;
}
if (!isRunning_.load()) {
VPE_LOGI("Video processing clear.");
VPE_LOGI("die.");
return false;
}
if (consumerSize == 0 || producerSize == 0) {
@@ -852,6 +1059,10 @@ void VpeVideoImpl::CheckSpuriousWakeup()
bool VpeVideoImpl::CheckStopping()
{
if (!isRunning_.load()) {
VPE_LOGI("Skip when died.");
return true;
}
std::lock_guard<std::mutex> lock(lock_);
return CheckStoppingLocked();
}
@@ -876,11 +1087,13 @@ void VpeVideoImpl::ClearQueue(std::queue<SurfaceBufferInfo>& bufferQueue)
void VpeVideoImpl::ClearConsumerLocked(std::queue<SurfaceBufferInfo>& bufferQueue)
{
CHECK_AND_RETURN_LOG(consumer_ != nullptr, "input surface is null!");
while (!bufferQueue.empty()) {
auto bufferInfo = bufferQueue.front();
auto err = consumer_->ReleaseBuffer(bufferInfo.buffer, -1);
if (err != GSERROR_OK) {
VPE_LOGW("Failed to ReleaseBuffer({ %{public}s }):%{public}d", ToString(bufferInfo.buffer).c_str(), err);
VPE_LOGW("Failed to ReleaseBuffer({ %{public}s }):%{public}s", ToString(bufferInfo.buffer).c_str(),
AlgorithmUtils::ToString(err).c_str());
}
bufferQueue.pop();
}
@@ -898,6 +1111,7 @@ void VpeVideoImpl::ClearBufferQueues()
ClearQueue(producerBufferQueue_);
renderBufferQueue_.clear();
ClearQueue(flushBufferQueue_);
producerBufferCache_.clear();
attachBufferQueue_.swap(tempQueue2);
attachBufferIDs_.clear();
}
@@ -906,31 +1120,34 @@ void VpeVideoImpl::ClearBufferQueues()
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWhenIdle(std::function<VPEAlgoErrCode(void)>&& operation,
const std::string& errorMessage)
const std::string& errorMessage, const LogInfo& logInfo)
{
return ExecuteWithCheck([this] { return state_.load() == VPEState::IDLE; }, std::move(operation), errorMessage);
return ExecuteWithCheck([this] { return state_.load() == VPEState::IDLE; }, std::move(operation), errorMessage,
logInfo);
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWhenNotIdle(std::function<VPEAlgoErrCode(void)>&& operation,
const std::string& errorMessage)
const std::string& errorMessage, const LogInfo& logInfo)
{
return ExecuteWithCheck([this] { return state_.load() != VPEState::IDLE; }, std::move(operation), errorMessage);
return ExecuteWithCheck([this] { return state_.load() != VPEState::IDLE; }, std::move(operation), errorMessage,
logInfo);
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWhenRunning(std::function<VPEAlgoErrCode(void)>&& operation,
const std::string& errorMessage)
const std::string& errorMessage, const LogInfo& logInfo)
{
return ExecuteWithCheck([this] { return state_.load() == VPEState::RUNNING; }, std::move(operation), errorMessage);
return ExecuteWithCheck([this] { return state_.load() == VPEState::RUNNING; }, std::move(operation), errorMessage,
logInfo);
}
VPEAlgoErrCode VpeVideoImpl::ExecuteWithCheck(std::function<bool(void)>&& checker,
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage)
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage, const LogInfo& logInfo)
{
std::lock_guard<std::mutex> lock(lock_);
if (checker()) {
return operation();
}
VPE_LOGW("%{public}s", errorMessage.c_str());
VPE_ORG_LOGW(logInfo, "%{public}s", errorMessage.c_str());
return VPE_ALGO_ERR_INVALID_OPERATION;
}
@@ -21,6 +21,7 @@
#include "algorithm_errors.h"
#include "algorithm_video_common.h"
#include "surface_buffer.h"
#include "graphic_common_c.h"
#define VPE_TO_STR(val) (std::string(#val) + "(" + std::to_string(static_cast<int>(val)) + ")")
@@ -29,6 +30,7 @@ namespace Media {
namespace VideoProcessingEngine {
class AlgorithmUtils {
public:
static std::string ToString(GSError errorCode);
static std::string ToString(VPEAlgoErrCode errorCode);
static std::string ToString(VPEAlgoState state);
static bool CopySurfaceBufferToSurfaceBuffer(const sptr<SurfaceBuffer>& srcBuffer,
@@ -17,6 +17,7 @@
#define ALGORITHM_VIDEO_IMPL_H
#include <atomic>
#include <chrono>
#include <cinttypes>
#include <condition_variable>
#include <functional>
@@ -30,9 +31,12 @@
#include "refbase.h"
#include "surface.h"
#include "surface_buffer.h"
#include "sync_fence.h"
#include "algorithm_errors.h"
#include "algorithm_video.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
@@ -60,16 +64,23 @@ protected:
VpeVideoImpl(VpeVideoImpl&&) = delete;
VpeVideoImpl& operator=(VpeVideoImpl&&) = delete;
// These funcions may be called by derived class as necessary.
bool IsInitialized() const;
VPEAlgoErrCode Initialize();
VPEAlgoErrCode Deinitialize();
void RefreshBuffers();
void OnOutputFormatChanged(const Format& format);
// These funcions may be overried by derived class as necessary.
virtual VPEAlgoErrCode OnInitialize();
virtual VPEAlgoErrCode OnDeinitialize();
virtual VPEAlgoErrCode Process(const sptr<SurfaceBuffer>& sourceImage, sptr<SurfaceBuffer>& destinationImage);
// This function will be called after disable, you may reset such as timeout protection status in derived class.
// if you do NOT reset the protection status, the feature may not response properly when user call Enable() again.
virtual VPEAlgoErrCode ResetAfterDisable();
virtual bool IsDisableAfterProcessFail();
virtual bool IsProducerSurfaceValid(const sptr<Surface>& surface);
virtual bool IsConsumerBufferValid(const sptr<SurfaceBuffer>& buffer);
virtual VPEAlgoErrCode UpdateRequestCfg(const sptr<Surface>& surface, BufferRequestConfig& requestCfg);
virtual void UpdateRequestCfg(const sptr<SurfaceBuffer>& consumerBuffer, BufferRequestConfig& requestCfg);
@@ -82,8 +93,11 @@ private:
struct SurfaceBufferInfo {
sptr<SurfaceBuffer> buffer{};
sptr<SyncFence> fence{};
VpeBufferFlag bufferFlag{VPE_BUFFER_FLAG_NONE};
int64_t timestamp{};
bool isFlushed{};
std::chrono::time_point<std::chrono::steady_clock> flushedTime{};
};
class ConsumerListener : public IBufferConsumerListener {
@@ -109,23 +123,27 @@ private:
GSError OnConsumerBufferAvailable();
GSError OnProducerBufferReleased();
bool CheckEnableNotifyStatus(bool isEnable, const std::string& status);
VPEAlgoErrCode DisableLocked();
VPEAlgoErrCode UpdateProducerLocked();
VPEAlgoErrCode RenderOutputBuffer(uint32_t index, int64_t renderTimestamp, bool render);
sptr<Surface> CreateConsumerSurfaceLocked();
bool RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode);
bool RequestBuffer(SurfaceBufferInfo& bufferInfo, GSError& errorCode, const LogInfoEx& logInfos);
void PrepareBuffers();
void AttachAndRefreshProducerBuffers(const sptr<Surface>& producer);
void AttachBuffers(const sptr<Surface>& producer, std::queue<SurfaceBufferInfo>& bufferQueue);
void RefreshProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue,
std::function<bool(SurfaceBufferInfo&)>&& refresher);
bool AttachAndRefreshProducerBuffers(const sptr<Surface>& producer);
void AddProducerBuffers(std::queue<SurfaceBufferInfo>& bufferQueue, std::set<uint32_t>& producerBufferIDs);
void AddBufferToCache(const SurfaceBufferInfo& bufferInfo);
void DelBufferFromCache(const SurfaceBufferInfo& bufferInfo);
void CheckAndUpdateProducerCache();
void ProcessBuffers();
bool GetConsumerAndProducerBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo);
bool ProcessBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo);
void BypassBuffer(SurfaceBufferInfo& srcBufferInfo, SurfaceBufferInfo& dstBufferInfo);
void OutputBuffer(const SurfaceBufferInfo& bufferInfo, const SurfaceBufferInfo& bufferImage,
std::function<void(void)>&& getReadyToRender);
std::function<void(void)>&& getReadyToRender, const LogInfo& logInfo);
void NotifyEnableStatus(uint32_t type, const std::string& status);
bool PopBuffer(std::queue<SurfaceBufferInfo>& bufferQueue, uint32_t index, SurfaceBufferInfo& bufferInfo,
std::function<void(sptr<SurfaceBuffer>&)>&& func);
std::function<void(sptr<SurfaceBuffer>&)>&& func, const LogInfoEx& logInfos);
void PrintBufferSize() const;
void SetRequestCfgLocked(const sptr<SurfaceBuffer>& buffer);
bool WaitTrigger();
@@ -136,11 +154,14 @@ private:
void ClearConsumerLocked(std::queue<SurfaceBufferInfo>& bufferQueue);
void ClearBufferQueues();
VPEAlgoErrCode ExecuteWhenIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
VPEAlgoErrCode ExecuteWhenNotIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
VPEAlgoErrCode ExecuteWhenRunning(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
VPEAlgoErrCode ExecuteWhenIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage,
const LogInfo& logInfo);
VPEAlgoErrCode ExecuteWhenNotIdle(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage,
const LogInfo& logInfo);
VPEAlgoErrCode ExecuteWhenRunning(std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage,
const LogInfo& logInfo);
VPEAlgoErrCode ExecuteWithCheck(std::function<bool(void)>&& checker,
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage);
std::function<VPEAlgoErrCode(void)>&& operation, const std::string& errorMessage, const LogInfo& logInfo);
// Common
uint32_t type_{};
@@ -149,6 +170,15 @@ private:
std::condition_variable cvTrigger_{};
std::condition_variable cvDone_{};
// [WARNING]
// The lock must be held in the following order:
// waitLock_
// lock_
// taskLock_
// producerLock_
// consumerBufferLock_
// bufferLock_
mutable std::mutex waitLock_{};
mutable std::mutex lock_{};
// Guarded by lock_ begin
std::atomic<bool> isInitialized_{false};
@@ -184,9 +214,11 @@ private:
mutable std::mutex bufferLock_{};
// Guarded by bufferLock_ begin
std::atomic<bool> needPrepareBuffersForNewProducer_{false};
std::queue<SurfaceBufferInfo> producerBufferQueue_{};
std::unordered_map<uint32_t, SurfaceBufferInfo> renderBufferQueue_{};
std::queue<SurfaceBufferInfo> flushBufferQueue_{};
std::unordered_map<uint32_t, SurfaceBufferInfo> producerBufferCache_{};
std::queue<SurfaceBufferInfo> attachBufferQueue_{};
std::set<uint32_t> attachBufferIDs_{};
// Guarded by bufferLock_ end
@@ -0,0 +1,155 @@
/*
* 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_MODEL_PATH_H
#define VPE_MODEL_PATH_H
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
enum VpeModelKey {
VPE_MODE_KEY_INVALID = -1,
AILIGHT_NORMAL,
AILIGHT_STRONG,
AILIGHT_CLS,
AIHDR_PIC,
HDR_COMPOSE,
SDR_CONVERT,
HDR_DECOMPOSE,
IMAGE_AISR_ALGO_CONFIG,
IMAGE_SR_MODEL_0,
IMAGE_SR_MODEL_1,
IMAGE_SR_MODEL_2,
IMAGE_SR_MODEL_3,
IMAGE_SR_MODEL_4,
CALC_HIST_COMP_SHADER_0,
CALC_HIST_COMP_RGB_SHADER_1,
CALC_HIST_COMP_LIMIT_SHADER_1,
CALC_HIST_COMP_FULL_SHADER_1,
SDR2SDR_VIDEO_CONVERT_EBU_Y2Y,
SDR2SDR_VIDEO_CONVERT_EBU_Y2R,
SDR2SDR_VIDEO_CONVERT_EBU_R2Y,
SDR2SDR_VIDEO_CONVERT_EBU_R2R,
SDR2SDR_VIDEO_CONVERT_SMPTE_Y2Y,
SDR2SDR_VIDEO_CONVERT_SMPTE_Y2R,
SDR2SDR_VIDEO_CONVERT_SMPTE_R2Y,
SDR2SDR_VIDEO_CONVERT_SMPTE_R2R,
HDR2HDR_VIDEO_PQ2HLG_Y2Y,
HDR2HDR_VIDEO_PQ2HLG_Y2R,
HDR2HDR_VIDEO_PQ2HLG_R2Y,
HDR2HDR_VIDEO_PQ2HLG_R2R,
HDR2HDR_VIDEO_HLG2PQ_Y2Y,
HDR2HDR_VIDEO_HLG2PQ_Y2R,
HDR2HDR_VIDEO_HLG2PQ_R2Y,
HDR2HDR_VIDEO_HLG2PQ_R2R,
HDR2SDR_VIDEO_CONVERT_HLG_Y2Y,
HDR2SDR_VIDEO_CONVERT_HLG_Y2R,
HDR2SDR_VIDEO_CONVERT_HLG_R2Y,
HDR2SDR_VIDEO_CONVERT_HLG_R2R,
HDR2SDR_VIDEO_CONVERT_HLG_Y2Y_DEFAULT,
HDR2SDR_VIDEO_CONVERT_HLG_Y2R_DEFAULT,
HDR2SDR_VIDEO_CONVERT_HLG_R2Y_DEFAULT,
HDR2SDR_VIDEO_CONVERT_HLG_R2R_DEFAULT,
HDR2SDR_VIDEO_CONVERT_PQ_Y2Y,
HDR2SDR_VIDEO_CONVERT_PQ_Y2R,
HDR2SDR_VIDEO_CONVERT_PQ_R2Y,
HDR2SDR_VIDEO_CONVERT_PQ_R2R,
VIDEO_AISR_ALGO_CONFIG,
VIDEO_SR_MODEL_0,
VIDEO_SR_MODEL_1,
VIDEO_SR_MODEL_2,
VIDEO_SR_MODEL_3,
VIDEO_SR_MODEL_4,
VIDEO_SR_MODEL_5,
VIDEO_SR_MODEL_6,
VIDEO_SR_MODEL_7,
VIDEO_SR_BILINEAR_CL_KERNEL,
VIDEO_SR_BICUBIC_CL_KERNEL,
VIDEO_SR_SR_CL_KERNEL,
EVE_10bit_SCALE_KERNEL,
VIDEO_AIHDR_ALGO_CONFIG,
VIDEO_AIHDR_MODEL,
IMAGE_SR_10bit_CONVERT_KERNEL,
VPE_MODEL_KEY_NUM,
};
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",
"/sys_prod/etc/VideoProcessingEngine/aihdr_pic.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr_compose.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr_convert.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr_decompose.bin",
"/sys_prod/etc/VideoProcessingEngine/image_aisr_algo_config.xml",
"/sys_prod/etc/VideoProcessingEngine/Image_SR_Model_576x576_20240402.omc",
"/sys_prod/etc/VideoProcessingEngine/Image_SR_Model_848x1104_20240402.omc",
"/sys_prod/etc/VideoProcessingEngine/Image_SR_Model_1104x1488_20240402.omc",
"/sys_prod/etc/VideoProcessingEngine/Image_SR_Model_1488x1104_20240402.omc",
"/sys_prod/etc/VideoProcessingEngine/Image_SR_Model_1872x1360_20240402.omc",
"/sys_prod/etc/VideoProcessingEngine/calcHistCompShader0.bin",
"/sys_prod/etc/VideoProcessingEngine/calcHistCompRgbShader1.bin",
"/sys_prod/etc/VideoProcessingEngine/calcHistCompLimitShader1.bin",
"/sys_prod/etc/VideoProcessingEngine/calcHistCompFullShader1.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_ebu_y2y.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_ebu_y2r.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_ebu_r2y.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_ebu_r2r.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_smpte_y2y.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_smpte_y2r.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_smpte_r2y.bin",
"/sys_prod/etc/VideoProcessingEngine/sdr2sdr_video_convert_smpte_r2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_pq2hlg_y2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_pq2hlg_y2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_pq2hlg_r2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_pq2hlg_r2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_hlg2pq_y2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_hlg2pq_y2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_hlg2pq_r2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2hdr_video_hlg2pq_r2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_y2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_y2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_r2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_r2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_y2y_default.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_y2r_default.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_r2y_default.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_hlg_r2r_default.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_pq_y2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_pq_y2r.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_pq_r2y.bin",
"/sys_prod/etc/VideoProcessingEngine/hdr2sdr_video_pq_r2r.bin",
"/sys_prod/etc/VideoProcessingEngine/video_aisr_ohos_config.xml",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_576x576_2x.omc",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_576x1024_2x.omc",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_1024x576_2x.omc",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_768x1280_2x.omc",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_1280x768_2x.omc",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_1088x1920_1x.omc",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_1920x1088_1x.omc",
"/sys_prod/etc/VideoProcessingEngine/Video_SR_Model_1920x1920_1x.omc",
"/sys_prod/etc/VideoProcessingEngine/bilinear.bin",
"/sys_prod/etc/VideoProcessingEngine/bicubic.bin",
"/sys_prod/etc/VideoProcessingEngine/sr.bin",
"/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 // 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
@@ -13,27 +13,28 @@
* limitations under the License.
*/
#ifndef ALGORITHM_TYPES_H
#define ALGORITHM_TYPES_H
#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 {
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
namespace Extension {
struct ContrastEnhancerExtension : public ExtensionBase {
ContrastEnhancerCreator creator;
ContrastEnhancerCapabilitiesBuilder capabilitiesBuilder;
};
} // namespace Extension
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // ALGORITHM_TYPES_H
#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_) {