* Copyright (C) 2026 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 "preprocessor_encoder.h"
#include <mutex>
#include "avcodec_errors.h"
#include "avcodec_log.h"
#include "avcodeclist_impl.h"
#include "media_core.h"
#include "preprocessor_format_utils.h"
#include "statistics_event_reporter.h"
#include "event_info_extented_key.h"
namespace {
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "PreprocessorEncoder"};
constexpr size_t MAX_LENGTH = 255;
static std::mutex g_interfaceMutex;
}
namespace OHOS {
namespace MediaAVCodec {
}
}
namespace OHOS {
namespace MediaAVCodec {
bool PreprocessorEncoder::IsPrimaryEncoderMagic(AVMagic magic)
{
return magic == AVMagic::AVCODEC_MAGIC_PRIMARY_VIDEO_ENCODER;
}
bool PreprocessorEncoder::IsSecondaryEncoderMagic(AVMagic magic)
{
return magic == AVMagic::AVCODEC_MAGIC_SECONDARY_VIDEO_ENCODER;
}
bool PreprocessorEncoder::IsPreprocEncoderMagic(AVMagic magic)
{
return IsPrimaryEncoderMagic(magic) || IsSecondaryEncoderMagic(magic);
}
bool PreprocessorEncoder::IsValidPreprocEncoderMime(const char *mime)
{
CHECK_AND_RETURN_RET_LOG(mime != nullptr, false, "Mime is nullptr!");
size_t len = strnlen(mime, MAX_LENGTH);
CHECK_AND_RETURN_RET_LOG(len > 0 && len <= MAX_LENGTH, false, "Mime is too long!");
std::string mimeStr(mime);
AVCodecListImpl codecList;
CHECK_AND_RETURN_RET_LOG(codecList.Init() == AVCS_ERR_OK, false, "Init AVCodecList failed!");
CapabilityData *cap = codecList.GetCapability(mimeStr, true, AVCodecCategory::AVCODEC_NONE);
CHECK_AND_RETURN_RET_LOG(cap != nullptr, false, "Video encoder capability is not found: %{public}s", mime);
return cap->codecType == static_cast<int32_t>(AVCodecType::AVCODEC_TYPE_VIDEO_ENCODER) && cap->mimeType == mimeStr;
}
std::string PreprocessorEncoder::GenerateEncoderId(const std::string &prefix)
{
static std::atomic<uint64_t> counter{0};
uint64_t id = counter.fetch_add(1);
return prefix + "_" + std::to_string(id);
}
PreprocessorEncoder::PreprocessorEncoder(AVMagic magic) : OH_AVCodec(magic)
{
AVCODEC_LOGI("PreprocessorEncoder created");
}
PreprocessorEncoder::~PreprocessorEncoder()
{
DetachPeerEncoder();
UnregisterEncoderFromManager();
AVCODEC_LOGI("PreprocessorEncoder destroyed");
}
OH_AVErrCode PreprocessorEncoder::CreatePrimary(const char *mime, OH_AVCodec **codec)
{
CHECK_AND_RETURN_RET_LOG(codec != nullptr, AV_ERR_INVALID_VAL, "Codec is nullptr! It must not be nullptr!");
CHECK_AND_RETURN_RET_LOG(*codec == nullptr, AV_ERR_INVALID_VAL,
"The pointer stored in codec is not nullptr! It must be nullptr!");
CHECK_AND_RETURN_RET_LOG(IsValidPreprocEncoderMime(mime), AV_ERR_INVALID_VAL,
"Invalid or unsupported video encoder mime!");
auto encoder = std::make_unique<PreprocessorEncoder>(AVMagic::AVCODEC_MAGIC_PRIMARY_VIDEO_ENCODER);
CHECK_AND_RETURN_RET_LOG(encoder != nullptr, AV_ERR_NO_MEMORY, "PreprocessorEncoder create failed!");
OH_AVErrCode ret = encoder->InitAsPrimary(mime);
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, ret, "InitAsPrimary failed!");
Media::Meta meta;
meta.SetData(Media::Tag::AV_CODEC_CALLER_PID, getprocpid());
meta.SetData(EventInfoExtentedKey::ADVANCED_FEATURE.data(), "PreprocEnc");
StatisticsEventReporter::Report(StatisticsEventType::ADVANCED_FEATURE_INFO, meta);
std::scoped_lock interfaceLock(g_interfaceMutex);
CHECK_AND_RETURN_RET_LOG(*codec == nullptr, AV_ERR_INVALID_VAL,
"The pointer stored in codec is not nullptr! It must be nullptr!");
*codec = encoder.release();
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::CreateSecondary(OH_AVCodec *primary, OH_AVCodec **secondary)
{
std::scoped_lock interfaceLock(g_interfaceMutex);
CHECK_AND_RETURN_RET_LOG(primary != nullptr, AV_ERR_INVALID_VAL, "Primary is nullptr!");
CHECK_AND_RETURN_RET_LOG(secondary != nullptr, AV_ERR_INVALID_VAL, "Codec is nullptr! It must not be nullptr!");
CHECK_AND_RETURN_RET_LOG(*secondary == nullptr, AV_ERR_INVALID_VAL,
"The pointer stored in codec is not nullptr! It must be nullptr!");
CHECK_AND_RETURN_RET_LOG(IsPrimaryEncoderMagic(primary->magic_), AV_ERR_INVALID_VAL, "Primary magic error!");
auto *primaryEnc = reinterpret_cast<PreprocessorEncoder *>(primary);
std::scoped_lock primaryLock(primaryEnc->instanceMutex_);
CHECK_AND_RETURN_RET_LOG(primaryEnc->secondary_ == nullptr, AV_ERR_OPERATE_NOT_PERMIT,
"Secondary encoder already exists!");
auto encoder = std::make_unique<PreprocessorEncoder>(AVMagic::AVCODEC_MAGIC_SECONDARY_VIDEO_ENCODER);
CHECK_AND_RETURN_RET_LOG(encoder != nullptr, AV_ERR_NO_MEMORY, "PreprocessorEncoder create failed!");
OH_AVErrCode ret = encoder->InitAsSecondary(primaryEnc);
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, ret, "InitAsSecondary failed!");
Media::Meta meta;
meta.SetData(Media::Tag::AV_CODEC_CALLER_PID, getprocpid());
meta.SetData(EventInfoExtentedKey::ADVANCED_FEATURE.data(), "OneInDualOut");
StatisticsEventReporter::Report(StatisticsEventType::ADVANCED_FEATURE_INFO, meta);
*secondary = encoder.release();
return AV_ERR_OK;
}
void PreprocessorEncoder::Destroy(OH_AVCodec* codec)
{
std::scoped_lock interfaceLock(g_interfaceMutex);
auto* preprocEnc = reinterpret_cast<PreprocessorEncoder*>(codec);
if (preprocEnc == nullptr) {
return;
}
(void)preprocEnc->Release();
if (!IsPrimaryEncoderMagic(codec->magic_)) {
preprocEnc->DetachFromPrimaryEncoder();
delete preprocEnc;
return;
}
auto secondaryEnc = preprocEnc->DetachSecondaryEncoder();
if (secondaryEnc) {
(void)secondaryEnc->Release();
delete secondaryEnc;
}
delete preprocEnc;
return;
}
OH_AVErrCode PreprocessorEncoder::InitAsPrimary(const char *mime)
{
isPrimary_ = true;
mime_ = mime;
encoderId_ = GenerateEncoderId("primary");
auto videoEncoder = VideoEncoderFactory::CreateByMime(mime_);
CHECK_AND_RETURN_RET_LOG(videoEncoder != nullptr, AV_ERR_NO_MEMORY, "VideoEncoder create failed!");
videoEncoderObject_ = std::make_shared<VideoEncoderObject>(videoEncoder);
CHECK_AND_RETURN_RET_LOG(videoEncoderObject_ != nullptr, AV_ERR_NO_MEMORY, "VideoEncoderObject create failed!");
preprocMgr_ = std::make_shared<PreprocessorManager>();
CHECK_AND_RETURN_RET_LOG(preprocMgr_ != nullptr, AV_ERR_NO_MEMORY, "PreprocessorManager create failed!");
preprocMgr_->CreateSharedSurface();
auto preprocessor = std::make_shared<Preprocessor>(mime);
CHECK_AND_RETURN_RET_LOG(preprocessor != nullptr, AV_ERR_NO_MEMORY, "Preprocessor create failed!");
preprocessors_[encoderId_] = preprocessor;
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::InitAsSecondary(PreprocessorEncoder *primary)
{
isPrimary_ = false;
mime_ = primary->mime_;
encoderId_ = GenerateEncoderId("secondary");
auto videoEncoder = VideoEncoderFactory::CreateByMime(mime_);
CHECK_AND_RETURN_RET_LOG(videoEncoder != nullptr, AV_ERR_NO_MEMORY, "VideoEncoder create failed!");
videoEncoderObject_ = std::make_shared<VideoEncoderObject>(videoEncoder);
CHECK_AND_RETURN_RET_LOG(videoEncoderObject_ != nullptr, AV_ERR_NO_MEMORY, "VideoEncoderObject create failed!");
auto preprocessor = std::make_shared<Preprocessor>(mime_);
CHECK_AND_RETURN_RET_LOG(preprocessor != nullptr, AV_ERR_NO_MEMORY, "Preprocessor create failed!");
preprocessors_[encoderId_] = preprocessor;
preprocMgr_ = primary->preprocMgr_;
primary_ = primary;
primary_->secondary_ = this;
return AV_ERR_OK;
}
void PreprocessorEncoder::CreateSharedSurface()
{
if (preprocMgr_) {
preprocMgr_->CreateSharedSurface();
}
}
sptr<Surface> PreprocessorEncoder::GetSharedSurface()
{
if (preprocMgr_) {
return preprocMgr_->GetSharedSurface();
}
return nullptr;
}
void PreprocessorEncoder::RegisterEncoderToManager()
{
if (preprocMgr_) {
auto preprocessor = preprocessors_[encoderId_];
auto streamChangedCb = [this](const Media::Format& format) {
OnStreamChanged(format);
};
auto errorCb = [this](int32_t errorCode) {
OnPreprocessError(errorCode);
};
preprocMgr_->RegisterEncoder(encoderId_, preprocessor, encoderSurface_, streamChangedCb, errorCb);
}
}
void PreprocessorEncoder::UnregisterEncoderFromManager()
{
if (preprocMgr_) {
preprocMgr_->UnregisterEncoder(encoderId_);
}
}
void PreprocessorEncoder::DetachPeerEncoder()
{
if (isPrimary_) {
auto *secondary = secondary_;
secondary_ = nullptr;
if (secondary != nullptr && secondary->primary_ == this) {
secondary->primary_ = nullptr;
}
return;
}
DetachFromPrimaryEncoder();
}
PreprocessorEncoder* PreprocessorEncoder::DetachSecondaryEncoder()
{
auto *secondary = secondary_;
secondary_ = nullptr;
if (secondary != nullptr && secondary->primary_ == this) {
secondary->primary_ = nullptr;
}
return secondary;
}
void PreprocessorEncoder::DetachFromPrimaryEncoder()
{
auto *primary = primary_;
primary_ = nullptr;
if (primary != nullptr && primary->secondary_ == this) {
primary->secondary_ = nullptr;
}
}
OH_AVErrCode PreprocessorEncoder::RegisterCallback(struct OH_AVCodecCallback callback, void *userData)
{
std::scoped_lock lock(instanceMutex_);
asyncCallback_.onError = callback.onError;
asyncCallback_.onStreamChanged = callback.onStreamChanged;
userData_ = userData;
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
if (videoEncoderObject_->callback_ != nullptr) {
videoEncoderObject_->callback_->UpdateCallback(callback, userData);
} else {
videoEncoderObject_->callback_ = std::make_shared<NativeVideoEncoderCallback>(this, callback, userData);
}
int32_t ret = videoEncoderObject_->videoEncoder_->SetCallback(
std::static_pointer_cast<MediaCodecCallback>(videoEncoderObject_->callback_));
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Video encoder register callback failed!");
}
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::Configure(const Media::Format &format)
{
std::scoped_lock lock(instanceMutex_);
auto ret = ConfigureVideoEncoder(format);
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Configure video encoder failed!");
ret = ConfigurePreprocessor(format);
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Configure preprocessor failed!");
if (encoderSurface_ == nullptr) {
ret = CreateEncoderSurface();
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AV_ERR_OPERATE_NOT_PERMIT, "Create internal surface failed!");
}
RegisterEncoderToManager();
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::SetParameter(const Media::Format &format)
{
std::scoped_lock lock(instanceMutex_);
auto preprocessor = GetPreprocessor();
if (!preprocessor) {
return AV_ERR_INVALID_VAL;
}
int32_t ret = AVCS_ERR_OK;
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
ret = videoEncoderObject_->videoEncoder_->SetParameter(format);
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"PreprocessorEncoder set parameter failed!");
}
ret = preprocessor->ValidateConfiguration(format, false);
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"PreprocessorEncoder validate preprocessor parameter failed!");
ret = preprocessor->SetParameter(format);
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"PreprocessorEncoder set preprocessor parameter failed!");
return AV_ERR_OK;
}
sptr<Surface> PreprocessorEncoder::GetSurface()
{
std::scoped_lock lock(instanceMutex_);
return GetSharedSurface();
}
int32_t PreprocessorEncoder::ConfigureVideoEncoder(const Media::Format &format)
{
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
int32_t bitrateMode = -1;
bool bitrateModeExist = format.GetIntValue(OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode);
if (bitrateModeExist && bitrateMode == SQR) {
int64_t bitrate;
int64_t maxBitrate;
bool bitrateExist = format.GetLongValue(OH_MD_KEY_BITRATE, bitrate);
bool maxBitrateExist = format.GetLongValue(OH_MD_KEY_MAX_BITRATE, maxBitrate);
if (bitrateExist && !maxBitrateExist) {
AVCODEC_LOGW("In SQR bitrate mode, param %{public}s is not set, param %{public}s will be used instead",
OH_MD_KEY_MAX_BITRATE, OH_MD_KEY_BITRATE);
Media::Format formatTemp = format;
formatTemp.PutLongValue(OH_MD_KEY_MAX_BITRATE, bitrate);
return videoEncoderObject_->videoEncoder_->Configure(formatTemp);
}
}
int32_t ret = videoEncoderObject_->videoEncoder_->Configure(format);
return ret;
}
return AVCS_ERR_OK;
}
int32_t PreprocessorEncoder::ConfigurePreprocessor(const Media::Format &format)
{
auto preprocessor = GetPreprocessor();
if (preprocessor) {
auto ret = preprocessor->ValidateConfiguration(format, true);
if (ret != AVCS_ERR_OK) {
return ret;
}
return preprocessor->Configure(format);
}
return AVCS_ERR_OK;
}
int32_t PreprocessorEncoder::CreateEncoderSurface()
{
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
auto surface = videoEncoderObject_->videoEncoder_->CreateInputSurface();
if (surface == nullptr && encoderSurface_ == nullptr) {
return AVCS_ERR_NO_MEMORY;
}
if (surface != nullptr) {
encoderSurface_ = surface;
}
}
return AVCS_ERR_OK;
}
std::optional<OH_AVBuffer*> PreprocessorEncoder::GetTransData(const uint32_t& index,
std::shared_ptr<AVBuffer>& buffer,
bool isOutput)
{
CHECK_AND_RETURN_RET_LOG(videoEncoderObject_ && videoEncoderObject_->videoEncoder_, std::nullopt,
"Context video encoder is nullptr!");
return videoEncoderObject_->GetTransData(index, buffer, isOutput);
}
std::shared_ptr<Preprocessor> PreprocessorEncoder::GetPreprocessor()
{
auto it = preprocessors_.find(encoderId_);
if (it != preprocessors_.end()) {
return it->second;
}
return nullptr;
}
OH_AVErrCode PreprocessorEncoder::Start()
{
std::scoped_lock lock(instanceMutex_);
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
int32_t ret = videoEncoderObject_->videoEncoder_->Start();
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Video encoder start failed!");
}
auto preprocessor = GetPreprocessor();
if (preprocessor) {
preprocessor->FlushTimeStamp();
}
if (preprocMgr_) {
preprocMgr_->SetEncoderRunning(encoderId_, true);
}
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::Stop()
{
std::scoped_lock lock(instanceMutex_);
if (preprocMgr_) {
preprocMgr_->NotifyEosNowIfPending(encoderId_);
}
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
int32_t ret = videoEncoderObject_->videoEncoder_->Stop();
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Video encoder stop failed!");
videoEncoderObject_->ClearBufferList();
}
if (preprocMgr_) {
preprocMgr_->SetEncoderRunning(encoderId_, false);
}
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::Flush()
{
std::scoped_lock lock(instanceMutex_);
if (preprocMgr_) {
preprocMgr_->NotifyEosNowIfPending(encoderId_);
}
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
int32_t ret = videoEncoderObject_->videoEncoder_->Flush();
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Video encoder flush failed!");
videoEncoderObject_->ClearBufferList();
}
if (preprocMgr_) {
preprocMgr_->SetEncoderRunning(encoderId_, false);
}
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::Reset()
{
std::scoped_lock lock(instanceMutex_);
if (preprocMgr_) {
preprocMgr_->NotifyEosNowIfPending(encoderId_);
}
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
int32_t ret = videoEncoderObject_->videoEncoder_->Reset();
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Video encoder reset failed!");
videoEncoderObject_->ClearBufferList();
}
if (preprocMgr_) {
preprocMgr_->SetEncoderRunning(encoderId_, false);
UnregisterEncoderFromManager();
}
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::Release()
{
std::scoped_lock lock(instanceMutex_);
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
if (preprocMgr_) {
preprocMgr_->SetEncoderRunning(encoderId_, false);
}
int32_t ret = videoEncoderObject_->videoEncoder_->Release();
videoEncoderObject_->StopCallback();
videoEncoderObject_->ClearBufferList();
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"PreprocessorEncoder release failed!");
videoEncoderObject_.reset();
}
magic_ = AVMagic::AVCODEC_MAGIC_INVALID_ENTITY;
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::NotifyEos()
{
std::scoped_lock lock(instanceMutex_);
CHECK_AND_RETURN_RET_LOG(preprocMgr_, AV_ERR_OPERATE_NOT_PERMIT, "PreprocessorManager is not found");
if (preprocMgr_) {
std::shared_ptr<VideoEncoderObject> videoEncoderObject = videoEncoderObject_;
std::string encoderId = encoderId_;
bool requestRet = preprocMgr_->RequestNotifyEos(encoderId_, [videoEncoderObject, encoderId]() {
if (!(videoEncoderObject && videoEncoderObject->videoEncoder_)) {
AVCODEC_LOGE("Video encoder is nullptr when async notify eos: %{public}s", encoderId.c_str());
return;
}
int32_t ret = videoEncoderObject->videoEncoder_->NotifyEos();
if (ret != AV_ERR_OK) {
AVCODEC_LOGE("Async notify eos failed for %{public}s, ret=%{public}d", encoderId.c_str(), ret);
}
});
CHECK_AND_RETURN_RET_LOG(requestRet, AV_ERR_INVALID_STATE, "Request async notify eos failed!");
}
return AV_ERR_OK;
}
OH_AVErrCode PreprocessorEncoder::ReleaseOutputBuffer(uint32_t index)
{
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
int32_t ret = videoEncoderObject_->videoEncoder_->ReleaseOutputBuffer(index);
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(ret)),
"Preprocessor release output buffer failed!");
}
return AV_ERR_OK;
}
void PreprocessorEncoder::OnStreamChanged(const Media::Format& format)
{
if (asyncCallback_.onStreamChanged == nullptr) {
return;
}
OHOS::sptr<OH_AVFormat> object = new (std::nothrow) OH_AVFormat(format);
if (object == nullptr) {
AVCODEC_LOGE("OH_AVFormat create failed in OnStreamChanged");
return;
}
asyncCallback_.onStreamChanged(this, reinterpret_cast<OH_AVFormat*>(object.GetRefPtr()), userData_);
}
void PreprocessorEncoder::OnPreprocessError(int32_t errorCode)
{
if (asyncCallback_.onError == nullptr) {
return;
}
OH_AVErrCode avErrorCode = AVCSErrorToOHAVErrCode(static_cast<AVCodecServiceErrCode>(errorCode));
asyncCallback_.onError(this, static_cast<int32_t>(avErrorCode), userData_);
}
OH_AVFormat* PreprocessorEncoder::GetOutputDescription()
{
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
Format format;
int32_t ret = videoEncoderObject_->videoEncoder_->GetOutputFormat(format);
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr,
"PreprocessorEncoder get output description failed!");
OH_AVFormat* avFormat = OH_AVFormat_Create();
CHECK_AND_RETURN_RET_LOG(avFormat != nullptr, nullptr, "PreprocessorEncoder create output format failed!");
avFormat->format_ = format;
return avFormat;
}
return nullptr;
}
OH_AVFormat* PreprocessorEncoder::GetInputDescription()
{
auto preprocessor = GetPreprocessor();
CHECK_AND_RETURN_RET_LOG(preprocessor != nullptr, nullptr, "Preprocessor not found for GetInputDescription!");
Format format;
if (videoEncoderObject_ && videoEncoderObject_->videoEncoder_) {
Format encoderFormat;
int32_t ret = videoEncoderObject_->videoEncoder_->GetInputFormat(encoderFormat);
if (ret == AVCS_ERR_OK) {
format = encoderFormat;
}
}
if (preprocMgr_) {
PreprocessorManager::BufferDataInfo bufInfo;
if (preprocMgr_->PeekPendingBufferData(encoderId_, bufInfo)) {
format.PutIntValue(Media::Tag::VIDEO_WIDTH, bufInfo.width);
format.PutIntValue(Media::Tag::VIDEO_HEIGHT, bufInfo.height);
format.PutIntValue(OHOS::Media::Tag::VIDEO_GRAPHIC_PIXEL_FORMAT, bufInfo.format);
VideoPixelFormat mappedFmt;
if (GraphicPixelFmtToVideoPixelFmt(static_cast<GraphicPixelFormat>(bufInfo.format), mappedFmt)) {
format.PutIntValue(Media::Tag::VIDEO_PIXEL_FORMAT, static_cast<int32_t>(mappedFmt));
}
if (bufInfo.stride > 0) {
format.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE, bufInfo.stride);
}
if (bufInfo.height > 0) {
format.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, bufInfo.height);
}
}
}
if (preprocessor->IsCropEnabled()) {
format.PutIntValue(OH_MD_KEY_VIDEO_ENCODER_PREPROC_CROP_LEFT, preprocessor->GetCropLeft());
format.PutIntValue(OH_MD_KEY_VIDEO_ENCODER_PREPROC_CROP_RIGHT, preprocessor->GetCropRight());
format.PutIntValue(OH_MD_KEY_VIDEO_ENCODER_PREPROC_CROP_TOP, preprocessor->GetCropTop());
format.PutIntValue(OH_MD_KEY_VIDEO_ENCODER_PREPROC_CROP_BOTTOM, preprocessor->GetCropBottom());
}
if (preprocessor->IsDownsamplingEnabled()) {
format.PutIntValue(OH_MD_KEY_VIDEO_ENCODER_PREPROC_DOWNSAMPLING_WIDTH, preprocessor->GetDownsamplingWidth());
format.PutIntValue(OH_MD_KEY_VIDEO_ENCODER_PREPROC_DOWNSAMPLING_HEIGHT, preprocessor->GetDownsamplingHeight());
}
OH_AVFormat* avFormat = OH_AVFormat_Create();
CHECK_AND_RETURN_RET_LOG(avFormat != nullptr, nullptr, "PreprocessorEncoder create input format failed!");
avFormat->format_ = format;
return avFormat;
}
}
}