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
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef IVIDEO_PROCESSING_ALGORITHM_H
#define IVIDEO_PROCESSING_ALGORITHM_H
#include <cinttypes>
#include <string>
#include <vector>
#include "surface_buffer_info.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class IVideoProcessingAlgorithm {
public:
virtual int Initialize() = 0;
virtual int Deinitialize() = 0;
virtual bool HasClient() const = 0;
virtual int Add(const std::string& clientName, uint32_t& clientID) = 0;
virtual int Del(uint32_t clientID) = 0;
virtual int SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter) = 0;
virtual int GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter) = 0;
virtual int UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) = 0;
virtual int Process(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) = 0;
virtual int ComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy) = 0;
virtual int DecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap) = 0;
protected:
IVideoProcessingAlgorithm() = default;
virtual ~IVideoProcessingAlgorithm() = default;
IVideoProcessingAlgorithm(const IVideoProcessingAlgorithm&) = delete;
IVideoProcessingAlgorithm& operator=(const IVideoProcessingAlgorithm&) = delete;
IVideoProcessingAlgorithm(IVideoProcessingAlgorithm&&) = delete;
IVideoProcessingAlgorithm& operator=(IVideoProcessingAlgorithm&&) = delete;
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // IVIDEO_PROCESSING_ALGORITHM_H
@@ -0,0 +1,117 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VIDEO_PROCESSING_ALGORITHM_BASE_H
#define VIDEO_PROCESSING_ALGORITHM_BASE_H
#include <atomic>
#include <functional>
#include <mutex>
#include <string>
#include "algorithm_errors.h"
#include "ivideo_processing_algorithm.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VideoProcessingAlgorithmBase : public IVideoProcessingAlgorithm {
public:
int Initialize() final;
int Deinitialize() final;
bool HasClient() const final;
int Add(const std::string& clientName, uint32_t& clientID) final;
int Del(uint32_t clientID) final;
int UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) final;
int Process(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) final;
int ComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy) final;
int DecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap) final;
protected:
VideoProcessingAlgorithmBase(const std::string& feature, uint32_t id) : feature_(feature), featureID_(id) {}
virtual ~VideoProcessingAlgorithmBase() = default;
VideoProcessingAlgorithmBase(const VideoProcessingAlgorithmBase&) = delete;
VideoProcessingAlgorithmBase& operator=(const VideoProcessingAlgorithmBase&) = delete;
VideoProcessingAlgorithmBase(VideoProcessingAlgorithmBase&&) = delete;
VideoProcessingAlgorithmBase& operator=(VideoProcessingAlgorithmBase&&) = delete;
// Note: called by algorithm derived classes
virtual inline bool IsValid(const SurfaceBufferInfo& info) const // Derived classes can modify the checker if needed
{
return info.surfacebuffer != nullptr;
}
template <typename T>
static inline int CallSetParameter(std::function<int(const T&)>&& setter, const std::vector<uint8_t>& parameter,
const LogInfo& logInfo)
{
if (parameter.size() != sizeof(T)) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: size=%{public}zu(Expected:%{public}zu)!",
parameter.size(), sizeof(T));
return VPE_ALGO_ERR_INVALID_VAL;
}
return setter(*reinterpret_cast<const T*>(parameter.data()));
}
template <typename T>
static inline int CallGetParameter(std::function<int(T&)>&& getter, std::vector<uint8_t>& parameter)
{
parameter.resize(sizeof(T));
return getter(*reinterpret_cast<T*>(parameter.data()));
}
// Note: implement by algorithm derived classes
virtual int OnInitializeLocked();
virtual int OnDeinitializeLocked();
virtual int AddClientIDLocked(const std::string& clientName, uint32_t& clientID);
virtual int DelClientIDLocked(uint32_t clientID, bool& isEmpty);
virtual size_t GetClientSizeLocked() const;
virtual void ClearClientsLocked();
virtual int DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image);
virtual int DoProcess(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output);
virtual int DoComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy);
virtual int DoDecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap);
int ReturnNotSupport(const LogInfo& logInfo) const;
bool GenerateClientID(std::function<bool(uint32_t)>&& isDuplicate, uint32_t& clientID);
// Note: Data members to be accessed by algorithm derived classes
const std::string feature_{};
uint32_t featureID_{};
mutable std::mutex lock_{};
// Guarded by lock_ begin
bool isInitialized_{};
// Guarded by lock_ end
private:
uint32_t GenerateClientID();
// Guarded by lock_ begin
std::atomic<bool> hasClient_{};
uint32_t clientIdBase_{};
// Guarded by lock_ end
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_BASE_H
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VIDEO_PROCESSING_ALGORITHM_FACTORY_H
#define VIDEO_PROCESSING_ALGORITHM_FACTORY_H
#include <memory>
#include <string>
#include "ivideo_processing_algorithm.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VideoProcessingAlgorithmFactory {
public:
VideoProcessingAlgorithmFactory();
~VideoProcessingAlgorithmFactory();
VideoProcessingAlgorithmFactory(const VideoProcessingAlgorithmFactory&) = delete;
VideoProcessingAlgorithmFactory& operator=(const VideoProcessingAlgorithmFactory&) = delete;
VideoProcessingAlgorithmFactory(VideoProcessingAlgorithmFactory&&) = delete;
VideoProcessingAlgorithmFactory& operator=(VideoProcessingAlgorithmFactory&&) = delete;
std::shared_ptr<IVideoProcessingAlgorithm> Create(const std::string& feature) const;
private:
bool LoadDynamicAlgorithm(const std::string& path);
void UnloadDynamicAlgorithm();
void GenerateFeatureIDs();
void* handle_{};
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_FACTORY_H
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VIDEO_PROCESSING_ALGORITHM_FACTORY_COMMON_H
#define VIDEO_PROCESSING_ALGORITHM_FACTORY_COMMON_H
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include "ivideo_processing_algorithm.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
using VpeAlgorithmCreator = std::function<std::shared_ptr<IVideoProcessingAlgorithm>(const std::string&, uint32_t)>;
struct VpeAlgorithmCreatorInfo {
uint32_t id;
VpeAlgorithmCreator creator;
};
using VpeAlgorithmCreatorMap = std::unordered_map<std::string, VpeAlgorithmCreatorInfo>;
// NOTE:
// All algorithms MUST be derived from VideoProcessingAlgorithmWithData or VideoProcessingAlgorithmWithoutData.
// And algorithms MUST keep the input parameters of constructor like (const std::string& feature, uint32_t id).
template <typename T>
std::shared_ptr<IVideoProcessingAlgorithm> CreateVpeAlgorithm(const std::string& feature, uint32_t id)
{
return std::make_shared<T>(feature, id);
}
template <typename T>
VpeAlgorithmCreatorInfo MakeCreator()
{
VpeAlgorithmCreatorInfo info {
.id = 0,
.creator = CreateVpeAlgorithm<T>,
};
return info;
}
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_FACTORY_COMMON_H
@@ -0,0 +1,233 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VIDEO_PROCESSING_ALGORITHM_WITH_DATA_H
#define VIDEO_PROCESSING_ALGORITHM_WITH_DATA_H
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include "algorithm_errors.h"
#include "video_processing_algorithm_base.h"
#include "vpe_log.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
template <typename T>
class VideoProcessingAlgorithmWithData : public VideoProcessingAlgorithmBase {
public:
int SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter) final
{
auto set = &VideoProcessingAlgorithmWithData::OnSetParameter;
return Execute(clientID, std::bind(set, this, std::placeholders::_1, tag, parameter), VPE_LOG_INFO);
}
int GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter) final
{
auto get = &VideoProcessingAlgorithmWithData::OnGetParameter;
return Execute(clientID, std::bind(get, this, std::placeholders::_1, tag, parameter), VPE_LOG_INFO);
}
int DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) final
{
auto update = &VideoProcessingAlgorithmWithData::OnUpdateMetadata;
return Execute(clientID, std::bind(update, this, std::placeholders::_1, image), VPE_LOG_INFO);
}
int DoProcess(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) final
{
auto process = &VideoProcessingAlgorithmWithData::OnProcess;
return Execute(clientID, std::bind(process, this, std::placeholders::_1, input, output), VPE_LOG_INFO);
}
int DoComposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap,
SurfaceBufferInfo& outputHdrImage, bool legacy) final
{
auto compose = &VideoProcessingAlgorithmWithData::OnComposeImage;
return Execute(clientID,
std::bind(compose, this, std::placeholders::_1, inputSdrImage, inputGainmap, outputHdrImage, legacy),
VPE_LOG_INFO);
}
int DoDecomposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage,
SurfaceBufferInfo& outputGainmap) final
{
auto decompose = &VideoProcessingAlgorithmWithData::OnDecomposeImage;
return Execute(clientID,
std::bind(decompose, this, std::placeholders::_1, inputImage, outputSdrImage, outputGainmap), VPE_LOG_INFO);
}
protected:
using ClientInfo = std::pair<std::string, std::shared_ptr<T>>;
VideoProcessingAlgorithmWithData(const std::string& feature, uint32_t id)
: VideoProcessingAlgorithmBase(feature, id) {}
virtual ~VideoProcessingAlgorithmWithData() = default;
VideoProcessingAlgorithmWithData(const VideoProcessingAlgorithmWithData&) = delete;
VideoProcessingAlgorithmWithData& operator=(const VideoProcessingAlgorithmWithData&) = delete;
VideoProcessingAlgorithmWithData(VideoProcessingAlgorithmWithData&&) = delete;
VideoProcessingAlgorithmWithData& operator=(VideoProcessingAlgorithmWithData&&) = delete;
// NOTE: Would be override by the actual algorithm when necessary.
// The input ClientInfo& clientInfo is already checked for all OnXXX functions.
// It's NOT necessary to check clientInfo.second whether is nullptr.
// Actual methods begin
// int OnInitializeLocked() - declared by VideoProcessingAlgorithmBase
// int OnDeinitializeLocked() - declared by VideoProcessingAlgorithmBase
virtual int OnContextInitializeLocked([[maybe_unused]] ClientInfo& clientInfo)
{
return VPE_ALGO_ERR_OK;
}
virtual int OnContextDeinitializeLocked([[maybe_unused]] ClientInfo& clientInfo)
{
return VPE_ALGO_ERR_OK;
}
virtual int OnSetParameter([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] int tag, [[maybe_unused]] const std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnGetParameter([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] int tag, [[maybe_unused]] std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnUpdateMetadata([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] SurfaceBufferInfo& image)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnProcess([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] const SurfaceBufferInfo& input,
[[maybe_unused]] SurfaceBufferInfo& output)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnComposeImage([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] const SurfaceBufferInfo& inputSdrImage,
[[maybe_unused]] const SurfaceBufferInfo& inputGainmap,
[[maybe_unused]] SurfaceBufferInfo& outputHdrImage, [[maybe_unused]] bool legacy)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
virtual int OnDecomposeImage([[maybe_unused]] ClientInfo& clientInfo,
[[maybe_unused]] const SurfaceBufferInfo& inputImage,
[[maybe_unused]] SurfaceBufferInfo& outputSdrImage,
[[maybe_unused]] SurfaceBufferInfo& outputGainmap)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
// Actual methods end
// Utils methods would be called by the derived algorithm class
ClientInfo GetContext(uint32_t clientID)
{
std::lock_guard<std::mutex>lock(lock_);
return GetContextLocked(clientID);
}
ClientInfo GetContextLocked(uint32_t clientID)
{
auto it = contexts_.find(clientID);
if (it == contexts_.end()) [[unlikely]] {
return std::make_pair("", nullptr);
}
return it->second;
}
private:
int AddClientIDLocked(const std::string& clientName, uint32_t& clientID) final
{
uint32_t id;
if (!GenerateClientID([this](uint32_t id) { return contexts_.find(id) != contexts_.end(); }, id)) {
return VPE_ALGO_ERR_INVALID_STATE;
}
auto context = std::make_shared<T>();
CHECK_AND_RETURN_RET_LOG(context != nullptr, VPE_ALGO_ERR_NO_MEMORY, "Failed to create context for %{public}s!",
clientName.c_str());
contexts_[id] = std::make_pair(clientName, context);
clientID = id;
return OnContextInitializeLocked(contexts_[id]);
}
int DelClientIDLocked(uint32_t clientID, bool& isEmpty) final
{
auto it = contexts_.find(clientID);
CHECK_AND_RETURN_RET_LOG(it != contexts_.end(), VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: clientID:%{public}u!", clientID);
int ret = OnContextDeinitializeLocked(it->second);
contexts_.erase(it);
isEmpty = contexts_.empty();
return ret;
}
size_t GetClientSizeLocked() const final
{
return contexts_.size();
}
void ClearClientsLocked() final
{
for (auto& [id, info] : contexts_) {
CHECK_AND_LOG(OnContextDeinitializeLocked(info) == VPE_ALGO_ERR_OK,
"Failed to deinitialize(id:%{public}d, client:%{public}s)", id, info.first.c_str());
}
contexts_.clear();
}
int Execute(uint32_t clientID, std::function<int(ClientInfo&)>&& operation,
const LogInfo& logInfo)
{
ClientInfo ctxt;
{
std::lock_guard<std::mutex>lock(lock_);
if (!isInitialized_) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Oops! Not initialized!");
return VPE_ALGO_ERR_INVALID_STATE;
}
ctxt = GetContextLocked(clientID);
if (ctxt.first.empty() || ctxt.second == nullptr) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: client(%{public}u) for '%{public}s'!",
clientID, ctxt.first.c_str());
return VPE_ALGO_ERR_INVALID_PARAM;
}
}
return operation(ctxt);
}
// Guarded by lock_ begin
std::unordered_map<uint32_t, ClientInfo> contexts_{};
// Guarded by lock_ end
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_WITH_DATA_H
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VIDEO_PROCESSING_ALGORITHM_WITHOUT_DATA_H
#define VIDEO_PROCESSING_ALGORITHM_WITHOUT_DATA_H
#include <functional>
#include <string>
#include <unordered_map>
#include "video_processing_algorithm_base.h"
namespace OHOS {
namespace Media {
namespace VideoProcessingEngine {
class VideoProcessingAlgorithmWithoutData : public VideoProcessingAlgorithmBase {
public:
int SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter) final;
int GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter) final;
int DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image) final;
int DoProcess(uint32_t clientID, const SurfaceBufferInfo& input, SurfaceBufferInfo& output) final;
int DoComposeImage(uint32_t clientID, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy) final;
int DoDecomposeImage(uint32_t clientID, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap) final;
protected:
VideoProcessingAlgorithmWithoutData(const std::string& feature, uint32_t id)
: VideoProcessingAlgorithmBase(feature, id) {}
virtual ~VideoProcessingAlgorithmWithoutData() = default;
VideoProcessingAlgorithmWithoutData(const VideoProcessingAlgorithmWithoutData&) = delete;
VideoProcessingAlgorithmWithoutData& operator=(const VideoProcessingAlgorithmWithoutData&) = delete;
VideoProcessingAlgorithmWithoutData(VideoProcessingAlgorithmWithoutData&&) = delete;
VideoProcessingAlgorithmWithoutData& operator=(VideoProcessingAlgorithmWithoutData&&) = delete;
// NOTE: Would be override by the actual algorithm when necessary
// Actual methods begin
// int OnInitializeLocked() - declared by VideoProcessingAlgorithmBase
// int OnDeinitializeLocked() - declared by VideoProcessingAlgorithmBase
virtual int OnSetParameter(const std::string& clientName, int tag, const std::vector<uint8_t>& parameter);
virtual int OnGetParameter(const std::string& clientName, int tag, std::vector<uint8_t>& parameter);
virtual int OnUpdateMetadata(const std::string& clientName, SurfaceBufferInfo& image);
virtual int OnProcess(const std::string& clientName, const SurfaceBufferInfo& input, SurfaceBufferInfo& output);
virtual int OnComposeImage(const std::string& clientName, const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap, SurfaceBufferInfo& outputHdrImage, bool legacy);
virtual int OnDecomposeImage(const std::string& clientName, const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage, SurfaceBufferInfo& outputGainmap);
// Actual methods end
private:
int AddClientIDLocked(const std::string& clientName, uint32_t& clientID) final;
int DelClientIDLocked(uint32_t clientID, bool& isEmpty) final;
void ClearClientsLocked() final;
int Execute(uint32_t clientID, std::function<int(const std::string&)>&& operation, const LogInfo& logInfo);
// Guarded by lock_ begin
std::unordered_map<uint32_t, std::string> clients_{};
// Guarded by lock_ end
};
} // namespace VideoProcessingEngine
} // namespace Media
} // namespace OHOS
#endif // VIDEO_PROCESSING_ALGORITHM_WITHOUT_DATA_H
@@ -0,0 +1,225 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "video_processing_algorithm_base.h"
#include "algorithm_errors.h"
#include "video_processing_algorithm_factory.h"
#include "vpe_sa_types.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
constexpr uint32_t MAX_CLIENT_GEN_COUNT = 500;
}
int VideoProcessingAlgorithmBase::Initialize()
{
std::lock_guard<std::mutex> lock(lock_);
if (isInitialized_) {
VPE_LOGW("Already initialized!");
return VPE_ALGO_ERR_OK;
}
int ret = OnInitializeLocked();
if (ret != VPE_ALGO_ERR_OK) {
VPE_LOGE("Failed to initialize!");
return ret;
}
isInitialized_ = true;
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::Deinitialize()
{
std::lock_guard<std::mutex> lock(lock_);
if (!isInitialized_) {
VPE_LOGW("Already deinitialized!");
return VPE_ALGO_ERR_OK;
}
ClearClientsLocked();
int ret = OnDeinitializeLocked();
if (ret != VPE_ALGO_ERR_OK) {
VPE_LOGE("Failed to deinitialize!");
return ret;
}
isInitialized_ = false;
return VPE_ALGO_ERR_OK;
}
bool VideoProcessingAlgorithmBase::HasClient() const
{
return hasClient_.load();
}
int VideoProcessingAlgorithmBase::Add(const std::string& clientName, uint32_t& clientID)
{
CHECK_AND_RETURN_RET_LOG(!clientName.empty(), VPE_ALGO_ERR_INVALID_PARAM, "Invalid input: clientName is empty!");
std::lock_guard<std::mutex> lock(lock_);
int ret = AddClientIDLocked(clientName, clientID);
CHECK_AND_RETURN_RET_LOG(ret == VPE_ALGO_ERR_OK, ret, "Failed to add client for %{public}s!", clientName.c_str());
hasClient_ = true;
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::Del(uint32_t clientID)
{
std::lock_guard<std::mutex> lock(lock_);
bool isEmpty;
int ret = DelClientIDLocked(clientID, isEmpty);
CHECK_AND_RETURN_RET_LOG(ret == VPE_ALGO_ERR_OK, ret, "Failed to del client(%{public}u)!", clientID);
if (isEmpty) {
hasClient_ = false;
}
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::UpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image)
{
CHECK_AND_RETURN_RET_LOG(IsValid(image), VPE_ALGO_ERR_INVALID_PARAM, "Invalid input: %{public}s!",
image.str().c_str());
return DoUpdateMetadata(clientID, image);
}
int VideoProcessingAlgorithmBase::Process(uint32_t clientID,
const SurfaceBufferInfo& input, SurfaceBufferInfo& output)
{
CHECK_AND_RETURN_RET_LOG(IsValid(input) && IsValid(output), VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: input={%{public}s} output={%{public}s}!", input.str().c_str(), output.str().c_str());
return DoProcess(clientID, input, output);
}
int VideoProcessingAlgorithmBase::ComposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap,
SurfaceBufferInfo& outputHdrImage, bool legacy)
{
CHECK_AND_RETURN_RET_LOG(IsValid(inputSdrImage) && IsValid(inputGainmap) && IsValid(outputHdrImage),
VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: inputSdrImage={%{public}s} inputGainmap={%{public}s} outputHdrImage={%{public}s}!",
inputSdrImage.str().c_str(), inputGainmap.str().c_str(), outputHdrImage.str().c_str());
return DoComposeImage(clientID, inputSdrImage, inputGainmap, outputHdrImage, legacy);
}
int VideoProcessingAlgorithmBase::DecomposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage,
SurfaceBufferInfo& outputGainmap)
{
CHECK_AND_RETURN_RET_LOG(IsValid(inputImage) && IsValid(outputSdrImage) && IsValid(outputGainmap),
VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: inputImage={%{public}s} outputSdrImage={%{public}s} outputGainmap={%{public}s}!",
inputImage.str().c_str(), outputSdrImage.str().c_str(), outputGainmap.str().c_str());
return DoDecomposeImage(clientID, inputImage, outputSdrImage, outputGainmap);
}
int VideoProcessingAlgorithmBase::OnInitializeLocked()
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::OnDeinitializeLocked()
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::AddClientIDLocked([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] uint32_t& clientID)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DelClientIDLocked([[maybe_unused]] uint32_t clientID, [[maybe_unused]] bool& isEmpty)
{
return VPE_ALGO_ERR_OK;
}
size_t VideoProcessingAlgorithmBase::GetClientSizeLocked() const
{
return 0;
}
void VideoProcessingAlgorithmBase::ClearClientsLocked()
{
}
int VideoProcessingAlgorithmBase::DoUpdateMetadata([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] SurfaceBufferInfo& image)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DoProcess([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] const SurfaceBufferInfo& input, [[maybe_unused]] SurfaceBufferInfo& output)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DoComposeImage([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] const SurfaceBufferInfo& inputSdrImage,
[[maybe_unused]] const SurfaceBufferInfo& inputGainmap,
[[maybe_unused]] SurfaceBufferInfo& outputHdrImage, [[maybe_unused]] bool legacy)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::DoDecomposeImage([[maybe_unused]] uint32_t clientID,
[[maybe_unused]] const SurfaceBufferInfo& inputImage,
[[maybe_unused]] SurfaceBufferInfo& outputSdrImage,
[[maybe_unused]] SurfaceBufferInfo& outputGainmap)
{
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmBase::ReturnNotSupport(const LogInfo& logInfo) const
{
VPE_ORG_LOGE(logInfo, "Not support this operation!");
return VPE_ALGO_ERR_OPERATION_NOT_SUPPORTED;
}
bool VideoProcessingAlgorithmBase::GenerateClientID(std::function<bool(uint32_t)>&& isDuplicate, uint32_t& clientID)
{
uint32_t id;
uint32_t i = 0;
do {
// MAX_CLIENT_GEN_COUNT will control the ID generation times,
// it will avoid an infinite loop during ID generation.
if (i++ > MAX_CLIENT_GEN_COUNT) {
VPE_LOGE("Failed to generate new client ID, maybe too many clients(size:%{public}zu).",
GetClientSizeLocked());
return false;
}
id = GenerateClientID();
} while (isDuplicate(id));
clientID = id;
return true;
}
uint32_t VideoProcessingAlgorithmBase::GenerateClientID()
{
// clientIdBase_ CAN overflow after self-adding, because the ID value maybe reused.
// And MAX_CLIENT_GEN_COUNT will control the ID generation times,
// it will avoid an infinite loop during ID generation.
// +---------------------------------------+
// | High <----------------------> Low |
// +---------+-----------------------------+
// | 1 Byte | 3 Bytes |
// +---------+---------+---------+---------+
// |FeatureID| ClientID |
// +---------+---------+---------+---------+
return (featureID_ << 24) | (clientIdBase_++ & 0xFFFFFF);
}
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "video_processing_algorithm_factory.h"
#include <dlfcn.h>
#include "algorithm_errors.h"
#include "video_processing_algorithm_factory_common.h"
#include "vpe_log.h"
// NOTE: Add header file of static algorithm which would be called by VPE SA below:
// algorithm begin
// algorithm end
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
namespace {
const std::string DYNAMIC_ALGORITHM_LIBRARY_PATH = "libvideoprocessingengineservice_ext.z.so";
VpeAlgorithmCreatorMap g_creators = {
// NOTE: Add static algorithm which would be called by VPE SA below:
// algorithm begin
// algorithm end
};
}
VideoProcessingAlgorithmFactory::VideoProcessingAlgorithmFactory()
{
VPE_LOGD("step in");
if (!LoadDynamicAlgorithm(DYNAMIC_ALGORITHM_LIBRARY_PATH)) {
UnloadDynamicAlgorithm();
}
GenerateFeatureIDs();
}
VideoProcessingAlgorithmFactory::~VideoProcessingAlgorithmFactory()
{
UnloadDynamicAlgorithm();
}
std::shared_ptr<IVideoProcessingAlgorithm> VideoProcessingAlgorithmFactory::Create(const std::string& feature) const
{
auto it = g_creators.find(feature);
if (it == g_creators.end()) {
return nullptr;
}
return it->second.creator(feature, it->second.id);
}
bool VideoProcessingAlgorithmFactory::LoadDynamicAlgorithm(const std::string& path)
{
handle_ = dlopen(path.c_str(), RTLD_NOW);
if (handle_ == nullptr) {
VPE_LOGD("Can't open library '%{public}s' - %{public}s", path.c_str(), dlerror());
return false;
}
using GetCreator = VpeAlgorithmCreatorMap* (*)();
auto getCreator = reinterpret_cast<GetCreator>(dlsym(handle_, "GetDynamicAlgorithmCreator"));
if (getCreator == nullptr) {
VPE_LOGD("Failed to locate GetDynamicAlgorithmCreator in '%{public}s' - %{public}s", path.c_str(), dlerror());
return false;
}
auto dynamicAlgorithms = getCreator();
if (dynamicAlgorithms == nullptr) {
VPE_LOGD("Failed to GetDynamicAlgorithmCreator() from '%{public}s'", path.c_str());
return false;
}
auto staticSize = g_creators.size();
auto dynamicSize = dynamicAlgorithms->size();
g_creators.merge(*dynamicAlgorithms);
VPE_LOGI("Algorithms: { static:%{public}zu + dynamic:%{public}zu -> total:%{public}zu }",
staticSize, dynamicSize, g_creators.size());
return true;
}
void VideoProcessingAlgorithmFactory::UnloadDynamicAlgorithm()
{
if (handle_ != nullptr) {
dlclose(handle_);
handle_ = nullptr;
}
}
void VideoProcessingAlgorithmFactory::GenerateFeatureIDs()
{
// When GenerateFeatureIDs be called, the g_creators size is fixed.
// And we fill algorithm feature ID here from 1 to N.
uint32_t id = 0;
for (auto& creatorInfo : g_creators) {
creatorInfo.second.id = ++id;
}
}
@@ -0,0 +1,159 @@
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "video_processing_algorithm_without_data.h"
#include "algorithm_errors.h"
#include "vpe_log.h"
using namespace OHOS;
using namespace OHOS::Media::VideoProcessingEngine;
using namespace std::placeholders;
int VideoProcessingAlgorithmWithoutData::SetParameter(uint32_t clientID, int tag, const std::vector<uint8_t>& parameter)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnSetParameter, this, _1, tag, parameter),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::GetParameter(uint32_t clientID, int tag, std::vector<uint8_t>& parameter)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnGetParameter, this, _1, tag, parameter),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoUpdateMetadata(uint32_t clientID, SurfaceBufferInfo& image)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnUpdateMetadata, this, _1, image),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoProcess(uint32_t clientID,
const SurfaceBufferInfo& input, SurfaceBufferInfo& output)
{
return Execute(clientID, std::bind(&VideoProcessingAlgorithmWithoutData::OnProcess, this, _1, input, output),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoComposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputSdrImage,
const SurfaceBufferInfo& inputGainmap,
SurfaceBufferInfo& outputHdrImage, bool legacy)
{
auto compose = &VideoProcessingAlgorithmWithoutData::OnComposeImage;
return Execute(clientID, std::bind(compose, this, _1, inputSdrImage, inputGainmap, outputHdrImage, legacy),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::DoDecomposeImage(uint32_t clientID,
const SurfaceBufferInfo& inputImage,
SurfaceBufferInfo& outputSdrImage,
SurfaceBufferInfo& outputGainmap)
{
auto decompose = &VideoProcessingAlgorithmWithoutData::OnDecomposeImage;
return Execute(clientID, std::bind(decompose, this, _1, inputImage, outputSdrImage, outputGainmap),
VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnSetParameter([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] int tag, [[maybe_unused]] const std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnGetParameter([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] int tag, [[maybe_unused]] std::vector<uint8_t>& parameter)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnUpdateMetadata([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] SurfaceBufferInfo& image)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnProcess([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] const SurfaceBufferInfo& input,
[[maybe_unused]] SurfaceBufferInfo& output)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnComposeImage([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] const SurfaceBufferInfo& inputSdrImage,
[[maybe_unused]] const SurfaceBufferInfo& inputGainmap,
[[maybe_unused]] SurfaceBufferInfo& outputHdrImage, [[maybe_unused]] bool legacy)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::OnDecomposeImage([[maybe_unused]] const std::string& clientName,
[[maybe_unused]] const SurfaceBufferInfo& inputImage,
[[maybe_unused]] SurfaceBufferInfo& outputSdrImage,
[[maybe_unused]] SurfaceBufferInfo& outputGainmap)
{
return ReturnNotSupport(VPE_LOG_INFO);
}
int VideoProcessingAlgorithmWithoutData::AddClientIDLocked(const std::string& clientName, uint32_t& clientID)
{
uint32_t id;
if (!GenerateClientID([this](uint32_t id) { return clients_.find(id) != clients_.end(); }, id)) {
return VPE_ALGO_ERR_INVALID_STATE;
}
clients_[id] = clientName;
clientID = id;
return VPE_ALGO_ERR_OK;
}
int VideoProcessingAlgorithmWithoutData::DelClientIDLocked(uint32_t clientID, bool& isEmpty)
{
auto it = clients_.find(clientID);
CHECK_AND_RETURN_RET_LOG(it != clients_.end(), VPE_ALGO_ERR_INVALID_PARAM,
"Invalid input: clientID:%{public}u!", clientID);
clients_.erase(it);
isEmpty = clients_.empty();
return VPE_ALGO_ERR_OK;
}
void VideoProcessingAlgorithmWithoutData::ClearClientsLocked()
{
clients_.clear();
}
int VideoProcessingAlgorithmWithoutData::Execute(uint32_t clientID, std::function<int(const std::string&)>&& operation,
const LogInfo& logInfo)
{
std::string clientName;
{
std::lock_guard<std::mutex> lock(lock_);
if (!isInitialized_) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Oops! Not initialized!");
return VPE_ALGO_ERR_INVALID_STATE;
}
auto it = clients_.find(clientID);
if (it == clients_.end()) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: client(%{public}u)!", clientID);
return VPE_ALGO_ERR_INVALID_PARAM;
}
clientName = it->second;
if (clientName.empty()) [[unlikely]] {
VPE_ORG_LOGE(logInfo, "Invalid input: client(%{public}u) for ''!", clientID);
return VPE_ALGO_ERR_INVALID_PARAM;
}
}
return operation(clientName);
}